diff options
author | Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | 2017-03-17 06:05:18 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2017-03-23 07:45:50 -0400 |
commit | f6dd8449cd50de25881b76cecf1086bebeb11fe8 (patch) | |
tree | fa757139b73dc9a8e79e46952d93db19dd5e8068 | |
parent | c1ae3cfa0e89fa1a7ecc4c99031f5e9ae99d9201 (diff) |
mfd: wm831x: Add basic device tree binding
Add the basic ability to register the device through device tree, more
work is needed to get each individual sub-driver functioning correctly
but this is enough to get the device to probe from device tree.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r-- | drivers/mfd/wm831x-core.c | 29 | ||||
-rw-r--r-- | drivers/mfd/wm831x-i2c.c | 19 | ||||
-rw-r--r-- | drivers/mfd/wm831x-irq.c | 6 | ||||
-rw-r--r-- | drivers/mfd/wm831x-spi.c | 18 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/core.h | 9 |
5 files changed, 66 insertions, 15 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 3e0e99ec5836..13a4c1190dca 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
22 | 24 | ||
23 | #include <linux/mfd/wm831x/core.h> | 25 | #include <linux/mfd/wm831x/core.h> |
24 | #include <linux/mfd/wm831x/pdata.h> | 26 | #include <linux/mfd/wm831x/pdata.h> |
@@ -1613,12 +1615,24 @@ struct regmap_config wm831x_regmap_config = { | |||
1613 | }; | 1615 | }; |
1614 | EXPORT_SYMBOL_GPL(wm831x_regmap_config); | 1616 | EXPORT_SYMBOL_GPL(wm831x_regmap_config); |
1615 | 1617 | ||
1618 | const struct of_device_id wm831x_of_match[] = { | ||
1619 | { .compatible = "wlf,wm8310", .data = (void *)WM8310 }, | ||
1620 | { .compatible = "wlf,wm8311", .data = (void *)WM8311 }, | ||
1621 | { .compatible = "wlf,wm8312", .data = (void *)WM8312 }, | ||
1622 | { .compatible = "wlf,wm8320", .data = (void *)WM8320 }, | ||
1623 | { .compatible = "wlf,wm8321", .data = (void *)WM8321 }, | ||
1624 | { .compatible = "wlf,wm8325", .data = (void *)WM8325 }, | ||
1625 | { .compatible = "wlf,wm8326", .data = (void *)WM8326 }, | ||
1626 | { }, | ||
1627 | }; | ||
1628 | EXPORT_SYMBOL_GPL(wm831x_of_match); | ||
1629 | |||
1616 | /* | 1630 | /* |
1617 | * Instantiate the generic non-control parts of the device. | 1631 | * Instantiate the generic non-control parts of the device. |
1618 | */ | 1632 | */ |
1619 | int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | 1633 | int wm831x_device_init(struct wm831x *wm831x, int irq) |
1620 | { | 1634 | { |
1621 | struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); | 1635 | struct wm831x_pdata *pdata = &wm831x->pdata; |
1622 | int rev, wm831x_num; | 1636 | int rev, wm831x_num; |
1623 | enum wm831x_parent parent; | 1637 | enum wm831x_parent parent; |
1624 | int ret, i; | 1638 | int ret, i; |
@@ -1627,8 +1641,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1627 | mutex_init(&wm831x->key_lock); | 1641 | mutex_init(&wm831x->key_lock); |
1628 | dev_set_drvdata(wm831x->dev, wm831x); | 1642 | dev_set_drvdata(wm831x->dev, wm831x); |
1629 | 1643 | ||
1630 | if (pdata) | 1644 | wm831x->soft_shutdown = pdata->soft_shutdown; |
1631 | wm831x->soft_shutdown = pdata->soft_shutdown; | ||
1632 | 1645 | ||
1633 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); | 1646 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); |
1634 | if (ret < 0) { | 1647 | if (ret < 0) { |
@@ -1663,7 +1676,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1663 | */ | 1676 | */ |
1664 | if (ret == 0) { | 1677 | if (ret == 0) { |
1665 | dev_info(wm831x->dev, "Device is an engineering sample\n"); | 1678 | dev_info(wm831x->dev, "Device is an engineering sample\n"); |
1666 | ret = id; | 1679 | ret = wm831x->type; |
1667 | } | 1680 | } |
1668 | 1681 | ||
1669 | switch (ret) { | 1682 | switch (ret) { |
@@ -1736,9 +1749,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1736 | /* This will need revisiting in future but is OK for all | 1749 | /* This will need revisiting in future but is OK for all |
1737 | * current parts. | 1750 | * current parts. |
1738 | */ | 1751 | */ |
1739 | if (parent != id) | 1752 | if (parent != wm831x->type) |
1740 | dev_warn(wm831x->dev, "Device was registered as a WM%lx\n", | 1753 | dev_warn(wm831x->dev, "Device was registered as a WM%x\n", |
1741 | id); | 1754 | wm831x->type); |
1742 | 1755 | ||
1743 | /* Bootstrap the user key */ | 1756 | /* Bootstrap the user key */ |
1744 | ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY); | 1757 | ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY); |
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 824bcbaa9624..781af060f32d 100644 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
22 | #include <linux/regmap.h> | 24 | #include <linux/regmap.h> |
23 | 25 | ||
24 | #include <linux/mfd/wm831x/core.h> | 26 | #include <linux/mfd/wm831x/core.h> |
@@ -27,15 +29,26 @@ | |||
27 | static int wm831x_i2c_probe(struct i2c_client *i2c, | 29 | static int wm831x_i2c_probe(struct i2c_client *i2c, |
28 | const struct i2c_device_id *id) | 30 | const struct i2c_device_id *id) |
29 | { | 31 | { |
32 | struct wm831x_pdata *pdata = dev_get_platdata(&i2c->dev); | ||
33 | const struct of_device_id *of_id; | ||
30 | struct wm831x *wm831x; | 34 | struct wm831x *wm831x; |
35 | enum wm831x_parent type; | ||
31 | int ret; | 36 | int ret; |
32 | 37 | ||
38 | if (i2c->dev.of_node) { | ||
39 | of_id = of_match_device(wm831x_of_match, &i2c->dev); | ||
40 | type = (enum wm831x_parent)of_id->data; | ||
41 | } else { | ||
42 | type = (enum wm831x_parent)id->driver_data; | ||
43 | } | ||
44 | |||
33 | wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL); | 45 | wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL); |
34 | if (wm831x == NULL) | 46 | if (wm831x == NULL) |
35 | return -ENOMEM; | 47 | return -ENOMEM; |
36 | 48 | ||
37 | i2c_set_clientdata(i2c, wm831x); | 49 | i2c_set_clientdata(i2c, wm831x); |
38 | wm831x->dev = &i2c->dev; | 50 | wm831x->dev = &i2c->dev; |
51 | wm831x->type = type; | ||
39 | 52 | ||
40 | wm831x->regmap = devm_regmap_init_i2c(i2c, &wm831x_regmap_config); | 53 | wm831x->regmap = devm_regmap_init_i2c(i2c, &wm831x_regmap_config); |
41 | if (IS_ERR(wm831x->regmap)) { | 54 | if (IS_ERR(wm831x->regmap)) { |
@@ -45,7 +58,10 @@ static int wm831x_i2c_probe(struct i2c_client *i2c, | |||
45 | return ret; | 58 | return ret; |
46 | } | 59 | } |
47 | 60 | ||
48 | return wm831x_device_init(wm831x, id->driver_data, i2c->irq); | 61 | if (pdata) |
62 | memcpy(&wm831x->pdata, pdata, sizeof(*pdata)); | ||
63 | |||
64 | return wm831x_device_init(wm831x, i2c->irq); | ||
49 | } | 65 | } |
50 | 66 | ||
51 | static int wm831x_i2c_remove(struct i2c_client *i2c) | 67 | static int wm831x_i2c_remove(struct i2c_client *i2c) |
@@ -94,6 +110,7 @@ static struct i2c_driver wm831x_i2c_driver = { | |||
94 | .driver = { | 110 | .driver = { |
95 | .name = "wm831x", | 111 | .name = "wm831x", |
96 | .pm = &wm831x_pm_ops, | 112 | .pm = &wm831x_pm_ops, |
113 | .of_match_table = of_match_ptr(wm831x_of_match), | ||
97 | }, | 114 | }, |
98 | .probe = wm831x_i2c_probe, | 115 | .probe = wm831x_i2c_probe, |
99 | .remove = wm831x_i2c_remove, | 116 | .remove = wm831x_i2c_remove, |
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index dfea8b9c2fe6..c01239a600db 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -564,7 +564,7 @@ static const struct irq_domain_ops wm831x_irq_domain_ops = { | |||
564 | 564 | ||
565 | int wm831x_irq_init(struct wm831x *wm831x, int irq) | 565 | int wm831x_irq_init(struct wm831x *wm831x, int irq) |
566 | { | 566 | { |
567 | struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); | 567 | struct wm831x_pdata *pdata = &wm831x->pdata; |
568 | struct irq_domain *domain; | 568 | struct irq_domain *domain; |
569 | int i, ret, irq_base; | 569 | int i, ret, irq_base; |
570 | 570 | ||
@@ -579,7 +579,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
579 | } | 579 | } |
580 | 580 | ||
581 | /* Try to dynamically allocate IRQs if no base is specified */ | 581 | /* Try to dynamically allocate IRQs if no base is specified */ |
582 | if (pdata && pdata->irq_base) { | 582 | if (pdata->irq_base) { |
583 | irq_base = irq_alloc_descs(pdata->irq_base, 0, | 583 | irq_base = irq_alloc_descs(pdata->irq_base, 0, |
584 | WM831X_NUM_IRQS, 0); | 584 | WM831X_NUM_IRQS, 0); |
585 | if (irq_base < 0) { | 585 | if (irq_base < 0) { |
@@ -608,7 +608,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
608 | return -EINVAL; | 608 | return -EINVAL; |
609 | } | 609 | } |
610 | 610 | ||
611 | if (pdata && pdata->irq_cmos) | 611 | if (pdata->irq_cmos) |
612 | i = 0; | 612 | i = 0; |
613 | else | 613 | else |
614 | i = WM831X_IRQ_OD; | 614 | i = WM831X_IRQ_OD; |
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 80482aeb246a..c332e2885b26 100644 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
17 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
18 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
19 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
@@ -23,12 +25,19 @@ | |||
23 | 25 | ||
24 | static int wm831x_spi_probe(struct spi_device *spi) | 26 | static int wm831x_spi_probe(struct spi_device *spi) |
25 | { | 27 | { |
28 | struct wm831x_pdata *pdata = dev_get_platdata(&spi->dev); | ||
26 | const struct spi_device_id *id = spi_get_device_id(spi); | 29 | const struct spi_device_id *id = spi_get_device_id(spi); |
30 | const struct of_device_id *of_id; | ||
27 | struct wm831x *wm831x; | 31 | struct wm831x *wm831x; |
28 | enum wm831x_parent type; | 32 | enum wm831x_parent type; |
29 | int ret; | 33 | int ret; |
30 | 34 | ||
31 | type = (enum wm831x_parent)id->driver_data; | 35 | if (spi->dev.of_node) { |
36 | of_id = of_match_device(wm831x_of_match, &spi->dev); | ||
37 | type = (enum wm831x_parent)of_id->data; | ||
38 | } else { | ||
39 | type = (enum wm831x_parent)id->driver_data; | ||
40 | } | ||
32 | 41 | ||
33 | wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL); | 42 | wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL); |
34 | if (wm831x == NULL) | 43 | if (wm831x == NULL) |
@@ -38,6 +47,7 @@ static int wm831x_spi_probe(struct spi_device *spi) | |||
38 | 47 | ||
39 | spi_set_drvdata(spi, wm831x); | 48 | spi_set_drvdata(spi, wm831x); |
40 | wm831x->dev = &spi->dev; | 49 | wm831x->dev = &spi->dev; |
50 | wm831x->type = type; | ||
41 | 51 | ||
42 | wm831x->regmap = devm_regmap_init_spi(spi, &wm831x_regmap_config); | 52 | wm831x->regmap = devm_regmap_init_spi(spi, &wm831x_regmap_config); |
43 | if (IS_ERR(wm831x->regmap)) { | 53 | if (IS_ERR(wm831x->regmap)) { |
@@ -47,7 +57,10 @@ static int wm831x_spi_probe(struct spi_device *spi) | |||
47 | return ret; | 57 | return ret; |
48 | } | 58 | } |
49 | 59 | ||
50 | return wm831x_device_init(wm831x, type, spi->irq); | 60 | if (pdata) |
61 | memcpy(&wm831x->pdata, pdata, sizeof(*pdata)); | ||
62 | |||
63 | return wm831x_device_init(wm831x, spi->irq); | ||
51 | } | 64 | } |
52 | 65 | ||
53 | static int wm831x_spi_remove(struct spi_device *spi) | 66 | static int wm831x_spi_remove(struct spi_device *spi) |
@@ -97,6 +110,7 @@ static struct spi_driver wm831x_spi_driver = { | |||
97 | .driver = { | 110 | .driver = { |
98 | .name = "wm831x", | 111 | .name = "wm831x", |
99 | .pm = &wm831x_spi_pm, | 112 | .pm = &wm831x_spi_pm, |
113 | .of_match_table = of_match_ptr(wm831x_of_match), | ||
100 | }, | 114 | }, |
101 | .id_table = wm831x_spi_ids, | 115 | .id_table = wm831x_spi_ids, |
102 | .probe = wm831x_spi_probe, | 116 | .probe = wm831x_spi_probe, |
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 76c22648436f..b49fa67612f1 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
23 | #include <linux/mfd/wm831x/auxadc.h> | 23 | #include <linux/mfd/wm831x/auxadc.h> |
24 | #include <linux/mfd/wm831x/pdata.h> | ||
25 | #include <linux/of.h> | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * Register values. | 28 | * Register values. |
@@ -367,6 +369,9 @@ struct wm831x { | |||
367 | 369 | ||
368 | struct regmap *regmap; | 370 | struct regmap *regmap; |
369 | 371 | ||
372 | struct wm831x_pdata pdata; | ||
373 | enum wm831x_parent type; | ||
374 | |||
370 | int irq; /* Our chip IRQ */ | 375 | int irq; /* Our chip IRQ */ |
371 | struct mutex irq_lock; | 376 | struct mutex irq_lock; |
372 | struct irq_domain *irq_domain; | 377 | struct irq_domain *irq_domain; |
@@ -412,7 +417,7 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg, | |||
412 | int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, | 417 | int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, |
413 | int count, u16 *buf); | 418 | int count, u16 *buf); |
414 | 419 | ||
415 | int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq); | 420 | int wm831x_device_init(struct wm831x *wm831x, int irq); |
416 | void wm831x_device_exit(struct wm831x *wm831x); | 421 | void wm831x_device_exit(struct wm831x *wm831x); |
417 | int wm831x_device_suspend(struct wm831x *wm831x); | 422 | int wm831x_device_suspend(struct wm831x *wm831x); |
418 | void wm831x_device_shutdown(struct wm831x *wm831x); | 423 | void wm831x_device_shutdown(struct wm831x *wm831x); |
@@ -427,4 +432,6 @@ static inline int wm831x_irq(struct wm831x *wm831x, int irq) | |||
427 | 432 | ||
428 | extern struct regmap_config wm831x_regmap_config; | 433 | extern struct regmap_config wm831x_regmap_config; |
429 | 434 | ||
435 | extern const struct of_device_id wm831x_of_match[]; | ||
436 | |||
430 | #endif | 437 | #endif |