diff mbox

[v4,2/5] mfd: lm3533: Support initialization from Device Tree

Message ID 20161226181153.11271-2-bjorn.andersson@linaro.org
State Superseded
Headers show

Commit Message

Bjorn Andersson Dec. 26, 2016, 6:11 p.m. UTC
From: Bjorn Andersson <bjorn.andersson@sonymobile.com>


Implement support for initialization of the lm3533 driver core and
probing child devices from Device Tree.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

---

Changes since v3:
- Moved parsing of child of nodes into each child driver
- Use of_platform_populate() to instanciate child devices

 drivers/mfd/lm3533-core.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

-- 
2.11.0

Comments

Bjorn Andersson Jan. 4, 2017, 7:26 p.m. UTC | #1
On Wed 04 Jan 03:54 PST 2017, Lee Jones wrote:

> On Mon, 26 Dec 2016, Bjorn Andersson wrote:

> 

> > From: Bjorn Andersson <bjorn.andersson@sonymobile.com>

> > 

> > Implement support for initialization of the lm3533 driver core and

> > probing child devices from Device Tree.

> > 


[..]

> > @@ -512,6 +514,11 @@ static int lm3533_device_init(struct lm3533 *lm3533)

> >  	lm3533_device_bl_init(lm3533);

> >  	lm3533_device_led_init(lm3533);

> >  

> > +	if (lm3533->dev->of_node) {

> > +		of_platform_populate(lm3533->dev->of_node, NULL, NULL,

> > +				     lm3533->dev);

> > +	}

> 

> I think it's save to call of_platform_populate(), even if !of_node.

> It will just fail and return an error code, which you are ignoring

> anyway.

> 


I thought so too, but that's apparently how you trigger probing children
of the root node. So we're stuck with a conditional.

[..]

> >  static int lm3533_i2c_probe(struct i2c_client *i2c,

> >  					const struct i2c_device_id *id)

> >  {


[..]

> >  

> > +	if (i2c->dev.of_node) {

> 

> I'd prefer this check to be placed in lm3533_pdata_from_of_node().

> 

> Just return silently if !dev->of_node.

> 


I agree, will update this.

> > +		ret = lm3533_pdata_from_of_node(lm3533->dev);

> > +		if (ret < 0)

> > +			return ret;

> > +	}

> > +

> >  	return lm3533_device_init(lm3533);

> >  }

> >  


Regards,
Bjorn
Lee Jones Jan. 6, 2017, 9:53 a.m. UTC | #2
On Thu, 05 Jan 2017, Bjorn Andersson wrote:

> On Wed 04 Jan 23:49 PST 2017, Lee Jones wrote:

> 

> > On Wed, 04 Jan 2017, Bjorn Andersson wrote:

> > 

> > > On Wed 04 Jan 03:54 PST 2017, Lee Jones wrote:

> > > 

> > > > On Mon, 26 Dec 2016, Bjorn Andersson wrote:

> > > > 

> > > > > From: Bjorn Andersson <bjorn.andersson@sonymobile.com>

> > > > > 

> > > > > Implement support for initialization of the lm3533 driver core and

> > > > > probing child devices from Device Tree.

> > > > > 

> > > 

> > > [..]

> > > 

> > > > > @@ -512,6 +514,11 @@ static int lm3533_device_init(struct lm3533 *lm3533)

> > > > >  	lm3533_device_bl_init(lm3533);

> > > > >  	lm3533_device_led_init(lm3533);

> > > > >  

> > > > > +	if (lm3533->dev->of_node) {

> > > > > +		of_platform_populate(lm3533->dev->of_node, NULL, NULL,

> > > > > +				     lm3533->dev);

> > > > > +	}

> > > > 

> > > > I think it's save to call of_platform_populate(), even if !of_node.

> > > > It will just fail and return an error code, which you are ignoring

> > > > anyway.

> > > > 

> > > 

> > > I thought so too, but that's apparently how you trigger probing children

> > > of the root node. So we're stuck with a conditional.

> > 

> > Ah, so this is to protect against the case where DT is present, but a

> > node for this device is not (or is disabled), so is left unprobed.

> > Then the bind is initiated via I2C?  Or something else?

> > 

> 

> In the event that a new lm3533 is spawned from sysfs we would not have

> platform_data when entering lm3533_device_init() and just bail early.

> 

> Therefor, this issue would be limited to the odd case of lm3533 being

> initiated from code (e.g. a board file) on a DT enabled system. In which

> case it will create and probe new devices from the root of the DT.


Eewww, do we really want to support that?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Lee Jones Jan. 9, 2017, 8:36 a.m. UTC | #3
On Fri, 06 Jan 2017, Bjorn Andersson wrote:

> On Fri 06 Jan 01:53 PST 2017, Lee Jones wrote:

> 

> > On Thu, 05 Jan 2017, Bjorn Andersson wrote:

> > 

