Skip to contentSkip to conversation

enable I2C devices behind I2C bus on Gen2

PATCH Applied Andy Shevchenko 5 participants 12 messages Oct 23, 2015 – Nov 9, 2015

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

v4 cover enable I2C devices behind I2C bus on Gen2

There is a board in the wild, i.e. Intel Galileo Gen2, that has ACPI enumerated devices behind I2C bus. This patch series dedicated to enable those devices.

The MFD framework is also updated to cope with interesting implementation of the cell descriptions under ACPI MFD (patch 1).

The patches 5 and 6 are pretty independent and could be applied ahead, though they don't make much sense without previous ones.

Wolfram, since Lee acknowledged patches 1-3, can you pull them to your tree?

Tested on the actual Intel Galileo Gen2 by Ismo (gpio expanders) and me (at24).

Cc Thierry Reding <[email protected]>

Changelog v4:
- amend at24 patch to satisfy sparse (Wolfram)
- drop applied patches

Changelog v3:
- append ACKs from Rafael (from ACPI angle)
- drop upstreamed patches (GPIO pca953x)

Changelog v2:
- append tags
- re-make patch 3 (suggested by Lee)
- improve patch 8 (suggested by Thierry)

Andy Shevchenko (5):
mfd: core: redo ACPI matching of the children devices
mfd: intel_quark_i2c_gpio: load gpio driver first
mfd: intel_quark_i2c_gpio: support devices behind i2c bus
at24: enable ACPI device found on Galileo Gen2
pwm-pca9685: enable ACPI device found on Galileo Gen2

 Documentation/acpi/enumeration.txt | 11 +++++---
 drivers/mfd/intel_quark_i2c_gpio.c | 33 ++++++++++++++++--------
 drivers/mfd/mfd-core.c             | 52 ++++++++++++++++++++++++++------------
 drivers/misc/eeprom/at24.c         | 22 +++++++++++++---
 drivers/pwm/Kconfig                |  2 +-
 drivers/pwm/pwm-pca9685.c          | 20 ++++++++++++---
 include/linux/mfd/core.h           | 10 ++++++--
 7 files changed, 111 insertions(+), 39 deletions(-)
Signature · 1 line
2.6.1
#1 lore raw

PATCH v4 1/5 mfd: core: redo ACPI matching of the children devices

There is at least one board on the market, i.e. Intel Galileo Gen2, that uses _ADR to distinguish the devices under one actual device. Due to this we have to improve the quirk in the MFD core to handle that board.

---
 Documentation/acpi/enumeration.txt | 11 +++++---
 drivers/mfd/mfd-core.c             | 52 ++++++++++++++++++++++++++------------
 include/linux/mfd/core.h           | 10 ++++++--
 3 files changed, 52 insertions(+), 21 deletions(-)
Documentation/acpi/enumeration.txt +8 -3
index b731b29..a91ec5a 100644
@@ -347,13 +347,18 @@ For the first case, the MFD drivers do not need to do anything. The
 resulting child platform device will have its ACPI_COMPANION() set to point
 to the parent device.
 
-If the ACPI namespace has a device that we can match using an ACPI id,
-the id should be set like:
+If the ACPI namespace has a device that we can match using an ACPI id or ACPI
+adr, the cell should be set like:
+
+	static struct mfd_cell_acpi_match my_subdevice_cell_acpi_match = {
+		.pnpid = "XYZ0001",
+		.adr = 0,
+	};
 
 	static struct mfd_cell my_subdevice_cell = {
 		.name = "my_subdevice",
 		/* set the resources relative to the parent */
-		.acpi_pnpid = "XYZ0001",
+		.acpi_match = &my_subdevice_cell_acpi_match,
 	};
 
 The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
drivers/mfd/mfd-core.c +36 -16

65 lines not on this page · raw message

include/linux/mfd/core.h +8 -2
index a76bc10..27dac3f 100644
@@ -18,6 +18,12 @@
 
 struct irq_domain;
 
