diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2014-01-23 07:43:28 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2014-03-19 04:58:05 -0400 |
commit | a381b13e2aa064122325de9deaec51d6e4765ad7 (patch) | |
tree | 88ae5275f6b737eafc4dbce1834b19ba8729a50d | |
parent | 47ec66a17cca571eb7038b7835dff7cbd5851b90 (diff) |
mfd: tc3589x: Reform device tree probing
This changes the following mechanisms in the TC3589x device tree
probing path:
- Use the .of_match_table in struct device_driver to match the
device in the device tree.
- Add matches for the proper compatible strings "toshiba,..."
and all sub-variants, just as is done for the .id matches.
- Move over all the allocation of platform data etc to the
tc3589x_of_probe() function and follow the pattern of passing
a platform data pointer back, or an error pointer on error,
as found in the STMPE driver.
- Match the new (proper) compatible strings for the GPIO and
keypad MFD cells.
- Use of_device_is_compatible() rather than just !strcmp()
to discover which cells to instantiate.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/mfd/tc3589x.c | 84 |
1 files changed, 59 insertions, 25 deletions
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 2cf636c267d9..bd83accc0f6d 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c | |||
@@ -13,8 +13,10 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_device.h> | ||
16 | #include <linux/mfd/core.h> | 17 | #include <linux/mfd/core.h> |
17 | #include <linux/mfd/tc3589x.h> | 18 | #include <linux/mfd/tc3589x.h> |
19 | #include <linux/err.h> | ||
18 | 20 | ||
19 | /** | 21 | /** |
20 | * enum tc3589x_version - indicates the TC3589x version | 22 | * enum tc3589x_version - indicates the TC3589x version |
@@ -160,7 +162,7 @@ static const struct mfd_cell tc3589x_dev_gpio[] = { | |||
160 | .name = "tc3589x-gpio", | 162 | .name = "tc3589x-gpio", |
161 | .num_resources = ARRAY_SIZE(gpio_resources), | 163 | .num_resources = ARRAY_SIZE(gpio_resources), |
162 | .resources = &gpio_resources[0], | 164 | .resources = &gpio_resources[0], |
163 | .of_compatible = "tc3589x-gpio", | 165 | .of_compatible = "toshiba,tc3589x-gpio", |
164 | }, | 166 | }, |
165 | }; | 167 | }; |
166 | 168 | ||
@@ -169,7 +171,7 @@ static const struct mfd_cell tc3589x_dev_keypad[] = { | |||
169 | .name = "tc3589x-keypad", | 171 | .name = "tc3589x-keypad", |
170 | .num_resources = ARRAY_SIZE(keypad_resources), | 172 | .num_resources = ARRAY_SIZE(keypad_resources), |
171 | .resources = &keypad_resources[0], | 173 | .resources = &keypad_resources[0], |
172 | .of_compatible = "tc3589x-keypad", | 174 | .of_compatible = "toshiba,tc3589x-keypad", |
173 | }, | 175 | }, |
174 | }; | 176 | }; |
175 | 177 | ||
@@ -318,45 +320,74 @@ static int tc3589x_device_init(struct tc3589x *tc3589x) | |||
318 | return ret; | 320 | return ret; |
319 | } | 321 | } |
320 | 322 | ||
321 | static int tc3589x_of_probe(struct device_node *np, | 323 | #ifdef CONFIG_OF |
322 | struct tc3589x_platform_data *pdata) | 324 | static const struct of_device_id tc3589x_match[] = { |
325 | /* Legacy compatible string */ | ||
326 | { .compatible = "tc3589x", .data = (void *) TC3589X_UNKNOWN }, | ||
327 | { .compatible = "toshiba,tc35890", .data = (void *) TC3589X_TC35890 }, | ||
328 | { .compatible = "toshiba,tc35892", .data = (void *) TC3589X_TC35892 }, | ||
329 | { .compatible = "toshiba,tc35893", .data = (void *) TC3589X_TC35893 }, | ||
330 | { .compatible = "toshiba,tc35894", .data = (void *) TC3589X_TC35894 }, | ||
331 | { .compatible = "toshiba,tc35895", .data = (void *) TC3589X_TC35895 }, | ||
332 | { .compatible = "toshiba,tc35896", .data = (void *) TC3589X_TC35896 }, | ||
333 | { } | ||
334 | }; | ||
335 | |||
336 | MODULE_DEVICE_TABLE(of, tc3589x_match); | ||
337 | |||
338 | static struct tc3589x_platform_data * | ||
339 | tc3589x_of_probe(struct device *dev, enum tc3589x_version *version) | ||
323 | { | 340 | { |
341 | struct device_node *np = dev->of_node; | ||
342 | struct tc3589x_platform_data *pdata; | ||
324 | struct device_node *child; | 343 | struct device_node *child; |
344 | const struct of_device_id *of_id; | ||
345 | |||
346 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
347 | if (!pdata) | ||
348 | return ERR_PTR(-ENOMEM); | ||
349 | |||
350 | of_id = of_match_device(tc3589x_match, dev); | ||
351 | if (!of_id) | ||
352 | return ERR_PTR(-ENODEV); | ||
353 | *version = (enum tc3589x_version) of_id->data; | ||
325 | 354 | ||
326 | for_each_child_of_node(np, child) { | 355 | for_each_child_of_node(np, child) { |
327 | if (!strcmp(child->name, "tc3589x_gpio")) { | 356 | if (of_device_is_compatible(child, "toshiba,tc3589x-gpio")) |
328 | pdata->block |= TC3589x_BLOCK_GPIO; | 357 | pdata->block |= TC3589x_BLOCK_GPIO; |
329 | } | 358 | if (of_device_is_compatible(child, "toshiba,tc3589x-keypad")) |
330 | if (!strcmp(child->name, "tc3589x_keypad")) { | ||
331 | pdata->block |= TC3589x_BLOCK_KEYPAD; | 359 | pdata->block |= TC3589x_BLOCK_KEYPAD; |
332 | } | ||
333 | } | 360 | } |
334 | 361 | ||
335 | return 0; | 362 | return pdata; |
336 | } | 363 | } |
364 | #else | ||
365 | static inline struct tc3589x_platform_data * | ||
366 | tc3589x_of_probe(struct device *dev, enum tc3589x_version *version) | ||
367 | { | ||
368 | dev_err(dev, "no device tree support\n"); | ||
369 | return ERR_PTR(-ENODEV); | ||
370 | } | ||
371 | #endif | ||
337 | 372 | ||
338 | static int tc3589x_probe(struct i2c_client *i2c, | 373 | static int tc3589x_probe(struct i2c_client *i2c, |
339 | const struct i2c_device_id *id) | 374 | const struct i2c_device_id *id) |
340 | { | 375 | { |
341 | struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
342 | struct device_node *np = i2c->dev.of_node; | 376 | struct device_node *np = i2c->dev.of_node; |
377 | struct tc3589x_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
343 | struct tc3589x *tc3589x; | 378 | struct tc3589x *tc3589x; |
379 | enum tc3589x_version version; | ||
344 | int ret; | 380 | int ret; |
345 | 381 | ||
346 | if (!pdata) { | 382 | if (!pdata) { |
347 | if (np) { | 383 | pdata = tc3589x_of_probe(&i2c->dev, &version); |
348 | pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); | 384 | if (IS_ERR(pdata)) { |
349 | if (!pdata) | ||
350 | return -ENOMEM; | ||
351 | |||
352 | ret = tc3589x_of_probe(np, pdata); | ||
353 | if (ret) | ||
354 | return ret; | ||
355 | } | ||
356 | else { | ||
357 | dev_err(&i2c->dev, "No platform data or DT found\n"); | 385 | dev_err(&i2c->dev, "No platform data or DT found\n"); |
358 | return -EINVAL; | 386 | return PTR_ERR(pdata); |
359 | } | 387 | } |
388 | } else { | ||
389 | /* When not probing from device tree we have this ID */ | ||
390 | version = id->driver_data; | ||
360 | } | 391 | } |
361 | 392 | ||
362 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | 393 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
@@ -375,7 +406,7 @@ static int tc3589x_probe(struct i2c_client *i2c, | |||
375 | tc3589x->pdata = pdata; | 406 | tc3589x->pdata = pdata; |
376 | tc3589x->irq_base = pdata->irq_base; | 407 | tc3589x->irq_base = pdata->irq_base; |
377 | 408 | ||
378 | switch (id->driver_data) { | 409 | switch (version) { |
379 | case TC3589X_TC35893: | 410 | case TC3589X_TC35893: |
380 | case TC3589X_TC35895: | 411 | case TC3589X_TC35895: |
381 | case TC3589X_TC35896: | 412 | case TC3589X_TC35896: |
@@ -471,9 +502,12 @@ static const struct i2c_device_id tc3589x_id[] = { | |||
471 | MODULE_DEVICE_TABLE(i2c, tc3589x_id); | 502 | MODULE_DEVICE_TABLE(i2c, tc3589x_id); |
472 | 503 | ||
473 | static struct i2c_driver tc3589x_driver = { | 504 | static struct i2c_driver tc3589x_driver = { |
474 | .driver.name = "tc3589x", | 505 | .driver = { |
475 | .driver.owner = THIS_MODULE, | 506 | .name = "tc3589x", |
476 | .driver.pm = &tc3589x_dev_pm_ops, | 507 | .owner = THIS_MODULE, |
508 | .pm = &tc3589x_dev_pm_ops, | ||
509 | .of_match_table = of_match_ptr(tc3589x_match), | ||
510 | }, | ||
477 | .probe = tc3589x_probe, | 511 | .probe = tc3589x_probe, |
478 | .remove = tc3589x_remove, | 512 | .remove = tc3589x_remove, |
479 | .id_table = tc3589x_id, | 513 | .id_table = tc3589x_id, |