mfd: wm831x: add WM8326 support again
author黄涛 <huangtao@rock-chips.com>
Mon, 20 Feb 2012 09:46:43 +0000 (17:46 +0800)
committer黄涛 <huangtao@rock-chips.com>
Mon, 20 Feb 2012 09:46:43 +0000 (17:46 +0800)
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-spi.c
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h

index dd8c9d9b18812e5251e3c4f0ff12ce9c7e947da7..79139876a1ec697f34dacb4fe5db5b1582fede1f 100755 (executable)
@@ -1460,7 +1460,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
        int rev;
        enum wm831x_parent parent;
-       int ret;
+       int ret, i;
 
        mutex_init(&wm831x->io_lock);
        mutex_init(&wm831x->key_lock);
@@ -1473,7 +1473,11 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
                goto err;
        }
-       if (ret != 0x6204) {
+       switch (ret) {
+       case 0x6204:
+       case 0x6246:
+               break;
+       default:
                dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
                ret = -EINVAL;
                goto err;
@@ -1558,6 +1562,12 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
                break;
 
+       case WM8326:
+               parent = WM8326;
+               wm831x->num_gpio = 12;
+               dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
+               break;
+
        default:
                dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
                ret = -EINVAL;
@@ -1592,6 +1602,17 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                }
        }
 
+       if (pdata) {
+               for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+                       if (!pdata->gpio_defaults[i])
+                               continue;
+
+                       wm831x_reg_write(wm831x,
+                                        WM831X_GPIO1_CONTROL + i,
+                                        pdata->gpio_defaults[i] & 0xffff);
+               }
+       }
+
        ret = wm831x_irq_init(wm831x, irq);
        if (ret != 0)
                goto err;
@@ -1627,21 +1648,12 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                break;
 
        case WM8320:
-               ret = mfd_add_devices(wm831x->dev, -1,
-                                     wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, 0);
-               break;
-
        case WM8321:
-               ret = mfd_add_devices(wm831x->dev, -1,
-                                     wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, 0);
-               break;
-
        case WM8325:
+       case WM8326:
                ret = mfd_add_devices(wm831x->dev, -1,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, 0);
+                                     NULL, wm831x->irq_base);
                break;
 
        default:
index 9c840dcf1f04615bada2300defad902d00ea8552..1c9a5163616773b5f07b5dad53701115967db39e 100755 (executable)
@@ -110,16 +110,16 @@ static int wm831x_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
-static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
+static int wm831x_i2c_suspend(struct device *dev)
 {
-       struct wm831x *wm831x = i2c_get_clientdata(i2c);
+       struct wm831x *wm831x = dev_get_drvdata(dev);
 
        return wm831x_device_suspend(wm831x);
 }
 
