mfd: wm831x: Add basic device tree binding
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Fri, 17 Mar 2017 10:05:18 +0000 (10:05 +0000)
committerLee Jones <lee.jones@linaro.org>
Thu, 23 Mar 2017 11:45:50 +0000 (11:45 +0000)
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>
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm831x-spi.c
include/linux/mfd/wm831x/core.h

index 3e0e99e..13a4c11 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
@@ -1613,12 +1615,24 @@ struct regmap_config wm831x_regmap_config = {
 };
 EXPORT_SYMBOL_GPL(wm831x_regmap_config);
 
+const struct of_device_id wm831x_of_match[] = {
+       { .compatible = "wlf,wm8310", .data = (void *)WM8310 },
+       { .compatible = "wlf,wm8311", .data = (void *)WM8311 },
+       { .compatible = "wlf,wm8312", .data = (void *)WM8312 },
+       { .compatible = "wlf,wm8320", .data = (void *)WM8320 },
+       { .compatible = "wlf,wm8321", .data = (void *)WM8321 },
+       { .compatible = "wlf,wm8325", .data = (void *)WM8325 },
+       { .compatible = "wlf,wm8326", .data = (void *)WM8326 },
+       { },
+};
+EXPORT_SYMBOL_GPL(wm831x_of_match);
+
 /*
  * Instantiate the generic non-control parts of the device.
  */
-int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
+int wm831x_device_init(struct wm831x *wm831x, int irq)
 {
-       struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
+       struct wm831x_pdata *pdata = &wm831x->pdata;
        int rev, wm831x_num;
        enum wm831x_parent parent;
        int ret, i;
@@ -1627,8 +1641,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        mutex_init(&wm831x->key_lock);
        dev_set_drvdata(wm831x->dev, wm831x);
 
-       if (pdata)
-               wm831x->soft_shutdown = pdata->soft_shutdown;
+       wm831x->soft_shutdown = pdata->soft_shutdown;
 
        ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
        if (ret < 0) {
@@ -1663,7 +1676,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
         */
        if (ret == 0) {
                dev_info(wm831x->dev, "Device is an engineering sample\n");
-               ret = id;
+               ret = wm831x->type;
        }
 
        switch (ret) {
@@ -1736,9 +1749,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        /* This will need revisiting in future but is OK for all
         * current parts.
         */
-       if (parent != id)
-               dev_warn(wm831x->dev, "Device was registered as a WM%lx\n",
-                        id);
+       if (parent != wm831x->type)
+               dev_warn(wm831x->dev, "Device was registered as a WM%x\n",
+                        wm831x->type);
 
        /* Bootstrap the user key */
        ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
index 824bcba..781af06 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/regmap.h>
 
 #include <linux/mfd/wm831x/core.h>
 static int wm831x_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
+       struct wm831x_pdata *pdata = dev_get_platdata(&i2c->dev);
+       const struct of_device_id *of_id;
        struct wm831x *wm831x;
+       enum wm831x_parent type;
        int ret;
 
+       if (i2c->dev.of_node) {
+               of_id = of_match_device(wm831x_of_match, &i2c->dev);
+               type = (enum wm831x_parent)of_id->data;
+       } else {
+               type = (enum wm831x_parent)id->driver_data;
+       }
+
        wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL);
        if (wm831x == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm831x);
        wm831x->dev = &i2c->dev;
+       wm831x->type = type;
 
        wm831x->regmap = devm_regmap_init_i2c(i2c, &wm831x_regmap_config);
        if (IS_ERR(wm831x->regmap)) {
@@ -45,7 +58,10 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
+       if (pdata)
+               memcpy(&wm831x->pdata, pdata, sizeof(*pdata));
+
+       return wm831x_device_init(wm831x, i2c->irq);
 }
 
 static int wm831x_i2c_remove(struct i2c_client *i2c)
@@ -94,6 +110,7 @@ static struct i2c_driver wm831x_i2c_driver = {
        .driver = {
                .name = "wm831x",
                .pm = &wm831x_pm_ops,
+               .of_match_table = of_match_ptr(wm831x_of_match),
        },
        .probe = wm831x_i2c_probe,
        .remove = wm831x_i2c_remove,
index dfea8b9..c01239a 100644 (file)
@@ -564,7 +564,7 @@ static const struct irq_domain_ops wm831x_irq_domain_ops = {
 
 int wm831x_irq_init(struct wm831x *wm831x, int irq)
 {
-       struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev);
+       struct wm831x_pdata *pdata = &wm831x->pdata;
        struct irq_domain *domain;
        int i, ret, irq_base;
 
@@ -579,7 +579,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
        }
 
        /* Try to dynamically allocate IRQs if no base is specified */
-       if (pdata && pdata->irq_base) {
+       if (pdata->irq_base) {
                irq_base = irq_alloc_descs(pdata->irq_base, 0,
                                           WM831X_NUM_IRQS, 0);
                if (irq_base < 0) {
@@ -608,7 +608,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                return -EINVAL;
        }
 
-       if (pdata && pdata->irq_cmos)
+       if (pdata->irq_cmos)
                i = 0;
        else
                i = WM831X_IRQ_OD;
index 80482ae..c332e28 100644 (file)
@@ -14,6 +14,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
 #include <linux/regmap.h>
 
 static int wm831x_spi_probe(struct spi_device *spi)
 {
+       struct wm831x_pdata *pdata = dev_get_platdata(&spi->dev);
        const struct spi_device_id *id = spi_get_device_id(spi);
+       const struct of_device_id *of_id;
        struct wm831x *wm831x;
        enum wm831x_parent type;
        int ret;
 
-       type = (enum wm831x_parent)id->driver_data;
+       if (spi->dev.of_node) {
+               of_id = of_match_device(wm831x_of_match, &spi->dev);
+               type = (enum wm831x_parent)of_id->data;
+       } else {
+               type = (enum wm831x_parent)id->driver_data;
+       }
 
        wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL);
        if (wm831x == NULL)
@@ -38,6 +47,7 @@ static int wm831x_spi_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, wm831x);
        wm831x->dev = &spi->dev;
+       wm831x->type = type;
 
        wm831x->regmap = devm_regmap_init_spi(spi, &wm831x_regmap_config);
        if (IS_ERR(wm831x->regmap)) {
@@ -47,7 +57,10 @@ static int wm831x_spi_probe(struct spi_device *spi)
                return ret;
        }
 
-       return wm831x_device_init(wm831x, type, spi->irq);
+       if (pdata)
+               memcpy(&wm831x->pdata, pdata, sizeof(*pdata));
+
+       return wm831x_device_init(wm831x, spi->irq);
 }
 
 static int wm831x_spi_remove(struct spi_device *spi)
@@ -97,6 +110,7 @@ static struct spi_driver wm831x_spi_driver = {
        .driver = {
                .name   = "wm831x",
                .pm     = &wm831x_spi_pm,
+               .of_match_table = of_match_ptr(wm831x_of_match),
        },
        .id_table       = wm831x_spi_ids,
        .probe          = wm831x_spi_probe,
index 76c2264..b49fa67 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/list.h>
 #include <linux/regmap.h>
 #include <linux/mfd/wm831x/auxadc.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/of.h>
 
 /*
  * Register values.
@@ -367,6 +369,9 @@ struct wm831x {
 
        struct regmap *regmap;
 
+       struct wm831x_pdata pdata;
+       enum wm831x_parent type;
+
        int irq;  /* Our chip IRQ */
        struct mutex irq_lock;
        struct irq_domain *irq_domain;
@@ -412,7 +417,7 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
 int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
                     int count, u16 *buf);
 
-int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
+int wm831x_device_init(struct wm831x *wm831x, int irq);
 void wm831x_device_exit(struct wm831x *wm831x);
 int wm831x_device_suspend(struct wm831x *wm831x);
 void wm831x_device_shutdown(struct wm831x *wm831x);
@@ -427,4 +432,6 @@ static inline int wm831x_irq(struct wm831x *wm831x, int irq)
 
 extern struct regmap_config wm831x_regmap_config;
 
+extern const struct of_device_id wm831x_of_match[];
+
 #endif