diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-07-25 04:46:01 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:30 -0400 |
commit | 42cd2366fb9b58cdfc1855be32b31a78e40b2079 (patch) | |
tree | 58f335a86f7c2f127509642499d1fd2a27d21ff9 | |
parent | 60e540d617b40eb3d37f1dd99c97af588ff9b70b (diff) |
sm501: gpio I2C support
Add support for adding the GPIO based I2C resources.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Cc: Arnaud Patard <apatard@mandriva.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/mfd/sm501.c | 76 | ||||
-rw-r--r-- | include/linux/sm501.h | 10 |
2 files changed, 84 insertions, 2 deletions
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index c3e5a48f6148..107215b28805 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
23 | #include <linux/i2c-gpio.h> | ||
23 | 24 | ||
24 | #include <linux/sm501.h> | 25 | #include <linux/sm501.h> |
25 | #include <linux/sm501-regs.h> | 26 | #include <linux/sm501-regs.h> |
@@ -1086,6 +1087,11 @@ static void sm501_gpio_remove(struct sm501_devdata *sm) | |||
1086 | dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n"); | 1087 | dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n"); |
1087 | } | 1088 | } |
1088 | 1089 | ||
1090 | static int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
1091 | { | ||
1092 | struct sm501_gpio *gpio = &sm->gpio; | ||
1093 | return pin + (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base; | ||
1094 | } | ||
1089 | #else | 1095 | #else |
1090 | static int sm501_register_gpio(struct sm501_devdata *sm) | 1096 | static int sm501_register_gpio(struct sm501_devdata *sm) |
1091 | { | 1097 | { |
@@ -1095,8 +1101,66 @@ static int sm501_register_gpio(struct sm501_devdata *sm) | |||
1095 | static void sm501_gpio_remove(struct sm501_devdata *sm) | 1101 | static void sm501_gpio_remove(struct sm501_devdata *sm) |
1096 | { | 1102 | { |
1097 | } | 1103 | } |
1104 | |||
1105 | static int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
1106 | { | ||
1107 | return -1; | ||
1108 | } | ||
1098 | #endif | 1109 | #endif |
1099 | 1110 | ||
1111 | static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, | ||
1112 | struct sm501_platdata_gpio_i2c *iic) | ||
1113 | { | ||
1114 | struct i2c_gpio_platform_data *icd; | ||
1115 | struct platform_device *pdev; | ||
1116 | |||
1117 | pdev = sm501_create_subdev(sm, "i2c-gpio", 0, | ||
1118 | sizeof(struct i2c_gpio_platform_data)); | ||
1119 | if (!pdev) | ||
1120 | return -ENOMEM; | ||
1121 | |||
1122 | icd = pdev->dev.platform_data; | ||
1123 | |||
1124 | /* We keep the pin_sda and pin_scl fields relative in case the | ||
1125 | * same platform data is passed to >1 SM501. | ||
1126 | */ | ||
1127 | |||
1128 | icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda); | ||
1129 | icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl); | ||
1130 | icd->timeout = iic->timeout; | ||
1131 | icd->udelay = iic->udelay; | ||
1132 | |||
1133 | /* note, we can't use either of the pin numbers, as the i2c-gpio | ||
1134 | * driver uses the platform.id field to generate the bus number | ||
1135 | * to register with the i2c core; The i2c core doesn't have enough | ||
1136 | * entries to deal with anything we currently use. | ||
1137 | */ | ||
1138 | |||
1139 | pdev->id = iic->bus_num; | ||
1140 | |||
1141 | dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n", | ||
1142 | iic->bus_num, | ||
1143 | icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl); | ||
1144 | |||
1145 | return sm501_register_device(sm, pdev); | ||
1146 | } | ||
1147 | |||
1148 | static int sm501_register_gpio_i2c(struct sm501_devdata *sm, | ||
1149 | struct sm501_platdata *pdata) | ||
1150 | { | ||
1151 | struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c; | ||
1152 | int index; | ||
1153 | int ret; | ||
1154 | |||
1155 | for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) { | ||
1156 | ret = sm501_register_gpio_i2c_instance(sm, iic); | ||
1157 | if (ret < 0) | ||
1158 | return ret; | ||
1159 | } | ||
1160 | |||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1100 | /* sm501_dbg_regs | 1164 | /* sm501_dbg_regs |
1101 | * | 1165 | * |
1102 | * Debug attribute to attach to parent device to show core registers | 1166 | * Debug attribute to attach to parent device to show core registers |
@@ -1204,6 +1268,7 @@ static unsigned int sm501_mem_local[] = { | |||
1204 | static int sm501_init_dev(struct sm501_devdata *sm) | 1268 | static int sm501_init_dev(struct sm501_devdata *sm) |
1205 | { | 1269 | { |
1206 | struct sm501_initdata *idata; | 1270 | struct sm501_initdata *idata; |
1271 | struct sm501_platdata *pdata; | ||
1207 | resource_size_t mem_avail; | 1272 | resource_size_t mem_avail; |
1208 | unsigned long dramctrl; | 1273 | unsigned long dramctrl; |
1209 | unsigned long devid; | 1274 | unsigned long devid; |
@@ -1242,7 +1307,9 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
1242 | 1307 | ||
1243 | /* check to see if we have some device initialisation */ | 1308 | /* check to see if we have some device initialisation */ |
1244 | 1309 | ||
1245 | idata = sm->platdata ? sm->platdata->init : NULL; | 1310 | pdata = sm->platdata; |
1311 | idata = pdata ? pdata->init : NULL; | ||
1312 | |||
1246 | if (idata) { | 1313 | if (idata) { |
1247 | sm501_init_regs(sm, idata); | 1314 | sm501_init_regs(sm, idata); |
1248 | 1315 | ||
@@ -1254,6 +1321,13 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
1254 | sm501_register_gpio(sm); | 1321 | sm501_register_gpio(sm); |
1255 | } | 1322 | } |
1256 | 1323 | ||
1324 | if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) { | ||
1325 | if (!sm->gpio.registered) | ||
1326 | dev_err(sm->dev, "no gpio registered for i2c gpio.\n"); | ||
1327 | else | ||
1328 | sm501_register_gpio_i2c(sm, pdata); | ||
1329 | } | ||
1330 | |||
1257 | ret = sm501_check_clocks(sm); | 1331 | ret = sm501_check_clocks(sm); |
1258 | if (ret) { | 1332 | if (ret) { |
1259 | dev_err(sm->dev, "M1X and M clocks sourced from different " | 1333 | dev_err(sm->dev, "M1X and M clocks sourced from different " |
diff --git a/include/linux/sm501.h b/include/linux/sm501.h index a8d02f36ad32..214f93209b8c 100644 --- a/include/linux/sm501.h +++ b/include/linux/sm501.h | |||
@@ -86,11 +86,19 @@ struct sm501_platdata_fb { | |||
86 | struct sm501_platdata_fbsub *fb_pnl; | 86 | struct sm501_platdata_fbsub *fb_pnl; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /* gpio i2c */ | 89 | /* gpio i2c |
90 | * | ||
91 | * Note, we have to pass in the bus number, as the number used will be | ||
92 | * passed to the i2c-gpio driver's platform_device.id, subsequently used | ||
93 | * to register the i2c bus. | ||
94 | */ | ||
90 | 95 | ||
91 | struct sm501_platdata_gpio_i2c { | 96 | struct sm501_platdata_gpio_i2c { |
97 | unsigned int bus_num; | ||
92 | unsigned int pin_sda; | 98 | unsigned int pin_sda; |
93 | unsigned int pin_scl; | 99 | unsigned int pin_scl; |
100 | int udelay; | ||
101 | int timeout; | ||
94 | }; | 102 | }; |
95 | 103 | ||
96 | /* sm501_initdata | 104 | /* sm501_initdata |