aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c64xx/Kconfig1
-rw-r--r--drivers/mfd/Kconfig15
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/wm831x-core.c138
-rw-r--r--drivers/mfd/wm831x-i2c.c143
-rw-r--r--include/linux/mfd/wm831x/core.h12
6 files changed, 171 insertions, 139 deletions
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 1e4d78af7d84..546db5cb8929 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -185,6 +185,7 @@ config SMDK6410_WM1192_EV1
185 select REGULATOR_WM831X 185 select REGULATOR_WM831X
186 select S3C24XX_GPIO_EXTRA64 186 select S3C24XX_GPIO_EXTRA64
187 select MFD_WM831X 187 select MFD_WM831X
188 select MFD_WM831X_I2C
188 help 189 help
189 The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC 190 The Wolfson Microelectronics 1192-EV1 is a WM831x based PMIC
190 daughtercard for the Samsung SMDK6410 reference platform. 191 daughtercard for the Samsung SMDK6410 reference platform.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6c6b9f02d177..2fb1e892331c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -315,14 +315,19 @@ config MFD_WM8400
315 the functionality of the device. 315 the functionality of the device.
316 316
317config MFD_WM831X 317config MFD_WM831X
318 bool "Support Wolfson Microelectronics WM831x/2x PMICs" 318 bool
319 depends on GENERIC_HARDIRQS
320
321config MFD_WM831X_I2C
322 bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
319 select MFD_CORE 323 select MFD_CORE
324 select MFD_WM831X
320 depends on I2C=y && GENERIC_HARDIRQS 325 depends on I2C=y && GENERIC_HARDIRQS
321 help 326 help
322 Support for the Wolfson Microelecronics WM831x and WM832x PMICs. 327 Support for the Wolfson Microelecronics WM831x and WM832x PMICs
323 This driver provides common support for accessing the device, 328 when controlled using I2C. This driver provides common support
324 additional drivers must be enabled in order to use the 329 for accessing the device, additional drivers must be enabled in
325 functionality of the device. 330 order to use the functionality of the device.
326 331
327config MFD_WM8350 332config MFD_WM8350
328 bool 333 bool
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 70b26999dc81..c9ef41b13bf3 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
24obj-$(CONFIG_MFD_WM8400) += wm8400-core.o 24obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
25wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o 25wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
26obj-$(CONFIG_MFD_WM831X) += wm831x.o 26obj-$(CONFIG_MFD_WM831X) += wm831x.o
27obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o
27wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o 28wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
28wm8350-objs += wm8350-irq.o 29wm8350-objs += wm8350-irq.o
29obj-$(CONFIG_MFD_WM8350) += wm8350.o 30obj-$(CONFIG_MFD_WM8350) += wm8350.o
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index ad36579bc815..7d2563fc15c6 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -14,7 +14,6 @@
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/i2c.h>
18#include <linux/bcd.h> 17#include <linux/bcd.h>
19#include <linux/delay.h> 18#include <linux/delay.h>
20#include <linux/mfd/core.h> 19#include <linux/mfd/core.h>
@@ -90,15 +89,6 @@ int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
90}; 89};
91EXPORT_SYMBOL_GPL(wm831x_isinkv_values); 90EXPORT_SYMBOL_GPL(wm831x_isinkv_values);
92 91
93enum wm831x_parent {
94 WM8310 = 0x8310,
95 WM8311 = 0x8311,
96 WM8312 = 0x8312,
97 WM8320 = 0x8320,
98 WM8321 = 0x8321,
99 WM8325 = 0x8325,
100};
101
102static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) 92static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg)
103{ 93{
104 if (!wm831x->locked) 94 if (!wm831x->locked)
@@ -1447,7 +1437,7 @@ static struct mfd_cell backlight_devs[] = {
1447/* 1437/*
1448 * Instantiate the generic non-control parts of the device. 1438 * Instantiate the generic non-control parts of the device.
1449 */ 1439 */
1450static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) 1440int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1451{ 1441{
1452 struct wm831x_pdata *pdata = wm831x->dev->platform_data; 1442 struct wm831x_pdata *pdata = wm831x->dev->platform_data;
1453 int rev; 1443 int rev;
@@ -1673,7 +1663,7 @@ err:
1673 return ret; 1663 return ret;
1674} 1664}
1675 1665
1676static void wm831x_device_exit(struct wm831x *wm831x) 1666void wm831x_device_exit(struct wm831x *wm831x)
1677{ 1667{
1678 wm831x_otp_exit(wm831x); 1668 wm831x_otp_exit(wm831x);
1679 mfd_remove_devices(wm831x->dev); 1669 mfd_remove_devices(wm831x->dev);
@@ -1683,7 +1673,7 @@ static void wm831x_device_exit(struct wm831x *wm831x)
1683 kfree(wm831x); 1673 kfree(wm831x);
1684} 1674}
1685 1675
1686static int wm831x_device_suspend(struct wm831x *wm831x) 1676int wm831x_device_suspend(struct wm831x *wm831x)
1687{ 1677{
1688 int reg, mask; 1678 int reg, mask;
1689 1679
@@ -1719,126 +1709,6 @@ static int wm831x_device_suspend(struct wm831x *wm831x)
1719 return 0; 1709 return 0;
1720} 1710}
1721 1711
1722static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, 1712MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
1723 int bytes, void *dest)
1724{
1725 struct i2c_client *i2c = wm831x->control_data;
1726 int ret;
1727 u16 r = cpu_to_be16(reg);
1728
1729 ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
1730 if (ret < 0)
1731 return ret;
1732 if (ret != 2)
1733 return -EIO;
1734
1735 ret = i2c_master_recv(i2c, dest, bytes);
1736 if (ret < 0)
1737 return ret;
1738 if (ret != bytes)
1739 return -EIO;
1740 return 0;
1741}
1742
1743/* Currently we allocate the write buffer on the stack; this is OK for
1744 * small writes - if we need to do large writes this will need to be
1745 * revised.
1746 */
1747static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
1748 int bytes, void *src)
1749{
1750 struct i2c_client *i2c = wm831x->control_data;
1751 unsigned char msg[bytes + 2];
1752 int ret;
1753
1754 reg = cpu_to_be16(reg);
1755 memcpy(&msg[0], &reg, 2);
1756 memcpy(&msg[2], src, bytes);
1757
1758 ret = i2c_master_send(i2c, msg, bytes + 2);
1759 if (ret < 0)
1760 return ret;
1761 if (ret < bytes + 2)
1762 return -EIO;
1763
1764 return 0;
1765}
1766
1767static int wm831x_i2c_probe(struct i2c_client *i2c,
1768 const struct i2c_device_id *id)
1769{
1770 struct wm831x *wm831x;
1771
1772 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
1773 if (wm831x == NULL)
1774 return -ENOMEM;
1775
1776 i2c_set_clientdata(i2c, wm831x);
1777 wm831x->dev = &i2c->dev;
1778 wm831x->control_data = i2c;
1779 wm831x->read_dev = wm831x_i2c_read_device;
1780 wm831x->write_dev = wm831x_i2c_write_device;
1781
1782 return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
1783}
1784
1785static int wm831x_i2c_remove(struct i2c_client *i2c)
1786{
1787 struct wm831x *wm831x = i2c_get_clientdata(i2c);
1788
1789 wm831x_device_exit(wm831x);
1790
1791 return 0;
1792}
1793
1794static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
1795{
1796 struct wm831x *wm831x = i2c_get_clientdata(i2c);
1797
1798 return wm831x_device_suspend(wm831x);
1799}
1800
1801static const struct i2c_device_id wm831x_i2c_id[] = {
1802 { "wm8310", WM8310 },
1803 { "wm8311", WM8311 },
1804 { "wm8312", WM8312 },
1805 { "wm8320", WM8320 },
1806 { "wm8321", WM8321 },
1807 { "wm8325", WM8325 },
1808 { }
1809};
1810MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
1811
1812
1813static struct i2c_driver wm831x_i2c_driver = {
1814 .driver = {
1815 .name = "wm831x",
1816 .owner = THIS_MODULE,
1817 },
1818 .probe = wm831x_i2c_probe,
1819 .remove = wm831x_i2c_remove,
1820 .suspend = wm831x_i2c_suspend,
1821 .id_table = wm831x_i2c_id,
1822};
1823
1824static int __init wm831x_i2c_init(void)
1825{
1826 int ret;
1827
1828 ret = i2c_add_driver(&wm831x_i2c_driver);
1829 if (ret != 0)
1830 pr_err("Failed to register wm831x I2C driver: %d\n", ret);
1831
1832 return ret;
1833}
1834subsys_initcall(wm831x_i2c_init);
1835
1836static void __exit wm831x_i2c_exit(void)
1837{
1838 i2c_del_driver(&wm831x_i2c_driver);
1839}
1840module_exit(wm831x_i2c_exit);
1841
1842MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC");
1843MODULE_LICENSE("GPL"); 1713MODULE_LICENSE("GPL");
1844MODULE_AUTHOR("Mark Brown"); 1714MODULE_AUTHOR("Mark Brown");
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
new file mode 100644
index 000000000000..156b19859e81
--- /dev/null
+++ b/drivers/mfd/wm831x-i2c.c
@@ -0,0 +1,143 @@
1/*
2 * wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs
3 *
4 * Copyright 2009,2010 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/i2c.h>
18#include <linux/delay.h>
19#include <linux/mfd/core.h>
20#include <linux/slab.h>
21
22#include <linux/mfd/wm831x/core.h>
23#include <linux/mfd/wm831x/pdata.h>
24
25static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg,
26 int bytes, void *dest)
27{
28 struct i2c_client *i2c = wm831x->control_data;
29 int ret;
30 u16 r = cpu_to_be16(reg);
31
32 ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
33 if (ret < 0)
34 return ret;
35 if (ret != 2)
36 return -EIO;
37
38 ret = i2c_master_recv(i2c, dest, bytes);
39 if (ret < 0)
40 return ret;
41 if (ret != bytes)
42 return -EIO;
43 return 0;
44}
45
46/* Currently we allocate the write buffer on the stack; this is OK for
47 * small writes - if we need to do large writes this will need to be
48 * revised.
49 */
50static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
51 int bytes, void *src)
52{
53 struct i2c_client *i2c = wm831x->control_data;
54 unsigned char msg[bytes + 2];
55 int ret;
56
57 reg = cpu_to_be16(reg);
58 memcpy(&msg[0], &reg, 2);
59 memcpy(&msg[2], src, bytes);
60
61 ret = i2c_master_send(i2c, msg, bytes + 2);
62 if (ret < 0)
63 return ret;
64 if (ret < bytes + 2)
65 return -EIO;
66
67 return 0;
68}
69
70static int wm831x_i2c_probe(struct i2c_client *i2c,
71 const struct i2c_device_id *id)
72{
73 struct wm831x *wm831x;
74
75 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
76 if (wm831x == NULL)
77 return -ENOMEM;
78
79 i2c_set_clientdata(i2c, wm831x);
80 wm831x->dev = &i2c->dev;
81 wm831x->control_data = i2c;
82 wm831x->read_dev = wm831x_i2c_read_device;
83 wm831x->write_dev = wm831x_i2c_write_device;
84
85 return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
86}
87
88static int wm831x_i2c_remove(struct i2c_client *i2c)
89{
90 struct wm831x *wm831x = i2c_get_clientdata(i2c);
91
92 wm831x_device_exit(wm831x);
93
94 return 0;
95}
96
97static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
98{
99 struct wm831x *wm831x = i2c_get_clientdata(i2c);
100
101 return wm831x_device_suspend(wm831x);
102}
103
104static const struct i2c_device_id wm831x_i2c_id[] = {
105 { "wm8310", WM8310 },
106 { "wm8311", WM8311 },
107 { "wm8312", WM8312 },
108 { "wm8320", WM8320 },
109 { "wm8321", WM8321 },
110 { "wm8325", WM8325 },
111 { }
112};
113MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
114
115
116static struct i2c_driver wm831x_i2c_driver = {
117 .driver = {
118 .name = "wm831x",
119 .owner = THIS_MODULE,
120 },
121 .probe = wm831x_i2c_probe,
122 .remove = wm831x_i2c_remove,
123 .suspend = wm831x_i2c_suspend,
124 .id_table = wm831x_i2c_id,
125};
126
127static int __init wm831x_i2c_init(void)
128{
129 int ret;
130
131 ret = i2c_add_driver(&wm831x_i2c_driver);
132 if (ret != 0)
133 pr_err("Failed to register wm831x I2C driver: %d\n", ret);
134
135 return ret;
136}
137subsys_initcall(wm831x_i2c_init);
138
139static void __exit wm831x_i2c_exit(void)
140{
141 i2c_del_driver(&wm831x_i2c_driver);
142}
143module_exit(wm831x_i2c_exit);
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index eb5bd4e0e03c..a1239c48b41a 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -238,6 +238,15 @@ struct regulator_dev;
238 238
239#define WM831X_NUM_IRQ_REGS 5 239#define WM831X_NUM_IRQ_REGS 5
240 240
241enum wm831x_parent {
242 WM8310 = 0x8310,
243 WM8311 = 0x8311,
244 WM8312 = 0x8312,
245 WM8320 = 0x8320,
246 WM8321 = 0x8321,
247 WM8325 = 0x8325,
248};
249
241struct wm831x { 250struct wm831x {
242 struct mutex io_lock; 251 struct mutex io_lock;
243 252
@@ -285,6 +294,9 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
285int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, 294int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
286 int count, u16 *buf); 295 int count, u16 *buf);
287 296
297int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
298void wm831x_device_exit(struct wm831x *wm831x);
299int wm831x_device_suspend(struct wm831x *wm831x);
288int wm831x_irq_init(struct wm831x *wm831x, int irq); 300int wm831x_irq_init(struct wm831x *wm831x, int irq);
289void wm831x_irq_exit(struct wm831x *wm831x); 301void wm831x_irq_exit(struct wm831x *wm831x);
290 302