aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-powermac.c98
1 files changed, 71 insertions, 27 deletions
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}