+/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
+struct mfd_cell_acpi_match {
+	const char			*pnpid;
+	const unsigned long long	adr;
+};
+
 /*
  * This struct describes the MFD part ("cell").
  * After registration the copy of this structure will become the platform data
@@ -44,8 +50,8 @@ struct mfd_cell {
 	 */
 	const char		*of_compatible;
 
-	/* Matches ACPI PNP id, either _HID or _CID */
-	const char		*acpi_pnpid;
+	/* Matches ACPI */
+	const struct mfd_cell_acpi_match	*acpi_match;
 
 	/*
 	 * These resources can be specified relative to the parent device.
Signature · 1 line
2.6.1
#2 lore raw

PATCH v4 2/5 mfd: intel_quark_i2c_gpio: load gpio driver first

In reply to Andy Shevchenko

On Intel Galileo boards the GPIO expander is connected to i2c bus. Moreover it is able to generate interrupt, but interrupt line is connected to GPIO. That's why we have to have GPIO driver in place when we will probe i2c host with device connected to it.

---
 drivers/mfd/intel_quark_i2c_gpio.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/mfd/intel_quark_i2c_gpio.c +9 -10
index 1ce1603..958c134 100644
@@ -90,19 +90,19 @@ static struct resource intel_quark_gpio_res[] = {
 
 static struct mfd_cell intel_quark_mfd_cells[] = {
 	{
-		.id = MFD_I2C_BAR,
-		.name = "i2c_designware",
-		.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
-		.resources = intel_quark_i2c_res,
-		.ignore_resource_conflicts = true,
-	},
-	{
 		.id = MFD_GPIO_BAR,
 		.name = "gpio-dwapb",
 		.num_resources = ARRAY_SIZE(intel_quark_gpio_res),
 		.resources = intel_quark_gpio_res,
 		.ignore_resource_conflicts = true,
 	},
+	{
+		.id = MFD_I2C_BAR,
+		.name = "i2c_designware",
+		.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
+		.resources = intel_quark_i2c_res,
+		.ignore_resource_conflicts = true,
+	},
 };
 
 static const struct pci_device_id intel_quark_mfd_ids[] = {
@@ -248,12 +248,11 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
 
 	dev_set_drvdata(&pdev->dev, quark_mfd);
 
-	ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[MFD_I2C_BAR]);
+	ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
 	if (ret)
 		return ret;
 
-	ret = intel_quark_gpio_setup(pdev,
-				     &intel_quark_mfd_cells[MFD_GPIO_BAR]);
+	ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
 	if (ret)
 		return ret;
 
Signature · 1 line
2.6.1
#3 lore raw

PATCH v4 3/5 mfd: intel_quark_i2c_gpio: support devices behind i2c bus

In reply to Andy Shevchenko

On Intel Galileo Gen2 the GPIO expanders are connected to the i2c bus. For those devices the ACPI table has specific parameters that refer to an actual i2c host controller. Since MFD now copes with that specific configuration we have to provide a necessary information how to distinguish devices in ACPI namespace. Here the _ADR values are provided.

---
 drivers/mfd/intel_quark_i2c_gpio.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/mfd/intel_quark_i2c_gpio.c +14 -0
index 958c134..0421374 100644
@@ -31,6 +31,10 @@
 #define MFD_I2C_BAR		0
 #define MFD_GPIO_BAR		1
 
+/* ACPI _ADR value to match the child node */
+#define MFD_ACPI_MATCH_GPIO	0ULL
+#define MFD_ACPI_MATCH_I2C	1ULL
+
 /* The base GPIO number under GPIOLIB framework */
 #define INTEL_QUARK_MFD_GPIO_BASE	8
 
@@ -82,16 +86,25 @@ static struct resource intel_quark_i2c_res[] = {
 	},
 };
 
