diff options
Diffstat (limited to 'drivers/mfd/pcf50633-core.c')
-rw-r--r-- | drivers/mfd/pcf50633-core.c | 114 |
1 files changed, 35 insertions, 79 deletions
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 57868416c760..ff1a7e741ecd 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -23,45 +23,22 @@ | |||
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/regmap.h> | ||
27 | #include <linux/err.h> | ||
26 | 28 | ||
27 | #include <linux/mfd/pcf50633/core.h> | 29 | #include <linux/mfd/pcf50633/core.h> |
28 | 30 | ||
29 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | ||
30 | { | ||
31 | int ret; | ||
32 | |||
33 | ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg, | ||
34 | num, data); | ||
35 | if (ret < 0) | ||
36 | dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg); | ||
37 | |||
38 | return ret; | ||
39 | } | ||
40 | |||
41 | static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg, | ||
46 | num, data); | ||
47 | if (ret < 0) | ||
48 | dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg); | ||
49 | |||
50 | return ret; | ||
51 | |||
52 | } | ||
53 | |||
54 | /* Read a block of up to 32 regs */ | 31 | /* Read a block of up to 32 regs */ |
55 | int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, | 32 | int pcf50633_read_block(struct pcf50633 *pcf, u8 reg, |
56 | int nr_regs, u8 *data) | 33 | int nr_regs, u8 *data) |
57 | { | 34 | { |
58 | int ret; | 35 | int ret; |
59 | 36 | ||
60 | mutex_lock(&pcf->lock); | 37 | ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs); |
61 | ret = __pcf50633_read(pcf, reg, nr_regs, data); | 38 | if (ret != 0) |
62 | mutex_unlock(&pcf->lock); | 39 | return ret; |
63 | 40 | ||
64 | return ret; | 41 | return nr_regs; |
65 | } | 42 | } |
66 | EXPORT_SYMBOL_GPL(pcf50633_read_block); | 43 | EXPORT_SYMBOL_GPL(pcf50633_read_block); |
67 | 44 | ||
@@ -71,21 +48,22 @@ int pcf50633_write_block(struct pcf50633 *pcf , u8 reg, | |||
71 | { | 48 | { |
72 | int ret; | 49 | int ret; |
73 | 50 | ||
74 | mutex_lock(&pcf->lock); | 51 | ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs); |
75 | ret = __pcf50633_write(pcf, reg, nr_regs, data); | 52 | if (ret != 0) |
76 | mutex_unlock(&pcf->lock); | 53 | return ret; |
77 | 54 | ||
78 | return ret; | 55 | return nr_regs; |
79 | } | 56 | } |
80 | EXPORT_SYMBOL_GPL(pcf50633_write_block); | 57 | EXPORT_SYMBOL_GPL(pcf50633_write_block); |
81 | 58 | ||
82 | u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg) | 59 | u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg) |
83 | { | 60 | { |
84 | u8 val; | 61 | unsigned int val; |
62 | int ret; | ||
85 | 63 | ||
86 | mutex_lock(&pcf->lock); | 64 | ret = regmap_read(pcf->regmap, reg, &val); |
87 | __pcf50633_read(pcf, reg, 1, &val); | 65 | if (ret < 0) |
88 | mutex_unlock(&pcf->lock); | 66 | return -1; |
89 | 67 | ||
90 | return val; | 68 | return val; |
91 | } | 69 | } |
@@ -93,56 +71,19 @@ EXPORT_SYMBOL_GPL(pcf50633_reg_read); | |||
93 | 71 | ||
94 | int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val) | 72 | int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val) |
95 | { | 73 | { |
96 | int ret; | 74 | return regmap_write(pcf->regmap, reg, val); |
97 | |||
98 | mutex_lock(&pcf->lock); | ||
99 | ret = __pcf50633_write(pcf, reg, 1, &val); | ||
100 | mutex_unlock(&pcf->lock); | ||
101 | |||
102 | return ret; | ||
103 | } | 75 | } |
104 | EXPORT_SYMBOL_GPL(pcf50633_reg_write); | 76 | EXPORT_SYMBOL_GPL(pcf50633_reg_write); |
105 | 77 | ||
106 | int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val) | 78 | int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val) |
107 | { | 79 | { |
108 | int ret; | 80 | return regmap_update_bits(pcf->regmap, reg, mask, val); |
109 | u8 tmp; | ||
110 | |||
111 | val &= mask; | ||
112 | |||
113 | mutex_lock(&pcf->lock); | ||
114 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
115 | if (ret < 0) | ||
116 | goto out; | ||
117 | |||
118 | tmp &= ~mask; | ||
119 | tmp |= val; | ||
120 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
121 | |||
122 | out: | ||
123 | mutex_unlock(&pcf->lock); | ||
124 | |||
125 | return ret; | ||
126 | } | 81 | } |
127 | EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask); | 82 | EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask); |
128 | 83 | ||
129 | int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val) | 84 | int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val) |
130 | { | 85 | { |
131 | int ret; | 86 | return regmap_update_bits(pcf->regmap, reg, val, 0); |
132 | u8 tmp; | ||
133 | |||
134 | mutex_lock(&pcf->lock); | ||
135 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
136 | if (ret < 0) | ||
137 | goto out; | ||
138 | |||
139 | tmp &= ~val; | ||
140 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
141 | |||
142 | out: | ||
143 | mutex_unlock(&pcf->lock); | ||
144 | |||
145 | return ret; | ||
146 | } | 87 | } |
147 | EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits); | 88 | EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits); |
148 | 89 | ||
@@ -251,6 +192,11 @@ static int pcf50633_resume(struct device *dev) | |||
251 | 192 | ||
252 | static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume); | 193 | static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume); |
253 | 194 | ||
195 | static struct regmap_config pcf50633_regmap_config = { | ||
196 | .reg_bits = 8, | ||
197 | .val_bits = 8, | ||
198 | }; | ||
199 | |||
254 | static int __devinit pcf50633_probe(struct i2c_client *client, | 200 | static int __devinit pcf50633_probe(struct i2c_client *client, |
255 | const struct i2c_device_id *ids) | 201 | const struct i2c_device_id *ids) |
256 | { | 202 | { |
@@ -272,16 +218,23 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
272 | 218 | ||
273 | mutex_init(&pcf->lock); | 219 | mutex_init(&pcf->lock); |
274 | 220 | ||
221 | pcf->regmap = regmap_init_i2c(client, &pcf50633_regmap_config); | ||
222 | if (IS_ERR(pcf->regmap)) { | ||
223 | ret = PTR_ERR(pcf->regmap); | ||
224 | dev_err(pcf->dev, "Failed to allocate register map: %d\n", | ||
225 | ret); | ||
226 | goto err_free; | ||
227 | } | ||
228 | |||
275 | i2c_set_clientdata(client, pcf); | 229 | i2c_set_clientdata(client, pcf); |
276 | pcf->dev = &client->dev; | 230 | pcf->dev = &client->dev; |
277 | pcf->i2c_client = client; | ||
278 | 231 | ||
279 | version = pcf50633_reg_read(pcf, 0); | 232 | version = pcf50633_reg_read(pcf, 0); |
280 | variant = pcf50633_reg_read(pcf, 1); | 233 | variant = pcf50633_reg_read(pcf, 1); |
281 | if (version < 0 || variant < 0) { | 234 | if (version < 0 || variant < 0) { |
282 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); | 235 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); |
283 | ret = -ENODEV; | 236 | ret = -ENODEV; |
284 | goto err_free; | 237 | goto err_regmap; |
285 | } | 238 | } |
286 | 239 | ||
287 | dev_info(pcf->dev, "Probed device version %d variant %d\n", | 240 | dev_info(pcf->dev, "Probed device version %d variant %d\n", |
@@ -328,6 +281,8 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
328 | 281 | ||
329 | return 0; | 282 | return 0; |
330 | 283 | ||
284 | err_regmap: | ||
285 | regmap_exit(pcf->regmap); | ||
331 | err_free: | 286 | err_free: |
332 | kfree(pcf); | 287 | kfree(pcf); |
333 | 288 | ||
@@ -351,6 +306,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
351 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) | 306 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) |
352 | platform_device_unregister(pcf->regulator_pdev[i]); | 307 | platform_device_unregister(pcf->regulator_pdev[i]); |
353 | 308 | ||
309 | regmap_exit(pcf->regmap); | ||
354 | kfree(pcf); | 310 | kfree(pcf); |
355 | 311 | ||
356 | return 0; | 312 | return 0; |