diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2012-11-13 03:28:44 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-11-21 10:07:59 -0500 |
commit | 2473d25a2f61985f8980c7c3d41cb85da1abea0f (patch) | |
tree | c2e4fac586be1b902fb679712c2a65637d487fe0 /drivers/mfd | |
parent | afc45898f62c7b139fca3cf0b72fb8ec476fee3f (diff) |
mfd: twl-core: Convert to use regmap for I/O
Remove the custom code to do I/O and replace it with standard regmap calls.
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl-core.c | 147 |
1 files changed, 80 insertions, 67 deletions
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 1dfd58344425..5043f505a230 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/regmap.h> | ||
35 | #include <linux/clk.h> | 36 | #include <linux/clk.h> |
36 | #include <linux/err.h> | 37 | #include <linux/err.h> |
37 | #include <linux/device.h> | 38 | #include <linux/device.h> |
@@ -171,13 +172,7 @@ EXPORT_SYMBOL(twl_rev); | |||
171 | /* Structure for each TWL4030/TWL6030 Slave */ | 172 | /* Structure for each TWL4030/TWL6030 Slave */ |
172 | struct twl_client { | 173 | struct twl_client { |
173 | struct i2c_client *client; | 174 | struct i2c_client *client; |
174 | u8 address; | 175 | struct regmap *regmap; |
175 | |||
176 | /* max numb of i2c_msg required is for read =2 */ | ||
177 | struct i2c_msg xfer_msg[2]; | ||
178 | |||
179 | /* To lock access to xfer_msg */ | ||
180 | struct mutex xfer_lock; | ||
181 | }; | 176 | }; |
182 | 177 | ||
183 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; | 178 | static struct twl_client twl_modules[TWL_NUM_SLAVES]; |
@@ -225,6 +220,33 @@ static struct twl_mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | |||
225 | { 3, TWL4030_BASEADD_SECURED_REG }, | 220 | { 3, TWL4030_BASEADD_SECURED_REG }, |
226 | }; | 221 | }; |
227 | 222 | ||
223 | static struct regmap_config twl4030_regmap_config[4] = { | ||
224 | { | ||
225 | /* Address 0x48 */ | ||
226 | .reg_bits = 8, | ||
227 | .val_bits = 8, | ||
228 | .max_register = 0xff, | ||
229 | }, | ||
230 | { | ||
231 | /* Address 0x49 */ | ||
232 | .reg_bits = 8, | ||
233 | .val_bits = 8, | ||
234 | .max_register = 0xff, | ||
235 | }, | ||
236 | { | ||
237 | /* Address 0x4a */ | ||
238 | .reg_bits = 8, | ||
239 | .val_bits = 8, | ||
240 | .max_register = 0xff, | ||
241 | }, | ||
242 | { | ||
243 | /* Address 0x4b */ | ||
244 | .reg_bits = 8, | ||
245 | .val_bits = 8, | ||
246 | .max_register = 0xff, | ||
247 | }, | ||
248 | }; | ||
249 | |||
228 | static struct twl_mapping twl6030_map[] = { | 250 | static struct twl_mapping twl6030_map[] = { |
229 | /* | 251 | /* |
230 | * NOTE: don't change this table without updating the | 252 | * NOTE: don't change this table without updating the |
@@ -262,6 +284,27 @@ static struct twl_mapping twl6030_map[] = { | |||
262 | { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, | 284 | { SUB_CHIP_ID1, TWL6025_BASEADD_CHARGER }, |
263 | }; | 285 | }; |
264 | 286 | ||
287 | static struct regmap_config twl6030_regmap_config[3] = { | ||
288 | { | ||
289 | /* Address 0x48 */ | ||
290 | .reg_bits = 8, | ||
291 | .val_bits = 8, | ||
292 | .max_register = 0xff, | ||
293 | }, | ||
294 | { | ||
295 | /* Address 0x49 */ | ||
296 | .reg_bits = 8, | ||
297 | .val_bits = 8, | ||
298 | .max_register = 0xff, | ||
299 | }, | ||
300 | { | ||
301 | /* Address 0x4a */ | ||
302 | .reg_bits = 8, | ||
303 | .val_bits = 8, | ||
304 | .max_register = 0xff, | ||
305 | }, | ||
306 | }; | ||
307 | |||
265 | /*----------------------------------------------------------------------*/ | 308 | /*----------------------------------------------------------------------*/ |
266 | 309 | ||
267 | /* Exported Functions */ | 310 | /* Exported Functions */ |
@@ -283,7 +326,6 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
283 | int ret; | 326 | int ret; |
284 | int sid; | 327 | int sid; |
285 | struct twl_client *twl; | 328 | struct twl_client *twl; |
286 | struct i2c_msg *msg; | ||
287 | 329 | ||
288 | if (unlikely(mod_no > TWL_MODULE_LAST)) { | 330 | if (unlikely(mod_no > TWL_MODULE_LAST)) { |
289 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 331 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
@@ -301,32 +343,14 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
301 | } | 343 | } |
302 | twl = &twl_modules[sid]; | 344 | twl = &twl_modules[sid]; |
303 | 345 | ||
304 | mutex_lock(&twl->xfer_lock); | 346 | ret = regmap_bulk_write(twl->regmap, twl_map[mod_no].base + reg, |
305 | /* | 347 | &value[1], num_bytes); |
306 | * [MSG1]: fill the register address data | 348 | |
307 | * fill the data Tx buffer | 349 | if (ret) |
308 | */ | 350 | pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n", |
309 | msg = &twl->xfer_msg[0]; | 351 | DRIVER_NAME, mod_no, reg, num_bytes); |
310 | msg->addr = twl->address; | 352 | |
311 | msg->len = num_bytes + 1; | 353 | return ret; |
312 | msg->flags = 0; | ||
313 | msg->buf = value; | ||
314 | /* over write the first byte of buffer with the register address */ | ||
315 | *value = twl_map[mod_no].base + reg; | ||
316 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); | ||
317 | mutex_unlock(&twl->xfer_lock); | ||
318 | |||
319 | /* i2c_transfer returns number of messages transferred */ | ||
320 | if (ret != 1) { | ||
321 | pr_err("%s: i2c_write failed to transfer all messages\n", | ||
322 | DRIVER_NAME); | ||
323 | if (ret < 0) | ||
324 | return ret; | ||
325 | else | ||
326 | return -EIO; | ||
327 | } else { | ||
328 | return 0; | ||
329 | } | ||
330 | } | 354 | } |
331 | EXPORT_SYMBOL(twl_i2c_write); | 355 | EXPORT_SYMBOL(twl_i2c_write); |
332 | 356 | ||
@@ -342,10 +366,8 @@ EXPORT_SYMBOL(twl_i2c_write); | |||
342 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 366 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
343 | { | 367 | { |
344 | int ret; | 368 | int ret; |
345 | u8 val; | ||
346 | int sid; | 369 | int sid; |
347 | struct twl_client *twl; | 370 | struct twl_client *twl; |
348 | struct i2c_msg *msg; | ||
349 | 371 | ||
350 | if (unlikely(mod_no > TWL_MODULE_LAST)) { | 372 | if (unlikely(mod_no > TWL_MODULE_LAST)) { |
351 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 373 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
@@ -363,34 +385,14 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |||
363 | } | 385 | } |
364 | twl = &twl_modules[sid]; | 386 | twl = &twl_modules[sid]; |
365 | 387 | ||
366 | mutex_lock(&twl->xfer_lock); | 388 | ret = regmap_bulk_read(twl->regmap, twl_map[mod_no].base + reg, |
367 | /* [MSG1] fill the register address data */ | 389 | value, num_bytes); |
368 | msg = &twl->xfer_msg[0]; | 390 | |
369 | msg->addr = twl->address; | 391 | if (ret) |
370 | msg->len = 1; | 392 | pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n", |
371 | msg->flags = 0; /* Read the register value */ | 393 | DRIVER_NAME, mod_no, reg, num_bytes); |
372 | val = twl_map[mod_no].base + reg; | 394 | |
373 | msg->buf = &val; | 395 | return ret; |
374 | /* [MSG2] fill the data rx buffer */ | ||
375 | msg = &twl->xfer_msg[1]; | ||
376 | msg->addr = twl->address; | ||
377 | msg->flags = I2C_M_RD; /* Read the register value */ | ||
378 | msg->len = num_bytes; /* only n bytes */ | ||
379 | msg->buf = value; | ||
380 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); | ||
381 | mutex_unlock(&twl->xfer_lock); | ||
382 | |||
383 | /* i2c_transfer returns number of messages transferred */ | ||
384 | if (ret != 2) { | ||
385 | pr_err("%s: i2c_read failed to transfer all messages\n", | ||
386 | DRIVER_NAME); | ||
387 | if (ret < 0) | ||
388 | return ret; | ||
389 | else | ||
390 | return -EIO; | ||
391 | } else { | ||
392 | return 0; | ||
393 | } | ||
394 | } | 396 | } |
395 | EXPORT_SYMBOL(twl_i2c_read); | 397 | EXPORT_SYMBOL(twl_i2c_read); |
396 | 398 | ||
@@ -1184,6 +1186,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1184 | struct twl4030_platform_data *pdata = client->dev.platform_data; | 1186 | struct twl4030_platform_data *pdata = client->dev.platform_data; |
1185 | struct device_node *node = client->dev.of_node; | 1187 | struct device_node *node = client->dev.of_node; |
1186 | struct platform_device *pdev; | 1188 | struct platform_device *pdev; |
1189 | struct regmap_config *twl_regmap_config; | ||
1187 | int irq_base = 0; | 1190 | int irq_base = 0; |
1188 | int status; | 1191 | int status; |
1189 | unsigned i, num_slaves; | 1192 | unsigned i, num_slaves; |
@@ -1237,22 +1240,23 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1237 | if ((id->driver_data) & TWL6030_CLASS) { | 1240 | if ((id->driver_data) & TWL6030_CLASS) { |
1238 | twl_id = TWL6030_CLASS_ID; | 1241 | twl_id = TWL6030_CLASS_ID; |
1239 | twl_map = &twl6030_map[0]; | 1242 | twl_map = &twl6030_map[0]; |
1243 | twl_regmap_config = twl6030_regmap_config; | ||
1240 | num_slaves = TWL_NUM_SLAVES - 1; | 1244 | num_slaves = TWL_NUM_SLAVES - 1; |
1241 | } else { | 1245 | } else { |
1242 | twl_id = TWL4030_CLASS_ID; | 1246 | twl_id = TWL4030_CLASS_ID; |
1243 | twl_map = &twl4030_map[0]; | 1247 | twl_map = &twl4030_map[0]; |
1248 | twl_regmap_config = twl4030_regmap_config; | ||
1244 | num_slaves = TWL_NUM_SLAVES; | 1249 | num_slaves = TWL_NUM_SLAVES; |
1245 | } | 1250 | } |
1246 | 1251 | ||
1247 | for (i = 0; i < num_slaves; i++) { | 1252 | for (i = 0; i < num_slaves; i++) { |
1248 | struct twl_client *twl = &twl_modules[i]; | 1253 | struct twl_client *twl = &twl_modules[i]; |
1249 | 1254 | ||
1250 | twl->address = client->addr + i; | ||
1251 | if (i == 0) { | 1255 | if (i == 0) { |
1252 | twl->client = client; | 1256 | twl->client = client; |
1253 | } else { | 1257 | } else { |
1254 | twl->client = i2c_new_dummy(client->adapter, | 1258 | twl->client = i2c_new_dummy(client->adapter, |
1255 | twl->address); | 1259 | client->addr + i); |
1256 | if (!twl->client) { | 1260 | if (!twl->client) { |
1257 | dev_err(&client->dev, | 1261 | dev_err(&client->dev, |
1258 | "can't attach client %d\n", i); | 1262 | "can't attach client %d\n", i); |
@@ -1260,7 +1264,16 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) | |||
1260 | goto fail; | 1264 | goto fail; |
1261 | } | 1265 | } |
1262 | } | 1266 | } |
1263 | mutex_init(&twl->xfer_lock); | 1267 | |
1268 | twl->regmap = devm_regmap_init_i2c(twl->client, | ||
1269 | &twl_regmap_config[i]); | ||
1270 | if (IS_ERR(twl->regmap)) { | ||
1271 | status = PTR_ERR(twl->regmap); | ||
1272 | dev_err(&client->dev, | ||
1273 | "Failed to allocate regmap %d, err: %d\n", i, | ||
1274 | status); | ||
1275 | goto fail; | ||
1276 | } | ||
1264 | } | 1277 | } |
1265 | 1278 | ||
1266 | inuse = true; | 1279 | inuse = true; |