+static struct mfd_cell_acpi_match intel_quark_acpi_match_i2c = {
+	.adr = MFD_ACPI_MATCH_I2C,
+};
+
 static struct resource intel_quark_gpio_res[] = {
 	[INTEL_QUARK_IORES_MEM] = {
 		.flags = IORESOURCE_MEM,
 	},
 };
 
+static struct mfd_cell_acpi_match intel_quark_acpi_match_gpio = {
+	.adr = MFD_ACPI_MATCH_GPIO,
+};
+
 static struct mfd_cell intel_quark_mfd_cells[] = {
 	{
 		.id = MFD_GPIO_BAR,
 		.name = "gpio-dwapb",
+		.acpi_match = &intel_quark_acpi_match_gpio,
 		.num_resources = ARRAY_SIZE(intel_quark_gpio_res),
 		.resources = intel_quark_gpio_res,
 		.ignore_resource_conflicts = true,
@@ -99,6 +112,7 @@ static struct mfd_cell intel_quark_mfd_cells[] = {
 	{
 		.id = MFD_I2C_BAR,
 		.name = "i2c_designware",
+		.acpi_match = &intel_quark_acpi_match_i2c,
 		.num_resources = ARRAY_SIZE(intel_quark_i2c_res),
 		.resources = intel_quark_i2c_res,
 		.ignore_resource_conflicts = true,
Signature · 1 line
2.6.1
#4 lore raw

PATCH v4 4/5 at24: enable ACPI device found on Galileo Gen2

In reply to Andy Shevchenko

There is a 24c08 chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via ACPI ID INT3499.

---
 drivers/misc/eeprom/at24.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)
drivers/misc/eeprom/at24.c +19 -3
index c6cb7f8..5d7c090 100644
@@ -21,6 +21,7 @@
 #include <linux/bitops.h>
 #include <linux/jiffies.h>
 #include <linux/of.h>
+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/at24.h>
 
@@ -131,6 +132,12 @@ static const struct i2c_device_id at24_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, at24_ids);
 
+static const struct acpi_device_id at24_acpi_ids[] = {
+	{ "INT3499", AT24_DEVICE_MAGIC(8192 / 8, 0) },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, at24_acpi_ids);
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -467,21 +474,29 @@ static void at24_get_ofdata(struct i2c_client *client,
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct at24_platform_data chip;
+	kernel_ulong_t magic = 0;
 	bool writable;
 	int use_smbus = 0;
 	int use_smbus_write = 0;
 	struct at24_data *at24;
 	int err;
 	unsigned i, num_addresses;
-	kernel_ulong_t magic;
 
 	if (client->dev.platform_data) {
 		chip = *(struct at24_platform_data *)client->dev.platform_data;
 	} else {
-		if (!id->driver_data)
+		if (id) {
+			magic = id->driver_data;
+		} else {
+			const struct acpi_device_id *aid;
+
+			aid = acpi_match_device(at24_acpi_ids, &client->dev);
+			if (aid)
+				magic = aid->driver_data;
+		}
+		if (!magic)
 			return -ENODEV;
 
-		magic = id->driver_data;
 		chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
 		magic >>= AT24_SIZE_BYTELEN;
 		chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
@@ -661,6 +676,7 @@ static int at24_remove(struct i2c_client *client)
 static struct i2c_driver at24_driver = {
 	.driver = {
 		.name = "at24",
+		.acpi_match_table = ACPI_PTR(at24_acpi_ids),
 	},
 	.probe = at24_probe,
 	.remove = at24_remove,
Signature · 1 line
2.6.1
#5 lore raw

Re: [PATCH v4 4/5] at24: enable ACPI device found on Galileo Gen2

Hi,

Quoted 2 lines · Andy Shevchenko

There is a 24c08 chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via ACPI ID INT3499.

I'm looking to do something similar with a 24C02 and would like to know if there is an ID already defined for that.

Is there a master list of ACPI IDs?

The best I found is here: http://www.uefi.org/PNP_ACPI_Registry
But that doesn't seem to have individual numbers and it indicates that the "INT" PNP ID is reserved by INTERPHASE CORPORATION.
Intel Corp looks to have "ICO" for the PNP ID and ACPI/INTC/INTL for ACPI IDs.

Thanks,
Ben

#6 lore raw

PATCH v4 5/5 pwm-pca9685: enable ACPI device found on Galileo Gen2

In reply to Andy Shevchenko

There is a chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via ACPI ID INT3492.

---
 drivers/pwm/Kconfig       |  2 +-
 drivers/pwm/pwm-pca9685.c | 20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)
drivers/pwm/Kconfig +1 -1
index 062630a..bb114ef 100644
@@ -242,7 +242,7 @@ config PWM_MXS
 
 config PWM_PCA9685
 	tristate "NXP PCA9685 PWM driver"
-	depends on OF && I2C
+	depends on I2C
 	select REGMAP_I2C
 	help
 	  Generic PWM framework driver for NXP PCA9685 LED controller.
drivers/pwm/pwm-pca9685.c +16 -4
index 70448a6..117fccf 100644
@@ -19,9 +19,11 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/pwm.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
@@ -297,7 +299,6 @@ static const struct regmap_config pca9685_regmap_i2c_config = {
 static int pca9685_pwm_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
-	struct device_node *np = client->dev.of_node;
 	struct pca9685 *pca;
 	int ret;
 	int mode2;
@@ -320,12 +321,12 @@ static int pca9685_pwm_probe(struct i2c_client *client,
 
 	regmap_read(pca->regmap, PCA9685_MODE2, &mode2);
 
-	if (of_property_read_bool(np, "invert"))
+	if (device_property_read_bool(&client->dev, "invert"))
 		mode2 |= MODE2_INVRT;
 	else
 		mode2 &= ~MODE2_INVRT;
 
-	if (of_property_read_bool(np, "open-drain"))
+	if (device_property_read_bool(&client->dev, "open-drain"))
 		mode2 &= ~MODE2_OUTDRV;
 	else
 		mode2 |= MODE2_OUTDRV;
@@ -363,16 +364,27 @@ static const struct i2c_device_id pca9685_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pca9685_id);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pca9685_acpi_ids[] = {
+	{ "INT3492", 0 },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(acpi, pca9685_acpi_ids);
+#endif
+
+#ifdef CONFIG_OF
 static const struct of_device_id pca9685_dt_ids[] = {
 	{ .compatible = "nxp,pca9685-pwm", },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, pca9685_dt_ids);
+#endif
 
 static struct i2c_driver pca9685_i2c_driver = {
 	.driver = {
 		.name = "pca9685-pwm",
-		.of_match_table = pca9685_dt_ids,
+		.acpi_match_table = ACPI_PTR(pca9685_acpi_ids),
+		.of_match_table = of_match_ptr(pca9685_dt_ids),
 	},
 	.probe = pca9685_pwm_probe,
 	.remove = pca9685_pwm_remove,
Signature · 1 line
2.6.1
#7 lore raw

Re: [PATCH v4 5/5] pwm-pca9685: enable ACPI device found on Galileo Gen2

Quoted 3 lines · Andy Shevchenko

There is a chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via
ACPI ID INT3492.

Thierry, ping?

Quoted 93 lines

---
 drivers/pwm/Kconfig       |  2 +- drivers/pwm/pwm-pca9685.c | 20 ++++++++++++++++----

 2 files changed, 17 insertions(+), 5 deletions(-)
drivers/pwm/Kconfig +0 -0
index 062630a..bb114ef 100644
@@ -242,7 +242,7 @@ config PWM_MXS


 config PWM_PCA9685
  tristate "NXP PCA9685 PWM driver"

drivers/pwm/Kconfig +1 -1
-	depends on OF && I2C
+	depends on I2C

  select REGMAP_I2C
  help
    Generic PWM framework driver for NXP PCA9685 LED controller.

drivers/pwm/pwm-pca9685.c +0 -0
index 70448a6..117fccf 100644
@@ -19,9 +19,11 @@
   * this program.  If not, see <http://www.gnu.org/licenses/>.
   */


+#include <linux/acpi.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/pwm.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>

drivers/pwm/pwm-pca9685.c +0 -1
@@ -297,7 +299,6 @@ static const struct regmap_config
 pca9685_regmap_i2c_config = {
  static int pca9685_pwm_probe(struct i2c_client *client,
  				const struct i2c_device_id *id)
  {
-	struct device_node *np = client->dev.of_node;
  	struct pca9685 *pca;
  	int ret;

  int mode2;

drivers/pwm/pwm-pca9685.c +0 -0
@@ -320,12 +321,12 @@ static int pca9685_pwm_probe(struct i2c_client
 *client,


  regmap_read(pca->regmap, PCA9685_MODE2, &mode2);

drivers/pwm/pwm-pca9685.c +1 -1
-	if (of_property_read_bool(np, "invert"))
+	if (device_property_read_bool(&client->dev, "invert"))

  mode2 |= MODE2_INVRT;
  else
  mode2 &= ~MODE2_INVRT;

drivers/pwm/pwm-pca9685.c +1 -1
-	if (of_property_read_bool(np, "open-drain"))
+	if (device_property_read_bool(&client->dev, "open-drain"))

  mode2 &= ~MODE2_OUTDRV;
  else
  mode2 |= MODE2_OUTDRV;

drivers/pwm/pwm-pca9685.c +0 -0
@@ -363,16 +364,27 @@ static const struct i2c_device_id pca9685_id[]
 = {
  };
  MODULE_DEVICE_TABLE(i2c, pca9685_id);

drivers/pwm/pwm-pca9685.c +9 -0
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pca9685_acpi_ids[] = {
+	{ "INT3492", 0 },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(acpi, pca9685_acpi_ids);
+#endif
+
+#ifdef CONFIG_OF

 static const struct of_device_id pca9685_dt_ids[] = { { .compatible = "nxp,pca9685-pwm", }, { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, pca9685_dt_ids); +#endif

 static struct i2c_driver pca9685_i2c_driver = { .driver = {
  .name = "pca9685-pwm",

drivers/pwm/pwm-pca9685.c +2 -1
-		.of_match_table = pca9685_dt_ids,
+		.acpi_match_table = ACPI_PTR(pca9685_acpi_ids),
+		.of_match_table = of_match_ptr(pca9685_dt_ids),

  },
  .probe = pca9685_pwm_probe,
  .remove = pca9685_pwm_remove,

Signature · 7 lines
Andy Shevchenko <[email protected]>
Intel Finland Oy

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#8 lore raw

Re: [PATCH v4 5/5] pwm-pca9685: enable ACPI device found on Galileo Gen2

Quoted 6 lines · Andy Shevchenko
Quoted 3 lines · Andy Shevchenko

There is a chip connected to i2c bus on Intel Galileo Gen2 board. Enable it via
ACPI ID INT3492.

Thierry, ping?

This should've been in linux-next for a couple of days now. I see that I didn't confirm via email, though, so:

Applied, thanks.
Thierry

#10 lore raw
Quoted 4 lines · Wolfram Sang
Quoted 2 lines

Wolfram, since Lee acknowledged patches 1-3, can you pull them to your tree?

So, I picked patches 1-4 to my for-next. Patch 5 is missing an ACK.

Right. Thanks!

Signature · 2 lines
Andy Shevchenko <[email protected]>
Intel Finland Oy
#11 lore raw
In reply to Wolfram Sang
Quoted 3 lines · Wolfram Sang
Quoted 1 line

Wolfram, since Lee acknowledged patches 1-3, can you pull them to your tree?

So, I picked patches 1-4 to my for-next. Patch 5 is missing an ACK.

Can you place these patches onto their own branch, tag it and send the appropriate pull-request out please?

Signature · 4 lines
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog