aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-06-10 14:28:10 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-08-22 07:23:22 -0400
commit1df5981b82d9eabdd6e66d1d9514164c02329345 (patch)
treec5fc2653d70a884d42957b2c7bc0c8cd49d8b895 /drivers
parentbd20eb541ebbb17a5e047cd20e74b9ccf19a4123 (diff)
mfd: Convert WM831x to use regmap API
Factor out the register read/write code to use the register map API. We still need some wm831x specific code and locking in place to check that the user key is handled correctly but only on the write side, reads are not affected by the key. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/Kconfig2
-rw-r--r--drivers/mfd/wm831x-core.c89
-rw-r--r--drivers/mfd/wm831x-i2c.c68
-rw-r--r--drivers/mfd/wm831x-spi.c60
4 files changed, 54 insertions, 165 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 21574bdf485f..cfae5c594d24 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -404,6 +404,7 @@ config MFD_WM831X_I2C
404 bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C" 404 bool "Support Wolfson Microelectronics WM831x/2x PMICs with I2C"
405 select MFD_CORE 405 select MFD_CORE
406 select MFD_WM831X 406 select MFD_WM831X
407 select REGMAP_I2C
407 depends on I2C=y && GENERIC_HARDIRQS 408 depends on I2C=y && GENERIC_HARDIRQS
408 help 409 help
409 Support for the Wolfson Microelecronics WM831x and WM832x PMICs 410 Support for the Wolfson Microelecronics WM831x and WM832x PMICs
@@ -415,6 +416,7 @@ config MFD_WM831X_SPI
415 bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI" 416 bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI"
416 select MFD_CORE 417 select MFD_CORE
417 select MFD_WM831X 418 select MFD_WM831X
419 select REGMAP_SPI
418 depends on SPI_MASTER && GENERIC_HARDIRQS 420 depends on SPI_MASTER && GENERIC_HARDIRQS
419 help 421 help
420 Support for the Wolfson Microelecronics WM831x and WM832x PMICs 422 Support for the Wolfson Microelecronics WM831x and WM832x PMICs
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 282e76ab678f..578e0c2ad82b 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -18,6 +18,7 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/mfd/core.h> 19#include <linux/mfd/core.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/err.h>
21 22
22#include <linux/mfd/wm831x/core.h> 23#include <linux/mfd/wm831x/core.h>
23#include <linux/mfd/wm831x/pdata.h> 24#include <linux/mfd/wm831x/pdata.h>
@@ -160,29 +161,6 @@ int wm831x_reg_unlock(struct wm831x *wm831x)
160} 161}
161EXPORT_SYMBOL_GPL(wm831x_reg_unlock); 162EXPORT_SYMBOL_GPL(wm831x_reg_unlock);
162 163
163static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
164 int bytes, void *dest)
165{
166 int ret, i;
167 u16 *buf = dest;
168
169 BUG_ON(bytes % 2);
170 BUG_ON(bytes <= 0);
171
172 ret = wm831x->read_dev(wm831x, reg, bytes, dest);
173 if (ret < 0)
174 return ret;
175
176 for (i = 0; i < bytes / 2; i++) {
177 buf[i] = be16_to_cpu(buf[i]);
178
179 dev_vdbg(wm831x->dev, "Read %04x from R%d(0x%x)\n",
180 buf[i], reg + i, reg + i);
181 }
182
183 return 0;
184}
185
186/** 164/**
187 * wm831x_reg_read: Read a single WM831x register. 165 * wm831x_reg_read: Read a single WM831x register.
188 * 166 *
@@ -191,14 +169,10 @@ static int wm831x_read(struct wm831x *wm831x, unsigned short reg,
191 */ 169 */
192int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg) 170int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg)
193{ 171{
194 unsigned short val; 172 unsigned int val;
195 int ret; 173 int ret;
196 174
197 mutex_lock(&wm831x->io_lock); 175 ret = regmap_read(wm831x->regmap, reg, &val);
198
199 ret = wm831x_read(wm831x, reg, 2, &val);
200
201 mutex_unlock(&wm831x->io_lock);
202 176
203 if (ret < 0) 177 if (ret < 0)
204 return ret; 178 return ret;
@@ -218,15 +192,7 @@ EXPORT_SYMBOL_GPL(wm831x_reg_read);
218int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg, 192int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
219 int count, u16 *buf) 193 int count, u16 *buf)
220{ 194{
221 int ret; 195 return regmap_bulk_read(wm831x->regmap, reg, buf, count);
222
223 mutex_lock(&wm831x->io_lock);
224
225 ret = wm831x_read(wm831x, reg, count * 2, buf);
226
227 mutex_unlock(&wm831x->io_lock);
228
229 return ret;
230} 196}
231EXPORT_SYMBOL_GPL(wm831x_bulk_read); 197EXPORT_SYMBOL_GPL(wm831x_bulk_read);
232 198
@@ -234,7 +200,7 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
234 int bytes, void *src) 200 int bytes, void *src)
235{ 201{
236 u16 *buf = src; 202 u16 *buf = src;
237 int i; 203 int i, ret;
238 204
239 BUG_ON(bytes % 2); 205 BUG_ON(bytes % 2);
240 BUG_ON(bytes <= 0); 206 BUG_ON(bytes <= 0);
@@ -245,11 +211,10 @@ static int wm831x_write(struct wm831x *wm831x, unsigned short reg,
245 211
246 dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n", 212 dev_vdbg(wm831x->dev, "Write %04x to R%d(0x%x)\n",
247 buf[i], reg + i, reg + i); 213 buf[i], reg + i, reg + i);
248 214 ret = regmap_write(wm831x->regmap, reg + i, buf[i]);
249 buf[i] = cpu_to_be16(buf[i]);
250 } 215 }
251 216
252 return wm831x->write_dev(wm831x, reg, bytes, src); 217 return 0;
253} 218}
254 219
255/** 220/**
@@ -286,20 +251,14 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg,
286 unsigned short mask, unsigned short val) 251 unsigned short mask, unsigned short val)
287{ 252{
288 int ret; 253 int ret;
289 u16 r;
290 254
291 mutex_lock(&wm831x->io_lock); 255 mutex_lock(&wm831x->io_lock);
292 256
293 ret = wm831x_read(wm831x, reg, 2, &r); 257 if (!wm831x_reg_locked(wm831x, reg))
294 if (ret < 0) 258 ret = regmap_update_bits(wm831x->regmap, reg, mask, val);
295 goto out; 259 else
296 260 ret = -EPERM;
297 r &= ~mask;
298 r |= val & mask;
299
300 ret = wm831x_write(wm831x, reg, 2, &r);
301 261
302out:
303 mutex_unlock(&wm831x->io_lock); 262 mutex_unlock(&wm831x->io_lock);
304 263
305 return ret; 264 return ret;
@@ -1292,6 +1251,12 @@ static struct mfd_cell backlight_devs[] = {
1292 }, 1251 },
1293}; 1252};
1294 1253
1254struct regmap_config wm831x_regmap_config = {
1255 .reg_bits = 16,
1256 .val_bits = 16,
1257};
1258EXPORT_SYMBOL_GPL(wm831x_regmap_config);
1259
1295/* 1260/*
1296 * Instantiate the generic non-control parts of the device. 1261 * Instantiate the generic non-control parts of the device.
1297 */ 1262 */
@@ -1309,7 +1274,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1309 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); 1274 ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
1310 if (ret < 0) { 1275 if (ret < 0) {
1311 dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret); 1276 dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
1312 goto err; 1277 goto err_regmap;
1313 } 1278 }
1314 switch (ret) { 1279 switch (ret) {
1315 case 0x6204: 1280 case 0x6204:
@@ -1318,20 +1283,20 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1318 default: 1283 default:
1319 dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret); 1284 dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
1320 ret = -EINVAL; 1285 ret = -EINVAL;
1321 goto err; 1286 goto err_regmap;
1322 } 1287 }
1323 1288
1324 ret = wm831x_reg_read(wm831x, WM831X_REVISION); 1289 ret = wm831x_reg_read(wm831x, WM831X_REVISION);
1325 if (ret < 0) { 1290 if (ret < 0) {
1326 dev_err(wm831x->dev, "Failed to read revision: %d\n", ret); 1291 dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
1327 goto err; 1292 goto err_regmap;
1328 } 1293 }
1329 rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT; 1294 rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;
1330 1295
1331 ret = wm831x_reg_read(wm831x, WM831X_RESET_ID); 1296 ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
1332 if (ret < 0) { 1297 if (ret < 0) {
1333 dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret); 1298 dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
1334 goto err; 1299 goto err_regmap;
1335 } 1300 }
1336 1301
1337 /* Some engineering samples do not have the ID set, rely on 1302 /* Some engineering samples do not have the ID set, rely on
@@ -1406,7 +1371,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1406 default: 1371 default:
1407 dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret); 1372 dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
1408 ret = -EINVAL; 1373 ret = -EINVAL;
1409 goto err; 1374 goto err_regmap;
1410 } 1375 }
1411 1376
1412 /* This will need revisiting in future but is OK for all 1377 /* This will need revisiting in future but is OK for all
@@ -1420,7 +1385,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1420 ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY); 1385 ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
1421 if (ret < 0) { 1386 if (ret < 0) {
1422 dev_err(wm831x->dev, "Failed to read security key: %d\n", ret); 1387 dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
1423 goto err; 1388 goto err_regmap;
1424 } 1389 }
1425 if (ret != 0) { 1390 if (ret != 0) {
1426 dev_warn(wm831x->dev, "Security key had non-zero value %x\n", 1391 dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
@@ -1433,7 +1398,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1433 ret = pdata->pre_init(wm831x); 1398 ret = pdata->pre_init(wm831x);
1434 if (ret != 0) { 1399 if (ret != 0) {
1435 dev_err(wm831x->dev, "pre_init() failed: %d\n", ret); 1400 dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
1436 goto err; 1401 goto err_regmap;
1437 } 1402 }
1438 } 1403 }
1439 1404
@@ -1456,7 +1421,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1456 1421
1457 ret = wm831x_irq_init(wm831x, irq); 1422 ret = wm831x_irq_init(wm831x, irq);
1458 if (ret != 0) 1423 if (ret != 0)
1459 goto err; 1424 goto err_regmap;
1460 1425
1461 wm831x_auxadc_init(wm831x); 1426 wm831x_auxadc_init(wm831x);
1462 1427
@@ -1552,8 +1517,9 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
1552 1517
1553err_irq: 1518err_irq:
1554 wm831x_irq_exit(wm831x); 1519 wm831x_irq_exit(wm831x);
1555err: 1520err_regmap:
1556 mfd_remove_devices(wm831x->dev); 1521 mfd_remove_devices(wm831x->dev);
1522 regmap_exit(wm831x->regmap);
1557 kfree(wm831x); 1523 kfree(wm831x);
1558 return ret; 1524 return ret;
1559} 1525}
@@ -1565,6 +1531,7 @@ void wm831x_device_exit(struct wm831x *wm831x)
1565 if (wm831x->irq_base) 1531 if (wm831x->irq_base)
1566 free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); 1532 free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
1567 wm831x_irq_exit(wm831x); 1533 wm831x_irq_exit(wm831x);
1534 regmap_exit(wm831x->regmap);
1568 kfree(wm831x); 1535 kfree(wm831x);
1569} 1536}
1570 1537
diff --git a/drivers/mfd/wm831x-i2c.c b/drivers/mfd/wm831x-i2c.c
index a06cbc739716..3ec6085d5fc0 100644
--- a/drivers/mfd/wm831x-i2c.c
+++ b/drivers/mfd/wm831x-i2c.c
@@ -18,67 +18,17 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/mfd/core.h> 19#include <linux/mfd/core.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/err.h>
22#include <linux/regmap.h>
21 23
22#include <linux/mfd/wm831x/core.h> 24#include <linux/mfd/wm831x/core.h>
23#include <linux/mfd/wm831x/pdata.h> 25#include <linux/mfd/wm831x/pdata.h>
24 26
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 struct i2c_msg xfer[2];
55 int ret;
56
57 reg = cpu_to_be16(reg);
58
59 xfer[0].addr = i2c->addr;
60 xfer[0].flags = 0;
61 xfer[0].len = 2;
62 xfer[0].buf = (char *)&reg;
63
64 xfer[1].addr = i2c->addr;
65 xfer[1].flags = I2C_M_NOSTART;
66 xfer[1].len = bytes;
67 xfer[1].buf = (char *)src;
68
69 ret = i2c_transfer(i2c->adapter, xfer, 2);
70 if (ret < 0)
71 return ret;
72 if (ret != 2)
73 return -EIO;
74
75 return 0;
76}
77
78static int wm831x_i2c_probe(struct i2c_client *i2c, 27static int wm831x_i2c_probe(struct i2c_client *i2c,
79 const struct i2c_device_id *id) 28 const struct i2c_device_id *id)
80{ 29{
81 struct wm831x *wm831x; 30 struct wm831x *wm831x;
31 int ret;
82 32
83 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL); 33 wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
84 if (wm831x == NULL) 34 if (wm831x == NULL)
@@ -86,9 +36,15 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
86 36
87 i2c_set_clientdata(i2c, wm831x); 37 i2c_set_clientdata(i2c, wm831x);
88 wm831x->dev = &i2c->dev; 38 wm831x->dev = &i2c->dev;
89 wm831x->control_data = i2c; 39
90 wm831x->read_dev = wm831x_i2c_read_device; 40 wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config);
91 wm831x->write_dev = wm831x_i2c_write_device; 41 if (IS_ERR(wm831x->regmap)) {
42 ret = PTR_ERR(wm831x->regmap);
43 dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
44 ret);
45 kfree(wm831x);
46 return ret;
47 }
92 48
93 return wm831x_device_init(wm831x, id->driver_data, i2c->irq); 49 return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
94} 50}
diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c
index eed8e4f7a5a1..dbe11472afce 100644
--- a/drivers/mfd/wm831x-spi.c
+++ b/drivers/mfd/wm831x-spi.c
@@ -16,58 +16,16 @@
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/pm.h> 17#include <linux/pm.h>
18#include <linux/spi/spi.h> 18#include <linux/spi/spi.h>
19#include <linux/regmap.h>
20#include <linux/err.h>
19 21
20#include <linux/mfd/wm831x/core.h> 22#include <linux/mfd/wm831x/core.h>
21 23
22static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
23 int bytes, void *dest)
24{
25 u16 tx_val;
26 u16 *d = dest;
27 int r, ret;
28
29 /* Go register at a time */
30 for (r = reg; r < reg + (bytes / 2); r++) {
31 tx_val = r | 0x8000;
32
33 ret = spi_write_then_read(wm831x->control_data,
34 (u8 *)&tx_val, 2, (u8 *)d, 2);
35 if (ret != 0)
36 return ret;
37
38 *d = be16_to_cpu(*d);
39
40 d++;
41 }
42
43 return 0;
44}
45
46static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
47 int bytes, void *src)
48{
49 struct spi_device *spi = wm831x->control_data;
50 u16 *s = src;
51 u16 data[2];
52 int ret, r;
53
54 /* Go register at a time */
55 for (r = reg; r < reg + (bytes / 2); r++) {
56 data[0] = r;
57 data[1] = *s++;
58
59 ret = spi_write(spi, (char *)&data, sizeof(data));
60 if (ret != 0)
61 return ret;
62 }
63
64 return 0;
65}
66
67static int __devinit wm831x_spi_probe(struct spi_device *spi) 24static int __devinit wm831x_spi_probe(struct spi_device *spi)
68{ 25{
69 struct wm831x *wm831x; 26 struct wm831x *wm831x;
70 enum wm831x_parent type; 27 enum wm831x_parent type;
28 int ret;
71 29
72 /* Currently SPI support for ID tables is unmerged, we're faking it */ 30 /* Currently SPI support for ID tables is unmerged, we're faking it */
73 if (strcmp(spi->modalias, "wm8310") == 0) 31 if (strcmp(spi->modalias, "wm8310") == 0)
@@ -98,9 +56,15 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
98 56
99 dev_set_drvdata(&spi->dev, wm831x); 57 dev_set_drvdata(&spi->dev, wm831x);
100 wm831x->dev = &spi->dev; 58 wm831x->dev = &spi->dev;
101 wm831x->control_data = spi; 59
102 wm831x->read_dev = wm831x_spi_read_device; 60 wm831x->regmap = regmap_init_spi(wm831x->dev, &wm831x_regmap_config);
103 wm831x->write_dev = wm831x_spi_write_device; 61 if (IS_ERR(wm831x->regmap)) {
62 ret = PTR_ERR(wm831x->regmap);
63 dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
64 ret);
65 kfree(wm831x);
66 return ret;
67 }
104 68
105 return wm831x_device_init(wm831x, type, spi->irq); 69 return wm831x_device_init(wm831x, type, spi->irq);
106} 70}