Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Krzysztof Kozlowski and committed by
Mark Brown
3e80f95b 219ef031

+62 -13
+62 -13
drivers/regulator/s2mps11.c
··· 25 25 #include <linux/mfd/samsung/core.h> 26 26 #include <linux/mfd/samsung/s2mps11.h> 27 27 28 - #define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators) 29 - 30 28 struct s2mps11_info { 29 + unsigned int rdev_num; 31 30 int ramp_delay2; 32 31 int ramp_delay34; 33 32 int ramp_delay5; ··· 342 343 .enable_mask = S2MPS11_ENABLE_MASK \ 343 344 } 344 345 345 - static const struct regulator_desc regulators[] = { 346 + static const struct regulator_desc s2mps11_regulators[] __initconst = { 346 347 regulator_desc_ldo2(1), 347 348 regulator_desc_ldo1(2), 348 349 regulator_desc_ldo1(3), ··· 393 394 regulator_desc_buck10, 394 395 }; 395 396 397 + /* 398 + * Allocates memory under 'regulators' pointer and copies there array 399 + * of regulator_desc for given device. 400 + * 401 + * Returns number of regulators or negative ERRNO on error. 402 + */ 403 + static int __init 404 + s2mps11_pmic_init_regulators_desc(struct platform_device *pdev, 405 + struct regulator_desc **regulators) 406 + { 407 + const struct regulator_desc *regulators_init; 408 + enum sec_device_type dev_type; 409 + int rdev_num; 410 + 411 + dev_type = platform_get_device_id(pdev)->driver_data; 412 + switch (dev_type) { 413 + case S2MPS11X: 414 + rdev_num = ARRAY_SIZE(s2mps11_regulators); 415 + regulators_init = s2mps11_regulators; 416 + break; 417 + default: 418 + dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type); 419 + return -EINVAL; 420 + }; 421 + 422 + *regulators = devm_kzalloc(&pdev->dev, 423 + sizeof(**regulators) * rdev_num, GFP_KERNEL); 424 + if (!*regulators) 425 + return -ENOMEM; 426 + 427 + memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num); 428 + 429 + return rdev_num; 430 + } 431 + 396 432 static int s2mps11_pmic_probe(struct platform_device *pdev) 397 433 { 398 434 struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); 399 - struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); 400 - struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX]; 435 + struct sec_platform_data *pdata = iodev->pdata; 436 + struct of_regulator_match *rdata = NULL; 401 437 struct device_node *reg_np = NULL; 402 438 struct regulator_config config = { }; 403 439 struct s2mps11_info *s2mps11; 404 - int i, ret; 440 + int i, ret = 0; 441 + struct regulator_desc *regulators = NULL; 442 + int rdev_num; 405 443 406 444 s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), 407 445 GFP_KERNEL); 408 446 if (!s2mps11) 409 447 return -ENOMEM; 448 + 449 + rdev_num = s2mps11_pmic_init_regulators_desc(pdev, &regulators); 450 + if (rdev_num < 0) 451 + return rdev_num; 410 452 411 453 if (!iodev->dev->of_node) { 412 454 if (pdata) { ··· 459 419 } 460 420 } 461 421 462 - for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) 422 + rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL); 423 + if (!rdata) 424 + return -ENOMEM; 425 + 426 + for (i = 0; i < rdev_num; i++) 463 427 rdata[i].name = regulators[i].name; 464 428 465 429 reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); 466 430 if (!reg_np) { 467 431 dev_err(&pdev->dev, "could not find regulators sub-node\n"); 468 - return -EINVAL; 432 + ret = -EINVAL; 433 + goto out; 469 434 } 470 435 471 - of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); 436 + of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num); 472 437 473 438 common_reg: 474 439 platform_set_drvdata(pdev, s2mps11); 440 + s2mps11->rdev_num = rdev_num; 475 441 476 442 config.dev = &pdev->dev; 477 443 config.regmap = iodev->regmap_pmic; 478 444 config.driver_data = s2mps11; 479 - for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { 445 + for (i = 0; i < rdev_num; i++) { 480 446 struct regulator_dev *regulator; 481 447 482 448 if (!reg_np) { ··· 499 453 ret = PTR_ERR(regulator); 500 454 dev_err(&pdev->dev, "regulator init failed for %d\n", 501 455 i); 502 - return ret; 456 + goto out; 503 457 } 504 458 } 505 459 506 - return 0; 460 + out: 461 + kfree(rdata); 462 + 463 + return ret; 507 464 } 508 465 509 466 static const struct platform_device_id s2mps11_pmic_id[] = { 510 - { "s2mps11-pmic", 0}, 467 + { "s2mps11-pmic", S2MPS11X}, 511 468 { }, 512 469 }; 513 470 MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);