Lines Matching +full:i2c +full:- +full:transfer +full:- +full:timeout +full:- +full:us

1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for the Renesas RZ/V2M I2C unit
5 * Copyright (C) 2016-2022 Renesas Electronics Corporation
15 #include <linux/i2c.h>
35 #define IICB0IICE BIT(7) /* I2C Enable */
92 complete(&priv->msg_tia_done); in rzv2m_i2c_tia_irq_handler()
111 pclk_hz = clk_get_rate(priv->clk); in rzv2m_i2c_clock_calculate()
120 priv->bus_mode = RZV2M_I2C_400K; in rzv2m_i2c_clock_calculate()
123 priv->bus_mode = RZV2M_I2C_100K; in rzv2m_i2c_clock_calculate()
126 dev_err(dev, "transfer speed is invalid\n"); in rzv2m_i2c_clock_calculate()
127 return -EINVAL; in rzv2m_i2c_clock_calculate()
129 config = &bitrate_configs[priv->bus_mode]; in rzv2m_i2c_clock_calculate()
131 /* IICB0WL = (percent_low / Transfer clock) x PCLK */ in rzv2m_i2c_clock_calculate()
132 priv->iicb0wl = total_pclks * config->percent_low / 100; in rzv2m_i2c_clock_calculate()
133 if (priv->iicb0wl > (BIT(10) - 1)) in rzv2m_i2c_clock_calculate()
134 return -EINVAL; in rzv2m_i2c_clock_calculate()
136 /* IICB0WH = ((percent_high / Transfer clock) x PCLK) - (tR + tF) */ in rzv2m_i2c_clock_calculate()
137 priv->iicb0wh = total_pclks - priv->iicb0wl - trf_pclks; in rzv2m_i2c_clock_calculate()
138 if (priv->iicb0wh > (BIT(10) - 1)) in rzv2m_i2c_clock_calculate()
139 return -EINVAL; in rzv2m_i2c_clock_calculate()
142 * Data hold time must be less than 0.9us in fast mode and in rzv2m_i2c_clock_calculate()
143 * 3.45us in standard mode. in rzv2m_i2c_clock_calculate()
146 hold_time_ns = div64_ul((u64)(priv->iicb0wl >> 2) * NSEC_PER_SEC, pclk_hz); in rzv2m_i2c_clock_calculate()
147 if (hold_time_ns > config->min_hold_time_ns) { in rzv2m_i2c_clock_calculate()
149 hold_time_ns, config->min_hold_time_ns); in rzv2m_i2c_clock_calculate()
150 return -EINVAL; in rzv2m_i2c_clock_calculate()
161 /* i2c disable */ in rzv2m_i2c_init()
162 writel(0, priv->base + IICB0CTL0); in rzv2m_i2c_init()
166 if (priv->bus_mode == RZV2M_I2C_400K) in rzv2m_i2c_init()
168 writel(i2c_ctl1, priv->base + IICB0CTL1); in rzv2m_i2c_init()
171 writel(priv->iicb0wl, priv->base + IICB0WL); in rzv2m_i2c_init()
172 writel(priv->iicb0wh, priv->base + IICB0WH); in rzv2m_i2c_init()
174 /* i2c enable after setting */ in rzv2m_i2c_init()
176 writel(i2c_ctl0, priv->base + IICB0CTL0); in rzv2m_i2c_init()
183 reinit_completion(&priv->msg_tia_done); in rzv2m_i2c_write_with_ack()
185 writel(data, priv->base + IICB0DAT); in rzv2m_i2c_write_with_ack()
187 time_left = wait_for_completion_timeout(&priv->msg_tia_done, in rzv2m_i2c_write_with_ack()
188 priv->adap.timeout); in rzv2m_i2c_write_with_ack()
190 return -ETIMEDOUT; in rzv2m_i2c_write_with_ack()
193 if ((readl(priv->base + IICB0STR0) & IICB0SSAC) != IICB0SSAC) in rzv2m_i2c_write_with_ack()
194 return -ENXIO; in rzv2m_i2c_write_with_ack()
205 reinit_completion(&priv->msg_tia_done); in rzv2m_i2c_read_with_ack()
208 bit_clrl(priv->base + IICB0CTL0, IICB0SLWT); in rzv2m_i2c_read_with_ack()
211 writel(IICB0WRET, priv->base + IICB0TRG); in rzv2m_i2c_read_with_ack()
214 time_left = wait_for_completion_timeout(&priv->msg_tia_done, in rzv2m_i2c_read_with_ack()
215 priv->adap.timeout); in rzv2m_i2c_read_with_ack()
217 return -ETIMEDOUT; in rzv2m_i2c_read_with_ack()
221 bit_clrl(priv->base + IICB0CTL0, IICB0SLAC); in rzv2m_i2c_read_with_ack()
224 data_tmp = readl(priv->base + IICB0DAT); in rzv2m_i2c_read_with_ack()
227 bit_setl(priv->base + IICB0CTL0, IICB0SLWT); in rzv2m_i2c_read_with_ack()
230 writel(IICB0WRET, priv->base + IICB0TRG); in rzv2m_i2c_read_with_ack()
233 time_left = wait_for_completion_timeout(&priv->msg_tia_done, in rzv2m_i2c_read_with_ack()
234 priv->adap.timeout); in rzv2m_i2c_read_with_ack()
236 return -ETIMEDOUT; in rzv2m_i2c_read_with_ack()
239 bit_setl(priv->base + IICB0CTL0, IICB0SLAC); in rzv2m_i2c_read_with_ack()
242 data_tmp = readl(priv->base + IICB0DAT); in rzv2m_i2c_read_with_ack()
256 for (i = 0; i < msg->len; i++) { in rzv2m_i2c_send()
257 ret = rzv2m_i2c_write_with_ack(priv, msg->buf[i]); in rzv2m_i2c_send()
272 for (i = 0; i < msg->len; i++) { in rzv2m_i2c_receive()
273 ret = rzv2m_i2c_read_with_ack(priv, &msg->buf[i], in rzv2m_i2c_receive()
274 (msg->len - 1) == i); in rzv2m_i2c_receive()
289 if (msg->flags & I2C_M_TEN) { in rzv2m_i2c_send_address()
291 * 10-bit address in rzv2m_i2c_send_address()
295 addr = 0xf0 | ((msg->addr & GENMASK(9, 8)) >> 7); in rzv2m_i2c_send_address()
296 addr |= !!(msg->flags & I2C_M_RD); in rzv2m_i2c_send_address()
303 ret = rzv2m_i2c_write_with_ack(priv, msg->addr & 0xff); in rzv2m_i2c_send_address()
305 /* 7-bit address */ in rzv2m_i2c_send_address()
318 writel(IICB0SPT, priv->base + IICB0TRG); in rzv2m_i2c_stop_condition()
319 return readl_poll_timeout(priv->base + IICB0STR0, in rzv2m_i2c_stop_condition()
321 100, jiffies_to_usecs(priv->adap.timeout)); in rzv2m_i2c_stop_condition()
328 int ret, read = !!(msg->flags & I2C_M_RD); in rzv2m_i2c_xfer_msg()
331 writel(IICB0STT, priv->base + IICB0TRG); in rzv2m_i2c_xfer_msg()
344 if (ret == -ENXIO) in rzv2m_i2c_xfer_msg()
358 struct device *dev = priv->adap.dev.parent; in rzv2m_i2c_xfer()
366 if (readl(priv->base + IICB0STR0) & IICB0SSBS) { in rzv2m_i2c_xfer()
367 ret = -EAGAIN; in rzv2m_i2c_xfer()
371 /* I2C main transfer */ in rzv2m_i2c_xfer()
373 ret = rzv2m_i2c_xfer_msg(priv, &msgs[i], i == (num - 1)); in rzv2m_i2c_xfer()
400 bit_clrl(priv->base + IICB0CTL0, IICB0IICE); in rzv2m_i2c_disable()
417 struct device *dev = &pdev->dev; in rzv2m_i2c_probe()
426 return -ENOMEM; in rzv2m_i2c_probe()
428 priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in rzv2m_i2c_probe()
429 if (IS_ERR(priv->base)) in rzv2m_i2c_probe()
430 return PTR_ERR(priv->base); in rzv2m_i2c_probe()
432 priv->clk = devm_clk_get(dev, NULL); in rzv2m_i2c_probe()
433 if (IS_ERR(priv->clk)) in rzv2m_i2c_probe()
434 return dev_err_probe(dev, PTR_ERR(priv->clk), "Can't get clock\n"); in rzv2m_i2c_probe()
454 adap = &priv->adap; in rzv2m_i2c_probe()
455 adap->nr = pdev->id; in rzv2m_i2c_probe()
456 adap->algo = &rzv2m_i2c_algo; in rzv2m_i2c_probe()
457 adap->quirks = &rzv2m_i2c_quirks; in rzv2m_i2c_probe()
458 adap->dev.parent = dev; in rzv2m_i2c_probe()
459 adap->owner = THIS_MODULE; in rzv2m_i2c_probe()
460 device_set_node(&adap->dev, dev_fwnode(dev)); in rzv2m_i2c_probe()
462 strscpy(adap->name, pdev->name, sizeof(adap->name)); in rzv2m_i2c_probe()
463 init_completion(&priv->msg_tia_done); in rzv2m_i2c_probe()
489 struct device *dev = priv->adap.dev.parent; in rzv2m_i2c_remove()
491 i2c_del_adapter(&priv->adap); in rzv2m_i2c_remove()
523 { .compatible = "renesas,rzv2m-i2c" },
534 .name = "rzv2m-i2c",
543 MODULE_DESCRIPTION("RZ/V2M I2C bus driver");