> > > On Wed 04 Jan 23:49 PST 2017, Lee Jones wrote:

> > > 

> > > > On Wed, 04 Jan 2017, Bjorn Andersson wrote:

> > > > 

> > > > > On Wed 04 Jan 03:54 PST 2017, Lee Jones wrote:

> > > > > 

> > > > > > On Mon, 26 Dec 2016, Bjorn Andersson wrote:

> > > > > > 

> > > > > > > From: Bjorn Andersson <bjorn.andersson@sonymobile.com>

> > > > > > > 

> > > > > > > Implement support for initialization of the lm3533 driver core and

> > > > > > > probing child devices from Device Tree.

> > > > > > > 

> > > > > 

> > > > > [..]

> > > > > 

> > > > > > > @@ -512,6 +514,11 @@ static int lm3533_device_init(struct lm3533 *lm3533)

> > > > > > >  	lm3533_device_bl_init(lm3533);

> > > > > > >  	lm3533_device_led_init(lm3533);

> > > > > > >  

> > > > > > > +	if (lm3533->dev->of_node) {

> > > > > > > +		of_platform_populate(lm3533->dev->of_node, NULL, NULL,

> > > > > > > +				     lm3533->dev);

> > > > > > > +	}

> > > > > > 

> > > > > > I think it's save to call of_platform_populate(), even if !of_node.

> > > > > > It will just fail and return an error code, which you are ignoring

> > > > > > anyway.

> > > > > > 

> > > > > 

> > > > > I thought so too, but that's apparently how you trigger probing children

> > > > > of the root node. So we're stuck with a conditional.

> > > > 

> > > > Ah, so this is to protect against the case where DT is present, but a

> > > > node for this device is not (or is disabled), so is left unprobed.

> > > > Then the bind is initiated via I2C?  Or something else?

> > > > 

> > > 

> > > In the event that a new lm3533 is spawned from sysfs we would not have

> > > platform_data when entering lm3533_device_init() and just bail early.

> > > 

> > > Therefor, this issue would be limited to the odd case of lm3533 being

> > > initiated from code (e.g. a board file) on a DT enabled system. In which

> > > case it will create and probe new devices from the root of the DT.

> > 

> > Eewww, do we really want to support that?

> > 

> 

> As long as we support non-DT probing of the driver this is a possible

> scenario. And with modern ARM being DT-centric I think that if anyone

> uses this driver with a modern version of the Linux kernel it's likely

> that they would have this kind of hybrid solution.

> 

> So, although ugly, I think we should keep this conditional and hope that

> anyone using the driver will transition to use the DT binding.


Very well, but can you add a comment describing the reason for its
existence with a view to removing it further down the line?

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
Bjorn Andersson Jan. 11, 2017, 7:55 p.m. UTC | #4
On Mon 09 Jan 00:36 PST 2017, Lee Jones wrote:

> On Fri, 06 Jan 2017, Bjorn Andersson wrote:

> 

> > On Fri 06 Jan 01:53 PST 2017, Lee Jones wrote:

> > 

> > > On Thu, 05 Jan 2017, Bjorn Andersson wrote:

> > > 

> > > > On Wed 04 Jan 23:49 PST 2017, Lee Jones wrote:

> > > > 

> > > > > On Wed, 04 Jan 2017, Bjorn Andersson wrote:

> > > > > 

> > > > > > On Wed 04 Jan 03:54 PST 2017, Lee Jones wrote:

> > > > > > 

> > > > > > > On Mon, 26 Dec 2016, Bjorn Andersson wrote:

> > > > > > > 

> > > > > > > > From: Bjorn Andersson <bjorn.andersson@sonymobile.com>

> > > > > > > > 

> > > > > > > > Implement support for initialization of the lm3533 driver core and

> > > > > > > > probing child devices from Device Tree.

> > > > > > > > 

> > > > > > 

> > > > > > [..]

> > > > > > 

> > > > > > > > @@ -512,6 +514,11 @@ static int lm3533_device_init(struct lm3533 *lm3533)

> > > > > > > >  	lm3533_device_bl_init(lm3533);

> > > > > > > >  	lm3533_device_led_init(lm3533);

> > > > > > > >  

> > > > > > > > +	if (lm3533->dev->of_node) {

> > > > > > > > +		of_platform_populate(lm3533->dev->of_node, NULL, NULL,

> > > > > > > > +				     lm3533->dev);

> > > > > > > > +	}

> > > > > > > 

> > > > > > > I think it's save to call of_platform_populate(), even if !of_node.

> > > > > > > It will just fail and return an error code, which you are ignoring

> > > > > > > anyway.

> > > > > > > 

> > > > > > 

> > > > > > I thought so too, but that's apparently how you trigger probing children

> > > > > > of the root node. So we're stuck with a conditional.

> > > > > 

> > > > > Ah, so this is to protect against the case where DT is present, but a

> > > > > node for this device is not (or is disabled), so is left unprobed.

