[U-Boot] [PATCH V2 1/2] dm: allow setting driver_data before/during bind

From: Stephen Warren swarren@nvidia.com
This will allow a driver's bind function to use the driver data. One example is the Tegra186 GPIO driver, which instantiates child devices for each of its GPIO ports, yet supports two different HW instances each with a different set of ports, and identified by the udevice_id .data field.
Signed-off-by: Stephen Warren swarren@nvidia.com --- v2: * Introduce a separate function for the new functionality, rather than modifying device_bind().
This patch is a dependency for the upcoming Tegra186 GPIO driver too. --- doc/driver-model/README.txt | 23 ++++++++++++++--------- drivers/core/device.c | 25 ++++++++++++++++++++++--- drivers/core/lists.c | 4 ++-- include/dm/device-internal.h | 24 ++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt index 7a24552560d5..1b5ccec4b2e5 100644 --- a/doc/driver-model/README.txt +++ b/doc/driver-model/README.txt @@ -606,19 +606,24 @@ methods actually defined.
1. Bind stage
-A device and its driver are bound using one of these two methods: +U-Boot discovers devices using one of these two methods:
- - Scan the U_BOOT_DEVICE() definitions. U-Boot It looks up the -name specified by each, to find the appropriate driver. It then calls -device_bind() to create a new device and bind' it to its driver. This will -call the device's bind() method. + - Scan the U_BOOT_DEVICE() definitions. U-Boot looks up the name specified +by each, to find the appropriate U_BOOT_DRIVER() definition. In this case, +there is no path by which driver_data may be provided, but the U_BOOT_DEVICE() +may provide platdata.
- Scan through the device tree definitions. U-Boot looks at top-level nodes in the the device tree. It looks at the compatible string in each node -and uses the of_match part of the U_BOOT_DRIVER() structure to find the -right driver for each node. It then calls device_bind() to bind the -newly-created device to its driver (thereby creating a device structure). -This will also call the device's bind() method. +and uses the of_match table of the U_BOOT_DRIVER() structure to find the +right driver for each node. In this case, the of_match table may provide a +driver_data value, but platdata cannot be provided until later. + +For each device that is discovered, U-Boot then calls device_bind() to create a +new device, initializes various core fields of the device object such as name, +uclass & driver, initializes any optional fields of the device object that are +applicable such as of_offset, driver_data & platdata, and finally calls the +driver's bind() method if one is defined.
At this point all the devices are known, and bound to their drivers. There is a 'struct udevice' allocated for all devices. However, nothing has been diff --git a/drivers/core/device.c b/drivers/core/device.c index 2b12ce7835f0..a8f2380e4676 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -26,9 +26,10 @@
DECLARE_GLOBAL_DATA_PTR;
-int device_bind(struct udevice *parent, const struct driver *drv, - const char *name, void *platdata, int of_offset, - struct udevice **devp) +static int device_bind_common(struct udevice *parent, const struct driver *drv, + const char *name, void *platdata, + ulong driver_data, int of_offset, + struct udevice **devp) { struct udevice *dev; struct uclass *uc; @@ -56,6 +57,7 @@ int device_bind(struct udevice *parent, const struct driver *drv, INIT_LIST_HEAD(&dev->devres_head); #endif dev->platdata = platdata; + dev->driver_data = driver_data; dev->name = name; dev->of_offset = of_offset; dev->parent = parent; @@ -193,6 +195,23 @@ fail_alloc1: return ret; }
+int device_bind_with_driver_data(struct udevice *parent, + const struct driver *drv, const char *name, + ulong driver_data, int of_offset, + struct udevice **devp) +{ + return device_bind_common(parent, drv, name, NULL, driver_data, + of_offset, devp); +} + +int device_bind(struct udevice *parent, const struct driver *drv, + const char *name, void *platdata, int of_offset, + struct udevice **devp) +{ + return device_bind_common(parent, drv, name, platdata, 0, of_offset, + devp); +} + int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, const struct driver_info *info, struct udevice **devp) { diff --git a/drivers/core/lists.c b/drivers/core/lists.c index a72db13a119a..0c2771779096 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -170,7 +170,8 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, }
dm_dbg(" - found match at '%s'\n", entry->name); - ret = device_bind(parent, entry, name, NULL, offset, &dev); + ret = device_bind_with_driver_data(parent, entry, name, + id->data, offset, &dev); if (ret == -ENODEV) { dm_dbg("Driver '%s' refuses to bind\n", entry->name); continue; @@ -180,7 +181,6 @@ int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, ret); return ret; } else { - dev->driver_data = id->data; found = true; if (devp) *devp = dev; diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h index b348ad5231bd..0bf8707493a9 100644 --- a/include/dm/device-internal.h +++ b/include/dm/device-internal.h @@ -39,6 +39,30 @@ int device_bind(struct udevice *parent, const struct driver *drv, struct udevice **devp);
/** + * device_bind_with_driver_data() - Create a device and bind it to a driver + * + * Called to set up a new device attached to a driver, in the case where the + * driver was matched to the device by means of a match table that provides + * driver_data. + * + * Once bound a device exists but is not yet active until device_probe() is + * called. + * + * @parent: Pointer to device's parent, under which this driver will exist + * @drv: Device's driver + * @name: Name of device (e.g. device tree node name) + * @driver_data: The driver_data field from the driver's match table. + * @of_offset: Offset of device tree node for this device. This is -1 for + * devices which don't use device tree. + * @devp: if non-NULL, returns a pointer to the bound device + * @return 0 if OK, -ve on error + */ +int device_bind_with_driver_data(struct udevice *parent, + const struct driver *drv, const char *name, + ulong driver_data, int of_offset, + struct udevice **devp); + +/** * device_bind_by_name: Create a device and bind it to a driver * * This is a helper function used to bind devices which do not use device

From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
Cc: Hans de Goede hdegoede@redhat.com Signed-off-by: Stephen Warren swarren@nvidia.com --- v2: New patch. --- drivers/gpio/sunxi_gpio.c | 90 ++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 40 deletions(-)
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index a7cec18d57fb..94abbeb39adc 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -258,43 +258,30 @@ static int gpio_sunxi_probe(struct udevice *dev)
return 0; } + +struct sunxi_gpio_soc_data { + int start; + int no_banks; +}; + /** * We have a top-level GPIO device with no actual GPIOs. It has a child * device for each Sunxi bank. */ static int gpio_sunxi_bind(struct udevice *parent) { + struct sunxi_gpio_soc_data *soc_data = + (struct sunxi_gpio_soc_data *)dev_get_driver_data(parent); struct sunxi_gpio_platdata *plat = parent->platdata; struct sunxi_gpio_reg *ctlr; - int bank, no_banks, ret, start; + int bank, ret;
/* If this is a child device, there is nothing to do here */ if (plat) return 0;
- if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset, - "allwinner,sun6i-a31-r-pinctrl") == 0) { - start = 'L' - 'A'; - no_banks = 2; /* L & M */ - } else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset, - "allwinner,sun8i-a23-r-pinctrl") == 0 || - fdt_node_check_compatible(gd->fdt_blob, parent->of_offset, - "allwinner,sun8i-a83t-r-pinctrl") == 0 || - fdt_node_check_compatible(gd->fdt_blob, parent->of_offset, - "allwinner,sun8i-h3-r-pinctrl") == 0) { - start = 'L' - 'A'; - no_banks = 1; /* L only */ - } else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset, - "allwinner,sun9i-a80-r-pinctrl") == 0) { - start = 'L' - 'A'; - no_banks = 3; /* L, M & N */ - } else { - start = 0; - no_banks = SUNXI_GPIO_BANKS; - } - ctlr = (struct sunxi_gpio_reg *)dev_get_addr(parent); - for (bank = 0; bank < no_banks; bank++) { + for (bank = 0; bank < soc_data->no_banks; bank++) { struct sunxi_gpio_platdata *plat; struct udevice *dev;
@@ -302,7 +289,7 @@ static int gpio_sunxi_bind(struct udevice *parent) if (!plat) return -ENOMEM; plat->regs = &ctlr->gpio_bank[bank]; - plat->bank_name = gpio_bank_name(start + bank); + plat->bank_name = gpio_bank_name(soc_data->start + bank); plat->gpio_count = SUNXI_GPIOS_PER_BANK;
ret = device_bind(parent, parent->driver, @@ -315,23 +302,46 @@ static int gpio_sunxi_bind(struct udevice *parent) return 0; }
+static const struct sunxi_gpio_soc_data soc_data_a_all = { + .start = 0, + .no_banks = SUNXI_GPIO_BANKS, +}; + +static const struct sunxi_gpio_soc_data soc_data_l_1 = { + .start = 'L' - 'A', + .no_banks = 1, +}; + +static const struct sunxi_gpio_soc_data soc_data_l_2 = { + .start = 'L' - 'A', + .no_banks = 2, +}; + +static const struct sunxi_gpio_soc_data soc_data_l_3 = { + .start = 'L' - 'A', + .no_banks = 3, +}; + +#define ID(_compat_, _soc_data_) \ + { .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ } + static const struct udevice_id sunxi_gpio_ids[] = { - { .compatible = "allwinner,sun4i-a10-pinctrl" }, - { .compatible = "allwinner,sun5i-a10s-pinctrl" }, - { .compatible = "allwinner,sun5i-a13-pinctrl" }, - { .compatible = "allwinner,sun6i-a31-pinctrl" }, - { .compatible = "allwinner,sun6i-a31s-pinctrl" }, - { .compatible = "allwinner,sun7i-a20-pinctrl" }, - { .compatible = "allwinner,sun8i-a23-pinctrl" }, - { .compatible = "allwinner,sun8i-a33-pinctrl" }, - { .compatible = "allwinner,sun8i-a83t-pinctrl", }, - { .compatible = "allwinner,sun8i-h3-pinctrl" }, - { .compatible = "allwinner,sun9i-a80-pinctrl" }, - { .compatible = "allwinner,sun6i-a31-r-pinctrl" }, - { .compatible = "allwinner,sun8i-a23-r-pinctrl" }, - { .compatible = "allwinner,sun8i-a83t-r-pinctrl" }, - { .compatible = "allwinner,sun8i-h3-r-pinctrl", }, - { .compatible = "allwinner,sun9i-a80-r-pinctrl", }, + ID("allwinner,sun4i-a10-pinctrl", a_all), + ID("allwinner,sun5i-a10s-pinctrl", a_all), + ID("allwinner,sun5i-a13-pinctrl", a_all), + ID("allwinner,sun6i-a31-pinctrl", a_all), + ID("allwinner,sun6i-a31s-pinctrl", a_all), + ID("allwinner,sun7i-a20-pinctrl", a_all), + ID("allwinner,sun8i-a23-pinctrl", a_all), + ID("allwinner,sun8i-a33-pinctrl", a_all), + ID("allwinner,sun8i-a83t-pinctrl", a_all), + ID("allwinner,sun8i-h3-pinctrl", a_all), + ID("allwinner,sun9i-a80-pinctrl", a_all), + ID("allwinner,sun6i-a31-r-pinctrl", l_2), + ID("allwinner,sun8i-a23-r-pinctrl", l_1), + ID("allwinner,sun8i-a83t-r-pinctrl", l_1), + ID("allwinner,sun8i-h3-r-pinctrl", l_1), + ID("allwinner,sun9i-a80-r-pinctrl", l_3), { } };

Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
Cc: Hans de Goede hdegoede@redhat.com Signed-off-by: Stephen Warren swarren@nvidia.com
v2: New patch.
drivers/gpio/sunxi_gpio.c | 90 ++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 40 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
Comment below.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index a7cec18d57fb..94abbeb39adc 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -258,43 +258,30 @@ static int gpio_sunxi_probe(struct udevice *dev)
return 0;
}
+struct sunxi_gpio_soc_data {
int start;
int no_banks;
+};
/**
- We have a top-level GPIO device with no actual GPIOs. It has a child
- device for each Sunxi bank.
*/ static int gpio_sunxi_bind(struct udevice *parent) {
struct sunxi_gpio_soc_data *soc_data =
(struct sunxi_gpio_soc_data *)dev_get_driver_data(parent); struct sunxi_gpio_platdata *plat = parent->platdata; struct sunxi_gpio_reg *ctlr;
int bank, no_banks, ret, start;
int bank, ret; /* If this is a child device, there is nothing to do here */ if (plat) return 0;
if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
"allwinner,sun6i-a31-r-pinctrl") == 0) {
start = 'L' - 'A';
no_banks = 2; /* L & M */
} else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
"allwinner,sun8i-a23-r-pinctrl") == 0 ||
fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
"allwinner,sun8i-a83t-r-pinctrl") == 0 ||
fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
"allwinner,sun8i-h3-r-pinctrl") == 0) {
start = 'L' - 'A';
no_banks = 1; /* L only */
} else if (fdt_node_check_compatible(gd->fdt_blob, parent->of_offset,
"allwinner,sun9i-a80-r-pinctrl") == 0) {
start = 'L' - 'A';
no_banks = 3; /* L, M & N */
} else {
start = 0;
no_banks = SUNXI_GPIO_BANKS;
}
ctlr = (struct sunxi_gpio_reg *)dev_get_addr(parent);
for (bank = 0; bank < no_banks; bank++) {
for (bank = 0; bank < soc_data->no_banks; bank++) { struct sunxi_gpio_platdata *plat; struct udevice *dev;
@@ -302,7 +289,7 @@ static int gpio_sunxi_bind(struct udevice *parent) if (!plat) return -ENOMEM; plat->regs = &ctlr->gpio_bank[bank];
plat->bank_name = gpio_bank_name(start + bank);
plat->bank_name = gpio_bank_name(soc_data->start + bank); plat->gpio_count = SUNXI_GPIOS_PER_BANK; ret = device_bind(parent, parent->driver,
@@ -315,23 +302,46 @@ static int gpio_sunxi_bind(struct udevice *parent) return 0; }
+static const struct sunxi_gpio_soc_data soc_data_a_all = {
.start = 0,
.no_banks = SUNXI_GPIO_BANKS,
+};
+static const struct sunxi_gpio_soc_data soc_data_l_1 = {
.start = 'L' - 'A',
.no_banks = 1,
+};
+static const struct sunxi_gpio_soc_data soc_data_l_2 = {
.start = 'L' - 'A',
.no_banks = 2,
+};
+static const struct sunxi_gpio_soc_data soc_data_l_3 = {
.start = 'L' - 'A',
.no_banks = 3,
+};
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
{ .compatible = "allwinner,sun6i-a31-pinctrl" },
{ .compatible = "allwinner,sun6i-a31s-pinctrl" },
{ .compatible = "allwinner,sun7i-a20-pinctrl" },
{ .compatible = "allwinner,sun8i-a23-pinctrl" },
{ .compatible = "allwinner,sun8i-a33-pinctrl" },
{ .compatible = "allwinner,sun8i-a83t-pinctrl", },
{ .compatible = "allwinner,sun8i-h3-pinctrl" },
{ .compatible = "allwinner,sun9i-a80-pinctrl" },
{ .compatible = "allwinner,sun6i-a31-r-pinctrl" },
{ .compatible = "allwinner,sun8i-a23-r-pinctrl" },
{ .compatible = "allwinner,sun8i-a83t-r-pinctrl" },
{ .compatible = "allwinner,sun8i-h3-r-pinctrl", },
{ .compatible = "allwinner,sun9i-a80-r-pinctrl", },
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
ID("allwinner,sun5i-a13-pinctrl", a_all),
ID("allwinner,sun6i-a31-pinctrl", a_all),
ID("allwinner,sun6i-a31s-pinctrl", a_all),
ID("allwinner,sun7i-a20-pinctrl", a_all),
ID("allwinner,sun8i-a23-pinctrl", a_all),
ID("allwinner,sun8i-a33-pinctrl", a_all),
ID("allwinner,sun8i-a83t-pinctrl", a_all),
ID("allwinner,sun8i-h3-pinctrl", a_all),
ID("allwinner,sun9i-a80-pinctrl", a_all),
ID("allwinner,sun6i-a31-r-pinctrl", l_2),
ID("allwinner,sun8i-a23-r-pinctrl", l_1),
ID("allwinner,sun8i-a83t-r-pinctrl", l_1),
ID("allwinner,sun8i-h3-r-pinctrl", l_1),
ID("allwinner,sun9i-a80-r-pinctrl", l_3),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
{ }
};
-- 2.8.2
Regards, Simon

On 05/12/2016 11:43 AM, Simon Glass wrote:
Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
- static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
...
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
I originally did that, but you either end up with lines over 80 columns which checkpatch complains about, or multiple lines per entry which makes it harder to read for such a large table. Still, I can convert it if you want.

Hi Stephen,
On 12 May 2016 at 11:50, Stephen Warren swarren@wwwdotorg.org wrote:
On 05/12/2016 11:43 AM, Simon Glass wrote:
Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
- static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
...
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
I originally did that, but you either end up with lines over 80 columns which checkpatch complains about, or multiple lines per entry which makes it harder to read for such a large table. Still, I can convert it if you want.
I don't mind. See what Hans thinks.
Regards, Simon

Hi,
On 12-05-16 19:50, Stephen Warren wrote:
On 05/12/2016 11:43 AM, Simon Glass wrote:
Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
- static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
...
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
I originally did that, but you either end up with lines over 80 columns which checkpatch complains about, or multiple lines per entry which makes it harder to read for such a large table. Still, I can convert it if you want.
I'm fine with keeping the ID define:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Simon, I assume that you will upstream this one through your tree ?
Regards,
Hans

Hi Hans,
On 12 May 2016 at 11:51, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 12-05-16 19:50, Stephen Warren wrote:
On 05/12/2016 11:43 AM, Simon Glass wrote:
Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_
}
- static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
...
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
I originally did that, but you either end up with lines over 80 columns which checkpatch complains about, or multiple lines per entry which makes it harder to read for such a large table. Still, I can convert it if you want.
I'm fine with keeping the ID define:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Simon, I assume that you will upstream this one through your tree ?
Yes, thanks.
Regards, Simon

On 12 May 2016 at 20:42, Simon Glass sjg@chromium.org wrote:
Hi Hans,
On 12 May 2016 at 11:51, Hans de Goede hdegoede@redhat.com wrote:
Hi,
On 12-05-16 19:50, Stephen Warren wrote:
On 05/12/2016 11:43 AM, Simon Glass wrote:
Hi Stephen,
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
Now that the DM core sets driver_data before calling bind(), this driver can make use of driver_data to determine the set of child devices to create, rather than manually re-implementing the matching logic in code.
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
+#define ID(_compat_, _soc_data_) \
{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_
}
- static const struct udevice_id sunxi_gpio_ids[] = {
{ .compatible = "allwinner,sun4i-a10-pinctrl" },
{ .compatible = "allwinner,sun5i-a10s-pinctrl" },
{ .compatible = "allwinner,sun5i-a13-pinctrl" },
...
ID("allwinner,sun4i-a10-pinctrl", a_all),
ID("allwinner,sun5i-a10s-pinctrl", a_all),
I don't think the #define adds a lot of value - consider removing it an writing things out in full?
I originally did that, but you either end up with lines over 80 columns which checkpatch complains about, or multiple lines per entry which makes it harder to read for such a large table. Still, I can convert it if you want.
I'm fine with keeping the ID define:
Reviewed-by: Hans de Goede hdegoede@redhat.com
Simon, I assume that you will upstream this one through your tree ?
Yes, thanks.
Regards, Simon
Applied to u-boot-dm, thanks!

On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
This will allow a driver's bind function to use the driver data. One example is the Tegra186 GPIO driver, which instantiates child devices for each of its GPIO ports, yet supports two different HW instances each with a different set of ports, and identified by the udevice_id .data field.
Signed-off-by: Stephen Warren swarren@nvidia.com
v2:
- Introduce a separate function for the new functionality, rather than
modifying device_bind().
This patch is a dependency for the upcoming Tegra186 GPIO driver too.
doc/driver-model/README.txt | 23 ++++++++++++++--------- drivers/core/device.c | 25 ++++++++++++++++++++++--- drivers/core/lists.c | 4 ++-- include/dm/device-internal.h | 24 ++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 14 deletions(-)
Thanks.
Acked-by: Simon Glass sjg@chromium.org

On 12 May 2016 at 11:43, Simon Glass sjg@chromium.org wrote:
On 11 May 2016 at 15:26, Stephen Warren swarren@wwwdotorg.org wrote:
From: Stephen Warren swarren@nvidia.com
This will allow a driver's bind function to use the driver data. One example is the Tegra186 GPIO driver, which instantiates child devices for each of its GPIO ports, yet supports two different HW instances each with a different set of ports, and identified by the udevice_id .data field.
Signed-off-by: Stephen Warren swarren@nvidia.com
v2:
- Introduce a separate function for the new functionality, rather than
modifying device_bind().
This patch is a dependency for the upcoming Tegra186 GPIO driver too.
doc/driver-model/README.txt | 23 ++++++++++++++--------- drivers/core/device.c | 25 ++++++++++++++++++++++--- drivers/core/lists.c | 4 ++-- include/dm/device-internal.h | 24 ++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 14 deletions(-)
Thanks.
Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot-dm, thanks!
participants (3)
-
Hans de Goede
-
Simon Glass
-
Stephen Warren