diff mbox

[RFT,v3,06/14] regulator: max77802: Remove support for board files

Message ID 1414668053-31370-7-git-send-email-k.kozlowski@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Krzysztof Kozlowski Oct. 30, 2014, 11:20 a.m. UTC
The driver is used only on Exynos based boards with DTS support.
Convert the driver to DTS-only version. Parse all regulators at once,
not one-by-one. Remove dependency on data provided by max77686 MFD
driver.

Use new DT style parsing method for regulators init data. The regulator
driver now should have its own of_compatible property. If it is not
present then it will use "regulators" sub-node of parent's node.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
---
 drivers/regulator/max77802.c | 108 +++++++++++++++----------------------------
 1 file changed, 37 insertions(+), 71 deletions(-)

Comments

Javier Martinez Canillas Oct. 30, 2014, 11:50 a.m. UTC | #1
Hello Krzysztof,

On 10/30/2014 12:20 PM, Krzysztof Kozlowski wrote:
>  static int max77802_pmic_probe(struct platform_device *pdev)
>  {
>  	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> -	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
>  	struct max77802_regulator_prv *max77802;
> -	int i, ret = 0, val;
> +	int i, val;
>  	struct regulator_config config = { };
>  
> -	/* This is allocated by the MFD driver */
> -	if (!pdata) {
> -		dev_err(&pdev->dev, "no platform data found for regulator\n");
> -		return -ENODEV;
> -	}
> -
>  	max77802 = devm_kzalloc(&pdev->dev,
>  				sizeof(struct max77802_regulator_prv),
>  				GFP_KERNEL);
>  	if (!max77802)
>  		return -ENOMEM;
>  
> -	if (iodev->dev->of_node) {
> -		ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
> -		if (ret)
> -			return ret;
> +	if (!pdev->dev.of_node) {
> +		/*
> +		 * Backward DTS compatiblity where regulator driver had not
> +		 * a compatible property for itself.
> +		 */
> +		if (!iodev->dev->of_node) {
> +			dev_err(&pdev->dev, "No OF node for driver and its parent\n");
> +			return -EINVAL;
> +		}
> +		pdev->dev.of_node = of_get_child_by_name(iodev->dev->of_node,
> +								"regulators");
> +		max77802->missing_of_node = true;
>  	}

I may be missing something but I don't understand why a compatible string
for the regulators sub-node is needed. Isn't enough to just fill the
.regulators_node field in the struct regulator_desc? e.g:

    .regulators_node = of_match_ptr("regulators") for max77802
    .regulators_node = of_match_ptr("voltage-regulators") for max77686

AFAIU this should be enough for the core to extract the init_data and will
make your change much more simpler and you can drop patches 1-3 and 13-14.

Or maybe I misread the regulator_of_get_init_data() function?

Best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Krzysztof Kozlowski Oct. 30, 2014, 12:10 p.m. UTC | #2
On czw, 2014-10-30 at 12:50 +0100, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 10/30/2014 12:20 PM, Krzysztof Kozlowski wrote:
> >  static int max77802_pmic_probe(struct platform_device *pdev)
> >  {
> >  	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
> > -	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
> >  	struct max77802_regulator_prv *max77802;
> > -	int i, ret = 0, val;
> > +	int i, val;
> >  	struct regulator_config config = { };
> >  
> > -	/* This is allocated by the MFD driver */
> > -	if (!pdata) {
> > -		dev_err(&pdev->dev, "no platform data found for regulator\n");
> > -		return -ENODEV;
> > -	}
> > -
> >  	max77802 = devm_kzalloc(&pdev->dev,
> >  				sizeof(struct max77802_regulator_prv),
> >  				GFP_KERNEL);
> >  	if (!max77802)
> >  		return -ENOMEM;
> >  
> > -	if (iodev->dev->of_node) {
> > -		ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
> > -		if (ret)
> > -			return ret;
> > +	if (!pdev->dev.of_node) {
> > +		/*
> > +		 * Backward DTS compatiblity where regulator driver had not
> > +		 * a compatible property for itself.
> > +		 */
> > +		if (!iodev->dev->of_node) {
> > +			dev_err(&pdev->dev, "No OF node for driver and its parent\n");
> > +			return -EINVAL;
> > +		}
> > +		pdev->dev.of_node = of_get_child_by_name(iodev->dev->of_node,
> > +								"regulators");
> > +		max77802->missing_of_node = true;
> >  	}
> 
> I may be missing something but I don't understand why a compatible string
> for the regulators sub-node is needed. Isn't enough to just fill the
> .regulators_node field in the struct regulator_desc? e.g:
> 
>     .regulators_node = of_match_ptr("regulators") for max77802
>     .regulators_node = of_match_ptr("voltage-regulators") for max77686
> 
> AFAIU this should be enough for the core to extract the init_data and will
> make your change much more simpler and you can drop patches 1-3 and 13-14.
> 
> Or maybe I misread the regulator_of_get_init_data() function?

The regulator_of_get_init_data() searches from dev->of_node or its child
node.

But dev->of_node is NULL.

That's why of_compatible is needed.

Best regards,
Krzysztof


--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Oct. 30, 2014, 12:21 p.m. UTC | #3
Hello Krzysztof,

On 10/30/2014 01:10 PM, Krzysztof Kozlowski wrote:
>> 
>> I may be missing something but I don't understand why a compatible string
>> for the regulators sub-node is needed. Isn't enough to just fill the
>> .regulators_node field in the struct regulator_desc? e.g:
>> 
>>     .regulators_node = of_match_ptr("regulators") for max77802
>>     .regulators_node = of_match_ptr("voltage-regulators") for max77686
>> 
>> AFAIU this should be enough for the core to extract the init_data and will
>> make your change much more simpler and you can drop patches 1-3 and 13-14.
>> 
>> Or maybe I misread the regulator_of_get_init_data() function?
> 
> The regulator_of_get_init_data() searches from dev->of_node or its child
> node.
> 
> But dev->of_node is NULL.
> 
> That's why of_compatible is needed.

Yes but regulator_register() does dev = config->dev and config->dev is set
to config.dev = iodev->dev in the driver probe function which is the
pdev->dev.parent (the PMIC struct device) that has an associated of_node.

So, regulator_of_get_init_data() will call of_get_child_by_name() passing
the PMIC of_node and the sub-node name that contains the regulators. That
is, whatever was set in desc->regulators_node and that should be enough.

Best regards,
Javier

--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Krzysztof Kozlowski Oct. 30, 2014, 12:30 p.m. UTC | #4
On czw, 2014-10-30 at 13:21 +0100, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 10/30/2014 01:10 PM, Krzysztof Kozlowski wrote:
> >> 
> >> I may be missing something but I don't understand why a compatible string
> >> for the regulators sub-node is needed. Isn't enough to just fill the
> >> .regulators_node field in the struct regulator_desc? e.g:
> >> 
> >>     .regulators_node = of_match_ptr("regulators") for max77802
> >>     .regulators_node = of_match_ptr("voltage-regulators") for max77686
> >> 
> >> AFAIU this should be enough for the core to extract the init_data and will
> >> make your change much more simpler and you can drop patches 1-3 and 13-14.
> >> 
> >> Or maybe I misread the regulator_of_get_init_data() function?
> > 
> > The regulator_of_get_init_data() searches from dev->of_node or its child
> > node.
> > 
> > But dev->of_node is NULL.
> > 
> > That's why of_compatible is needed.
> 
> Yes but regulator_register() does dev = config->dev and config->dev is set
> to config.dev = iodev->dev in the driver probe function which is the
> pdev->dev.parent (the PMIC struct device) that has an associated of_node.
> 
> So, regulator_of_get_init_data() will call of_get_child_by_name() passing
> the PMIC of_node and the sub-node name that contains the regulators. That
> is, whatever was set in desc->regulators_node and that should be enough.

I missed that one in max77802 (in max77686: config.dev = &pdev->dev).
Now I wonder if it is proper to attach regulators to driver's parent
device. Consider regulator_register, around line 3640:
	rdev->dev.parent = dev;
The parent of regulators will be equal to parent of regulator driver -
main MFD driver.

Best regards,
Krzysztof


--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Oct. 30, 2014, 12:42 p.m. UTC | #5
Hello Krzysztof,

On 10/30/2014 01:30 PM, Krzysztof Kozlowski wrote:
tor_of_get_init_data() function?
>> > 
>> > The regulator_of_get_init_data() searches from dev->of_node or its child
>> > node.
>> > 
>> > But dev->of_node is NULL.
>> > 
>> > That's why of_compatible is needed.
>> 
>> Yes but regulator_register() does dev = config->dev and config->dev is set
>> to config.dev = iodev->dev in the driver probe function which is the
>> pdev->dev.parent (the PMIC struct device) that has an associated of_node.
>> 
>> So, regulator_of_get_init_data() will call of_get_child_by_name() passing
>> the PMIC of_node and the sub-node name that contains the regulators. That
>> is, whatever was set in desc->regulators_node and that should be enough.
> 
> I missed that one in max77802 (in max77686: config.dev = &pdev->dev).
> Now I wonder if it is proper to attach regulators to driver's parent
> device. Consider regulator_register, around line 3640:
> 	rdev->dev.parent = dev;
> The parent of regulators will be equal to parent of regulator driver -
> main MFD driver.
>

An early version of the max77802 regulator driver also set config.dev to
&pdev->dev but then Mark asked me if I was sure that it should not be the
MFD device instead.

I then read in regulator_register() that the rdev->dev.parent was set
to the device passed in config.dev as you said so I was convinced that it
should be the parent device instead.

Please take a look at [0] for that discussion.

Best regards,
Javier

[0]: https://lkml.org/lkml/2014/6/17/174
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Krzysztof Kozlowski Oct. 30, 2014, 12:53 p.m. UTC | #6
On czw, 2014-10-30 at 13:42 +0100, Javier Martinez Canillas wrote:
> Hello Krzysztof,
> 
> On 10/30/2014 01:30 PM, Krzysztof Kozlowski wrote:
> tor_of_get_init_data() function?
> >> > 
> >> > The regulator_of_get_init_data() searches from dev->of_node or its child
> >> > node.
> >> > 
> >> > But dev->of_node is NULL.
> >> > 
> >> > That's why of_compatible is needed.
> >> 
> >> Yes but regulator_register() does dev = config->dev and config->dev is set
> >> to config.dev = iodev->dev in the driver probe function which is the
> >> pdev->dev.parent (the PMIC struct device) that has an associated of_node.
> >> 
> >> So, regulator_of_get_init_data() will call of_get_child_by_name() passing
> >> the PMIC of_node and the sub-node name that contains the regulators. That
> >> is, whatever was set in desc->regulators_node and that should be enough.
> > 
> > I missed that one in max77802 (in max77686: config.dev = &pdev->dev).
> > Now I wonder if it is proper to attach regulators to driver's parent
> > device. Consider regulator_register, around line 3640:
> > 	rdev->dev.parent = dev;
> > The parent of regulators will be equal to parent of regulator driver -
> > main MFD driver.
> >
> 
> An early version of the max77802 regulator driver also set config.dev to
> &pdev->dev but then Mark asked me if I was sure that it should not be the
> MFD device instead.
> 
> I then read in regulator_register() that the rdev->dev.parent was set
> to the device passed in config.dev as you said so I was convinced that it
> should be the parent device instead.
> 
> Please take a look at [0] for that discussion.

To me a intuitive structure would be:
MFD device
  |
  - clock device
     |
     - clock1
     - clock2
  - regulator device
     |
     - LDO1
     - LDO2
etc.

This also maps to structure in DTS. dev_err* messages and any
allocations should be done on behalf of regulator device, not parent.

Various drivers do this differently... The wm8* drivers set it mostly to
parent (MFD)...

I do not insists, especially because using parent's device would make
this driver simpler.

Mark, maybe you could shed light on it?


Best regards,
Krzysztof


--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Javier Martinez Canillas Oct. 30, 2014, 2:02 p.m. UTC | #7
Hello Krzysztof,

On 10/30/2014 01:53 PM, Krzysztof Kozlowski wrote:
> 
> To me a intuitive structure would be:
> MFD device
>   |
>   - clock device
>      |
>      - clock1
>      - clock2
>   - regulator device
>      |
>      - LDO1
>      - LDO2
> etc.
> 
> This also maps to structure in DTS. dev_err* messages and any
> allocations should be done on behalf of regulator device, not parent.
>
> Various drivers do this differently... The wm8* drivers set it mostly to
> parent (MFD)...
>
> I do not insists, especially because using parent's device would make
> this driver simpler.
>

Another reason to set it to the parent is to lookup the regulator input supply
node. The regulator_register() function does:

	if (supply) {
		struct regulator_dev *r;

		r = regulator_dev_lookup(dev, supply, &ret);

where dev = config->dev so that will determine on which device node your
input supplies have to be defined. For example on the Peach Pit DTS has this:

	max77802: max77802-pmic@9 {
		...
		inb1-supply = <&tps65090_dcdc2>;
		...
		inb10-supply = <&tps65090_dcdc1>;

		inl1-supply = <&buck5_reg>;
		...
		inl10-supply = <&buck7_reg>;
		...

		regulators {
		...
		};
	};

which is how most (all?) DTS define the input supplies. If you instead
do config.dev = &pdev->dev, then the input supplies have to be in the
"regulators" node which is not the standard AFAICT.

This is not a problem for max77686 because I see that DTS don't define
the input supplies but I guess that is because the power scheme is not
completely modeled.
 
> Mark, maybe you could shed light on it?
> 
> 
> Best regards,
> Krzysztof
> 
> 

Best regards,
Javier
--
To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c
index 60daca2028e9..2cb938610230 100644
--- a/drivers/regulator/max77802.c
+++ b/drivers/regulator/max77802.c
@@ -70,7 +70,9 @@  static unsigned int ramp_table_77802_4bit[] = {
 };
 
 struct max77802_regulator_prv {
+	/* Array indexed by regulator id */
 	unsigned int opmode[MAX77802_REG_MAX];
+	bool missing_of_node;
 };
 
 static inline int max77802_map_mode(int mode)
@@ -362,6 +364,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */
 #define regulator_77802_desc_p_ldo(num, supply, log)	{		\
 	.name		= "LDO"#num,					\
+	.of_match	= of_match_ptr("LDO"#num),			\
 	.id		= MAX77802_LDO##num,				\
 	.supply_name	= "inl"#supply,					\
 	.ops		= &max77802_ldo_ops_logic##log,			\
@@ -380,6 +383,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */
 #define regulator_77802_desc_n_ldo(num, supply, log)   {		\
 	.name		= "LDO"#num,					\
+	.of_match	= of_match_ptr("LDO"#num),			\
 	.id		= MAX77802_LDO##num,				\
 	.supply_name	= "inl"#supply,					\
 	.ops		= &max77802_ldo_ops_logic##log,			\
@@ -398,6 +402,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* BUCKs 1, 6 */
 #define regulator_77802_desc_16_buck(num)	{		\
 	.name		= "BUCK"#num,					\
+	.of_match	= of_match_ptr("BUCK"#num),			\
 	.id		= MAX77802_BUCK##num,				\
 	.supply_name	= "inb"#num,					\
 	.ops		= &max77802_buck_16_dvs_ops,			\
@@ -416,6 +421,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* BUCKS 2-4 */
 #define regulator_77802_desc_234_buck(num)	{		\
 	.name		= "BUCK"#num,					\
+	.of_match	= of_match_ptr("BUCK"#num),			\
 	.id		= MAX77802_BUCK##num,				\
 	.supply_name	= "inb"#num,					\
 	.ops		= &max77802_buck_234_ops,			\
@@ -435,6 +441,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* BUCK 5 */
 #define regulator_77802_desc_buck5(num)		{		\
 	.name		= "BUCK"#num,					\
+	.of_match	= of_match_ptr("BUCK"#num),			\
 	.id		= MAX77802_BUCK##num,				\
 	.supply_name	= "inb"#num,					\
 	.ops		= &max77802_buck_dvs_ops,			\
@@ -453,6 +460,7 @@  static struct regulator_ops max77802_buck_dvs_ops = {
 /* BUCKs 7-10 */
 #define regulator_77802_desc_buck7_10(num)	{		\
 	.name		= "BUCK"#num,					\
+	.of_match	= of_match_ptr("BUCK"#num),			\
 	.id		= MAX77802_BUCK##num,				\
 	.supply_name	= "inb"#num,					\
 	.ops		= &max77802_buck_dvs_ops,			\
@@ -513,83 +521,31 @@  static struct regulator_desc regulators[] = {
 	regulator_77802_desc_n_ldo(35, 2, 1),
 };
 
-#ifdef CONFIG_OF
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
-					struct max77686_platform_data *pdata)
-{
-	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-	struct device_node *pmic_np, *regulators_np;
-	struct max77686_regulator_data *rdata;
-	struct of_regulator_match rmatch;
-	unsigned int i;
-
-	pmic_np = iodev->dev->of_node;
-	regulators_np = of_get_child_by_name(pmic_np, "regulators");
-	if (!regulators_np) {
-		dev_err(&pdev->dev, "could not find regulators sub-node\n");
-		return -EINVAL;
-	}
-
-	pdata->num_regulators = ARRAY_SIZE(regulators);
-	rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
-			     pdata->num_regulators, GFP_KERNEL);
-	if (!rdata) {
-		of_node_put(regulators_np);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < pdata->num_regulators; i++) {
-		rmatch.name = regulators[i].name;
-		rmatch.init_data = NULL;
-		rmatch.of_node = NULL;
-		if (of_regulator_match(&pdev->dev, regulators_np, &rmatch,
-				       1) != 1) {
-			dev_warn(&pdev->dev, "No matching regulator for '%s'\n",
-				 rmatch.name);
-			continue;
-		}
-		rdata[i].initdata = rmatch.init_data;
-		rdata[i].of_node = rmatch.of_node;
-		rdata[i].id = regulators[i].id;
-	}
-
-	pdata->regulators = rdata;
-	of_node_put(regulators_np);
-
-	return 0;
-}
-#else
-static int max77802_pmic_dt_parse_pdata(struct platform_device *pdev,
-					struct max77686_platform_data *pdata)
-{
-	return 0;
-}
-#endif /* CONFIG_OF */
-
 static int max77802_pmic_probe(struct platform_device *pdev)
 {
 	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-	struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
 	struct max77802_regulator_prv *max77802;
-	int i, ret = 0, val;
+	int i, val;
 	struct regulator_config config = { };
 
-	/* This is allocated by the MFD driver */
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data found for regulator\n");
-		return -ENODEV;
-	}
-
 	max77802 = devm_kzalloc(&pdev->dev,
 				sizeof(struct max77802_regulator_prv),
 				GFP_KERNEL);
 	if (!max77802)
 		return -ENOMEM;
 
-	if (iodev->dev->of_node) {
-		ret = max77802_pmic_dt_parse_pdata(pdev, pdata);
-		if (ret)
-			return ret;
+	if (!pdev->dev.of_node) {
+		/*
+		 * Backward DTS compatiblity where regulator driver had not
+		 * a compatible property for itself.
+		 */
+		if (!iodev->dev->of_node) {
+			dev_err(&pdev->dev, "No OF node for driver and its parent\n");
+			return -EINVAL;
+		}
+		pdev->dev.of_node = of_get_child_by_name(iodev->dev->of_node,
+								"regulators");
+		max77802->missing_of_node = true;
 	}
 
 	config.dev = iodev->dev;
@@ -599,11 +555,9 @@  static int max77802_pmic_probe(struct platform_device *pdev)
 
 	for (i = 0; i < MAX77802_REG_MAX; i++) {
 		struct regulator_dev *rdev;
-		int id = pdata->regulators[i].id;
+		int id = regulators[i].id;
 		int shift = max77802_get_opmode_shift(id);
-
-		config.init_data = pdata->regulators[i].initdata;
-		config.of_node = pdata->regulators[i].of_node;
+		int ret;
 
 		ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val);
 		if (ret < 0) {
@@ -627,15 +581,26 @@  static int max77802_pmic_probe(struct platform_device *pdev)
 		rdev = devm_regulator_register(&pdev->dev,
 					       &regulators[i], &config);
 		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
 			dev_err(&pdev->dev,
-				"regulator init failed for %d\n", i);
-			return PTR_ERR(rdev);
+				"regulator init failed for %d: %d\n", i, ret);
+			return ret;
 		}
 	}
 
 	return 0;
 }
 
+static int max77802_pmic_remove(struct platform_device *pdev)
+{
+	struct max77802_regulator_prv *max77802 = platform_get_drvdata(pdev);
+
+	if (max77802->missing_of_node)
+		of_node_put(pdev->dev.of_node);
+
+	return 0;
+}
+
 static const struct platform_device_id max77802_pmic_id[] = {
 	{"max77802-pmic", 0},
 	{ },
@@ -648,6 +613,7 @@  static struct platform_driver max77802_pmic_driver = {
 		.owner = THIS_MODULE,
 	},
 	.probe = max77802_pmic_probe,
+	.remove = max77802_pmic_remove,
 	.id_table = max77802_pmic_id,
 };