> > > > > Then the bind is initiated via I2C?  Or something else?

> > > > > 

> > > > 

> > > > In the event that a new lm3533 is spawned from sysfs we would not have

> > > > platform_data when entering lm3533_device_init() and just bail early.

> > > > 

> > > > Therefor, this issue would be limited to the odd case of lm3533 being

> > > > initiated from code (e.g. a board file) on a DT enabled system. In which

> > > > case it will create and probe new devices from the root of the DT.

> > > 

> > > Eewww, do we really want to support that?

> > > 

> > 

> > As long as we support non-DT probing of the driver this is a possible

> > scenario. And with modern ARM being DT-centric I think that if anyone

> > uses this driver with a modern version of the Linux kernel it's likely

> > that they would have this kind of hybrid solution.

> > 

> > So, although ugly, I think we should keep this conditional and hope that

> > anyone using the driver will transition to use the DT binding.

> 

> Very well, but can you add a comment describing the reason for its

> existence with a view to removing it further down the line?

> 


Sounds reasonable, I will prepare an updated patch with this.

Regards,
Bjorn
diff mbox

Patch

diff --git a/drivers/mfd/lm3533-core.c b/drivers/mfd/lm3533-core.c
index 5abcbb2e8849..f147677f05ff 100644
--- a/drivers/mfd/lm3533-core.c
+++ b/drivers/mfd/lm3533-core.c
@@ -18,6 +18,8 @@ 
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/mfd/core.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
 #include <linux/regmap.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -512,6 +514,11 @@  static int lm3533_device_init(struct lm3533 *lm3533)
 	lm3533_device_bl_init(lm3533);
 	lm3533_device_led_init(lm3533);
 
+	if (lm3533->dev->of_node) {
+		of_platform_populate(lm3533->dev->of_node, NULL, NULL,
+				     lm3533->dev);
+	}
+
 	ret = sysfs_create_group(&lm3533->dev->kobj, &lm3533_attribute_group);
 	if (ret < 0) {
 		dev_err(lm3533->dev, "failed to create sysfs attributes\n");
@@ -588,10 +595,73 @@  static const struct regmap_config regmap_config = {
 	.precious_reg	= lm3533_precious_register,
 };
 
+static int lm3533_of_parse_enum(struct device *dev, const char *propname,
+				const unsigned int *match, size_t num_matches)
+{
+	size_t i;
+	int ret;
+	u32 val;
+
+	ret = of_property_read_u32(dev->of_node, propname, &val);
+	if (ret < 0) {
+		dev_err(dev, "failed to parse %s\n", propname);
+		return ret;
+	}
+
+	for (i = 0; i < num_matches; i++) {
+		if (val == match[i])
+			return i;
+	}
+
+	dev_err(dev, "unsupported value of %s\n", propname);
+	return -EINVAL;
+}
+
+static int lm3533_pdata_from_of_node(struct device *dev)
+{
+	struct lm3533_platform_data *pdata;
+	int ret;
+	const unsigned int freqs[] = {
+		[LM3533_BOOST_FREQ_500KHZ] = 500000,
+		[LM3533_BOOST_FREQ_1000KHZ] = 1000000,
+	};
+	const unsigned int ovps[] = {
+		[LM3533_BOOST_OVP_16V] = 16000,
+		[LM3533_BOOST_OVP_24V] = 24000,
+		[LM3533_BOOST_OVP_32V] = 32000,
+		[LM3533_BOOST_OVP_40V] = 40000,
+	};
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->gpio_hwen = of_get_named_gpio(dev->of_node, "hwen-gpios", 0);
+	if (pdata->gpio_hwen < 0)
+		return pdata->gpio_hwen;
+
+	ret = lm3533_of_parse_enum(dev, "ti,boost-freq-hz",
+				   freqs, ARRAY_SIZE(freqs));
+	if (ret < 0)
+		return ret;
+	pdata->boost_freq = ret;
+
+	ret = lm3533_of_parse_enum(dev, "ti,boost-ovp-mv",
+				   ovps, ARRAY_SIZE(ovps));
+	if (ret < 0)
+		return ret;
+	pdata->boost_ovp = ret;
+
+	dev->platform_data = pdata;
+
+	return 0;
+}
+
 static int lm3533_i2c_probe(struct i2c_client *i2c,
 					const struct i2c_device_id *id)
 {
 	struct lm3533 *lm3533;
+	int ret;
 
 	dev_dbg(&i2c->dev, "%s\n", __func__);
 
@@ -608,6 +678,12 @@  static int lm3533_i2c_probe(struct i2c_client *i2c,
 	lm3533->dev = &i2c->dev;
 	lm3533->irq = i2c->irq;
 
+	if (i2c->dev.of_node) {
+		ret = lm3533_pdata_from_of_node(lm3533->dev);
+		if (ret < 0)
+			return ret;
+	}
+
 	return lm3533_device_init(lm3533);
 }