diff options
author | Juergen Beisert <jbe@pengutronix.de> | 2013-09-29 19:23:53 -0400 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2013-10-06 09:56:23 -0400 |
commit | 616228a164d4366f82d983c4a70d8006d9fb43f2 (patch) | |
tree | e9f46cd8b7cd8815131f41b26846f32a9a0e5284 /drivers/i2c | |
parent | 0acc2b321342aa813fa9fc485afb09fbc811f594 (diff) |
i2c: mxs: distinguish i.MX23 and i.MX28 based I2C controller
It seems the PIO mode does not work, or at least not like it works
on a i.MX28. Each short transfer needs about one second (without an
error message) but does not send anything on the I2C lines.
Signed-off-by: Juergen Beisert <jbe@pengutronix.de>
Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index f4a01675fa71..2cb0317b14fb 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -95,10 +95,17 @@ | |||
95 | #define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \ | 95 | #define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \ |
96 | MXS_I2C_CTRL0_MASTER_MODE) | 96 | MXS_I2C_CTRL0_MASTER_MODE) |
97 | 97 | ||
98 | enum mxs_i2c_devtype { | ||
99 | MXS_I2C_UNKNOWN = 0, | ||
100 | MXS_I2C_V1, | ||
101 | MXS_I2C_V2, | ||
102 | }; | ||
103 | |||
98 | /** | 104 | /** |
99 | * struct mxs_i2c_dev - per device, private MXS-I2C data | 105 | * struct mxs_i2c_dev - per device, private MXS-I2C data |
100 | * | 106 | * |
101 | * @dev: driver model device node | 107 | * @dev: driver model device node |
108 | * @dev_type: distinguish i.MX23/i.MX28 features | ||
102 | * @regs: IO registers pointer | 109 | * @regs: IO registers pointer |
103 | * @cmd_complete: completion object for transaction wait | 110 | * @cmd_complete: completion object for transaction wait |
104 | * @cmd_err: error code for last transaction | 111 | * @cmd_err: error code for last transaction |
@@ -106,6 +113,7 @@ | |||
106 | */ | 113 | */ |
107 | struct mxs_i2c_dev { | 114 | struct mxs_i2c_dev { |
108 | struct device *dev; | 115 | struct device *dev; |
116 | enum mxs_i2c_devtype dev_type; | ||
109 | void __iomem *regs; | 117 | void __iomem *regs; |
110 | struct completion cmd_complete; | 118 | struct completion cmd_complete; |
111 | int cmd_err; | 119 | int cmd_err; |
@@ -495,6 +503,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
495 | * is set to 8 bytes, transfers shorter than 8 bytes are transfered | 503 | * is set to 8 bytes, transfers shorter than 8 bytes are transfered |
496 | * using PIO mode while longer transfers use DMA. The 8 byte border is | 504 | * using PIO mode while longer transfers use DMA. The 8 byte border is |
497 | * based on this empirical measurement and a lot of previous frobbing. | 505 | * based on this empirical measurement and a lot of previous frobbing. |
506 | * Note: this special feature only works on i.MX28 SoC | ||
498 | */ | 507 | */ |
499 | i2c->cmd_err = 0; | 508 | i2c->cmd_err = 0; |
500 | if (0) { /* disable PIO mode until a proper fix is made */ | 509 | if (0) { /* disable PIO mode until a proper fix is made */ |
@@ -680,8 +689,28 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) | |||
680 | return 0; | 689 | return 0; |
681 | } | 690 | } |
682 | 691 | ||
692 | static struct platform_device_id mxs_i2c_devtype[] = { | ||
693 | { | ||
694 | .name = "imx23-i2c", | ||
695 | .driver_data = MXS_I2C_V1, | ||
696 | }, { | ||
697 | .name = "imx28-i2c", | ||
698 | .driver_data = MXS_I2C_V2, | ||
699 | }, { /* sentinel */ } | ||
700 | }; | ||
701 | MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype); | ||
702 | |||
703 | static const struct of_device_id mxs_i2c_dt_ids[] = { | ||
704 | { .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], }, | ||
705 | { .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], }, | ||
706 | { /* sentinel */ } | ||
707 | }; | ||
708 | MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); | ||
709 | |||
683 | static int mxs_i2c_probe(struct platform_device *pdev) | 710 | static int mxs_i2c_probe(struct platform_device *pdev) |
684 | { | 711 | { |
712 | const struct of_device_id *of_id = | ||
713 | of_match_device(mxs_i2c_dt_ids, &pdev->dev); | ||
685 | struct device *dev = &pdev->dev; | 714 | struct device *dev = &pdev->dev; |
686 | struct mxs_i2c_dev *i2c; | 715 | struct mxs_i2c_dev *i2c; |
687 | struct i2c_adapter *adap; | 716 | struct i2c_adapter *adap; |
@@ -693,6 +722,11 @@ static int mxs_i2c_probe(struct platform_device *pdev) | |||
693 | if (!i2c) | 722 | if (!i2c) |
694 | return -ENOMEM; | 723 | return -ENOMEM; |
695 | 724 | ||
725 | if (of_id) { | ||
726 | const struct platform_device_id *device_id = of_id->data; | ||
727 | i2c->dev_type = device_id->driver_data; | ||
728 | } | ||
729 | |||
696 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 730 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
697 | irq = platform_get_irq(pdev, 0); | 731 | irq = platform_get_irq(pdev, 0); |
698 | 732 | ||
@@ -768,12 +802,6 @@ static int mxs_i2c_remove(struct platform_device *pdev) | |||
768 | return 0; | 802 | return 0; |
769 | } | 803 | } |
770 | 804 | ||
771 | static const struct of_device_id mxs_i2c_dt_ids[] = { | ||
772 | { .compatible = "fsl,imx28-i2c", }, | ||
773 | { /* sentinel */ } | ||
774 | }; | ||
775 | MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); | ||
776 | |||
777 | static struct platform_driver mxs_i2c_driver = { | 805 | static struct platform_driver mxs_i2c_driver = { |
778 | .driver = { | 806 | .driver = { |
779 | .name = DRIVER_NAME, | 807 | .name = DRIVER_NAME, |