Lines Matching +full:i2c +full:- +full:transfer +full:- +full:timeout +full:- +full:us
1 // SPDX-License-Identifier: GPL-2.0
3 * I2C driver for the Renesas EMEV2 SoC
5 * Copyright (C) 2015 Wolfram Sang <wsa@sang-engineering.com>
7 * Copyright 2010-2015 Renesas Electronics Corporation
13 #include <linux/i2c.h>
23 /* I2C Registers */
34 /* I2C IICACT0 Masks */
37 /* I2C IICC0 Masks */
46 /* I2C IICCL0 Masks */
50 /* I2C IICSE0 Masks */
60 /* I2C IICF0 Masks */
76 writeb((readb(priv->base + reg) & ~clear) | set, priv->base + reg); in em_clear_set_bit()
84 reinit_completion(&priv->msg_done); in em_i2c_wait_for_event()
86 time_left = wait_for_completion_timeout(&priv->msg_done, priv->adap.timeout); in em_i2c_wait_for_event()
89 return -ETIMEDOUT; in em_i2c_wait_for_event()
91 status = readb(priv->base + I2C_OFS_IICSE0); in em_i2c_wait_for_event()
92 return status & I2C_BIT_ALD0 ? -EAGAIN : status; in em_i2c_wait_for_event()
109 /* If I2C active */ in em_i2c_reset()
110 if (readb(priv->base + I2C_OFS_IICACT0) & I2C_BIT_IICE0) { in em_i2c_reset()
111 /* Disable I2C operation */ in em_i2c_reset()
112 writeb(0, priv->base + I2C_OFS_IICACT0); in em_i2c_reset()
115 while (readb(priv->base + I2C_OFS_IICACT0) == 1 && retr) in em_i2c_reset()
116 retr--; in em_i2c_reset()
120 /* Transfer mode set */ in em_i2c_reset()
121 writeb(I2C_BIT_DFC0, priv->base + I2C_OFS_IICCL0); in em_i2c_reset()
124 writeb(I2C_BIT_STCEN | I2C_BIT_IICRSV, priv->base + I2C_OFS_IICF0); in em_i2c_reset()
126 /* I2C enable, 9 bit interrupt mode */ in em_i2c_reset()
127 writeb(I2C_BIT_WTIM0, priv->base + I2C_OFS_IICC0); in em_i2c_reset()
129 /* Enable I2C operation */ in em_i2c_reset()
130 writeb(I2C_BIT_IICE0, priv->base + I2C_OFS_IICACT0); in em_i2c_reset()
133 while (readb(priv->base + I2C_OFS_IICACT0) == 0 && retr) in em_i2c_reset()
134 retr--; in em_i2c_reset()
142 int count, status, read = !!(msg->flags & I2C_M_RD); in __em_i2c_xfer()
149 writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0); in __em_i2c_xfer()
175 for (count = 0; count < msg->len; count++) { in __em_i2c_xfer()
177 msg->buf[count] = readb(priv->base + I2C_OFS_IIC0); in __em_i2c_xfer()
188 writeb(msg->buf[count], priv->base + I2C_OFS_IIC0); in __em_i2c_xfer()
205 return status < 0 ? status : -ENXIO; in __em_i2c_xfer()
214 if (readb(priv->base + I2C_OFS_IICF0) & I2C_BIT_IICBSY) in em_i2c_xfer()
215 return -EAGAIN; in em_i2c_xfer()
218 ret = __em_i2c_xfer(adap, &msgs[i], (i == (num - 1))); in em_i2c_xfer()
223 /* I2C transfer completed */ in em_i2c_xfer()
233 if (!priv->slave) in em_i2c_slave_irq()
236 status = readb(priv->base + I2C_OFS_IICSE0); in em_i2c_slave_irq()
247 i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); in em_i2c_slave_irq()
252 /* Only handle interrupts addressed to us */ in em_i2c_slave_irq()
269 i2c_slave_event(priv->slave, event, &value); in em_i2c_slave_irq()
270 writeb(value, priv->base + I2C_OFS_IIC0); in em_i2c_slave_irq()
283 i2c_slave_event(priv->slave, I2C_SLAVE_WRITE_REQUESTED, in em_i2c_slave_irq()
287 value = readb(priv->base + I2C_OFS_IIC0); in em_i2c_slave_irq()
288 ret = i2c_slave_event(priv->slave, in em_i2c_slave_irq()
306 complete(&priv->msg_done); in em_i2c_irq_handler()
318 struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); in em_i2c_reg_slave()
320 if (priv->slave) in em_i2c_reg_slave()
321 return -EBUSY; in em_i2c_reg_slave()
323 if (slave->flags & I2C_CLIENT_TEN) in em_i2c_reg_slave()
324 return -EAFNOSUPPORT; in em_i2c_reg_slave()
326 priv->slave = slave; in em_i2c_reg_slave()
329 writeb(slave->addr << 1, priv->base + I2C_OFS_SVA0); in em_i2c_reg_slave()
336 struct em_i2c_device *priv = i2c_get_adapdata(slave->adapter); in em_i2c_unreg_slave()
338 WARN_ON(!priv->slave); in em_i2c_unreg_slave()
340 writeb(0, priv->base + I2C_OFS_SVA0); in em_i2c_unreg_slave()
347 synchronize_irq(priv->irq); in em_i2c_unreg_slave()
348 priv->slave = NULL; in em_i2c_unreg_slave()
366 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); in em_i2c_probe()
368 return -ENOMEM; in em_i2c_probe()
370 priv->base = devm_platform_ioremap_resource(pdev, 0); in em_i2c_probe()
371 if (IS_ERR(priv->base)) in em_i2c_probe()
372 return PTR_ERR(priv->base); in em_i2c_probe()
374 strscpy(priv->adap.name, "EMEV2 I2C", sizeof(priv->adap.name)); in em_i2c_probe()
376 sclk = devm_clk_get_enabled(&pdev->dev, "sclk"); in em_i2c_probe()
380 priv->adap.timeout = msecs_to_jiffies(100); in em_i2c_probe()
381 priv->adap.retries = 5; in em_i2c_probe()
382 priv->adap.dev.parent = &pdev->dev; in em_i2c_probe()
383 priv->adap.algo = &em_i2c_algo; in em_i2c_probe()
384 priv->adap.owner = THIS_MODULE; in em_i2c_probe()
385 priv->adap.dev.of_node = pdev->dev.of_node; in em_i2c_probe()
387 init_completion(&priv->msg_done); in em_i2c_probe()
390 i2c_set_adapdata(&priv->adap, priv); in em_i2c_probe()
392 em_i2c_reset(&priv->adap); in em_i2c_probe()
397 priv->irq = ret; in em_i2c_probe()
399 ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0, in em_i2c_probe()
404 ret = i2c_add_adapter(&priv->adap); in em_i2c_probe()
408 dev_info(&pdev->dev, "Added i2c controller %d, irq %d\n", priv->adap.nr, in em_i2c_probe()
409 priv->irq); in em_i2c_probe()
418 i2c_del_adapter(&priv->adap); in em_i2c_remove()
422 { .compatible = "renesas,iic-emev2", },
430 .name = "em-i2c",
436 MODULE_DESCRIPTION("EMEV2 I2C bus driver");
438 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");