diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2012-07-12 05:57:52 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-06 17:11:42 -0500 |
commit | cd0f34b08f98af72bb2f74fe4bd251558fc734d3 (patch) | |
tree | caee50770690b553ffbc10df5fb031fdde5e187c | |
parent | 5e53a69b44e893227b046a7bc74db3cb40d7f39b (diff) |
mfd: mc13xxx: Change probing details for mc13xxx devices
This removes auto-detection of which variant of mc13xxx is used because
mc34708 uses a different layout in the revision register that doesn't
allow differentiation any more.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Marc Reilly <marc@cpdesign.com.au>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/mfd/mc13xxx-core.c | 77 | ||||
-rw-r--r-- | drivers/mfd/mc13xxx-i2c.c | 16 | ||||
-rw-r--r-- | drivers/mfd/mc13xxx-spi.c | 25 | ||||
-rw-r--r-- | drivers/mfd/mc13xxx.h | 17 |
4 files changed, 60 insertions, 75 deletions
diff --git a/drivers/mfd/mc13xxx-core.c b/drivers/mfd/mc13xxx-core.c index 1aba0238f426..40afdb9b73f5 100644 --- a/drivers/mfd/mc13xxx-core.c +++ b/drivers/mfd/mc13xxx-core.c | |||
@@ -410,62 +410,36 @@ static irqreturn_t mc13xxx_irq_thread(int irq, void *data) | |||
410 | return IRQ_RETVAL(handled); | 410 | return IRQ_RETVAL(handled); |
411 | } | 411 | } |
412 | 412 | ||
413 | static const char *mc13xxx_chipname[] = { | ||
414 | [MC13XXX_ID_MC13783] = "mc13783", | ||
415 | [MC13XXX_ID_MC13892] = "mc13892", | ||
416 | }; | ||
417 | |||
418 | #define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask)) | 413 | #define maskval(reg, mask) (((reg) & (mask)) >> __ffs(mask)) |
419 | static int mc13xxx_identify(struct mc13xxx *mc13xxx) | 414 | static void mc13xxx_print_revision(struct mc13xxx *mc13xxx, u32 revision) |
420 | { | 415 | { |
421 | u32 icid; | 416 | dev_info(mc13xxx->dev, "%s: rev: %d.%d, " |
422 | u32 revision; | 417 | "fin: %d, fab: %d, icid: %d/%d\n", |
423 | int ret; | 418 | mc13xxx->variant->name, |
424 | 419 | maskval(revision, MC13XXX_REVISION_REVFULL), | |
425 | /* | 420 | maskval(revision, MC13XXX_REVISION_REVMETAL), |
426 | * Get the generation ID from register 46, as apparently some older | 421 | maskval(revision, MC13XXX_REVISION_FIN), |
427 | * IC revisions only have this info at this location. Newer ICs seem to | 422 | maskval(revision, MC13XXX_REVISION_FAB), |
428 | * have both. | 423 | maskval(revision, MC13XXX_REVISION_ICID), |
429 | */ | 424 | maskval(revision, MC13XXX_REVISION_ICIDCODE)); |
430 | ret = mc13xxx_reg_read(mc13xxx, 46, &icid); | 425 | } |
431 | if (ret) | ||
432 | return ret; | ||
433 | |||
434 | icid = (icid >> 6) & 0x7; | ||
435 | |||
436 | switch (icid) { | ||
437 | case 2: | ||
438 | mc13xxx->ictype = MC13XXX_ID_MC13783; | ||
439 | break; | ||
440 | case 7: | ||
441 | mc13xxx->ictype = MC13XXX_ID_MC13892; | ||
442 | break; | ||
443 | default: | ||
444 | mc13xxx->ictype = MC13XXX_ID_INVALID; | ||
445 | break; | ||
446 | } | ||
447 | 426 | ||
448 | if (mc13xxx->ictype == MC13XXX_ID_MC13783 || | 427 | /* These are only exported for mc13xxx-i2c and mc13xxx-spi */ |
449 | mc13xxx->ictype == MC13XXX_ID_MC13892) { | 428 | struct mc13xxx_variant mc13xxx_variant_mc13783 = { |
450 | ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision); | 429 | .name = "mc13783", |
451 | 430 | .print_revision = mc13xxx_print_revision, | |
452 | dev_info(mc13xxx->dev, "%s: rev: %d.%d, " | 431 | }; |
453 | "fin: %d, fab: %d, icid: %d/%d\n", | 432 | EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13783); |
454 | mc13xxx_chipname[mc13xxx->ictype], | ||
455 | maskval(revision, MC13XXX_REVISION_REVFULL), | ||
456 | maskval(revision, MC13XXX_REVISION_REVMETAL), | ||
457 | maskval(revision, MC13XXX_REVISION_FIN), | ||
458 | maskval(revision, MC13XXX_REVISION_FAB), | ||
459 | maskval(revision, MC13XXX_REVISION_ICID), | ||
460 | maskval(revision, MC13XXX_REVISION_ICIDCODE)); | ||
461 | } | ||
462 | 433 | ||
463 | return (mc13xxx->ictype == MC13XXX_ID_INVALID) ? -ENODEV : 0; | 434 | struct mc13xxx_variant mc13xxx_variant_mc13892 = { |
464 | } | 435 | .name = "mc13892", |
436 | .print_revision = mc13xxx_print_revision, | ||
437 | }; | ||
438 | EXPORT_SYMBOL_GPL(mc13xxx_variant_mc13892); | ||
465 | 439 | ||
466 | static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx) | 440 | static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx) |
467 | { | 441 | { |
468 | return mc13xxx_chipname[mc13xxx->ictype]; | 442 | return mc13xxx->variant->name; |
469 | } | 443 | } |
470 | 444 | ||
471 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx) | 445 | int mc13xxx_get_flags(struct mc13xxx *mc13xxx) |
@@ -653,13 +627,16 @@ int mc13xxx_common_init(struct mc13xxx *mc13xxx, | |||
653 | struct mc13xxx_platform_data *pdata, int irq) | 627 | struct mc13xxx_platform_data *pdata, int irq) |
654 | { | 628 | { |
655 | int ret; | 629 | int ret; |
630 | u32 revision; | ||
656 | 631 | ||
657 | mc13xxx_lock(mc13xxx); | 632 | mc13xxx_lock(mc13xxx); |
658 | 633 | ||
659 | ret = mc13xxx_identify(mc13xxx); | 634 | ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision); |
660 | if (ret) | 635 | if (ret) |
661 | goto err_revision; | 636 | goto err_revision; |
662 | 637 | ||
638 | mc13xxx->variant->print_revision(mc13xxx, revision); | ||
639 | |||
663 | /* mask all irqs */ | 640 | /* mask all irqs */ |
664 | ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff); | 641 | ret = mc13xxx_reg_write(mc13xxx, MC13XXX_IRQMASK0, 0x00ffffff); |
665 | if (ret) | 642 | if (ret) |
diff --git a/drivers/mfd/mc13xxx-i2c.c b/drivers/mfd/mc13xxx-i2c.c index 9d18dde3cd2a..4a0afc7f2d4e 100644 --- a/drivers/mfd/mc13xxx-i2c.c +++ b/drivers/mfd/mc13xxx-i2c.c | |||
@@ -24,7 +24,7 @@ | |||
24 | static const struct i2c_device_id mc13xxx_i2c_device_id[] = { | 24 | static const struct i2c_device_id mc13xxx_i2c_device_id[] = { |
25 | { | 25 | { |
26 | .name = "mc13892", | 26 | .name = "mc13892", |
27 | .driver_data = MC13XXX_ID_MC13892, | 27 | .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892, |
28 | }, { | 28 | }, { |
29 | /* sentinel */ | 29 | /* sentinel */ |
30 | } | 30 | } |
@@ -34,7 +34,7 @@ MODULE_DEVICE_TABLE(i2c, mc13xxx_i2c_device_id); | |||
34 | static const struct of_device_id mc13xxx_dt_ids[] = { | 34 | static const struct of_device_id mc13xxx_dt_ids[] = { |
35 | { | 35 | { |
36 | .compatible = "fsl,mc13892", | 36 | .compatible = "fsl,mc13892", |
37 | .data = (void *) &mc13xxx_i2c_device_id[0], | 37 | .data = &mc13xxx_variant_mc13892, |
38 | }, { | 38 | }, { |
39 | /* sentinel */ | 39 | /* sentinel */ |
40 | } | 40 | } |
@@ -76,11 +76,15 @@ static int mc13xxx_i2c_probe(struct i2c_client *client, | |||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
79 | ret = mc13xxx_common_init(mc13xxx, pdata, client->irq); | 79 | if (client->dev.of_node) { |
80 | const struct of_device_id *of_id = | ||
81 | of_match_device(mc13xxx_dt_ids, &client->dev); | ||
82 | mc13xxx->variant = of_id->data; | ||
83 | } else { | ||
84 | mc13xxx->variant = (void *)id->driver_data; | ||
85 | } | ||
80 | 86 | ||
81 | if (ret == 0 && (id->driver_data != mc13xxx->ictype)) | 87 | ret = mc13xxx_common_init(mc13xxx, pdata, client->irq); |
82 | dev_warn(mc13xxx->dev, | ||
83 | "device id doesn't match auto detection!\n"); | ||
84 | 88 | ||
85 | return ret; | 89 | return ret; |
86 | } | 90 | } |
diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 0bdb43a0aff0..9b1e60827f37 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c | |||
@@ -28,10 +28,10 @@ | |||
28 | static const struct spi_device_id mc13xxx_device_id[] = { | 28 | static const struct spi_device_id mc13xxx_device_id[] = { |
29 | { | 29 | { |
30 | .name = "mc13783", | 30 | .name = "mc13783", |
31 | .driver_data = MC13XXX_ID_MC13783, | 31 | .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13783, |
32 | }, { | 32 | }, { |
33 | .name = "mc13892", | 33 | .name = "mc13892", |
34 | .driver_data = MC13XXX_ID_MC13892, | 34 | .driver_data = (kernel_ulong_t)&mc13xxx_variant_mc13892, |
35 | }, { | 35 | }, { |
36 | /* sentinel */ | 36 | /* sentinel */ |
37 | } | 37 | } |
@@ -39,8 +39,8 @@ static const struct spi_device_id mc13xxx_device_id[] = { | |||
39 | MODULE_DEVICE_TABLE(spi, mc13xxx_device_id); | 39 | MODULE_DEVICE_TABLE(spi, mc13xxx_device_id); |
40 | 40 | ||
41 | static const struct of_device_id mc13xxx_dt_ids[] = { | 41 | static const struct of_device_id mc13xxx_dt_ids[] = { |
42 | { .compatible = "fsl,mc13783", .data = (void *) MC13XXX_ID_MC13783, }, | 42 | { .compatible = "fsl,mc13783", .data = &mc13xxx_variant_mc13783, }, |
43 | { .compatible = "fsl,mc13892", .data = (void *) MC13XXX_ID_MC13892, }, | 43 | { .compatible = "fsl,mc13892", .data = &mc13xxx_variant_mc13892, }, |
44 | { /* sentinel */ } | 44 | { /* sentinel */ } |
45 | }; | 45 | }; |
46 | MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids); | 46 | MODULE_DEVICE_TABLE(of, mc13xxx_dt_ids); |
@@ -144,19 +144,18 @@ static int mc13xxx_spi_probe(struct spi_device *spi) | |||
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
146 | 146 | ||
147 | ret = mc13xxx_common_init(mc13xxx, pdata, spi->irq); | 147 | if (spi->dev.of_node) { |
148 | const struct of_device_id *of_id = | ||
149 | of_match_device(mc13xxx_dt_ids, &spi->dev); | ||
148 | 150 | ||
149 | if (ret) { | 151 | mc13xxx->variant = of_id->data; |
150 | dev_set_drvdata(&spi->dev, NULL); | ||
151 | } else { | 152 | } else { |
152 | const struct spi_device_id *devid = | 153 | const struct spi_device_id *id_entry = spi_get_device_id(spi); |
153 | spi_get_device_id(spi); | 154 | |
154 | if (!devid || devid->driver_data != mc13xxx->ictype) | 155 | mc13xxx->variant = (void *)id_entry->driver_data; |
155 | dev_warn(mc13xxx->dev, | ||
156 | "device id doesn't match auto detection!\n"); | ||
157 | } | 156 | } |
158 | 157 | ||
159 | return ret; | 158 | return mc13xxx_common_init(mc13xxx, pdata, spi->irq); |
160 | } | 159 | } |
161 | 160 | ||
162 | static int __devexit mc13xxx_spi_remove(struct spi_device *spi) | 161 | static int __devexit mc13xxx_spi_remove(struct spi_device *spi) |
diff --git a/drivers/mfd/mc13xxx.h b/drivers/mfd/mc13xxx.h index bbba06feea06..78bf4c3c1fac 100644 --- a/drivers/mfd/mc13xxx.h +++ b/drivers/mfd/mc13xxx.h | |||
@@ -13,19 +13,24 @@ | |||
13 | #include <linux/regmap.h> | 13 | #include <linux/regmap.h> |
14 | #include <linux/mfd/mc13xxx.h> | 14 | #include <linux/mfd/mc13xxx.h> |
15 | 15 | ||
16 | enum mc13xxx_id { | 16 | #define MC13XXX_NUMREGS 0x3f |
17 | MC13XXX_ID_MC13783, | 17 | |
18 | MC13XXX_ID_MC13892, | 18 | struct mc13xxx; |
19 | MC13XXX_ID_INVALID, | 19 | |
20 | struct mc13xxx_variant { | ||
21 | const char *name; | ||
22 | void (*print_revision)(struct mc13xxx *mc13xxx, u32 revision); | ||
20 | }; | 23 | }; |
21 | 24 | ||
22 | #define MC13XXX_NUMREGS 0x3f | 25 | extern struct mc13xxx_variant |
26 | mc13xxx_variant_mc13783, | ||
27 | mc13xxx_variant_mc13892; | ||
23 | 28 | ||
24 | struct mc13xxx { | 29 | struct mc13xxx { |
25 | struct regmap *regmap; | 30 | struct regmap *regmap; |
26 | 31 | ||
27 | struct device *dev; | 32 | struct device *dev; |
28 | enum mc13xxx_id ictype; | 33 | const struct mc13xxx_variant *variant; |
29 | 34 | ||
30 | struct mutex lock; | 35 | struct mutex lock; |
31 | int irq; | 36 | int irq; |