Lines Matching +full:lpc1788 +full:- +full:i2c
1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Code portions referenced from the i2x-pxa and i2c-pnx drivers
17 #include <linux/i2c.h>
46 /* I2C SCL clock has different duty cycle depending on mode */
52 * 26 possible I2C status codes, but codes applicable only
83 static void i2c_lpc2k_reset(struct lpc2k_i2c *i2c) in i2c_lpc2k_reset() argument
86 writel(LPC24XX_CLEAR_ALL, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_reset()
87 writel(0, i2c->base + LPC24XX_I2ADDR); in i2c_lpc2k_reset()
88 writel(LPC24XX_I2EN, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_reset()
91 static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c) in i2c_lpc2k_clear_arb() argument
99 writel(LPC24XX_STO, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_clear_arb()
102 while (readl(i2c->base + LPC24XX_I2STAT) != M_I2C_IDLE) { in i2c_lpc2k_clear_arb()
105 i2c_lpc2k_reset(i2c); in i2c_lpc2k_clear_arb()
106 return -EBUSY; in i2c_lpc2k_clear_arb()
115 static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) in i2c_lpc2k_pump_msg() argument
121 * I2C in the LPC2xxx series is basically a state machine. in i2c_lpc2k_pump_msg()
124 status = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_pump_msg()
130 data = i2c_8bit_addr_from_msg(i2c->msg); in i2c_lpc2k_pump_msg()
132 writel(data, i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
133 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
142 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
143 writel(i2c->msg->buf[i2c->msg_idx], in i2c_lpc2k_pump_msg()
144 i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
145 } else if (i2c->is_last) { in i2c_lpc2k_pump_msg()
147 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
148 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
149 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
150 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
152 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
153 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
156 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
161 if (i2c->msg->len == 1) { in i2c_lpc2k_pump_msg()
163 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
166 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
169 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
174 * The I2C shows NACK status on reads, so we need to accept in i2c_lpc2k_pump_msg()
180 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
181 i2c->msg->buf[i2c->msg_idx] = in i2c_lpc2k_pump_msg()
182 readl(i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
186 if (i2c->msg_idx >= i2c->msg->len - 1 && i2c->is_last) { in i2c_lpc2k_pump_msg()
187 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
188 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
189 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
193 if (i2c->msg_idx >= i2c->msg->len - 1) { in i2c_lpc2k_pump_msg()
194 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
195 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
199 * One pre-last data input, send NACK to tell the target that in i2c_lpc2k_pump_msg()
202 if (i2c->msg_idx >= i2c->msg->len - 2) { in i2c_lpc2k_pump_msg()
203 /* One byte left to receive - NACK */ in i2c_lpc2k_pump_msg()
204 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
206 /* More than one byte left to receive - ACK */ in i2c_lpc2k_pump_msg()
207 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
210 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
211 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
218 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
219 i2c->msg_status = -ENXIO; in i2c_lpc2k_pump_msg()
220 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
225 i2c->msg_status = -EAGAIN; in i2c_lpc2k_pump_msg()
227 /* Release the I2C bus */ in i2c_lpc2k_pump_msg()
228 writel(LPC24XX_STA | LPC24XX_STO, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
229 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
234 i2c->msg_status = -EIO; in i2c_lpc2k_pump_msg()
235 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
240 if (i2c->msg_status != -EBUSY) in i2c_lpc2k_pump_msg()
241 wake_up(&i2c->wait); in i2c_lpc2k_pump_msg()
247 if (i2c->msg_status != 0) in i2c_lpc2k_pump_msg()
248 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
251 static int lpc2k_process_msg(struct lpc2k_i2c *i2c, int msgidx) in lpc2k_process_msg() argument
255 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
258 * A multi-message I2C transfer continues where the in lpc2k_process_msg()
259 * previous I2C transfer left off and uses the in lpc2k_process_msg()
260 * current condition of the I2C adapter. in lpc2k_process_msg()
262 if (unlikely(i2c->msg->flags & I2C_M_NOSTART)) { in lpc2k_process_msg()
263 WARN_ON(i2c->msg->len == 0); in lpc2k_process_msg()
265 if (!(i2c->msg->flags & I2C_M_RD)) { in lpc2k_process_msg()
267 writel(i2c->msg->buf[0], in lpc2k_process_msg()
268 i2c->base + LPC24XX_I2DAT); in lpc2k_process_msg()
269 i2c->msg_idx++; in lpc2k_process_msg()
273 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
276 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in lpc2k_process_msg()
279 enable_irq(i2c->irq); in lpc2k_process_msg()
282 if (wait_event_timeout(i2c->wait, i2c->msg_status != -EBUSY, in lpc2k_process_msg()
284 disable_irq_nosync(i2c->irq); in lpc2k_process_msg()
286 return -ETIMEDOUT; in lpc2k_process_msg()
289 return i2c->msg_status; in lpc2k_process_msg()
295 struct lpc2k_i2c *i2c = i2c_get_adapdata(adap); in i2c_lpc2k_xfer() local
300 stat = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_xfer()
303 return i2c_lpc2k_clear_arb(i2c); in i2c_lpc2k_xfer()
309 i2c->msg = &msgs[i]; in i2c_lpc2k_xfer()
310 i2c->msg_idx = 0; in i2c_lpc2k_xfer()
311 i2c->msg_status = -EBUSY; in i2c_lpc2k_xfer()
312 i2c->is_last = (i == (msg_num - 1)); in i2c_lpc2k_xfer()
314 ret = lpc2k_process_msg(i2c, i); in i2c_lpc2k_xfer()
324 struct lpc2k_i2c *i2c = dev_id; in i2c_lpc2k_handler() local
326 if (readl(i2c->base + LPC24XX_I2CONSET) & LPC24XX_SI) { in i2c_lpc2k_handler()
327 i2c_lpc2k_pump_msg(i2c); in i2c_lpc2k_handler()
347 struct lpc2k_i2c *i2c; in i2c_lpc2k_probe() local
353 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in i2c_lpc2k_probe()
354 if (!i2c) in i2c_lpc2k_probe()
355 return -ENOMEM; in i2c_lpc2k_probe()
357 i2c->base = devm_platform_ioremap_resource(pdev, 0); in i2c_lpc2k_probe()
358 if (IS_ERR(i2c->base)) in i2c_lpc2k_probe()
359 return PTR_ERR(i2c->base); in i2c_lpc2k_probe()
361 i2c->irq = platform_get_irq(pdev, 0); in i2c_lpc2k_probe()
362 if (i2c->irq < 0) in i2c_lpc2k_probe()
363 return i2c->irq; in i2c_lpc2k_probe()
365 init_waitqueue_head(&i2c->wait); in i2c_lpc2k_probe()
367 i2c->clk = devm_clk_get_enabled(&pdev->dev, NULL); in i2c_lpc2k_probe()
368 if (IS_ERR(i2c->clk)) { in i2c_lpc2k_probe()
369 dev_err(&pdev->dev, "failed to enable clock.\n"); in i2c_lpc2k_probe()
370 return PTR_ERR(i2c->clk); in i2c_lpc2k_probe()
373 ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, in i2c_lpc2k_probe()
374 dev_name(&pdev->dev), i2c); in i2c_lpc2k_probe()
376 dev_err(&pdev->dev, "can't request interrupt.\n"); in i2c_lpc2k_probe()
380 disable_irq_nosync(i2c->irq); in i2c_lpc2k_probe()
383 i2c_lpc2k_reset(i2c); in i2c_lpc2k_probe()
385 ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", in i2c_lpc2k_probe()
390 clkrate = clk_get_rate(i2c->clk); in i2c_lpc2k_probe()
392 dev_err(&pdev->dev, "can't get I2C base clock\n"); in i2c_lpc2k_probe()
393 return -EINVAL; in i2c_lpc2k_probe()
396 /* Setup I2C dividers to generate clock with proper duty cycle */ in i2c_lpc2k_probe()
405 writel(scl_high, i2c->base + LPC24XX_I2SCLH); in i2c_lpc2k_probe()
406 writel(clkrate - scl_high, i2c->base + LPC24XX_I2SCLL); in i2c_lpc2k_probe()
408 platform_set_drvdata(pdev, i2c); in i2c_lpc2k_probe()
410 i2c_set_adapdata(&i2c->adap, i2c); in i2c_lpc2k_probe()
411 i2c->adap.owner = THIS_MODULE; in i2c_lpc2k_probe()
412 strscpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); in i2c_lpc2k_probe()
413 i2c->adap.algo = &i2c_lpc2k_algorithm; in i2c_lpc2k_probe()
414 i2c->adap.dev.parent = &pdev->dev; in i2c_lpc2k_probe()
415 i2c->adap.dev.of_node = pdev->dev.of_node; in i2c_lpc2k_probe()
417 ret = i2c_add_adapter(&i2c->adap); in i2c_lpc2k_probe()
421 dev_info(&pdev->dev, "LPC2K I2C adapter\n"); in i2c_lpc2k_probe()
428 struct lpc2k_i2c *i2c = platform_get_drvdata(dev); in i2c_lpc2k_remove() local
430 i2c_del_adapter(&i2c->adap); in i2c_lpc2k_remove()
435 struct lpc2k_i2c *i2c = dev_get_drvdata(dev); in i2c_lpc2k_suspend() local
437 clk_disable(i2c->clk); in i2c_lpc2k_suspend()
444 struct lpc2k_i2c *i2c = dev_get_drvdata(dev); in i2c_lpc2k_resume() local
446 clk_enable(i2c->clk); in i2c_lpc2k_resume()
447 i2c_lpc2k_reset(i2c); in i2c_lpc2k_resume()
458 { .compatible = "nxp,lpc1788-i2c" },
467 .name = "lpc2k-i2c",
475 MODULE_DESCRIPTION("I2C driver for LPC2xxx devices");
477 MODULE_ALIAS("platform:lpc2k-i2c");