Commit e5b486841d572c5ac83c798f82f4f67cbbac5320
Committed by
Samuel Ortiz
1 parent
00969f23da
Exists in
master
and in
7 other branches
mfd: Factor out WM831x I2C I/O from the core driver
In preparation for the addition of SPI support for the WM831x move the I2C specific code into a separate file with a separate Kconfig option so the I2C support can be excluded from the build. Also update the 1133-EV1 PMIC module support for SMDK6410 to use the new symbol. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 6 changed files with 171 additions and 139 deletions Side-by-side Diff
arch/arm/mach-s3c64xx/Kconfig
drivers/mfd/Kconfig
... | ... | @@ -315,14 +315,19 @@ |
315 | 315 | the functionality of the device. |
316 | 316 | |
317 | 317 | config MFD_WM831X |
318 | - bool "Support Wolfson Microelectronics WM831x/2x PMICs" | |
318 | + bool | |
319 | + depends on GENERIC_HARDIRQS | |
320 | + | |
321 | +config MFD_WM831X_I2C | |
322 | + bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C" | |
319 | 323 | select MFD_CORE |
324 | + select MFD_WM831X | |
320 | 325 | depends on I2C=y && GENERIC_HARDIRQS |
321 | 326 | help |
322 | - Support for the Wolfson Microelecronics WM831x and WM832x PMICs. | |
323 | - This driver provides common support for accessing the device, | |
324 | - additional drivers must be enabled in order to use the | |
325 | - functionality of the device. | |
327 | + Support for the Wolfson Microelecronics WM831x and WM832x PMICs | |
328 | + when controlled using I2C. This driver provides common support | |
329 | + for accessing the device, additional drivers must be enabled in | |
330 | + order to use the functionality of the device. | |
326 | 331 | |
327 | 332 | config MFD_WM8350 |
328 | 333 | bool |
drivers/mfd/Makefile
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | obj-$(CONFIG_MFD_WM8400) += wm8400-core.o |
25 | 25 | wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o |
26 | 26 | obj-$(CONFIG_MFD_WM831X) += wm831x.o |
27 | +obj-$(CONFIG_MFD_WM831X_I2C) += wm831x-i2c.o | |
27 | 28 | wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o |
28 | 29 | wm8350-objs += wm8350-irq.o |
29 | 30 | obj-$(CONFIG_MFD_WM8350) += wm8350.o |
drivers/mfd/wm831x-core.c
... | ... | @@ -14,7 +14,6 @@ |
14 | 14 | |
15 | 15 | #include <linux/kernel.h> |
16 | 16 | #include <linux/module.h> |
17 | -#include <linux/i2c.h> | |
18 | 17 | #include <linux/bcd.h> |
19 | 18 | #include <linux/delay.h> |
20 | 19 | #include <linux/mfd/core.h> |
... | ... | @@ -90,15 +89,6 @@ |
90 | 89 | }; |
91 | 90 | EXPORT_SYMBOL_GPL(wm831x_isinkv_values); |
92 | 91 | |
93 | -enum wm831x_parent { | |
94 | - WM8310 = 0x8310, | |
95 | - WM8311 = 0x8311, | |
96 | - WM8312 = 0x8312, | |
97 | - WM8320 = 0x8320, | |
98 | - WM8321 = 0x8321, | |
99 | - WM8325 = 0x8325, | |
100 | -}; | |
101 | - | |
102 | 92 | static int wm831x_reg_locked(struct wm831x *wm831x, unsigned short reg) |
103 | 93 | { |
104 | 94 | if (!wm831x->locked) |
... | ... | @@ -1447,7 +1437,7 @@ |
1447 | 1437 | /* |
1448 | 1438 | * Instantiate the generic non-control parts of the device. |
1449 | 1439 | */ |
1450 | -static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |
1440 | +int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |
1451 | 1441 | { |
1452 | 1442 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
1453 | 1443 | int rev; |
... | ... | @@ -1673,7 +1663,7 @@ |
1673 | 1663 | return ret; |
1674 | 1664 | } |
1675 | 1665 | |
1676 | -static void wm831x_device_exit(struct wm831x *wm831x) | |
1666 | +void wm831x_device_exit(struct wm831x *wm831x) | |
1677 | 1667 | { |
1678 | 1668 | wm831x_otp_exit(wm831x); |
1679 | 1669 | mfd_remove_devices(wm831x->dev); |
... | ... | @@ -1683,7 +1673,7 @@ |
1683 | 1673 | kfree(wm831x); |
1684 | 1674 | } |
1685 | 1675 | |
1686 | -static int wm831x_device_suspend(struct wm831x *wm831x) | |
1676 | +int wm831x_device_suspend(struct wm831x *wm831x) | |
1687 | 1677 | { |
1688 | 1678 | int reg, mask; |
1689 | 1679 | |
... | ... | @@ -1719,127 +1709,7 @@ |
1719 | 1709 | return 0; |
1720 | 1710 | } |
1721 | 1711 | |
1722 | -static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, | |
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 | - */ | |
1747 | -static 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], ®, 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 | - | |
1767 | -static 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 | - | |
1785 | -static 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 | - | |
1794 | -static 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 | - | |
1801 | -static 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 | -}; | |
1810 | -MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | |
1811 | - | |
1812 | - | |
1813 | -static 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 | - | |
1824 | -static 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 | -} | |
1834 | -subsys_initcall(wm831x_i2c_init); | |
1835 | - | |
1836 | -static void __exit wm831x_i2c_exit(void) | |
1837 | -{ | |
1838 | - i2c_del_driver(&wm831x_i2c_driver); | |
1839 | -} | |
1840 | -module_exit(wm831x_i2c_exit); | |
1841 | - | |
1842 | -MODULE_DESCRIPTION("I2C support for the WM831X AudioPlus PMIC"); | |
1712 | +MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC"); | |
1843 | 1713 | MODULE_LICENSE("GPL"); |
1844 | 1714 | MODULE_AUTHOR("Mark Brown"); |
drivers/mfd/wm831x-i2c.c
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 | + | |
25 | +static 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 | + */ | |
50 | +static 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], ®, 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 | + | |
70 | +static 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 | + | |
88 | +static 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 | + | |
97 | +static 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 | + | |
104 | +static 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 | +}; | |
113 | +MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id); | |
114 | + | |
115 | + | |
116 | +static 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 | + | |
127 | +static 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 | +} | |
137 | +subsys_initcall(wm831x_i2c_init); | |
138 | + | |
139 | +static void __exit wm831x_i2c_exit(void) | |
140 | +{ | |
141 | + i2c_del_driver(&wm831x_i2c_driver); | |
142 | +} | |
143 | +module_exit(wm831x_i2c_exit); |
include/linux/mfd/wm831x/core.h
... | ... | @@ -238,6 +238,15 @@ |
238 | 238 | |
239 | 239 | #define WM831X_NUM_IRQ_REGS 5 |
240 | 240 | |
241 | +enum wm831x_parent { | |
242 | + WM8310 = 0x8310, | |
243 | + WM8311 = 0x8311, | |
244 | + WM8312 = 0x8312, | |
245 | + WM8320 = 0x8320, | |
246 | + WM8321 = 0x8321, | |
247 | + WM8325 = 0x8325, | |
248 | +}; | |
249 | + | |
241 | 250 | struct wm831x { |
242 | 251 | struct mutex io_lock; |
243 | 252 | |
... | ... | @@ -285,6 +294,9 @@ |
285 | 294 | int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, |
286 | 295 | int count, u16 *buf); |
287 | 296 | |
297 | +int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq); | |
298 | +void wm831x_device_exit(struct wm831x *wm831x); | |
299 | +int wm831x_device_suspend(struct wm831x *wm831x); | |
288 | 300 | int wm831x_irq_init(struct wm831x *wm831x, int irq); |
289 | 301 | void wm831x_irq_exit(struct wm831x *wm831x); |
290 | 302 |