diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 13 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 95 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 2 |
3 files changed, 85 insertions, 25 deletions
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 7e78f7c87857..3d471d56bf15 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -72,6 +72,7 @@ | |||
72 | 72 | ||
73 | #define MXS_I2C_QUEUESTAT (0x70) | 73 | #define MXS_I2C_QUEUESTAT (0x70) |
74 | #define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 | 74 | #define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 |
75 | #define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F | ||
75 | 76 | ||
76 | #define MXS_I2C_QUEUECMD (0x80) | 77 | #define MXS_I2C_QUEUECMD (0x80) |
77 | 78 | ||
@@ -219,14 +220,14 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
219 | int ret; | 220 | int ret; |
220 | int flags; | 221 | int flags; |
221 | 222 | ||
222 | init_completion(&i2c->cmd_complete); | ||
223 | |||
224 | dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", | 223 | dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", |
225 | msg->addr, msg->len, msg->flags, stop); | 224 | msg->addr, msg->len, msg->flags, stop); |
226 | 225 | ||
227 | if (msg->len == 0) | 226 | if (msg->len == 0) |
228 | return -EINVAL; | 227 | return -EINVAL; |
229 | 228 | ||
229 | init_completion(&i2c->cmd_complete); | ||
230 | |||
230 | flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; | 231 | flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; |
231 | 232 | ||
232 | if (msg->flags & I2C_M_RD) | 233 | if (msg->flags & I2C_M_RD) |
@@ -286,6 +287,7 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) | |||
286 | { | 287 | { |
287 | struct mxs_i2c_dev *i2c = dev_id; | 288 | struct mxs_i2c_dev *i2c = dev_id; |
288 | u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; | 289 | u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; |
290 | bool is_last_cmd; | ||
289 | 291 | ||
290 | if (!stat) | 292 | if (!stat) |
291 | return IRQ_NONE; | 293 | return IRQ_NONE; |
@@ -300,9 +302,14 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) | |||
300 | else | 302 | else |
301 | i2c->cmd_err = 0; | 303 | i2c->cmd_err = 0; |
302 | 304 | ||
303 | complete(&i2c->cmd_complete); | 305 | is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & |
306 | MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; | ||
307 | |||
308 | if (is_last_cmd || i2c->cmd_err) | ||
309 | complete(&i2c->cmd_complete); | ||
304 | 310 | ||
305 | writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); | 311 | writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); |
312 | |||
306 | return IRQ_HANDLED; | 313 | return IRQ_HANDLED; |
307 | } | 314 | } |
308 | 315 | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index d60364650990..f6733267fa9c 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/i2c-pxa.h> | 31 | #include <linux/i2c-pxa.h> |
32 | #include <linux/of.h> | ||
33 | #include <linux/of_device.h> | ||
32 | #include <linux/of_i2c.h> | 34 | #include <linux/of_i2c.h> |
33 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
34 | #include <linux/err.h> | 36 | #include <linux/err.h> |
@@ -1044,23 +1046,60 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { | |||
1044 | .functionality = i2c_pxa_functionality, | 1046 | .functionality = i2c_pxa_functionality, |
1045 | }; | 1047 | }; |
1046 | 1048 | ||
1047 | static int i2c_pxa_probe(struct platform_device *dev) | 1049 | static struct of_device_id i2c_pxa_dt_ids[] = { |
1050 | { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX }, | ||
1051 | { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX }, | ||
1052 | { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX }, | ||
1053 | {} | ||
1054 | }; | ||
1055 | MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); | ||
1056 | |||
1057 | static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, | ||
1058 | enum pxa_i2c_types *i2c_types) | ||
1048 | { | 1059 | { |
1049 | struct pxa_i2c *i2c; | 1060 | struct device_node *np = pdev->dev.of_node; |
1050 | struct resource *res; | 1061 | const struct of_device_id *of_id = |
1051 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 1062 | of_match_device(i2c_pxa_dt_ids, &pdev->dev); |
1052 | const struct platform_device_id *id = platform_get_device_id(dev); | ||
1053 | enum pxa_i2c_types i2c_type = id->driver_data; | ||
1054 | int ret; | 1063 | int ret; |
1055 | int irq; | ||
1056 | 1064 | ||
1057 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 1065 | if (!of_id) |
1058 | irq = platform_get_irq(dev, 0); | 1066 | return 1; |
1059 | if (res == NULL || irq < 0) | 1067 | ret = of_alias_get_id(np, "i2c"); |
1060 | return -ENODEV; | 1068 | if (ret < 0) { |
1069 | dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); | ||
1070 | return ret; | ||
1071 | } | ||
1072 | pdev->id = ret; | ||
1073 | if (of_get_property(np, "mrvl,i2c-polling", NULL)) | ||
1074 | i2c->use_pio = 1; | ||
1075 | if (of_get_property(np, "mrvl,i2c-fast-mode", NULL)) | ||
1076 | i2c->fast_mode = 1; | ||
1077 | *i2c_types = (u32)(of_id->data); | ||
1078 | return 0; | ||
1079 | } | ||
1061 | 1080 | ||
1062 | if (!request_mem_region(res->start, resource_size(res), res->name)) | 1081 | static int i2c_pxa_probe_pdata(struct platform_device *pdev, |
1063 | return -ENOMEM; | 1082 | struct pxa_i2c *i2c, |
1083 | enum pxa_i2c_types *i2c_types) | ||
1084 | { | ||
1085 | struct i2c_pxa_platform_data *plat = pdev->dev.platform_data; | ||
1086 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
1087 | |||
1088 | *i2c_types = id->driver_data; | ||
1089 | if (plat) { | ||
1090 | i2c->use_pio = plat->use_pio; | ||
1091 | i2c->fast_mode = plat->fast_mode; | ||
1092 | } | ||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | static int i2c_pxa_probe(struct platform_device *dev) | ||
1097 | { | ||
1098 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | ||
1099 | enum pxa_i2c_types i2c_type; | ||
1100 | struct pxa_i2c *i2c; | ||
1101 | struct resource *res = NULL; | ||
1102 | int ret, irq; | ||
1064 | 1103 | ||
1065 | i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL); | 1104 | i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL); |
1066 | if (!i2c) { | 1105 | if (!i2c) { |
@@ -1068,6 +1107,24 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1068 | goto emalloc; | 1107 | goto emalloc; |
1069 | } | 1108 | } |
1070 | 1109 | ||
1110 | ret = i2c_pxa_probe_dt(dev, i2c, &i2c_type); | ||
1111 | if (ret > 0) | ||
1112 | ret = i2c_pxa_probe_pdata(dev, i2c, &i2c_type); | ||
1113 | if (ret < 0) | ||
1114 | goto eclk; | ||
1115 | |||
1116 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
1117 | irq = platform_get_irq(dev, 0); | ||
1118 | if (res == NULL || irq < 0) { | ||
1119 | ret = -ENODEV; | ||
1120 | goto eclk; | ||
1121 | } | ||
1122 | |||
1123 | if (!request_mem_region(res->start, resource_size(res), res->name)) { | ||
1124 | ret = -ENOMEM; | ||
1125 | goto eclk; | ||
1126 | } | ||
1127 | |||
1071 | i2c->adap.owner = THIS_MODULE; | 1128 | i2c->adap.owner = THIS_MODULE; |
1072 | i2c->adap.retries = 5; | 1129 | i2c->adap.retries = 5; |
1073 | 1130 | ||
@@ -1109,21 +1166,16 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1109 | 1166 | ||
1110 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; | 1167 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; |
1111 | 1168 | ||
1112 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
1113 | if (plat) { | 1169 | if (plat) { |
1170 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
1114 | i2c->slave_addr = plat->slave_addr; | 1171 | i2c->slave_addr = plat->slave_addr; |
1115 | i2c->slave = plat->slave; | 1172 | i2c->slave = plat->slave; |
1116 | } | ||
1117 | #endif | 1173 | #endif |
1118 | |||
1119 | clk_enable(i2c->clk); | ||
1120 | |||
1121 | if (plat) { | ||
1122 | i2c->adap.class = plat->class; | 1174 | i2c->adap.class = plat->class; |
1123 | i2c->use_pio = plat->use_pio; | ||
1124 | i2c->fast_mode = plat->fast_mode; | ||
1125 | } | 1175 | } |
1126 | 1176 | ||
1177 | clk_enable(i2c->clk); | ||
1178 | |||
1127 | if (i2c->use_pio) { | 1179 | if (i2c->use_pio) { |
1128 | i2c->adap.algo = &i2c_pxa_pio_algorithm; | 1180 | i2c->adap.algo = &i2c_pxa_pio_algorithm; |
1129 | } else { | 1181 | } else { |
@@ -1234,6 +1286,7 @@ static struct platform_driver i2c_pxa_driver = { | |||
1234 | .name = "pxa2xx-i2c", | 1286 | .name = "pxa2xx-i2c", |
1235 | .owner = THIS_MODULE, | 1287 | .owner = THIS_MODULE, |
1236 | .pm = I2C_PXA_DEV_PM_OPS, | 1288 | .pm = I2C_PXA_DEV_PM_OPS, |
1289 | .of_match_table = i2c_pxa_dt_ids, | ||
1237 | }, | 1290 | }, |
1238 | .id_table = i2c_pxa_id_table, | 1291 | .id_table = i2c_pxa_id_table, |
1239 | }; | 1292 | }; |
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 6381604696d3..0ab4a9548745 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c | |||
@@ -755,7 +755,7 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); | |||
755 | 755 | ||
756 | static struct platform_driver tegra_i2c_driver = { | 756 | static struct platform_driver tegra_i2c_driver = { |
757 | .probe = tegra_i2c_probe, | 757 | .probe = tegra_i2c_probe, |
758 | .remove = tegra_i2c_remove, | 758 | .remove = __devexit_p(tegra_i2c_remove), |
759 | #ifdef CONFIG_PM | 759 | #ifdef CONFIG_PM |
760 | .suspend = tegra_i2c_suspend, | 760 | .suspend = tegra_i2c_suspend, |
761 | .resume = tegra_i2c_resume, | 761 | .resume = tegra_i2c_resume, |