• Home
  • Raw
  • Download

Lines Matching full:i2c

5  * Code portions referenced from the i2x-pxa and i2c-pnx drivers
17 #include <linux/i2c.h>
47 /* I2C SCL clock has different duty cycle depending on mode */
53 * 26 possible I2C status codes, but codes applicable only
84 static void i2c_lpc2k_reset(struct lpc2k_i2c *i2c) in i2c_lpc2k_reset() argument
87 writel(LPC24XX_CLEAR_ALL, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_reset()
88 writel(0, i2c->base + LPC24XX_I2ADDR); in i2c_lpc2k_reset()
89 writel(LPC24XX_I2EN, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_reset()
92 static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c) in i2c_lpc2k_clear_arb() argument
100 writel(LPC24XX_STO, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_clear_arb()
103 while (readl(i2c->base + LPC24XX_I2STAT) != M_I2C_IDLE) { in i2c_lpc2k_clear_arb()
106 i2c_lpc2k_reset(i2c); in i2c_lpc2k_clear_arb()
116 static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) in i2c_lpc2k_pump_msg() argument
122 * I2C in the LPC2xxx series is basically a state machine. in i2c_lpc2k_pump_msg()
125 status = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_pump_msg()
131 data = i2c_8bit_addr_from_msg(i2c->msg); in i2c_lpc2k_pump_msg()
133 writel(data, i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
134 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
143 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
144 writel(i2c->msg->buf[i2c->msg_idx], in i2c_lpc2k_pump_msg()
145 i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
146 } else if (i2c->is_last) { in i2c_lpc2k_pump_msg()
148 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
149 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
150 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
151 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
153 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
154 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
157 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
162 if (i2c->msg->len == 1) { in i2c_lpc2k_pump_msg()
164 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
167 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
170 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
175 * The I2C shows NACK status on reads, so we need to accept in i2c_lpc2k_pump_msg()
181 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
182 i2c->msg->buf[i2c->msg_idx] = in i2c_lpc2k_pump_msg()
183 readl(i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
187 if (i2c->msg_idx >= i2c->msg->len - 1 && i2c->is_last) { in i2c_lpc2k_pump_msg()
188 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
189 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
190 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
194 if (i2c->msg_idx >= i2c->msg->len - 1) { in i2c_lpc2k_pump_msg()
195 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
196 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
203 if (i2c->msg_idx >= i2c->msg->len - 2) { in i2c_lpc2k_pump_msg()
205 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
208 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
211 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
212 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
219 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
220 i2c->msg_status = -ENXIO; in i2c_lpc2k_pump_msg()
221 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
226 i2c->msg_status = -EAGAIN; in i2c_lpc2k_pump_msg()
228 /* Release the I2C bus */ in i2c_lpc2k_pump_msg()
229 writel(LPC24XX_STA | LPC24XX_STO, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
230 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
235 i2c->msg_status = -EIO; in i2c_lpc2k_pump_msg()
236 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
241 if (i2c->msg_status != -EBUSY) in i2c_lpc2k_pump_msg()
242 wake_up(&i2c->wait); in i2c_lpc2k_pump_msg()
248 if (i2c->msg_status != 0) in i2c_lpc2k_pump_msg()
249 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
252 static int lpc2k_process_msg(struct lpc2k_i2c *i2c, int msgidx) in lpc2k_process_msg() argument
256 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
259 * A multi-message I2C transfer continues where the in lpc2k_process_msg()
260 * previous I2C transfer left off and uses the in lpc2k_process_msg()
261 * current condition of the I2C adapter. in lpc2k_process_msg()
263 if (unlikely(i2c->msg->flags & I2C_M_NOSTART)) { in lpc2k_process_msg()
264 WARN_ON(i2c->msg->len == 0); in lpc2k_process_msg()
266 if (!(i2c->msg->flags & I2C_M_RD)) { in lpc2k_process_msg()
268 writel(i2c->msg->buf[0], in lpc2k_process_msg()
269 i2c->base + LPC24XX_I2DAT); in lpc2k_process_msg()
270 i2c->msg_idx++; in lpc2k_process_msg()
274 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
277 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in lpc2k_process_msg()
280 enable_irq(i2c->irq); in lpc2k_process_msg()
283 if (wait_event_timeout(i2c->wait, i2c->msg_status != -EBUSY, in lpc2k_process_msg()
285 disable_irq_nosync(i2c->irq); in lpc2k_process_msg()
290 return i2c->msg_status; in lpc2k_process_msg()
296 struct lpc2k_i2c *i2c = i2c_get_adapdata(adap); in i2c_lpc2k_xfer() local
301 stat = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_xfer()
304 return i2c_lpc2k_clear_arb(i2c); in i2c_lpc2k_xfer()
310 i2c->msg = &msgs[i]; in i2c_lpc2k_xfer()
311 i2c->msg_idx = 0; in i2c_lpc2k_xfer()
312 i2c->msg_status = -EBUSY; in i2c_lpc2k_xfer()
313 i2c->is_last = (i == (msg_num - 1)); in i2c_lpc2k_xfer()
315 ret = lpc2k_process_msg(i2c, i); in i2c_lpc2k_xfer()
325 struct lpc2k_i2c *i2c = dev_id; in i2c_lpc2k_handler() local
327 if (readl(i2c->base + LPC24XX_I2CONSET) & LPC24XX_SI) { in i2c_lpc2k_handler()
328 i2c_lpc2k_pump_msg(i2c); in i2c_lpc2k_handler()
348 struct lpc2k_i2c *i2c; in i2c_lpc2k_probe() local
354 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in i2c_lpc2k_probe()
355 if (!i2c) in i2c_lpc2k_probe()
358 i2c->base = devm_platform_ioremap_resource(pdev, 0); in i2c_lpc2k_probe()
359 if (IS_ERR(i2c->base)) in i2c_lpc2k_probe()
360 return PTR_ERR(i2c->base); in i2c_lpc2k_probe()
362 i2c->irq = platform_get_irq(pdev, 0); in i2c_lpc2k_probe()
363 if (i2c->irq < 0) in i2c_lpc2k_probe()
364 return i2c->irq; in i2c_lpc2k_probe()
366 init_waitqueue_head(&i2c->wait); in i2c_lpc2k_probe()
368 i2c->clk = devm_clk_get(&pdev->dev, NULL); in i2c_lpc2k_probe()
369 if (IS_ERR(i2c->clk)) { in i2c_lpc2k_probe()
371 return PTR_ERR(i2c->clk); in i2c_lpc2k_probe()
374 ret = clk_prepare_enable(i2c->clk); in i2c_lpc2k_probe()
380 ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, in i2c_lpc2k_probe()
381 dev_name(&pdev->dev), i2c); in i2c_lpc2k_probe()
387 disable_irq_nosync(i2c->irq); in i2c_lpc2k_probe()
390 i2c_lpc2k_reset(i2c); in i2c_lpc2k_probe()
397 clkrate = clk_get_rate(i2c->clk); in i2c_lpc2k_probe()
399 dev_err(&pdev->dev, "can't get I2C base clock\n"); in i2c_lpc2k_probe()
404 /* Setup I2C dividers to generate clock with proper duty cycle */ in i2c_lpc2k_probe()
413 writel(scl_high, i2c->base + LPC24XX_I2SCLH); in i2c_lpc2k_probe()
414 writel(clkrate - scl_high, i2c->base + LPC24XX_I2SCLL); in i2c_lpc2k_probe()
416 platform_set_drvdata(pdev, i2c); in i2c_lpc2k_probe()
418 i2c_set_adapdata(&i2c->adap, i2c); in i2c_lpc2k_probe()
419 i2c->adap.owner = THIS_MODULE; in i2c_lpc2k_probe()
420 strlcpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); in i2c_lpc2k_probe()
421 i2c->adap.algo = &i2c_lpc2k_algorithm; in i2c_lpc2k_probe()
422 i2c->adap.dev.parent = &pdev->dev; in i2c_lpc2k_probe()
423 i2c->adap.dev.of_node = pdev->dev.of_node; in i2c_lpc2k_probe()
425 ret = i2c_add_adapter(&i2c->adap); in i2c_lpc2k_probe()
429 dev_info(&pdev->dev, "LPC2K I2C adapter\n"); in i2c_lpc2k_probe()
434 clk_disable_unprepare(i2c->clk); in i2c_lpc2k_probe()
440 struct lpc2k_i2c *i2c = platform_get_drvdata(dev); in i2c_lpc2k_remove() local
442 i2c_del_adapter(&i2c->adap); in i2c_lpc2k_remove()
443 clk_disable_unprepare(i2c->clk); in i2c_lpc2k_remove()
451 struct lpc2k_i2c *i2c = dev_get_drvdata(dev); in i2c_lpc2k_suspend() local
453 clk_disable(i2c->clk); in i2c_lpc2k_suspend()
460 struct lpc2k_i2c *i2c = dev_get_drvdata(dev); in i2c_lpc2k_resume() local
462 clk_enable(i2c->clk); in i2c_lpc2k_resume()
463 i2c_lpc2k_reset(i2c); in i2c_lpc2k_resume()
479 { .compatible = "nxp,lpc1788-i2c" },
488 .name = "lpc2k-i2c",
496 MODULE_DESCRIPTION("I2C driver for LPC2xxx devices");
498 MODULE_ALIAS("platform:lpc2k-i2c");