aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2014-02-28 05:01:50 -0500
committerMark Brown <broonie@linaro.org>2014-03-02 21:08:55 -0500
commit3e80f95bfc5f490bda4785cb672490f7012a40d0 (patch)
tree07c2c244013ed9e2685153d4052f60a17d7cc33a
parent219ef031de434591bb6c85d22701ce8b23c4b1a4 (diff)
regulator: s2mps11: Copy supported regulators from initconst
Add __initconst to 'regulator_desc' array with supported regulators. During probe choose how many and which regulators will be supported according to device ID. Then copy the 'regulator_desc' array to allocated memory so the regulator core can use it. Additionally allocate array of of_regulator_match() dynamically (based on number of regulators) instead of allocation on the stack. This is needed for supporting different devices in s2mps11 driver and actually prepares the regulator driver for supporting the S2MPS14 device. Code for supporting the S2MPS14 device will add its own array of 'regulator_desc' (also marked as __initconst). This way memory footprint of the driver will be reduced (approximately 'regulators_desc' array for S2MPS11 occupies 5 kB on 32-bit ARM, for S2MPS14 will occupy 3 kB). Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Cc: Yadwinder Singh Brar <yadi.brar01@gmail.com> Reviewed-by: Yadwinder Singh Brar <yadi.brar@samsung.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/regulator/s2mps11.c75
1 files changed, 62 insertions, 13 deletions
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 189038aecbf5..ca66fc56fa58 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -25,9 +25,8 @@
25#include <linux/mfd/samsung/core.h> 25#include <linux/mfd/samsung/core.h>
26#include <linux/mfd/samsung/s2mps11.h> 26#include <linux/mfd/samsung/s2mps11.h>
27 27
28#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)
29
30struct s2mps11_info { 28struct s2mps11_info {
29 unsigned int rdev_num;
31 int ramp_delay2; 30 int ramp_delay2;
32 int ramp_delay34; 31 int ramp_delay34;
33 int ramp_delay5; 32 int ramp_delay5;
@@ -343,7 +342,7 @@ static struct regulator_ops s2mps11_buck_ops = {
343 .enable_mask = S2MPS11_ENABLE_MASK \ 342 .enable_mask = S2MPS11_ENABLE_MASK \
344} 343}
345 344
346static const struct regulator_desc regulators[] = { 345static const struct regulator_desc s2mps11_regulators[] __initconst = {
347 regulator_desc_ldo2(1), 346 regulator_desc_ldo2(1),
348 regulator_desc_ldo1(2), 347 regulator_desc_ldo1(2),
349 regulator_desc_ldo1(3), 348 regulator_desc_ldo1(3),
@@ -394,21 +393,62 @@ static const struct regulator_desc regulators[] = {
394 regulator_desc_buck10, 393 regulator_desc_buck10,
395}; 394};
396 395
396/*
397 * Allocates memory under 'regulators' pointer and copies there array
398 * of regulator_desc for given device.
399 *
400 * Returns number of regulators or negative ERRNO on error.
401 */
402static int __init
403s2mps11_pmic_init_regulators_desc(struct platform_device *pdev,
404 struct regulator_desc **regulators)
405{
406 const struct regulator_desc *regulators_init;
407 enum sec_device_type dev_type;
408 int rdev_num;
409
410 dev_type = platform_get_device_id(pdev)->driver_data;
411 switch (dev_type) {
412 case S2MPS11X:
413 rdev_num = ARRAY_SIZE(s2mps11_regulators);
414 regulators_init = s2mps11_regulators;
415 break;
416 default:
417 dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
418 return -EINVAL;
419 };
420
421 *regulators = devm_kzalloc(&pdev->dev,
422 sizeof(**regulators) * rdev_num, GFP_KERNEL);
423 if (!*regulators)
424 return -ENOMEM;
425
426 memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num);
427
428 return rdev_num;
429}
430
397static int s2mps11_pmic_probe(struct platform_device *pdev) 431static int s2mps11_pmic_probe(struct platform_device *pdev)
398{ 432{
399 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 433 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
400 struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 434 struct sec_platform_data *pdata = iodev->pdata;
401 struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX]; 435 struct of_regulator_match *rdata = NULL;
402 struct device_node *reg_np = NULL; 436 struct device_node *reg_np = NULL;
403 struct regulator_config config = { }; 437 struct regulator_config config = { };
404 struct s2mps11_info *s2mps11; 438 struct s2mps11_info *s2mps11;
405 int i, ret; 439 int i, ret = 0;
440 struct regulator_desc *regulators = NULL;
441 int rdev_num;
406 442
407 s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), 443 s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
408 GFP_KERNEL); 444 GFP_KERNEL);
409 if (!s2mps11) 445 if (!s2mps11)
410 return -ENOMEM; 446 return -ENOMEM;
411 447
448 rdev_num = s2mps11_pmic_init_regulators_desc(pdev, &regulators);
449 if (rdev_num < 0)
450 return rdev_num;
451
412 if (!iodev->dev->of_node) { 452 if (!iodev->dev->of_node) {
413 if (pdata) { 453 if (pdata) {
414 goto common_reg; 454 goto common_reg;
@@ -419,24 +459,30 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
419 } 459 }
420 } 460 }
421 461
422 for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) 462 rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
463 if (!rdata)
464 return -ENOMEM;
465
466 for (i = 0; i < rdev_num; i++)
423 rdata[i].name = regulators[i].name; 467 rdata[i].name = regulators[i].name;
424 468
425 reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); 469 reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
426 if (!reg_np) { 470 if (!reg_np) {
427 dev_err(&pdev->dev, "could not find regulators sub-node\n"); 471 dev_err(&pdev->dev, "could not find regulators sub-node\n");
428 return -EINVAL; 472 ret = -EINVAL;
473 goto out;
429 } 474 }
430 475
431 of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); 476 of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);
432 477
433common_reg: 478common_reg:
434 platform_set_drvdata(pdev, s2mps11); 479 platform_set_drvdata(pdev, s2mps11);
480 s2mps11->rdev_num = rdev_num;
435 481
436 config.dev = &pdev->dev; 482 config.dev = &pdev->dev;
437 config.regmap = iodev->regmap_pmic; 483 config.regmap = iodev->regmap_pmic;
438 config.driver_data = s2mps11; 484 config.driver_data = s2mps11;
439 for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { 485 for (i = 0; i < rdev_num; i++) {
440 struct regulator_dev *regulator; 486 struct regulator_dev *regulator;
441 487
442 if (!reg_np) { 488 if (!reg_np) {
@@ -453,15 +499,18 @@ common_reg:
453 ret = PTR_ERR(regulator); 499 ret = PTR_ERR(regulator);
454 dev_err(&pdev->dev, "regulator init failed for %d\n", 500 dev_err(&pdev->dev, "regulator init failed for %d\n",
455 i); 501 i);
456 return ret; 502 goto out;
457 } 503 }
458 } 504 }
459 505
460 return 0; 506out:
507 kfree(rdata);
508
509 return ret;
461} 510}
462 511
463static const struct platform_device_id s2mps11_pmic_id[] = { 512static const struct platform_device_id s2mps11_pmic_id[] = {
464 { "s2mps11-pmic", 0}, 513 { "s2mps11-pmic", S2MPS11X},
465 { }, 514 { },
466}; 515};
467MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id); 516MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);