Lines Matching +full:im +full:-
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* ------------------------------------------------------------------------- */
3 /* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */
4 /* ------------------------------------------------------------------------- */
5 /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
8 * With acknowledgements to i2c-algo-ibm_ocp.c by
11 * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
13 * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
16 * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
20 * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs
21 * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference
22 * - Make it work with IXP46x chips
23 * - Cleanup function names, coding style, etc
25 * - writing to slave address causes latchup on iop331.
40 #include "i2c-iop3xx.h"
59 __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_reset()
60 __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET); in iop3xx_i2c_reset()
61 __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_reset()
76 if (iop3xx_adap->gpio_scl) in iop3xx_i2c_enable()
77 gpiod_set_raw_value(iop3xx_adap->gpio_scl, 0); in iop3xx_i2c_enable()
78 if (iop3xx_adap->gpio_sda) in iop3xx_i2c_enable()
79 gpiod_set_raw_value(iop3xx_adap->gpio_sda, 0); in iop3xx_i2c_enable()
81 /* NB SR bits not same position as CR IE bits :-( */ in iop3xx_i2c_enable()
82 iop3xx_adap->SR_enabled = in iop3xx_i2c_enable()
89 __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_enable()
95 unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_transaction_cleanup()
100 __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_transaction_cleanup()
111 u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); in iop3xx_i2c_irq_handler()
113 if ((sr &= iop3xx_adap->SR_enabled)) { in iop3xx_i2c_irq_handler()
114 __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET); in iop3xx_i2c_irq_handler()
115 iop3xx_adap->SR_received |= sr; in iop3xx_i2c_irq_handler()
116 wake_up_interruptible(&iop3xx_adap->waitq); in iop3xx_i2c_irq_handler()
129 rc = -I2C_ERR_BERR; in iop3xx_i2c_error()
133 rc = -I2C_ERR_ALD; in iop3xx_i2c_error()
144 spin_lock_irqsave(&iop3xx_adap->lock, flags); in iop3xx_i2c_get_srstat()
145 sr = iop3xx_adap->SR_received; in iop3xx_i2c_get_srstat()
146 iop3xx_adap->SR_received = 0; in iop3xx_i2c_get_srstat()
147 spin_unlock_irqrestore(&iop3xx_adap->lock, flags); in iop3xx_i2c_get_srstat()
171 iop3xx_adap->waitq, in iop3xx_i2c_wait_event()
180 return -ETIMEDOUT; in iop3xx_i2c_wait_event()
233 unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_send_target_addr()
240 if (msg->addr == MYSAR) { in iop3xx_i2c_send_target_addr()
241 return -EBUSY; in iop3xx_i2c_send_target_addr()
244 __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET); in iop3xx_i2c_send_target_addr()
249 __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_send_target_addr()
259 unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_write_byte()
263 __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET); in iop3xx_i2c_write_byte()
271 __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_write_byte()
281 unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_read_byte()
293 __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); in iop3xx_i2c_read_byte()
297 *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET); in iop3xx_i2c_read_byte()
305 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; in iop3xx_i2c_writebytes()
310 rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii == count-1); in iop3xx_i2c_writebytes()
317 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; in iop3xx_i2c_readbytes()
322 rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii == count-1); in iop3xx_i2c_readbytes()
337 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; in iop3xx_i2c_handle_msg()
345 if ((pmsg->flags&I2C_M_RD)) { in iop3xx_i2c_handle_msg()
346 return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len); in iop3xx_i2c_handle_msg()
348 return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len); in iop3xx_i2c_handle_msg()
353 * master_xfer() - main read/write entry
359 struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; in iop3xx_i2c_master_xfer()
360 int im = 0; in iop3xx_i2c_master_xfer() local
368 for (im = 0; ret == 0 && im != num; im++) { in iop3xx_i2c_master_xfer()
369 ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]); in iop3xx_i2c_master_xfer()
377 return im; in iop3xx_i2c_master_xfer()
396 (struct i2c_algo_iop3xx_data *)padapter->algo_data; in iop3xx_i2c_remove()
398 unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET); in iop3xx_i2c_remove()
405 __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET); in iop3xx_i2c_remove()
407 iounmap(adapter_data->ioaddr); in iop3xx_i2c_remove()
408 release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); in iop3xx_i2c_remove()
425 ret = -ENOMEM; in iop3xx_i2c_probe()
431 ret = -ENOMEM; in iop3xx_i2c_probe()
435 adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev, in iop3xx_i2c_probe()
438 if (IS_ERR(adapter_data->gpio_scl)) { in iop3xx_i2c_probe()
439 ret = PTR_ERR(adapter_data->gpio_scl); in iop3xx_i2c_probe()
442 adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev, in iop3xx_i2c_probe()
445 if (IS_ERR(adapter_data->gpio_sda)) { in iop3xx_i2c_probe()
446 ret = PTR_ERR(adapter_data->gpio_sda); in iop3xx_i2c_probe()
452 ret = -ENODEV; in iop3xx_i2c_probe()
456 if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) { in iop3xx_i2c_probe()
457 ret = -EBUSY; in iop3xx_i2c_probe()
462 adapter_data->id = i2c_id++; in iop3xx_i2c_probe()
464 adapter_data->ioaddr = ioremap(res->start, IOP3XX_I2C_IO_SIZE); in iop3xx_i2c_probe()
465 if (!adapter_data->ioaddr) { in iop3xx_i2c_probe()
466 ret = -ENOMEM; in iop3xx_i2c_probe()
476 pdev->name, adapter_data); in iop3xx_i2c_probe()
481 memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); in iop3xx_i2c_probe()
482 new_adapter->owner = THIS_MODULE; in iop3xx_i2c_probe()
483 new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; in iop3xx_i2c_probe()
484 new_adapter->dev.parent = &pdev->dev; in iop3xx_i2c_probe()
485 new_adapter->dev.of_node = pdev->dev.of_node; in iop3xx_i2c_probe()
486 new_adapter->nr = pdev->id; in iop3xx_i2c_probe()
491 new_adapter->timeout = HZ; in iop3xx_i2c_probe()
492 new_adapter->algo = &iop3xx_i2c_algo; in iop3xx_i2c_probe()
494 init_waitqueue_head(&adapter_data->waitq); in iop3xx_i2c_probe()
495 spin_lock_init(&adapter_data->lock); in iop3xx_i2c_probe()
501 new_adapter->algo_data = adapter_data; in iop3xx_i2c_probe()
508 iounmap(adapter_data->ioaddr); in iop3xx_i2c_probe()
511 release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); in iop3xx_i2c_probe()
524 { .compatible = "intel,iop3xx-i2c", },
525 { .compatible = "intel,ixp4xx-i2c", },
534 .name = "IOP3xx-I2C",
541 MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
544 MODULE_ALIAS("platform:IOP3xx-I2C");