diff mbox

[3/6] mfd: stmpe: prope properly from the device tree

Message ID 1397659455-13638-4-git-send-email-linus.walleij@linaro.org
State New
Headers show

Commit Message

Linus Walleij April 16, 2014, 2:44 p.m. UTC
The current STMPE I2C probing code does not really match the
compatible strings - it matches node names happening to give
the right device name. Instead, let's introduce some real
compatible matching, more complex, more accurate.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/stmpe-i2c.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

Comments

Lee Jones April 17, 2014, 10:44 a.m. UTC | #1
> The current STMPE I2C probing code does not really match the
> compatible strings - it matches node names happening to give
> the right device name. Instead, let's introduce some real
> compatible matching, more complex, more accurate.
> 
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  drivers/mfd/stmpe-i2c.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 59 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
> index 0da02e11d58e..8902a600d978 100644
> --- a/drivers/mfd/stmpe-i2c.c
> +++ b/drivers/mfd/stmpe-i2c.c
> @@ -14,6 +14,7 @@
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/types.h>
> +#include <linux/of_device.h>
>  #include "stmpe.h"
>  
>  static int i2c_reg_read(struct stmpe *stmpe, u8 reg)
> @@ -52,15 +53,71 @@ static struct stmpe_client_info i2c_ci = {
>  	.write_block = i2c_block_write,
>  };
>  
> +#ifdef CONFIG_OF

Didn't you say that the only platform using this device is DT only? So
why don't we make the driver depend on OF and get rid of this ugly
#ifdeffery?

> +static const struct of_device_id stmpe_of_match[] = {
> +	{
> +		.compatible = "st,stmpe610",
> +		.data = (void *)STMPE610,
> +	},
> +	{
> +		.compatible = "st,stmpe801",
> +		.data = (void *)STMPE801,
> +	},
> +	{
> +		.compatible = "st,stmpe811",
> +		.data = (void *)STMPE811,
> +	},
> +	{
> +		.compatible = "st,stmpe1601",
> +		.data = (void *)STMPE1601,
> +	},
> +	{
> +		.compatible = "st,stmpe1801",
> +		.data = (void *)STMPE1801,
> +	},
> +	{
> +		.compatible = "st,stmpe2401",
> +		.data = (void *)STMPE2401,
> +	},
> +	{
> +		.compatible = "st,stmpe2403",
> +		.data = (void *)STMPE2403,
> +	},
> +	{},
> +};

If none of these stray over 80 chars, I think I'd like to see
of_device_id tables as single line entries (unlike mfd_cell structures
where there can be more than 2 entries, which I like spread out - I
know, double standards right?)

+static const struct of_device_id stmpe_of_match[] = {
+	{ .compatible = "st,stmpe610",  .data = (void *)STMPE610,  },
+	{ .compatible = "st,stmpe801",  .data = (void *)STMPE801,  },
+	{ .compatible = "st,stmpe811",  .data = (void *)STMPE811,  },
+	{ .compatible = "st,stmpe1601", .data = (void *)STMPE1601, },
+	{ .compatible = "st,stmpe1801", .data = (void *)STMPE1801, },
+	{ .compatible = "st,stmpe2401", .data = (void *)STMPE2401, },
+	{ .compatible = "st,stmpe2403", .data = (void *)STMPE2403, },
+	{},
+};

> +MODULE_DEVICE_TABLE(of, stmpe_of_match);
> +
> +int stmpe_i2c_of_probe(struct i2c_client *i2c)

Erm, static?

