Lines Matching refs:i2c
89 static void i2c_lpc2k_reset(struct lpc2k_i2c *i2c) in i2c_lpc2k_reset() argument
92 writel(LPC24XX_CLEAR_ALL, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_reset()
93 writel(0, i2c->base + LPC24XX_I2ADDR); in i2c_lpc2k_reset()
94 writel(LPC24XX_I2EN, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_reset()
97 static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c) in i2c_lpc2k_clear_arb() argument
105 writel(LPC24XX_STO, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_clear_arb()
108 while (readl(i2c->base + LPC24XX_I2STAT) != M_I2C_IDLE) { in i2c_lpc2k_clear_arb()
111 i2c_lpc2k_reset(i2c); in i2c_lpc2k_clear_arb()
121 static void i2c_lpc2k_pump_msg(struct lpc2k_i2c *i2c) in i2c_lpc2k_pump_msg() argument
130 status = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_pump_msg()
136 data = i2c->msg->addr << 1; in i2c_lpc2k_pump_msg()
137 if (i2c->msg->flags & I2C_M_RD) in i2c_lpc2k_pump_msg()
140 writel(data, i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
141 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
150 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
151 writel(i2c->msg->buf[i2c->msg_idx], in i2c_lpc2k_pump_msg()
152 i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
153 } else if (i2c->is_last) { in i2c_lpc2k_pump_msg()
155 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
156 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
157 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
158 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
160 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
161 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
164 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
169 if (i2c->msg->len == 1) { in i2c_lpc2k_pump_msg()
171 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
174 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
177 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
188 if (i2c->msg_idx < i2c->msg->len) { in i2c_lpc2k_pump_msg()
189 i2c->msg->buf[i2c->msg_idx] = in i2c_lpc2k_pump_msg()
190 readl(i2c->base + LPC24XX_I2DAT); in i2c_lpc2k_pump_msg()
194 if (i2c->msg_idx >= i2c->msg->len - 1 && i2c->is_last) { in i2c_lpc2k_pump_msg()
195 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
196 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
197 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
201 if (i2c->msg_idx >= i2c->msg->len - 1) { in i2c_lpc2k_pump_msg()
202 i2c->msg_status = 0; in i2c_lpc2k_pump_msg()
203 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
210 if (i2c->msg_idx >= i2c->msg->len - 2) { in i2c_lpc2k_pump_msg()
212 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
215 writel(LPC24XX_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
218 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
219 i2c->msg_idx++; in i2c_lpc2k_pump_msg()
226 writel(LPC24XX_STO_AA, i2c->base + LPC24XX_I2CONSET); in i2c_lpc2k_pump_msg()
227 i2c->msg_status = -ENXIO; in i2c_lpc2k_pump_msg()
228 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
233 i2c->msg_status = -EAGAIN; in i2c_lpc2k_pump_msg()
236 writel(LPC24XX_STA | LPC24XX_STO, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
237 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
242 i2c->msg_status = -EIO; in i2c_lpc2k_pump_msg()
243 disable_irq_nosync(i2c->irq); in i2c_lpc2k_pump_msg()
248 if (i2c->msg_status != -EBUSY) in i2c_lpc2k_pump_msg()
249 wake_up(&i2c->wait); in i2c_lpc2k_pump_msg()
255 if (i2c->msg_status != 0) in i2c_lpc2k_pump_msg()
256 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in i2c_lpc2k_pump_msg()
259 static int lpc2k_process_msg(struct lpc2k_i2c *i2c, int msgidx) in lpc2k_process_msg() argument
263 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
270 if (unlikely(i2c->msg->flags & I2C_M_NOSTART)) { in lpc2k_process_msg()
271 WARN_ON(i2c->msg->len == 0); in lpc2k_process_msg()
273 if (!(i2c->msg->flags & I2C_M_RD)) { in lpc2k_process_msg()
275 writel(i2c->msg->buf[0], in lpc2k_process_msg()
276 i2c->base + LPC24XX_I2DAT); in lpc2k_process_msg()
277 i2c->msg_idx++; in lpc2k_process_msg()
281 writel(LPC24XX_STA, i2c->base + LPC24XX_I2CONSET); in lpc2k_process_msg()
284 writel(LPC24XX_SI, i2c->base + LPC24XX_I2CONCLR); in lpc2k_process_msg()
287 enable_irq(i2c->irq); in lpc2k_process_msg()
290 if (wait_event_timeout(i2c->wait, i2c->msg_status != -EBUSY, in lpc2k_process_msg()
292 disable_irq_nosync(i2c->irq); in lpc2k_process_msg()
297 return i2c->msg_status; in lpc2k_process_msg()
303 struct lpc2k_i2c *i2c = i2c_get_adapdata(adap); in i2c_lpc2k_xfer() local
308 stat = readl(i2c->base + LPC24XX_I2STAT); in i2c_lpc2k_xfer()
311 return i2c_lpc2k_clear_arb(i2c); in i2c_lpc2k_xfer()
317 i2c->msg = &msgs[i]; in i2c_lpc2k_xfer()
318 i2c->msg_idx = 0; in i2c_lpc2k_xfer()
319 i2c->msg_status = -EBUSY; in i2c_lpc2k_xfer()
320 i2c->is_last = (i == (msg_num - 1)); in i2c_lpc2k_xfer()
322 ret = lpc2k_process_msg(i2c, i); in i2c_lpc2k_xfer()
332 struct lpc2k_i2c *i2c = dev_id; in i2c_lpc2k_handler() local
334 if (readl(i2c->base + LPC24XX_I2CONSET) & LPC24XX_SI) { in i2c_lpc2k_handler()
335 i2c_lpc2k_pump_msg(i2c); in i2c_lpc2k_handler()
355 struct lpc2k_i2c *i2c; in i2c_lpc2k_probe() local
362 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in i2c_lpc2k_probe()
363 if (!i2c) in i2c_lpc2k_probe()
367 i2c->base = devm_ioremap_resource(&pdev->dev, res); in i2c_lpc2k_probe()
368 if (IS_ERR(i2c->base)) in i2c_lpc2k_probe()
369 return PTR_ERR(i2c->base); in i2c_lpc2k_probe()
371 i2c->irq = platform_get_irq(pdev, 0); in i2c_lpc2k_probe()
372 if (i2c->irq < 0) { in i2c_lpc2k_probe()
374 return i2c->irq; in i2c_lpc2k_probe()
377 init_waitqueue_head(&i2c->wait); in i2c_lpc2k_probe()
379 i2c->clk = devm_clk_get(&pdev->dev, NULL); in i2c_lpc2k_probe()
380 if (IS_ERR(i2c->clk)) { in i2c_lpc2k_probe()
382 return PTR_ERR(i2c->clk); in i2c_lpc2k_probe()
385 ret = clk_prepare_enable(i2c->clk); in i2c_lpc2k_probe()
391 ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0, in i2c_lpc2k_probe()
392 dev_name(&pdev->dev), i2c); in i2c_lpc2k_probe()
398 disable_irq_nosync(i2c->irq); in i2c_lpc2k_probe()
401 i2c_lpc2k_reset(i2c); in i2c_lpc2k_probe()
408 clkrate = clk_get_rate(i2c->clk); in i2c_lpc2k_probe()
424 writel(scl_high, i2c->base + LPC24XX_I2SCLH); in i2c_lpc2k_probe()
425 writel(clkrate - scl_high, i2c->base + LPC24XX_I2SCLL); in i2c_lpc2k_probe()
427 platform_set_drvdata(pdev, i2c); in i2c_lpc2k_probe()
429 i2c_set_adapdata(&i2c->adap, i2c); in i2c_lpc2k_probe()
430 i2c->adap.owner = THIS_MODULE; in i2c_lpc2k_probe()
431 strlcpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name)); in i2c_lpc2k_probe()
432 i2c->adap.algo = &i2c_lpc2k_algorithm; in i2c_lpc2k_probe()
433 i2c->adap.dev.parent = &pdev->dev; in i2c_lpc2k_probe()
434 i2c->adap.dev.of_node = pdev->dev.of_node; in i2c_lpc2k_probe()
436 ret = i2c_add_adapter(&i2c->adap); in i2c_lpc2k_probe()
447 clk_disable_unprepare(i2c->clk); in i2c_lpc2k_probe()
453 struct lpc2k_i2c *i2c = platform_get_drvdata(dev); in i2c_lpc2k_remove() local
455 i2c_del_adapter(&i2c->adap); in i2c_lpc2k_remove()
456 clk_disable_unprepare(i2c->clk); in i2c_lpc2k_remove()
465 struct lpc2k_i2c *i2c = platform_get_drvdata(pdev); in i2c_lpc2k_suspend() local
467 clk_disable(i2c->clk); in i2c_lpc2k_suspend()
475 struct lpc2k_i2c *i2c = platform_get_drvdata(pdev); in i2c_lpc2k_resume() local
477 clk_enable(i2c->clk); in i2c_lpc2k_resume()
478 i2c_lpc2k_reset(i2c); in i2c_lpc2k_resume()