-static int wm831x_i2c_resume(struct i2c_client *i2c)
+static int wm831x_i2c_resume(struct device *dev)
 {
-       struct wm831x *wm831x = i2c_get_clientdata(i2c);
+       struct wm831x *wm831x = dev_get_drvdata(dev);
        int i;
        //set some intterupt again while resume 
        for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
@@ -151,20 +151,24 @@ static const struct i2c_device_id wm831x_i2c_id[] = {
        { "wm8320", WM8320 },
        { "wm8321", WM8321 },
        { "wm8325", WM8325 },
+       { "wm8326", WM8326 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
 
+static const struct dev_pm_ops wm831x_pm_ops = {
+       .suspend = wm831x_i2c_suspend,
+       .resume = wm831x_i2c_resume,
+};
 
 static struct i2c_driver wm831x_i2c_driver = {
        .driver = {
-                  .name = "wm831x",
-                  .owner = THIS_MODULE,
+               .name = "wm831x",
+               .owner = THIS_MODULE,
+               .pm = &wm831x_pm_ops,
        },
        .probe = wm831x_i2c_probe,
        .remove = wm831x_i2c_remove,
-       .suspend = wm831x_i2c_suspend,
-       .resume = wm831x_i2c_resume,
        .shutdown = wm831x_i2c_shutdown,
        .id_table = wm831x_i2c_id,
 };
@@ -172,16 +176,16 @@ static struct i2c_driver wm831x_i2c_driver = {
 static int __init wm831x_i2c_init(void)
 {
        int ret;
-       printk("%s \n", __FUNCTION__);
+
+       printk("%s\n", __FUNCTION__);
        ret = i2c_add_driver(&wm831x_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register wm831x I2C driver: %d\n", ret);
 
        return ret;
 }
-//subsys_initcall(wm831x_i2c_init);
-//fs_initcall(wm831x_i2c_init);
 subsys_initcall_sync(wm831x_i2c_init);
+
 static void __exit wm831x_i2c_exit(void)
 {
        i2c_del_driver(&wm831x_i2c_driver);
index 5635be1c96222998ae8650962bcf4fc49184fcf8..2411ea55c21ce1637a8d7723d3f240eb40301b44 100755 (executable)
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/spi/spi.h>
 #include <linux/gpio.h>
 
-
 #include <linux/mfd/wm831x/core.h>
 
 static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
@@ -84,6 +84,8 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
                type = WM8321;
        else if (strcmp(spi->modalias, "wm8325") == 0)
                type = WM8325;
+       else if (strcmp(spi->modalias, "wm8326") == 0)
+               type = WM8326;
        else {
                dev_err(&spi->dev, "Unknown device type\n");
                return -EINVAL;
@@ -127,24 +129,30 @@ static int __devexit wm831x_spi_remove(struct spi_device *spi)
        return 0;
 }
 
-static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+static int wm831x_spi_suspend(struct device *dev)
 {
-       struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+       struct wm831x *wm831x = dev_get_drvdata(dev);
+
        spin_lock(&wm831x->flag_lock);
        wm831x->flag_suspend = 1;
        spin_unlock(&wm831x->flag_lock);
        return wm831x_device_suspend(wm831x);
 }
 
+static const struct dev_pm_ops wm831x_spi_pm = {
+       .freeze = wm831x_spi_suspend,
+       .suspend = wm831x_spi_suspend,
+};
+
 static struct spi_driver wm8310_spi_driver = {
        .driver = {
                .name   = "wm8310",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8311_spi_driver = {
@@ -152,10 +160,10 @@ static struct spi_driver wm8311_spi_driver = {
                .name   = "wm8311",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8312_spi_driver = {
@@ -163,10 +171,10 @@ static struct spi_driver wm8312_spi_driver = {
                .name   = "wm8312",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8320_spi_driver = {
@@ -174,10 +182,10 @@ static struct spi_driver wm8320_spi_driver = {
                .name   = "wm8320",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8321_spi_driver = {
@@ -185,10 +193,10 @@ static struct spi_driver wm8321_spi_driver = {
                .name   = "wm8321",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8325_spi_driver = {
@@ -196,10 +204,21 @@ static struct spi_driver wm8325_spi_driver = {
                .name   = "wm8325",
                .bus    = &spi_bus_type,
                .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
+       },
+       .probe          = wm831x_spi_probe,
+       .remove         = __devexit_p(wm831x_spi_remove),
+};
+
+static struct spi_driver wm8326_spi_driver = {
+       .driver = {
+               .name   = "wm8326",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+               .pm     = &wm831x_spi_pm,
        },
        .probe          = wm831x_spi_probe,
        .remove         = __devexit_p(wm831x_spi_remove),
-       .suspend        = wm831x_spi_suspend,
 };
 
 static int __init wm831x_spi_init(void)
@@ -230,12 +249,17 @@ static int __init wm831x_spi_init(void)
        if (ret != 0)
                pr_err("Failed to register WM8325 SPI driver: %d\n", ret);
 
+       ret = spi_register_driver(&wm8326_spi_driver);
+       if (ret != 0)
+               pr_err("Failed to register WM8326 SPI driver: %d\n", ret);
+
        return 0;
 }
 subsys_initcall(wm831x_spi_init);
 
 static void __exit wm831x_spi_exit(void)
 {
+       spi_unregister_driver(&wm8326_spi_driver);
        spi_unregister_driver(&wm8325_spi_driver);
        spi_unregister_driver(&wm8321_spi_driver);
        spi_unregister_driver(&wm8320_spi_driver);
index b702517a76bc091cb2e1efb9732c9d5e40c64fc7..e7efae4eb4afc815bfc9ac06ac1d554bc3fc6348 100755 (executable)
@@ -240,6 +240,7 @@ struct regulator_dev;
 
 #define WM831X_NUM_IRQ_REGS 5
 #define WM831X_IRQ_LIST        1
+
 enum wm831x_parent {
        WM8310 = 0x8310,
        WM8311 = 0x8311,
@@ -247,6 +248,7 @@ enum wm831x_parent {
        WM8320 = 0x8320,
        WM8321 = 0x8321,
        WM8325 = 0x8325,
+       WM8326 = 0x8326,
 };
 
 struct wm831x {
index 92cefe8721e1f501044c1a7bb7e48595fcf37f65..4fd658079c0df91f17a0e0eb0e8a30d658d4c4e9 100755 (executable)
@@ -82,7 +82,10 @@ struct wm831x_touch_pdata {
        int isel;              /** Current for pen down (uA) */
        int rpu;               /** Pen down sensitivity resistor divider */
        int pressure;          /** Report pressure (boolean) */
-       int data_irq;          /** Touch data ready IRQ */
+       unsigned int data_irq; /** Touch data ready IRQ */
+       int data_irqf;         /** IRQ flags for data ready IRQ */
+       unsigned int pd_irq;   /** Touch pendown detect IRQ */
+       int pd_irqf;           /** IRQ flags for pen down IRQ */
 };
 
 enum wm831x_watchdog_action {
@@ -120,7 +123,13 @@ struct wm831x_gpio_keys_pdata {
 #define WM831X_MAX_LDO    11
 #define WM831X_MAX_ISINK  2
 
+#define WM831X_GPIO_CONFIGURE 0x10000
+#define WM831X_GPIO_NUM 16
+
 struct wm831x_pdata {
+       /** Used to distinguish multiple WM831x chips */
+       int wm831x_num;
+
        /** Called before subdevices are set up */
        int (*pre_init)(struct wm831x *wm831x);
        /** Called after subdevices are set up */
@@ -133,8 +142,13 @@ struct wm831x_pdata {
        int  settinginfolen;    
        int (*pin_type_init)(struct wm831x *wm831x);    
        //above add by sxj
+
+       /** Put the /IRQ line into CMOS mode */
+       bool irq_cmos;
+
        int irq_base;
        int gpio_base;
+       int gpio_defaults[WM831X_GPIO_NUM];
        struct wm831x_backlight_pdata *backlight;
        struct wm831x_backup_pdata *backup;
        struct wm831x_battery_pdata *battery;