Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e80f95b authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski Committed by Mark Brown
Browse files

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: default avatarKrzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Cc: Yadwinder Singh Brar <yadi.brar01@gmail.com>
Reviewed-by: default avatarYadwinder Singh Brar <yadi.brar@samsung.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 219ef031
Loading
Loading
Loading
Loading
+62 −13
Original line number Original line Diff line number Diff line
@@ -25,9 +25,8 @@
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps11.h>


#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators)

struct s2mps11_info {
struct s2mps11_info {
	unsigned int rdev_num;
	int ramp_delay2;
	int ramp_delay2;
	int ramp_delay34;
	int ramp_delay34;
	int ramp_delay5;
	int ramp_delay5;
@@ -343,7 +342,7 @@ static struct regulator_ops s2mps11_buck_ops = {
	.enable_mask	= S2MPS11_ENABLE_MASK			\
	.enable_mask	= S2MPS11_ENABLE_MASK			\
}
}


static const struct regulator_desc regulators[] = {
static const struct regulator_desc s2mps11_regulators[] __initconst = {
	regulator_desc_ldo2(1),
	regulator_desc_ldo2(1),
	regulator_desc_ldo1(2),
	regulator_desc_ldo1(2),
	regulator_desc_ldo1(3),
	regulator_desc_ldo1(3),
@@ -394,21 +393,62 @@ static const struct regulator_desc regulators[] = {
	regulator_desc_buck10,
	regulator_desc_buck10,
};
};


/*
 * Allocates memory under 'regulators' pointer and copies there array
 * of regulator_desc for given device.
 *
 * Returns number of regulators or negative ERRNO on error.
 */
static int __init
s2mps11_pmic_init_regulators_desc(struct platform_device *pdev,
		struct regulator_desc **regulators)
{
	const struct regulator_desc *regulators_init;
	enum sec_device_type dev_type;
	int rdev_num;

	dev_type = platform_get_device_id(pdev)->driver_data;
	switch (dev_type) {
	case S2MPS11X:
		rdev_num = ARRAY_SIZE(s2mps11_regulators);
		regulators_init = s2mps11_regulators;
		break;
	default:
		dev_err(&pdev->dev, "Invalid device type: %u\n", dev_type);
		return -EINVAL;
	};

	*regulators = devm_kzalloc(&pdev->dev,
			sizeof(**regulators) * rdev_num, GFP_KERNEL);
	if (!*regulators)
		return -ENOMEM;

	memcpy(*regulators, regulators_init, sizeof(**regulators) * rdev_num);

	return rdev_num;
}

static int s2mps11_pmic_probe(struct platform_device *pdev)
static int s2mps11_pmic_probe(struct platform_device *pdev)
{
{
	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
	struct sec_platform_data *pdata = iodev->pdata;
	struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX];
	struct of_regulator_match *rdata = NULL;
	struct device_node *reg_np = NULL;
	struct device_node *reg_np = NULL;
	struct regulator_config config = { };
	struct regulator_config config = { };
	struct s2mps11_info *s2mps11;
	struct s2mps11_info *s2mps11;
	int i, ret;
	int i, ret = 0;
	struct regulator_desc *regulators = NULL;
	int rdev_num;


	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
	s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
				GFP_KERNEL);
				GFP_KERNEL);
	if (!s2mps11)
	if (!s2mps11)
		return -ENOMEM;
		return -ENOMEM;


	rdev_num = s2mps11_pmic_init_regulators_desc(pdev, &regulators);
	if (rdev_num < 0)
		return rdev_num;

	if (!iodev->dev->of_node) {
	if (!iodev->dev->of_node) {
		if (pdata) {
		if (pdata) {
			goto common_reg;
			goto common_reg;
@@ -419,24 +459,30 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
		}
		}
	}
	}


	for (i = 0; i < S2MPS11_REGULATOR_CNT; i++)
	rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
	if (!rdata)
		return -ENOMEM;

	for (i = 0; i < rdev_num; i++)
		rdata[i].name = regulators[i].name;
		rdata[i].name = regulators[i].name;


	reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
	reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators");
	if (!reg_np) {
	if (!reg_np) {
		dev_err(&pdev->dev, "could not find regulators sub-node\n");
		dev_err(&pdev->dev, "could not find regulators sub-node\n");
		return -EINVAL;
		ret = -EINVAL;
		goto out;
	}
	}


	of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX);
	of_regulator_match(&pdev->dev, reg_np, rdata, rdev_num);


common_reg:
common_reg:
	platform_set_drvdata(pdev, s2mps11);
	platform_set_drvdata(pdev, s2mps11);
	s2mps11->rdev_num = rdev_num;


	config.dev = &pdev->dev;
	config.dev = &pdev->dev;
	config.regmap = iodev->regmap_pmic;
	config.regmap = iodev->regmap_pmic;
	config.driver_data = s2mps11;
	config.driver_data = s2mps11;
	for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
	for (i = 0; i < rdev_num; i++) {
		struct regulator_dev *regulator;
		struct regulator_dev *regulator;


		if (!reg_np) {
		if (!reg_np) {
@@ -453,15 +499,18 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
			ret = PTR_ERR(regulator);
			ret = PTR_ERR(regulator);
			dev_err(&pdev->dev, "regulator init failed for %d\n",
			dev_err(&pdev->dev, "regulator init failed for %d\n",
				i);
				i);
			return ret;
			goto out;
		}
		}
	}
	}


	return 0;
out:
	kfree(rdata);

	return ret;
}
}


static const struct platform_device_id s2mps11_pmic_id[] = {
static const struct platform_device_id s2mps11_pmic_id[] = {
	{ "s2mps11-pmic", 0},
	{ "s2mps11-pmic", S2MPS11X},
	{ },
	{ },
};
};
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);