diff options
author | Haojian Zhuang <haojian.zhuang@marvell.com> | 2012-03-01 00:04:44 -0500 |
---|---|---|
committer | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-03-06 20:32:03 -0500 |
commit | 63fe122bce0655ffdbbe3d23b1ee445c44ce65c2 (patch) | |
tree | 9562da38ea84a99d8ef670699274566ff7a6ab6e | |
parent | 699c20f3e6310aa2ff18610c7d0885ed54d64337 (diff) |
i2c: pxa: add OF support
Append these properties in below.
mrvl,i2c-polling
mrvl,i2c-fast-mode
Still keep slave, slave_addr and class in platform data.
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 95 |
1 files changed, 74 insertions, 21 deletions
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 | }; |