> +{
> +	const struct of_device_id *of_id;
> +
> +	of_id = of_match_device(stmpe_of_match, &i2c->dev);
> +	if (!of_id)
> +		return -EINVAL;
> +	return (int)of_id->data;
> +}
> +#else
> +int stmpe_i2c_of_probe(struct i2c_client *i2c)
> +{
> +	return -EINVAL;
> +}
> +#endif
> +
>  static int
>  stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
>  {
> +	int partnum;
> +
>  	i2c_ci.data = (void *)id;
>  	i2c_ci.irq = i2c->irq;
>  	i2c_ci.client = i2c;
>  	i2c_ci.dev = &i2c->dev;
>  
> -	return stmpe_probe(&i2c_ci, id->driver_data);

if (IS_DEFINED(OF)) {

> +	partnum = stmpe_i2c_of_probe(i2c);

Then you can remove the spare stmpe_i2c_of_probe(), or better still
make the whole driver depend on OF.

> +	if (partnum < 0)
> +		partnum = id->driver_data;

Should this be able to fail and for us to still carry on?

Or are we then running on an unsupported device?

> +	return stmpe_probe(&i2c_ci, partnum);
>  }
>  
>  static int stmpe_i2c_remove(struct i2c_client *i2c)
> @@ -89,6 +146,7 @@ static struct i2c_driver stmpe_i2c_driver = {
>  #ifdef CONFIG_PM
>  		.pm = &stmpe_dev_pm_ops,
>  #endif
> +		.of_match_table = of_match_ptr(stmpe_of_match),
>  	},
>  	.probe		= stmpe_i2c_probe,
>  	.remove		= stmpe_i2c_remove,
Linus Walleij April 23, 2014, 8:52 a.m. UTC | #2
On Thu, Apr 17, 2014 at 12:44 PM, Lee Jones <lee.jones@linaro.org> wrote:

>> +#ifdef CONFIG_OF
>
> Didn't you say that the only platform using this device is DT only? So
> why don't we make the driver depend on OF and get rid of this ugly
> #ifdeffery?

OK fixing.

>> +     {
>> +             .compatible = "st,stmpe2403",
>> +             .data = (void *)STMPE2403,
>> +     },
>> +     {},
>> +};
>
> If none of these stray over 80 chars, I think I'd like to see
> of_device_id tables as single line entries

OK.

>> +     if (partnum < 0)
>> +             partnum = id->driver_data;
>
> Should this be able to fail and for us to still carry on?

Actually yes, to stay compatible with elder device trees that use
the trick to just have the node name correspond to the I2C ID
instead of using compatible, this needs to be preserved. But I'll
add a small nag print about it.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
diff mbox

Patch

diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c
index 0da02e11d58e..8902a600d978 100644
--- a/drivers/mfd/stmpe-i2c.c
+++ b/drivers/mfd/stmpe-i2c.c
@@ -14,6 +14,7 @@ 
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/of_device.h>
 #include "stmpe.h"
 
 static int i2c_reg_read(struct stmpe *stmpe, u8 reg)
@@ -52,15 +53,71 @@  static struct stmpe_client_info i2c_ci = {
 	.write_block = i2c_block_write,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id stmpe_of_match[] = {
+	{
+		.compatible = "st,stmpe610",
+		.data = (void *)STMPE610,
+	},
+	{
+		.compatible = "st,stmpe801",
+		.data = (void *)STMPE801,
+	},
+	{
+		.compatible = "st,stmpe811",
+		.data = (void *)STMPE811,
+	},
+	{
+		.compatible = "st,stmpe1601",
+		.data = (void *)STMPE1601,
+	},
+	{
+		.compatible = "st,stmpe1801",
+		.data = (void *)STMPE1801,
+	},
+	{
+		.compatible = "st,stmpe2401",
+		.data = (void *)STMPE2401,
+	},
+	{
+		.compatible = "st,stmpe2403",
+		.data = (void *)STMPE2403,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, stmpe_of_match);
+
+int stmpe_i2c_of_probe(struct i2c_client *i2c)
+{
+	const struct of_device_id *of_id;
+
+	of_id = of_match_device(stmpe_of_match, &i2c->dev);
+	if (!of_id)
+		return -EINVAL;
+	return (int)of_id->data;
+}
+#else
+int stmpe_i2c_of_probe(struct i2c_client *i2c)
+{
+	return -EINVAL;
+}
+#endif
+
 static int
 stmpe_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
+	int partnum;
+
 	i2c_ci.data = (void *)id;
 	i2c_ci.irq = i2c->irq;
 	i2c_ci.client = i2c;
 	i2c_ci.dev = &i2c->dev;
 
-	return stmpe_probe(&i2c_ci, id->driver_data);
+	partnum = stmpe_i2c_of_probe(i2c);
+	if (partnum < 0)
+		partnum = id->driver_data;
+
+	return stmpe_probe(&i2c_ci, partnum);
 }
 
 static int stmpe_i2c_remove(struct i2c_client *i2c)
@@ -89,6 +146,7 @@  static struct i2c_driver stmpe_i2c_driver = {
 #ifdef CONFIG_PM
 		.pm = &stmpe_dev_pm_ops,
 #endif
+		.of_match_table = of_match_ptr(stmpe_of_match),
 	},
 	.probe		= stmpe_i2c_probe,
 	.remove		= stmpe_i2c_remove,