da9211-regulator.c (83bc90e11576f9c100f8ef4ba2bcd0b89212e3fb) | da9211-regulator.c (bf3baca6c54ce8a2f51687296f868dfe20d33f13) |
---|---|
1/* | 1/* |
2 * da9211-regulator.c - Regulator device driver for DA9211 | 2 * da9211-regulator.c - Regulator device driver for DA9211/DA9213 |
3 * Copyright (C) 2014 Dialog Semiconductor Ltd. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, --- 8 unchanged lines hidden (view full) --- 19#include <linux/module.h> 20#include <linux/init.h> 21#include <linux/slab.h> 22#include <linux/regulator/driver.h> 23#include <linux/regulator/machine.h> 24#include <linux/regmap.h> 25#include <linux/irq.h> 26#include <linux/interrupt.h> | 3 * Copyright (C) 2014 Dialog Semiconductor Ltd. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, --- 8 unchanged lines hidden (view full) --- 19#include <linux/module.h> 20#include <linux/init.h> 21#include <linux/slab.h> 22#include <linux/regulator/driver.h> 23#include <linux/regulator/machine.h> 24#include <linux/regmap.h> 25#include <linux/irq.h> 26#include <linux/interrupt.h> |
27#include <linux/regulator/of_regulator.h> |
|
27#include <linux/regulator/da9211.h> 28#include "da9211-regulator.h" 29 | 28#include <linux/regulator/da9211.h> 29#include "da9211-regulator.h" 30 |
31/* DEVICE IDs */ 32#define DA9211_DEVICE_ID 0x22 33#define DA9213_DEVICE_ID 0x23 34 |
|
30#define DA9211_BUCK_MODE_SLEEP 1 31#define DA9211_BUCK_MODE_SYNC 2 32#define DA9211_BUCK_MODE_AUTO 3 33 34/* DA9211 REGULATOR IDs */ 35#define DA9211_ID_BUCKA 0 36#define DA9211_ID_BUCKB 1 37 38struct da9211 { 39 struct device *dev; 40 struct regmap *regmap; 41 struct da9211_pdata *pdata; 42 struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; 43 int num_regulator; 44 int chip_irq; | 35#define DA9211_BUCK_MODE_SLEEP 1 36#define DA9211_BUCK_MODE_SYNC 2 37#define DA9211_BUCK_MODE_AUTO 3 38 39/* DA9211 REGULATOR IDs */ 40#define DA9211_ID_BUCKA 0 41#define DA9211_ID_BUCKB 1 42 43struct da9211 { 44 struct device *dev; 45 struct regmap *regmap; 46 struct da9211_pdata *pdata; 47 struct regulator_dev *rdev[DA9211_MAX_REGULATORS]; 48 int num_regulator; 49 int chip_irq; |
50 int chip_id; |
|
45}; 46 47static const struct regmap_range_cfg da9211_regmap_range[] = { 48 { 49 .selector_reg = DA9211_REG_PAGE_CON, 50 .selector_mask = DA9211_REG_PAGE_MASK, 51 .selector_shift = DA9211_REG_PAGE_SHIFT, 52 .window_start = 0, 53 .window_len = 256, 54 .range_min = 0, | 51}; 52 53static const struct regmap_range_cfg da9211_regmap_range[] = { 54 { 55 .selector_reg = DA9211_REG_PAGE_CON, 56 .selector_mask = DA9211_REG_PAGE_MASK, 57 .selector_shift = DA9211_REG_PAGE_SHIFT, 58 .window_start = 0, 59 .window_len = 256, 60 .range_min = 0, |
55 .range_max = 2*256, | 61 .range_max = 5*128, |
56 }, 57}; 58 59static const struct regmap_config da9211_regmap_config = { 60 .reg_bits = 8, 61 .val_bits = 8, | 62 }, 63}; 64 65static const struct regmap_config da9211_regmap_config = { 66 .reg_bits = 8, 67 .val_bits = 8, |
62 .max_register = 2 * 256, | 68 .max_register = 5 * 128, |
63 .ranges = da9211_regmap_range, 64 .num_ranges = ARRAY_SIZE(da9211_regmap_range), 65}; 66 67/* Default limits measured in millivolts and milliamps */ 68#define DA9211_MIN_MV 300 69#define DA9211_MAX_MV 1570 70#define DA9211_STEP_MV 10 71 | 69 .ranges = da9211_regmap_range, 70 .num_ranges = ARRAY_SIZE(da9211_regmap_range), 71}; 72 73/* Default limits measured in millivolts and milliamps */ 74#define DA9211_MIN_MV 300 75#define DA9211_MAX_MV 1570 76#define DA9211_STEP_MV 10 77 |
72/* Current limits for buck (uA) indices corresponds with register values */ | 78/* Current limits for DA9211 buck (uA) indices 79 * corresponds with register values 80 */ |
73static const int da9211_current_limits[] = { 74 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 75 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 76}; | 81static const int da9211_current_limits[] = { 82 2000000, 2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 83 3600000, 3800000, 4000000, 4200000, 4400000, 4600000, 4800000, 5000000 84}; |
85/* Current limits for DA9213 buck (uA) indices 86 * corresponds with register values 87 */ 88static const int da9213_current_limits[] = { 89 3000000, 3200000, 3400000, 3600000, 3800000, 4000000, 4200000, 4400000, 90 4600000, 4800000, 5000000, 5200000, 5400000, 5600000, 5800000, 6000000 91}; |
|
77 78static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) 79{ 80 int id = rdev_get_id(rdev); 81 struct da9211 *chip = rdev_get_drvdata(rdev); 82 unsigned int data; 83 int ret, mode = 0; 84 --- 39 unchanged lines hidden (view full) --- 124 0x03, val); 125} 126 127static int da9211_set_current_limit(struct regulator_dev *rdev, int min, 128 int max) 129{ 130 int id = rdev_get_id(rdev); 131 struct da9211 *chip = rdev_get_drvdata(rdev); | 92 93static unsigned int da9211_buck_get_mode(struct regulator_dev *rdev) 94{ 95 int id = rdev_get_id(rdev); 96 struct da9211 *chip = rdev_get_drvdata(rdev); 97 unsigned int data; 98 int ret, mode = 0; 99 --- 39 unchanged lines hidden (view full) --- 139 0x03, val); 140} 141 142static int da9211_set_current_limit(struct regulator_dev *rdev, int min, 143 int max) 144{ 145 int id = rdev_get_id(rdev); 146 struct da9211 *chip = rdev_get_drvdata(rdev); |
132 int i; | 147 int i, max_size; 148 const int *current_limits; |
133 | 149 |
150 switch (chip->chip_id) { 151 case DA9211: 152 current_limits = da9211_current_limits; 153 max_size = ARRAY_SIZE(da9211_current_limits)-1; 154 break; 155 case DA9213: 156 current_limits = da9213_current_limits; 157 max_size = ARRAY_SIZE(da9213_current_limits)-1; 158 break; 159 default: 160 return -EINVAL; 161 } 162 |
|
134 /* search for closest to maximum */ | 163 /* search for closest to maximum */ |
135 for (i = ARRAY_SIZE(da9211_current_limits)-1; i >= 0; i--) { 136 if (min <= da9211_current_limits[i] && 137 max >= da9211_current_limits[i]) { | 164 for (i = max_size; i >= 0; i--) { 165 if (min <= current_limits[i] && 166 max >= current_limits[i]) { |
138 return regmap_update_bits(chip->regmap, 139 DA9211_REG_BUCK_ILIM, 140 (0x0F << id*4), (i << id*4)); 141 } 142 } 143 144 return -EINVAL; 145} 146 147static int da9211_get_current_limit(struct regulator_dev *rdev) 148{ 149 int id = rdev_get_id(rdev); 150 struct da9211 *chip = rdev_get_drvdata(rdev); 151 unsigned int data; 152 int ret; | 167 return regmap_update_bits(chip->regmap, 168 DA9211_REG_BUCK_ILIM, 169 (0x0F << id*4), (i << id*4)); 170 } 171 } 172 173 return -EINVAL; 174} 175 176static int da9211_get_current_limit(struct regulator_dev *rdev) 177{ 178 int id = rdev_get_id(rdev); 179 struct da9211 *chip = rdev_get_drvdata(rdev); 180 unsigned int data; 181 int ret; |
182 const int *current_limits; |
|
153 | 183 |
184 switch (chip->chip_id) { 185 case DA9211: 186 current_limits = da9211_current_limits; 187 break; 188 case DA9213: 189 current_limits = da9213_current_limits; 190 break; 191 default: 192 return -EINVAL; 193 } 194 |
|
154 ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); 155 if (ret < 0) 156 return ret; 157 | 195 ret = regmap_read(chip->regmap, DA9211_REG_BUCK_ILIM, &data); 196 if (ret < 0) 197 return ret; 198 |
158 /* select one of 16 values: 0000 (2000mA) to 1111 (5000mA) */ | 199 /* select one of 16 values: 0000 (2000mA or 3000mA) 200 * to 1111 (5000mA or 6000mA). 201 */ |
159 data = (data >> id*4) & 0x0F; | 202 data = (data >> id*4) & 0x0F; |
160 return da9211_current_limits[data]; | 203 return current_limits[data]; |
161} 162 163static struct regulator_ops da9211_buck_ops = { 164 .get_mode = da9211_buck_get_mode, 165 .set_mode = da9211_buck_set_mode, 166 .enable = regulator_enable_regmap, 167 .disable = regulator_disable_regmap, 168 .is_enabled = regulator_is_enabled_regmap, --- 20 unchanged lines hidden (view full) --- 189 .owner = THIS_MODULE,\ 190} 191 192static struct regulator_desc da9211_regulators[] = { 193 DA9211_BUCK(BUCKA), 194 DA9211_BUCK(BUCKB), 195}; 196 | 204} 205 206static struct regulator_ops da9211_buck_ops = { 207 .get_mode = da9211_buck_get_mode, 208 .set_mode = da9211_buck_set_mode, 209 .enable = regulator_enable_regmap, 210 .disable = regulator_disable_regmap, 211 .is_enabled = regulator_is_enabled_regmap, --- 20 unchanged lines hidden (view full) --- 232 .owner = THIS_MODULE,\ 233} 234 235static struct regulator_desc da9211_regulators[] = { 236 DA9211_BUCK(BUCKA), 237 DA9211_BUCK(BUCKB), 238}; 239 |
240#ifdef CONFIG_OF 241static struct of_regulator_match da9211_matches[] = { 242 [DA9211_ID_BUCKA] = { .name = "BUCKA" }, 243 [DA9211_ID_BUCKB] = { .name = "BUCKB" }, 244 }; 245 246static struct da9211_pdata *da9211_parse_regulators_dt( 247 struct device *dev) 248{ 249 struct da9211_pdata *pdata; 250 struct device_node *node; 251 int i, num, n; 252 253 node = of_get_child_by_name(dev->of_node, "regulators"); 254 if (!node) { 255 dev_err(dev, "regulators node not found\n"); 256 return ERR_PTR(-ENODEV); 257 } 258 259 num = of_regulator_match(dev, node, da9211_matches, 260 ARRAY_SIZE(da9211_matches)); 261 of_node_put(node); 262 if (num < 0) { 263 dev_err(dev, "Failed to match regulators\n"); 264 return ERR_PTR(-EINVAL); 265 } 266 267 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 268 if (!pdata) 269 return ERR_PTR(-ENOMEM); 270 271 pdata->num_buck = num; 272 273 n = 0; 274 for (i = 0; i < ARRAY_SIZE(da9211_matches); i++) { 275 if (!da9211_matches[i].init_data) 276 continue; 277 278 pdata->init_data[n] = da9211_matches[i].init_data; 279 280 n++; 281 }; 282 283 return pdata; 284} 285#else 286static struct da9211_pdata *da9211_parse_regulators_dt( 287 struct device *dev) 288{ 289 return ERR_PTR(-ENODEV); 290} 291#endif 292 |
|
197static irqreturn_t da9211_irq_handler(int irq, void *data) 198{ 199 struct da9211 *chip = data; 200 int reg_val, err, ret = IRQ_NONE; 201 202 err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, ®_val); 203 if (err < 0) 204 goto error_i2c; --- 54 unchanged lines hidden (view full) --- 259 else 260 chip->num_regulator = 2; 261 } else { 262 dev_err(chip->dev, "Configuration is mismatched\n"); 263 return -EINVAL; 264 } 265 266 for (i = 0; i < chip->num_regulator; i++) { | 293static irqreturn_t da9211_irq_handler(int irq, void *data) 294{ 295 struct da9211 *chip = data; 296 int reg_val, err, ret = IRQ_NONE; 297 298 err = regmap_read(chip->regmap, DA9211_REG_EVENT_B, ®_val); 299 if (err < 0) 300 goto error_i2c; --- 54 unchanged lines hidden (view full) --- 355 else 356 chip->num_regulator = 2; 357 } else { 358 dev_err(chip->dev, "Configuration is mismatched\n"); 359 return -EINVAL; 360 } 361 362 for (i = 0; i < chip->num_regulator; i++) { |
267 if (chip->pdata) 268 config.init_data = 269 &(chip->pdata->init_data[i]); 270 | 363 config.init_data = chip->pdata->init_data[i]; |
271 config.dev = chip->dev; 272 config.driver_data = chip; 273 config.regmap = chip->regmap; 274 275 chip->rdev[i] = devm_regulator_register(chip->dev, 276 &da9211_regulators[i], &config); 277 if (IS_ERR(chip->rdev[i])) { 278 dev_err(chip->dev, --- 9 unchanged lines hidden (view full) --- 288 "Failed to update mask reg: %d\n", ret); 289 return ret; 290 } 291 } 292 } 293 294 return 0; 295} | 364 config.dev = chip->dev; 365 config.driver_data = chip; 366 config.regmap = chip->regmap; 367 368 chip->rdev[i] = devm_regulator_register(chip->dev, 369 &da9211_regulators[i], &config); 370 if (IS_ERR(chip->rdev[i])) { 371 dev_err(chip->dev, --- 9 unchanged lines hidden (view full) --- 381 "Failed to update mask reg: %d\n", ret); 382 return ret; 383 } 384 } 385 } 386 387 return 0; 388} |
389 390static const struct i2c_device_id da9211_i2c_id[] = { 391 {"da9211", DA9211}, 392 {"da9213", DA9213}, 393 {}, 394}; 395 396#ifdef CONFIG_OF 397static const struct of_device_id da9211_dt_ids[] = { 398 { .compatible = "dlg,da9211", .data = &da9211_i2c_id[0] }, 399 { .compatible = "dlg,da9213", .data = &da9211_i2c_id[1] }, 400 {}, 401}; 402#endif 403 |
|
296/* 297 * I2C driver interface functions 298 */ 299static int da9211_i2c_probe(struct i2c_client *i2c, 300 const struct i2c_device_id *id) 301{ 302 struct da9211 *chip; 303 int error, ret; | 404/* 405 * I2C driver interface functions 406 */ 407static int da9211_i2c_probe(struct i2c_client *i2c, 408 const struct i2c_device_id *id) 409{ 410 struct da9211 *chip; 411 int error, ret; |
412 unsigned int data; |
|
304 305 chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); | 413 414 chip = devm_kzalloc(&i2c->dev, sizeof(struct da9211), GFP_KERNEL); |
415 if (!chip) 416 return -ENOMEM; |
|
306 307 chip->dev = &i2c->dev; 308 chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); 309 if (IS_ERR(chip->regmap)) { 310 error = PTR_ERR(chip->regmap); | 417 418 chip->dev = &i2c->dev; 419 chip->regmap = devm_regmap_init_i2c(i2c, &da9211_regmap_config); 420 if (IS_ERR(chip->regmap)) { 421 error = PTR_ERR(chip->regmap); |
311 dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 422 dev_err(chip->dev, "Failed to allocate register map: %d\n", |
312 error); 313 return error; 314 } 315 316 i2c_set_clientdata(i2c, chip); 317 318 chip->pdata = i2c->dev.platform_data; | 423 error); 424 return error; 425 } 426 427 i2c_set_clientdata(i2c, chip); 428 429 chip->pdata = i2c->dev.platform_data; |
319 if (!chip->pdata) { 320 dev_err(&i2c->dev, "No platform init data supplied\n"); | 430 431 ret = regmap_read(chip->regmap, DA9211_REG_DEVICE_ID, &data); 432 if (ret < 0) { 433 dev_err(chip->dev, "Failed to read DEVICE_ID reg: %d\n", ret); 434 return ret; 435 } 436 437 switch (data) { 438 case DA9211_DEVICE_ID: 439 chip->chip_id = DA9211; 440 break; 441 case DA9213_DEVICE_ID: 442 chip->chip_id = DA9213; 443 break; 444 default: 445 dev_err(chip->dev, "Unsupported device id = 0x%x.\n", data); |
321 return -ENODEV; 322 } 323 | 446 return -ENODEV; 447 } 448 |
449 if (!chip->pdata) 450 chip->pdata = da9211_parse_regulators_dt(chip->dev); 451 452 if (IS_ERR(chip->pdata)) { 453 dev_err(chip->dev, "No regulators defined for the platform\n"); 454 return PTR_ERR(chip->pdata); 455 } 456 |
|
324 chip->chip_irq = i2c->irq; 325 326 if (chip->chip_irq != 0) { 327 ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL, 328 da9211_irq_handler, 329 IRQF_TRIGGER_LOW|IRQF_ONESHOT, 330 "da9211", chip); 331 if (ret != 0) { 332 dev_err(chip->dev, "Failed to request IRQ: %d\n", 333 chip->chip_irq); 334 return ret; 335 } 336 } else { 337 dev_warn(chip->dev, "No IRQ configured\n"); 338 } 339 340 ret = da9211_regulator_init(chip); 341 342 if (ret < 0) | 457 chip->chip_irq = i2c->irq; 458 459 if (chip->chip_irq != 0) { 460 ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL, 461 da9211_irq_handler, 462 IRQF_TRIGGER_LOW|IRQF_ONESHOT, 463 "da9211", chip); 464 if (ret != 0) { 465 dev_err(chip->dev, "Failed to request IRQ: %d\n", 466 chip->chip_irq); 467 return ret; 468 } 469 } else { 470 dev_warn(chip->dev, "No IRQ configured\n"); 471 } 472 473 ret = da9211_regulator_init(chip); 474 475 if (ret < 0) |
343 dev_err(&i2c->dev, "Failed to initialize regulator: %d\n", ret); | 476 dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret); |
344 345 return ret; 346} 347 | 477 478 return ret; 479} 480 |
348static const struct i2c_device_id da9211_i2c_id[] = { 349 {"da9211", 0}, 350 {}, 351}; 352 | |
353MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); 354 355static struct i2c_driver da9211_regulator_driver = { 356 .driver = { 357 .name = "da9211", 358 .owner = THIS_MODULE, 359 }, 360 .probe = da9211_i2c_probe, 361 .id_table = da9211_i2c_id, 362}; 363 364module_i2c_driver(da9211_regulator_driver); 365 366MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>"); | 481MODULE_DEVICE_TABLE(i2c, da9211_i2c_id); 482 483static struct i2c_driver da9211_regulator_driver = { 484 .driver = { 485 .name = "da9211", 486 .owner = THIS_MODULE, 487 }, 488 .probe = da9211_i2c_probe, 489 .id_table = da9211_i2c_id, 490}; 491 492module_i2c_driver(da9211_regulator_driver); 493 494MODULE_AUTHOR("James Ban <James.Ban.opensource@diasemi.com>"); |
367MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211"); | 495MODULE_DESCRIPTION("Regulator device driver for Dialog DA9211/DA9213"); |
368MODULE_LICENSE("GPL v2"); | 496MODULE_LICENSE("GPL v2"); |