From 4534f165f626890f14e89cf13eb0c0e1bac88dd7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Mon, 20 Feb 2012 17:46:43 +0800 Subject: [PATCH] mfd: wm831x: add WM8326 support again --- drivers/mfd/wm831x-core.c | 38 +++++++++++++++++++---------- drivers/mfd/wm831x-i2c.c | 26 +++++++++++--------- drivers/mfd/wm831x-spi.c | 42 +++++++++++++++++++++++++------- include/linux/mfd/wm831x/core.h | 2 ++ include/linux/mfd/wm831x/pdata.h | 16 +++++++++++- 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index dd8c9d9b1881..79139876a1ec 100755 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -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: diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c index 9c840dcf1f04..1c9a51636167 100755 --- a/drivers/mfd/wm831x-i2c.c +++ b/drivers/mfd/wm831x-i2c.c @@ -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); diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 5635be1c9622..2411ea55c21c 100755 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c @@ -14,10 +14,10 @@ #include #include +#include #include #include - #include 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); diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index b702517a76bc..e7efae4eb4af 100755 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -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 { diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h index 92cefe8721e1..4fd658079c0d 100755 --- a/include/linux/mfd/wm831x/pdata.h +++ b/include/linux/mfd/wm831x/pdata.h @@ -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; -- 2.34.1