aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-18 18:16:42 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-04-30 01:37:17 -0400
commit81e5d8646ff6bf323dddcf172aa3cef84468fa12 (patch)
treeacf9a3a4709118f4bb423d5887b1581546d8ae13
parent35000870fcfbb28757ad47de77b4645072d916b8 (diff)
i2c/powermac: Register i2c devices from device-tree
This causes i2c-powermac to register i2c devices exposed in the device-tree, enabling new-style probing of devices. Note that we prefix the IDs with "MAC," in order to prevent the generic drivers from matching. This is done on purpose as we only want drivers specifically tested/designed to operate on powermacs to match. This removes the special case we had for the AMS driver, and updates the driver's match table instead. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c1
-rw-r--r--drivers/i2c/busses/i2c-powermac.c98
-rw-r--r--drivers/macintosh/ams/ams-i2c.c2
3 files changed, 73 insertions, 28 deletions
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 03685a329d7d..fc536f2971c0 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -1503,6 +1503,7 @@ static int __init pmac_i2c_create_platform_devices(void)
1503 if (bus->platform_dev == NULL) 1503 if (bus->platform_dev == NULL)
1504 return -ENOMEM; 1504 return -ENOMEM;
1505 bus->platform_dev->dev.platform_data = bus; 1505 bus->platform_dev->dev.platform_data = bus;
1506 bus->platform_dev->dev.of_node = bus->busnode;
1506 platform_device_add(bus->platform_dev); 1507 platform_device_add(bus->platform_dev);
1507 } 1508 }
1508 1509
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 7b397c6f607e..31c47e18d83c 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -227,6 +227,72 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
227 return 0; 227 return 0;
228} 228}
229 229
230static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
231 struct pmac_i2c_bus *bus)
232{
233 struct i2c_client *newdev;
234 struct device_node *node;
235
236 for_each_child_of_node(adap->dev.of_node, node) {
237 struct i2c_board_info info = {};
238 struct dev_archdata dev_ad = {};
239 const __be32 *reg;
240 char tmp[16];
241 u32 addr;
242 int len;
243
244 /* Get address & channel */
245 reg = of_get_property(node, "reg", &len);
246 if (!reg || (len < sizeof(int))) {
247 dev_err(&adap->dev, "i2c-powermac: invalid reg on %s\n",
248 node->full_name);
249 continue;
250 }
251 addr = be32_to_cpup(reg);
252
253 /* Multibus setup, check channel */
254 if (!pmac_i2c_match_adapter(node, adap))
255 continue;
256
257 dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
258 node->full_name);
259
260 /* Make up a modalias. Note: we to _NOT_ want the standard
261 * i2c drivers to match with any of our powermac stuff
262 * unless they have been specifically modified to handle
263 * it on a case by case basis. For example, for thermal
264 * control, things like lm75 etc... shall match with their
265 * corresponding windfarm drivers, _NOT_ the generic ones,
266 * so we force a prefix of AAPL, onto the modalias to
267 * make that happen
268 */
269 if (of_modalias_node(node, tmp, sizeof(tmp)) < 0) {
270 dev_err(&adap->dev, "i2c-powermac: modalias failure"
271 " on %s\n", node->full_name);
272 continue;
273 }
274 snprintf(info.type, sizeof(info.type), "MAC,%s", tmp);
275
276 /* Fill out the rest of the info structure */
277 info.addr = (addr & 0xff) >> 1;
278 info.irq = irq_of_parse_and_map(node, 0);
279 info.of_node = of_node_get(node);
280 info.archdata = &dev_ad;
281
282 newdev = i2c_new_device(adap, &info);
283 if (!newdev) {
284 dev_err(&adap->dev, "i2c-powermac: Failure to register"
285 " %s\n", node->full_name);
286 of_node_put(node);
287 /* We do not dispose of the interrupt mapping on
288 * purpose. It's not necessary (interrupt cannot be
289 * re-used) and somebody else might have grabbed it
290 * via direct DT lookup so let's not bother
291 */
292 continue;
293 }
294 }
295}
230 296
231static int __devinit i2c_powermac_probe(struct platform_device *dev) 297static int __devinit i2c_powermac_probe(struct platform_device *dev)
232{ 298{
@@ -272,6 +338,7 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
272 adapter->algo = &i2c_powermac_algorithm; 338 adapter->algo = &i2c_powermac_algorithm;
273 i2c_set_adapdata(adapter, bus); 339 i2c_set_adapdata(adapter, bus);
274 adapter->dev.parent = &dev->dev; 340 adapter->dev.parent = &dev->dev;
341 adapter->dev.of_node = dev->dev.of_node;
275 rc = i2c_add_adapter(adapter); 342 rc = i2c_add_adapter(adapter);
276 if (rc) { 343 if (rc) {
277 printk(KERN_ERR "i2c-powermac: Adapter %s registration " 344 printk(KERN_ERR "i2c-powermac: Adapter %s registration "
@@ -281,33 +348,10 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
281 348
282 printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); 349 printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
283 350
284 if (!strncmp(basename, "uni-n", 5)) { 351 /* Cannot use of_i2c_register_devices() due to Apple device-tree
285 struct device_node *np; 352 * funkyness
286 const u32 *prop; 353 */
287 struct i2c_board_info info; 354 i2c_powermac_register_devices(adapter, bus);
288
289 /* Instantiate I2C motion sensor if present */
290 np = of_find_node_by_name(NULL, "accelerometer");
291 if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") &&
292 (prop = of_get_property(np, "reg", NULL))) {
293 int i2c_bus;
294 const char *tmp_bus;
295
296 /* look for bus either using "reg" or by path */
297 tmp_bus = strstr(np->full_name, "/i2c-bus@");
298 if (tmp_bus)
299 i2c_bus = *(tmp_bus + 9) - '0';
300 else
301 i2c_bus = ((*prop) >> 8) & 0x0f;
302
303 if (pmac_i2c_get_channel(bus) == i2c_bus) {
304 memset(&info, 0, sizeof(struct i2c_board_info));
305 info.addr = ((*prop) & 0xff) >> 1;
306 strlcpy(info.type, "ams", I2C_NAME_SIZE);
307 i2c_new_device(adapter, &info);
308 }
309 }
310 }
311 355
312 return rc; 356 return rc;
313} 357}
diff --git a/drivers/macintosh/ams/ams-i2c.c b/drivers/macintosh/ams/ams-i2c.c
index abeecd27b484..978eda8d6678 100644
--- a/drivers/macintosh/ams/ams-i2c.c
+++ b/drivers/macintosh/ams/ams-i2c.c
@@ -65,7 +65,7 @@ static int ams_i2c_probe(struct i2c_client *client,
65static int ams_i2c_remove(struct i2c_client *client); 65static int ams_i2c_remove(struct i2c_client *client);
66 66
67static const struct i2c_device_id ams_id[] = { 67static const struct i2c_device_id ams_id[] = {
68 { "ams", 0 }, 68 { "MAC,accelerometer_1", 0 },
69 { } 69 { }
70}; 70};
71MODULE_DEVICE_TABLE(i2c, ams_id); 71MODULE_DEVICE_TABLE(i2c, ams_id);