Lines Matching full:i2c
3 * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver
11 #include <linux/i2c.h>
202 /* Version of HS-I2C Hardware */
209 * @hw: the hardware variant of Exynos I2C controller
260 static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c) in exynos5_i2c_clr_pend_irq() argument
262 writel(readl(i2c->regs + HSI2C_INT_STATUS), in exynos5_i2c_clr_pend_irq()
263 i2c->regs + HSI2C_INT_STATUS); in exynos5_i2c_clr_pend_irq()
276 static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings) in exynos5_i2c_set_timing() argument
288 unsigned int clkin = clk_get_rate(i2c->clk); in exynos5_i2c_set_timing()
289 unsigned int op_clk = hs_timings ? i2c->op_clock : in exynos5_i2c_set_timing()
290 (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) ? I2C_MAX_STANDARD_MODE_FREQ : in exynos5_i2c_set_timing()
291 i2c->op_clock; in exynos5_i2c_set_timing()
308 if (i2c->variant->hw == I2C_TYPE_EXYNOSAUTOV9) { in exynos5_i2c_set_timing()
309 div = ((clkin / (16 * i2c->op_clock)) - 1); in exynos5_i2c_set_timing()
312 writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3); in exynos5_i2c_set_timing()
314 writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3); in exynos5_i2c_set_timing()
334 t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7; in exynos5_i2c_set_timing()
336 if (i2c->variant->hw != I2C_TYPE_EXYNOS7) in exynos5_i2c_set_timing()
341 dev_err(i2c->dev, "%s clock set-up failed\n", in exynos5_i2c_set_timing()
360 dev_dbg(i2c->dev, "tSTART_SU: %X, tSTART_HD: %X, tSTOP_SU: %X\n", in exynos5_i2c_set_timing()
362 dev_dbg(i2c->dev, "tDATA_SU: %X, tSCL_L: %X, tSCL_H: %X\n", in exynos5_i2c_set_timing()
364 dev_dbg(i2c->dev, "nClkDiv: %X, tSR_RELEASE: %X\n", in exynos5_i2c_set_timing()
366 dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd); in exynos5_i2c_set_timing()
369 writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1); in exynos5_i2c_set_timing()
370 writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2); in exynos5_i2c_set_timing()
371 writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3); in exynos5_i2c_set_timing()
373 writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_FS1); in exynos5_i2c_set_timing()
374 writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_FS2); in exynos5_i2c_set_timing()
375 writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3); in exynos5_i2c_set_timing()
377 writel(i2c_timing_sla, i2c->regs + HSI2C_TIMING_SLA); in exynos5_i2c_set_timing()
382 static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c) in exynos5_hsi2c_clock_setup() argument
385 int ret = exynos5_i2c_set_timing(i2c, false); in exynos5_hsi2c_clock_setup()
387 if (ret < 0 || i2c->op_clock < I2C_MAX_FAST_MODE_PLUS_FREQ) in exynos5_hsi2c_clock_setup()
390 return exynos5_i2c_set_timing(i2c, true); in exynos5_hsi2c_clock_setup()
394 * exynos5_i2c_init: configures the controller for I2C functionality
395 * Programs I2C controller for Master mode operation
397 static void exynos5_i2c_init(struct exynos5_i2c *i2c) in exynos5_i2c_init() argument
399 u32 i2c_conf = readl(i2c->regs + HSI2C_CONF); in exynos5_i2c_init()
400 u32 i2c_timeout = readl(i2c->regs + HSI2C_TIMEOUT); in exynos5_i2c_init()
404 writel(i2c_timeout, i2c->regs + HSI2C_TIMEOUT); in exynos5_i2c_init()
407 i2c->regs + HSI2C_CTL); in exynos5_i2c_init()
408 writel(HSI2C_TRAILING_COUNT, i2c->regs + HSI2C_TRAILIG_CTL); in exynos5_i2c_init()
410 if (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) { in exynos5_i2c_init()
411 writel(HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)), in exynos5_i2c_init()
412 i2c->regs + HSI2C_ADDR); in exynos5_i2c_init()
416 writel(i2c_conf | HSI2C_AUTO_MODE, i2c->regs + HSI2C_CONF); in exynos5_i2c_init()
419 static void exynos5_i2c_reset(struct exynos5_i2c *i2c) in exynos5_i2c_reset() argument
424 i2c_ctl = readl(i2c->regs + HSI2C_CTL); in exynos5_i2c_reset()
426 writel(i2c_ctl, i2c->regs + HSI2C_CTL); in exynos5_i2c_reset()
428 i2c_ctl = readl(i2c->regs + HSI2C_CTL); in exynos5_i2c_reset()
430 writel(i2c_ctl, i2c->regs + HSI2C_CTL); in exynos5_i2c_reset()
433 exynos5_hsi2c_clock_setup(i2c); in exynos5_i2c_reset()
435 exynos5_i2c_init(i2c); in exynos5_i2c_reset()
447 struct exynos5_i2c *i2c = dev_id; in exynos5_i2c_irq() local
452 i2c->state = -EINVAL; in exynos5_i2c_irq()
454 spin_lock(&i2c->lock); in exynos5_i2c_irq()
456 int_status = readl(i2c->regs + HSI2C_INT_STATUS); in exynos5_i2c_irq()
457 writel(int_status, i2c->regs + HSI2C_INT_STATUS); in exynos5_i2c_irq()
460 switch (i2c->variant->hw) { in exynos5_i2c_irq()
465 i2c->trans_done = 1; in exynos5_i2c_irq()
466 i2c->state = 0; in exynos5_i2c_irq()
468 dev_dbg(i2c->dev, "Deal with arbitration lose\n"); in exynos5_i2c_irq()
469 i2c->state = -EAGAIN; in exynos5_i2c_irq()
472 dev_dbg(i2c->dev, "No ACK from device\n"); in exynos5_i2c_irq()
473 i2c->state = -ENXIO; in exynos5_i2c_irq()
476 dev_dbg(i2c->dev, "No device\n"); in exynos5_i2c_irq()
477 i2c->state = -ENXIO; in exynos5_i2c_irq()
480 dev_dbg(i2c->dev, "Accessing device timed out\n"); in exynos5_i2c_irq()
481 i2c->state = -ETIMEDOUT; in exynos5_i2c_irq()
490 trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); in exynos5_i2c_irq()
492 dev_dbg(i2c->dev, "No ACK from device\n"); in exynos5_i2c_irq()
493 i2c->state = -ENXIO; in exynos5_i2c_irq()
496 dev_dbg(i2c->dev, "No device\n"); in exynos5_i2c_irq()
497 i2c->state = -ENXIO; in exynos5_i2c_irq()
500 dev_dbg(i2c->dev, "Deal with arbitration lose\n"); in exynos5_i2c_irq()
501 i2c->state = -EAGAIN; in exynos5_i2c_irq()
504 dev_dbg(i2c->dev, "Accessing device timed out\n"); in exynos5_i2c_irq()
505 i2c->state = -ETIMEDOUT; in exynos5_i2c_irq()
508 i2c->trans_done = 1; in exynos5_i2c_irq()
509 i2c->state = 0; in exynos5_i2c_irq()
515 if ((i2c->msg->flags & I2C_M_RD) && (int_status & in exynos5_i2c_irq()
517 fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); in exynos5_i2c_irq()
519 len = min(fifo_level, i2c->msg->len - i2c->msg_ptr); in exynos5_i2c_irq()
523 readl(i2c->regs + HSI2C_RX_DATA); in exynos5_i2c_irq()
524 i2c->msg->buf[i2c->msg_ptr++] = byte; in exynos5_i2c_irq()
527 i2c->state = 0; in exynos5_i2c_irq()
529 fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); in exynos5_i2c_irq()
532 len = i2c->variant->fifo_depth - fifo_level; in exynos5_i2c_irq()
533 if (len > (i2c->msg->len - i2c->msg_ptr)) { in exynos5_i2c_irq()
534 u32 int_en = readl(i2c->regs + HSI2C_INT_ENABLE); in exynos5_i2c_irq()
537 writel(int_en, i2c->regs + HSI2C_INT_ENABLE); in exynos5_i2c_irq()
538 len = i2c->msg->len - i2c->msg_ptr; in exynos5_i2c_irq()
542 byte = i2c->msg->buf[i2c->msg_ptr++]; in exynos5_i2c_irq()
543 writel(byte, i2c->regs + HSI2C_TX_DATA); in exynos5_i2c_irq()
546 i2c->state = 0; in exynos5_i2c_irq()
550 if ((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) || in exynos5_i2c_irq()
551 (i2c->state < 0)) { in exynos5_i2c_irq()
552 writel(0, i2c->regs + HSI2C_INT_ENABLE); in exynos5_i2c_irq()
553 exynos5_i2c_clr_pend_irq(i2c); in exynos5_i2c_irq()
554 complete(&i2c->msg_complete); in exynos5_i2c_irq()
557 spin_unlock(&i2c->lock); in exynos5_i2c_irq()
570 static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c) in exynos5_i2c_wait_bus_idle() argument
578 trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); in exynos5_i2c_wait_bus_idle()
588 static void exynos5_i2c_bus_recover(struct exynos5_i2c *i2c) in exynos5_i2c_bus_recover() argument
592 val = readl(i2c->regs + HSI2C_CTL) | HSI2C_RXCHON; in exynos5_i2c_bus_recover()
593 writel(val, i2c->regs + HSI2C_CTL); in exynos5_i2c_bus_recover()
594 val = readl(i2c->regs + HSI2C_CONF) & ~HSI2C_AUTO_MODE; in exynos5_i2c_bus_recover()
595 writel(val, i2c->regs + HSI2C_CONF); in exynos5_i2c_bus_recover()
602 writel(HSI2C_CMD_READ_DATA, i2c->regs + HSI2C_MANUAL_CMD); in exynos5_i2c_bus_recover()
603 exynos5_i2c_wait_bus_idle(i2c); in exynos5_i2c_bus_recover()
604 writel(HSI2C_CMD_SEND_STOP, i2c->regs + HSI2C_MANUAL_CMD); in exynos5_i2c_bus_recover()
605 exynos5_i2c_wait_bus_idle(i2c); in exynos5_i2c_bus_recover()
607 val = readl(i2c->regs + HSI2C_CTL) & ~HSI2C_RXCHON; in exynos5_i2c_bus_recover()
608 writel(val, i2c->regs + HSI2C_CTL); in exynos5_i2c_bus_recover()
609 val = readl(i2c->regs + HSI2C_CONF) | HSI2C_AUTO_MODE; in exynos5_i2c_bus_recover()
610 writel(val, i2c->regs + HSI2C_CONF); in exynos5_i2c_bus_recover()
613 static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c) in exynos5_i2c_bus_check() argument
617 if (i2c->variant->hw == I2C_TYPE_EXYNOS5) in exynos5_i2c_bus_check()
627 u32 st = readl(i2c->regs + HSI2C_TRANS_STATUS); in exynos5_i2c_bus_check()
635 exynos5_i2c_bus_recover(i2c); in exynos5_i2c_bus_check()
641 * i2c: struct exynos5_i2c pointer for the current bus
649 static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) in exynos5_i2c_message_start() argument
659 if (i2c->variant->hw == I2C_TYPE_EXYNOS5) in exynos5_i2c_message_start()
664 i2c_ctl = readl(i2c->regs + HSI2C_CTL); in exynos5_i2c_message_start()
668 if (i2c->msg->flags & I2C_M_RD) { in exynos5_i2c_message_start()
673 trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ? in exynos5_i2c_message_start()
674 (i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len; in exynos5_i2c_message_start()
682 trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ? in exynos5_i2c_message_start()
683 (i2c->variant->fifo_depth * 1 / 4) : i2c->msg->len; in exynos5_i2c_message_start()
689 i2c_addr = HSI2C_SLV_ADDR_MAS(i2c->msg->addr); in exynos5_i2c_message_start()
691 if (i2c->op_clock >= I2C_MAX_FAST_MODE_PLUS_FREQ) in exynos5_i2c_message_start()
692 i2c_addr |= HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)); in exynos5_i2c_message_start()
694 writel(i2c_addr, i2c->regs + HSI2C_ADDR); in exynos5_i2c_message_start()
696 writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); in exynos5_i2c_message_start()
697 writel(i2c_ctl, i2c->regs + HSI2C_CTL); in exynos5_i2c_message_start()
699 exynos5_i2c_bus_check(i2c); in exynos5_i2c_message_start()
705 spin_lock_irqsave(&i2c->lock, flags); in exynos5_i2c_message_start()
706 writel(int_en, i2c->regs + HSI2C_INT_ENABLE); in exynos5_i2c_message_start()
710 i2c_auto_conf |= i2c->msg->len; in exynos5_i2c_message_start()
712 writel(i2c_auto_conf, i2c->regs + HSI2C_AUTO_CONF); in exynos5_i2c_message_start()
713 spin_unlock_irqrestore(&i2c->lock, flags); in exynos5_i2c_message_start()
716 static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, in exynos5_i2c_xfer_msg() argument
722 i2c->msg = msgs; in exynos5_i2c_xfer_msg()
723 i2c->msg_ptr = 0; in exynos5_i2c_xfer_msg()
724 i2c->trans_done = 0; in exynos5_i2c_xfer_msg()
726 reinit_completion(&i2c->msg_complete); in exynos5_i2c_xfer_msg()
728 exynos5_i2c_message_start(i2c, stop); in exynos5_i2c_xfer_msg()
730 timeout = wait_for_completion_timeout(&i2c->msg_complete, in exynos5_i2c_xfer_msg()
735 ret = i2c->state; in exynos5_i2c_xfer_msg()
742 ret = exynos5_i2c_wait_bus_idle(i2c); in exynos5_i2c_xfer_msg()
745 exynos5_i2c_reset(i2c); in exynos5_i2c_xfer_msg()
747 dev_warn(i2c->dev, "%s timeout\n", in exynos5_i2c_xfer_msg()
758 struct exynos5_i2c *i2c = adap->algo_data; in exynos5_i2c_xfer() local
761 ret = clk_enable(i2c->pclk); in exynos5_i2c_xfer()
765 ret = clk_enable(i2c->clk); in exynos5_i2c_xfer()
770 ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num); in exynos5_i2c_xfer()
775 clk_disable(i2c->clk); in exynos5_i2c_xfer()
777 clk_disable(i2c->pclk); in exynos5_i2c_xfer()
795 struct exynos5_i2c *i2c; in exynos5_i2c_probe() local
798 i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL); in exynos5_i2c_probe()
799 if (!i2c) in exynos5_i2c_probe()
802 if (of_property_read_u32(np, "clock-frequency", &i2c->op_clock)) in exynos5_i2c_probe()
803 i2c->op_clock = I2C_MAX_STANDARD_MODE_FREQ; in exynos5_i2c_probe()
805 strscpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name)); in exynos5_i2c_probe()
806 i2c->adap.owner = THIS_MODULE; in exynos5_i2c_probe()
807 i2c->adap.algo = &exynos5_i2c_algorithm; in exynos5_i2c_probe()
808 i2c->adap.retries = 3; in exynos5_i2c_probe()
810 i2c->dev = &pdev->dev; in exynos5_i2c_probe()
811 i2c->clk = devm_clk_get(&pdev->dev, "hsi2c"); in exynos5_i2c_probe()
812 if (IS_ERR(i2c->clk)) { in exynos5_i2c_probe()
817 i2c->pclk = devm_clk_get_optional(&pdev->dev, "hsi2c_pclk"); in exynos5_i2c_probe()
818 if (IS_ERR(i2c->pclk)) { in exynos5_i2c_probe()
819 return dev_err_probe(&pdev->dev, PTR_ERR(i2c->pclk), in exynos5_i2c_probe()
823 ret = clk_prepare_enable(i2c->pclk); in exynos5_i2c_probe()
827 ret = clk_prepare_enable(i2c->clk); in exynos5_i2c_probe()
831 i2c->regs = devm_platform_ioremap_resource(pdev, 0); in exynos5_i2c_probe()
832 if (IS_ERR(i2c->regs)) { in exynos5_i2c_probe()
833 ret = PTR_ERR(i2c->regs); in exynos5_i2c_probe()
837 i2c->adap.dev.of_node = np; in exynos5_i2c_probe()
838 i2c->adap.algo_data = i2c; in exynos5_i2c_probe()
839 i2c->adap.dev.parent = &pdev->dev; in exynos5_i2c_probe()
842 exynos5_i2c_clr_pend_irq(i2c); in exynos5_i2c_probe()
844 spin_lock_init(&i2c->lock); in exynos5_i2c_probe()
845 init_completion(&i2c->msg_complete); in exynos5_i2c_probe()
847 i2c->irq = ret = platform_get_irq(pdev, 0); in exynos5_i2c_probe()
851 ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, in exynos5_i2c_probe()
852 IRQF_NO_SUSPEND, dev_name(&pdev->dev), i2c); in exynos5_i2c_probe()
854 dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", i2c->irq); in exynos5_i2c_probe()
858 i2c->variant = of_device_get_match_data(&pdev->dev); in exynos5_i2c_probe()
860 ret = exynos5_hsi2c_clock_setup(i2c); in exynos5_i2c_probe()
864 exynos5_i2c_reset(i2c); in exynos5_i2c_probe()
866 ret = i2c_add_adapter(&i2c->adap); in exynos5_i2c_probe()
870 platform_set_drvdata(pdev, i2c); in exynos5_i2c_probe()
872 clk_disable(i2c->clk); in exynos5_i2c_probe()
873 clk_disable(i2c->pclk); in exynos5_i2c_probe()
878 clk_disable_unprepare(i2c->clk); in exynos5_i2c_probe()
881 clk_disable_unprepare(i2c->pclk); in exynos5_i2c_probe()
887 struct exynos5_i2c *i2c = platform_get_drvdata(pdev); in exynos5_i2c_remove() local
889 i2c_del_adapter(&i2c->adap); in exynos5_i2c_remove()
891 clk_unprepare(i2c->clk); in exynos5_i2c_remove()
892 clk_unprepare(i2c->pclk); in exynos5_i2c_remove()
900 struct exynos5_i2c *i2c = dev_get_drvdata(dev); in exynos5_i2c_suspend_noirq() local
902 i2c_mark_adapter_suspended(&i2c->adap); in exynos5_i2c_suspend_noirq()
903 clk_unprepare(i2c->clk); in exynos5_i2c_suspend_noirq()
904 clk_unprepare(i2c->pclk); in exynos5_i2c_suspend_noirq()
911 struct exynos5_i2c *i2c = dev_get_drvdata(dev); in exynos5_i2c_resume_noirq() local
914 ret = clk_prepare_enable(i2c->pclk); in exynos5_i2c_resume_noirq()
918 ret = clk_prepare_enable(i2c->clk); in exynos5_i2c_resume_noirq()
922 ret = exynos5_hsi2c_clock_setup(i2c); in exynos5_i2c_resume_noirq()
926 exynos5_i2c_init(i2c); in exynos5_i2c_resume_noirq()
927 clk_disable(i2c->clk); in exynos5_i2c_resume_noirq()
928 clk_disable(i2c->pclk); in exynos5_i2c_resume_noirq()
929 i2c_mark_adapter_resumed(&i2c->adap); in exynos5_i2c_resume_noirq()
934 clk_disable_unprepare(i2c->clk); in exynos5_i2c_resume_noirq()
936 clk_disable_unprepare(i2c->pclk); in exynos5_i2c_resume_noirq()
958 MODULE_DESCRIPTION("Exynos5 HS-I2C Bus driver");