dm: add dev_get_reg() for getting device node's reg
cover dm: add dev_get_reg() for getting device node's reg
commit: dm: core: Enable optional use of fdt_translate_address()
enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
For this purpose this patch set introduces new core function:
fdt_addr_t dev_get_reg(struct udevice *dev)
which returns the 'reg' value in the same way as previously dev_get_addr().
This fixes s5p gpio driver and booting issue on few Exynos based boards:
- Trats2
- Odroid U3/X2
As an example of use, this patch set also modifies i2c uclass driver by using the new function for getting chip address.
Przemyslaw Marczak (3):
dm: core: extend API by new function: dev_get_reg()
gpio: s5p: use dev_get_reg() instead of dev_get_addr()
dm: i2c: get chip address with dev_get_reg()
drivers/core/device.c | 17 +++++++++++++---- drivers/gpio/s5p_gpio.c | 2 +- drivers/i2c/i2c-uclass.c | 17 ++++++++--------- include/dm/device.h | 23 +++++++++++++++++++++++ include/i2c.h | 11 ++++------- 5 files changed, 49 insertions(+), 21 deletions(-)
Signature · 1 line
1.9.1
PATCH 1/3 dm: core: extend API by new function: dev_get_reg()
After changes introduced to dev_get_addr() by:
commit: dm: core: Enable optional use of fdt_translate_address()
the mentioned function is not allowed to parse the 'reg' property of child node for which the '#size-cells == 0'.
To fill the gap, this commit introduces new core function dev_get_reg(), which makes it possible to get the 'reg' property's value for that use case.
--- drivers/core/device.c | 17 +++++++++++++---- include/dm/device.h | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-)
drivers/core/device.c +13 -4
@@ -581,6 +581,18 @@ const char *dev_get_uclass_name(struct udevice *dev)return dev->uclass->uc_drv->name; } +fdt_addr_t dev_get_reg (struct udevice *dev) +{ +#if CONFIG_IS_ENABLED (OF_CONTROL ) +return fdtdec_get_addr_size_auto_parent (gd->fdt_blob, + dev->parent->of_offset, + dev->of_offset,"reg" , +0 ,NULL ); +#else +return FDT_ADDR_T_NONE ; +#endif +} +fdt_addr_t dev_get_addr (struct udevice *dev) {#if CONFIG_IS_ENABLED (OF_CONTROL )
@@ -601,14 +613,11 @@ fdt_addr_t dev_get_addr(struct udevice *dev) dev->of_offset, reg); } + addr =dev_get_reg (dev);/* * Use the "simple" translate function for less complex * bus setups. */ - addr =fdtdec_get_addr_size_auto_parent (gd->fdt_blob, - dev->parent->of_offset, - dev->of_offset,"reg" , -0 ,NULL );if (CONFIG_IS_ENABLED (SIMPLE_BUS ) && addr !=FDT_ADDR_T_NONE ) {if (device_get_uclass_id (dev->parent) ==UCLASS_SIMPLE_BUS ) addr =simple_bus_translate (dev->parent, addr);
include/dm/device.h +23 -0
@@ -445,8 +445,31 @@ int device_find_first_child(struct udevice *parent, struct udevice **devp);int device_find_next_child (struct udevice **devp);/** +* dev_get_reg() - Get the reg property of a device +* +* This returns the address without bus/child address space translation. +* +* @dev: Pointer to a device +* +* @return addr +*/ +fdt_addr_t dev_get_reg (struct udevice *dev); + +/** * dev_get_addr() - Get the reg property of a device * +* The returned address value depends on a config options: +* Case 1: CONFIG_OF_TRANSLATE=y (default) +* Result: Make bus/child address space translation, that dependents on "ranges" +* property. +* +* Case 2: CONFIG_OF_TRANSLATE is not set +* Result: Decode only device node's 'reg' property, without translation. +* +* Case 3: CONFIG_OF_TRANSLATE is not set; CONFIG_SIMPLE_BUS=y +* Result: When 'dev->parent' is a simple bus - then do the same as in case 1, +* otherwise do the same as in case 2. +* * @dev: Pointer to a device * * @return addr
Signature · 1 line
1.9.1
PATCH 2/3 gpio: s5p: use dev_get_reg() instead of dev_get_addr()
In reply to Przemyslaw MarczakIn a result of enabling the CONFIG_OF_TRANSLAE, function dev_get_addr(), doesn't support device tree nodes with 'size-cells == 0'.
But this is the way how the s5p gpio driver's compatible device tree nodes are defined. Switching the driver to use function dev_get_reg(), fixes this issue.
--- drivers/gpio/s5p_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/s5p_gpio.c +1 -1
@@ -350,7 +350,7 @@ static int gpio_exynos_bind(struct udevice *parent) dev->of_offset = node; - reg =dev_get_addr (dev); + reg =dev_get_reg (dev);if (reg !=FDT_ADDR_T_NONE ) bank = (struct s5p_gpio_bank *)((ulong )base + reg);
Signature · 1 line
1.9.1
PATCH 3/3 dm: i2c: get chip address with dev_get_reg()
In reply to Przemyslaw MarczakThis commit cleanups the I2C uclass driver by:
- simplify i2c_child_post_bind() method
- cleanups i2c_chip_ofdata_to_platdata(), by calling dev_get_reg() for getting chip address
--- drivers/i2c/i2c-uclass.c | 17 ++++++++--------- include/i2c.h | 11 ++++------- 2 files changed, 12 insertions(+), 16 deletions(-)
drivers/i2c/i2c-uclass.c +8 -9
@@ -467,16 +467,17 @@ int i2c_deblock(struct udevice *bus)return ops->deblock (bus); } -int i2c_chip_ofdata_to_platdata (const void *blob,int node, -struct dm_i2c_chip *chip) +int i2c_chip_ofdata_to_platdata (struct udevice *dev) { - chip->offset_len =fdtdec_get_int (gd->fdt_blob, node, +struct dm_i2c_chip *chip =dev_get_parent_platdata (dev); + + chip->offset_len =fdtdec_get_int (gd->fdt_blob, dev->of_offset,"u-boot,i2c-offset-len" ,1 ); chip->flags =0 ; - chip->chip_addr =fdtdec_get_int (gd->fdt_blob, node,"reg" ,-1 ); -if (chip->chip_addr ==-1 ) { + chip->chip_addr =dev_get_reg (dev); +if (chip->chip_addr ==FDT_ADDR_T_NONE ) {debug ("%s: I2C Node '%s' has no 'reg' property\n" , __func__, -fdt_get_name (blob, node,NULL )); +fdt_get_name (gd->fdt_blob, dev->of_offset,NULL ));return -EINVAL ; }
@@ -501,12 +502,10 @@ static int i2c_post_bind(struct udevice *dev)static int i2c_child_post_bind (struct udevice *dev) { -struct dm_i2c_chip *plat =dev_get_parent_platdata (dev); -if (dev->of_offset ==-1 )return 0 ; -return i2c_chip_ofdata_to_platdata (gd->fdt_blob, dev->of_offset, plat); +return i2c_chip_ofdata_to_platdata (dev); }UCLASS_DRIVER (i2c) = {
include/i2c.h +4 -7
@@ -518,15 +518,12 @@ int i2c_get_chip_for_busnum(int busnum, int chip_addr, uint offset_len,* i2c_chip_ofdata_to_platdata() - Decode standard I2C platform data * * This decodes the chip address from a device tree node and puts it into -* its dm_i2c_chip structure. This should be called in your driver's -* ofdata_to_platdata() method. +* its dm_i2c_chip structure. This is called after device's bind inside +* uclass driver's i2c_child_post_bind() method. * -* @blob: Device tree blob -* @node: Node offset to read from -* @spi: Place to put the decoded information +* @dev: pointer to a chip device */ -int i2c_chip_ofdata_to_platdata (const void *blob,int node, -struct dm_i2c_chip *chip); +int i2c_chip_ofdata_to_platdata (struct udevice *dev);/** * i2c_dump_msgs() - Dump a list of I2C messages
Signature · 1 line
1.9.1
cover dm: add dev_get_reg() for getting device node's reg
In reply to Przemyslaw MarczakQuoted 9 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Quoted 7 lines
For this purpose this patch set introduces new core function:
fdt_addr_tdev_get_reg(struct udevice *dev)
which returns the 'reg' value in the same way as previouslydev_get_addr().This fixes s5p gpio driver and booting issue on few Exynos based boards:
- Trats2
- Odroid U3/X2
Looking at arch/arm/dts/exynos4412-trats2.dts, I see the following:
i2c at 138d0000 {
samsung,i2c-sda-delay = <100>;
samsung,i2c-slave-addr = <0x10>;
samsung,i2c-max-bus-freq = <100000>;
status = "okay";
max77686_pmic at 09 {
compatible = "maxim,max77686";
interrupts = <7 0>;
reg = <0x09 0 0>;Is that the node you're having problems with? If so, I believe this may simply be due to invalid DT content. In exynos4.dtsi, that i2c node is defined as:
i2c at 138d0000 {
#address-cells = <1>;
#size-cells = <0>;Thus, any reg property in a child of that node must only contain a single cell (the sum of #address-cells and #size-cells in the parent). Does fixing the DT so it's valid solve your issue at all?
cover dm: add dev_get_reg() for getting device node's reg
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 7 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Ah, I guess the problem is caused by the following code in __of_translate_address():
bus->count_cells(blob, parent, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) {
printf("%s: Bad cell count for %s\n", __FUNCTION__,That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains the address that's being translated. Then, translation can stop there.
Something like skipping the check on ns in the above code if parent == addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.
This would allow for translation to occur for buses other than the CPU's root MMIO space, yet not attempt to translate across known address space boundaries (i.e. where address translation is known to be impossible).
cover dm: add dev_get_reg() for getting device node's reg
Hello Stephen,
Quoted 17 lines · Stephen Warren
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 7 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,
Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 7 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains the address that's being translated. Then, translation can stop there.
This is okay but then, all device tree blobs should be defined in a proper way.
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Quoted 10 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's root MMIO space, yet not attempt to translate across known address space boundaries (i.e. where address translation is known to be impossible).
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com
cover dm: add dev_get_reg() for getting device node's reg
Quoted 42 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 17 lines · Stephen Warren
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 7 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 7 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains the address that's being translated. Then, translation can stop there.
Quoted 2 lines
This is okay but then, all device tree blobs should be defined in a proper way.
Well, why shouldn't that be true? There are rules for how DTs must be constructed. Nobody should expect DTs that violate those rules to work in any particular way.
Quoted 5 lines
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (
s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.
It sounds like there are many bugs to fix:-)
Quoted 2 lines
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Adding an extra function sounds OK, although I stand by my comment that the caller should pass in a parameter indicating the root of the address space, so that both #address-cells and #size-cells can be checked all the way up the chain, and #size-cells should only be allowed to be 0 at the root of the translation, not at any intermediate point.
Quoted 11 lines
Quoted 7 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's root MMIO space, yet not attempt to translate across known address space boundaries (i.e. where address translation is known to be impossible).
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
I don't think so; that patch removes all checks on #size-cells rather than only removing/ignoring the check at the root of the address space.
Quoted 2 lines
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Both Linux and U-Boot should conform to the DT specification. So, if there's a difference between the two, there's likely a bug.
cover dm: add dev_get_reg() for getting device node's reg
Hello,
Quoted 52 lines · Stephen Warren
Quoted 44 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 19 lines · Stephen Warren
Quoted 11 lines · Stephen Warren
Quoted 9 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Quoted 6 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 7 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains the address that's being translated. Then, translation can stop there.
Quoted 2 lines
This is okay but then, all device tree blobs should be defined in a proper way.
Well, why shouldn't that be true? There are rules for how DTs must be constructed. Nobody should expect DTs that violate those rules to work in any particular way.
Quoted 8 lines
Quoted 5 lines
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (
s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.It sounds like there are many bugs to fix:-)
Unfortunately... :(
Quoted 21 lines
Quoted 2 lines
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Adding an extra function sounds OK, although I stand by my comment that the caller should pass in a parameter indicating the root of the address space, so that both #address-cells and #size-cells can be checked all the way up the chain, and #size-cells should only be allowed to be 0 at the root of the translation, not at any intermediate point.
Quoted 11 lines
Quoted 7 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's root MMIO space, yet not attempt to translate across known address space boundaries (i.e. where address translation is known to be impossible).
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
Quoted 10 lines
I don't think so; that patch removes all checks on #size-cells rather than only removing/ignoring the check at the root of the address space.
Quoted 2 lines
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Both Linux and U-Boot should conform to the DT specification. So, if there's a difference between the two, there's likely a bug.
According to your comments with the new parameter, I think that we don't need this. As Simon wrote in one of his reply:
"How would the caller know this root?".
What about adding a check that the parent defines "ranges" property and if not - then don't check the #size-cells?
So with this simple check, we could fix all present issues, beside the later fdt/drivers fixing.
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com
cover dm: add dev_get_reg() for getting device node's reg
Quoted 103 lines · Przemyslaw Marczak
Hello,
Quoted 55 lines · Stephen Warren
Quoted 47 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 20 lines · Stephen Warren
Quoted 12 lines · Stephen Warren
Quoted 10 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot,
e.g. by I2C uclass or S5P GPIO - the last one is broken at present.Quoted 6 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 9 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct
way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains
the address that's being translated. Then, translation can stop there.Quoted 2 lines
This is okay but then, all device tree blobs should be defined in a proper way.
Well, why shouldn't that be true? There are rules for how DTs must be constructed. Nobody should expect DTs that violate those rules to work in any particular way.
Quoted 8 lines
Quoted 5 lines
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (
s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.It sounds like there are many bugs to fix:-)
Unfortunately... :(
Quoted 23 lines
Quoted 2 lines
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Adding an extra function sounds OK, although I stand by my comment that the caller should pass in a parameter indicating the root of the address space, so that both #address-cells and #size-cells can be checked all the way up the chain, and #size-cells should only be allowed to be 0 at the root of the translation, not at any intermediate point.
Quoted 10 lines
Quoted 9 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's
root MMIO space, yet not attempt to translate across known address space
boundaries (i.e. where address translation is known to be impossible).Quoted 3 lines
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
Quoted 10 lines
I don't think so; that patch removes all checks on #size-cells rather than only removing/ignoring the check at the root of the address space.
Quoted 2 lines
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Both Linux and U-Boot should conform to the DT specification. So, if there's a difference between the two, there's likely a bug.
Quoted 4 lines
According to your comments with the new parameter, I think that we don't need this. As Simon wrote in one of his reply:
"How would the caller know this root?".
This is a facet of the hardware.
The root of the MMIO address space is the root of the DT.
The root of any other kind of address space is the IO controller that "hosts" the address space, i.e. the I2C or SPI controller.
Every device knows semantically what its address represents, and hence can trivially determine the root node of the address space.
Device driver writers shouldn't have to care about this, so likely some form of helper function should be provided by I2C/SPI/... subsystems to hide these details. IIRC (although I haven't looked in a while) this is exactly how/why the Linux kernel avoids this kind of issue; the I2C/SPI/... subsystem, handles parsing of reg properties before any device-specific driver is invoked.
cover dm: add dev_get_reg() for getting device node's reg
Hi Stephen,
Quoted 135 lines · Stephen Warren
Quoted 118 lines · Przemyslaw Marczak
Hello,
Quoted 64 lines · Stephen Warren
Quoted 54 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 25 lines · Stephen Warren
Quoted 15 lines · Stephen Warren
Quoted 11 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot,
e.g. by I2C uclass or S5P GPIO - the last one is broken at present.Quoted 6 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 9 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct
way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains
the address that's being translated. Then, translation can stop there.Quoted 2 lines
This is okay but then, all device tree blobs should be defined in a proper way.
Well, why shouldn't that be true? There are rules for how DTs must be constructed. Nobody should expect DTs that violate those rules to work in any particular way.
Quoted 9 lines
Quoted 5 lines
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (
s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.It sounds like there are many bugs to fix:-)
Unfortunately... :(
Quoted 29 lines
Quoted 2 lines
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Adding an extra function sounds OK, although I stand by my comment that the caller should pass in a parameter indicating the root of the address space, so that both #address-cells and #size-cells can be checked all the way up the chain, and #size-cells should only be allowed to be 0 at the root of the translation, not at any intermediate point.
Quoted 11 lines
Quoted 9 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's
root MMIO space, yet not attempt to translate across known address space
boundaries (i.e. where address translation is known to be impossible).Quoted 3 lines
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
I don't think so; that patch removes all checks on #size-cells rather than only removing/ignoring the check at the root of the address space.
Quoted 8 lines
Quoted 2 lines
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Both Linux and U-Boot should conform to the DT specification. So, if there's a difference between the two, there's likely a bug.
Quoted 4 lines
According to your comments with the new parameter, I think that we don't need this. As Simon wrote in one of his reply:
"How would the caller know this root?".
This is a facet of the hardware.
The root of the MMIO address space is the root of the DT.
The root of any other kind of address space is the IO controller that "hosts" the address space, i.e. the I2C or SPI controller.
Every device knows semantically what its address represents, and hence can trivially determine the root node of the address space.
Quoted 6 lines
Device driver writers shouldn't have to care about this, so likely some form of helper function should be provided by I2C/SPI/... subsystems to hide these details. IIRC (although I haven't looked in a while) this is exactly how/why the Linux kernel avoids this kind of issue; the I2C/SPI/... subsystem, handles parsing of reg properties before any device-specific driver is invoked.
OK, then I suppose we could do this in a uclass pre_probe() method. But this would be different from how every current driver works (it is the driver's responsibility to call dev_get_addr()).
I'm not super-keen on dev_get_reg() as it adds confusion - why is one reg dealth with differently from another. Perhaps just a different name, like dev_get_bus_addr()?
Re Linux, can someone trace through the of_address_to_resource() call and see what it actually does? It seems to call of_translate_address() but presumably does not suffer from this problem. So maybe I am missing something. The S3C I2C driver calls platform_get_resource() which is presumably set up by a call to of_address_to_resource()?
There is way too much code there to bring into U-Boot, but we can try to do similar things.
Let's solve this in a general way for the next release.
Regards,
Simon
cover dm: add dev_get_reg() for getting device node's reg
On 01/05/2016 05:24 PM, Simon Glass wrote:...
Quoted 9 lines
I'm not super-keen on
dev_get_reg()as it adds confusion - why is one reg dealt with differently from another. Perhaps just a different name, likedev_get_bus_addr()?Re Linux, can someone trace through the
of_address_to_resource()call and see what it actually does? It seems to callof_translate_address()but presumably does not suffer from this problem. So maybe I am missing something. The S3C I2C driver callsplatform_get_resource()which is presumably set up by a call toof_address_to_resource()?
At least in ARM DT land, most MMIO devices are "platform devices". There are also e.g. PCIe devices, but they're enumerated via HW protocols, not by parsing DT.
Construction of a platform device works as follows in the Linux source:
For each node that's found by scanning the DT, a struct platform_device is created to represent it, in drivers/of/platform.c of_device_alloc(). Note that this scanning process is only performed on DT nodes known to represent MMIO buses; recursion into child nodes is explicitly performed by drivers for particular nodes, and takes a different path for nodes representing non-MMIO buses, as described later, since the node's driver will be different. This scanning process is core code that executes before the kernel has any idea re: which type of device the child nodes represent, or which driver will manage them. This struct contains the values of a number of core resource types that are represented in DT, such as addresses, IRQs, etc. The address values are filled in via the following call stack:
drivers/of/platform.c of_device_alloc()
->
drivers/of/address.c of_address_to_resource()
->
drivers/of/address.c of_get_address()
[reads the reg property, picks out a single index in it, performs BE->LE conversion]
then unconditionally calls the following on the address:
drivers/of/address.c __of_address_to_resource()
[translates the address to the CPU address space, then writes the result into the supplied pointer, which the caller has set up to point into a struct resource associated with the struct platform_device]
->
drivers/of/address.c of_translate_address()
->
drivers/of/address.c __of_translate_address()
This is essentially exactly identical to U-Boot's __of_translate_address(), modulo a few printf()/debug() differences, and a few more of_node_get/put() calls in order to support dynamic modifications to the DT.
The driver for the a DT node is responsible for enumerating (or triggering enumeration of) any child nodes. For a node known to represent an MMIO bus (e.g. simple-bus), the algorithm above will simply be applied recursively. For a node that represents some kind of non-MMIO bus controller/host, custom (bus-type-specific) code is typically applied. In many cases, this custom code will parse the reg property of child nodes according to the semantics of that bus's definition of the reg property, and provide that value to the device driver for the child node. Examples of reg parsing in Linux are:
drivers/i2c/i2c-core.c of_i2c_register_device() about 20 lines in. Note that I2C addresses aren't simple integer values, but also encode some flags too, such as 7-vs-10-bit addresses, and whether the DT node represents a slave device that Linux should implement, or a regular device.
drivers/spi/spi.c of_register_spi_device() about 20 lines in. Here, the address is the identify of the chip select wire, which may be driven by the SPI controller, or via GPIOs, depending on the controller HW.
drivers/of/of_mdio.c of_mdio_parse_addr(). Here, the address is a simple integer, with a range check.
drivers/mmc/core/core.c mmc_of_find_child_device(). At least SDIO buses/devices (as opposed to eMMC/SD devices) appear to be able to host multiple functions, and DT appears to be able to represent each function as a separate child node of the SDIO controller.
drivers/spmi/spmi.c of_spmi_register_devices() about 10 lines in. I don't know what SPMI is, but the interpretation of the reg property in this code seems to have a few bus-specific rules.
drivers/nvmem/core.c of_nvmem_cell_get() about 25 lines in. I don't know what nvmem is, but reg here seems to be a pretty simple base/size pair.
All of this discussion implies to me that drivers (for buses) really should be calling different functions (or executing different local custom code) to parse the reg property. The property is interpreted quite differently depending on bus type.
Whether that means creating dev_get_addr_mmio() and dev_get_addr_i2c() such that dev_get_addr() doesn't unconditionally translate addresses vs. moving reg parsing into subsystem core code rather than drivers vs. any other solution seems like an implementation detail. The main point is that we certainly can't rely on a single dev_get_addr() that just works for all reg properties.
All file and line count references above are relative to Linux kernel version v4.4-rc8.
cover dm: add dev_get_reg() for getting device node's reg
In reply to Simon GlassHello,
Quoted 145 lines · Simon Glass
Hi Stephen,
Quoted 135 lines · Stephen Warren
Quoted 118 lines · Przemyslaw Marczak
Hello,
Quoted 64 lines · Stephen Warren
Quoted 54 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 25 lines · Stephen Warren
Quoted 15 lines · Stephen Warren
Quoted 11 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot,
e.g. by I2C uclass or S5P GPIO - the last one is broken at present.Quoted 6 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Quoted 7 lines
Ah, I guess the problem is caused by the following code in
__of_translate_address():bus->count_cells(blob, parent, &na, &ns); if (!OF_CHECK_COUNTS(na, ns)) { printf("%s: Bad cell count for %s\n", __FUNCTION__,Yes, and this is what my previous patch 'fixes'.
[1] https://patchwork.ozlabs.org/patch/537372/
However Linux makes the translate in the same way.
Quoted 9 lines
That's because the function assumes it's called for MMIO addresses. However, reg values for I2C devices aren't MMIO addresses, so those assumptions don't apply. So, there is an argument for introducing some new functionality. I'm not sure that a whole new function is the correct
way to go though. Rather, the existing translation functions should be enhanced to know the location of root of the address space that contains
the address that's being translated. Then, translation can stop there.Quoted 2 lines
This is okay but then, all device tree blobs should be defined in a proper way.
Well, why shouldn't that be true? There are rules for how DTs must be constructed. Nobody should expect DTs that violate those rules to work in any particular way.
Quoted 9 lines
Quoted 5 lines
The problem is, that there are some additions and various assumptions in the drivers, e.g. the exynos gpio driver (
s5p_gpio.c) is checking the reg's property value for each bank. But the driver in Linux hardcodes those values, however for both cases this is wrong, because the gpio regs could be mapped with ranges.It sounds like there are many bugs to fix:-)
Unfortunately... :(
Quoted 29 lines
Quoted 2 lines
Even that issues above, I would prefer introduce a function or modify the existing one to allow keeping this as it is.
Adding an extra function sounds OK, although I stand by my comment that the caller should pass in a parameter indicating the root of the address space, so that both #address-cells and #size-cells can be checked all the way up the chain, and #size-cells should only be allowed to be 0 at the root of the translation, not at any intermediate point.
Quoted 11 lines
Quoted 9 lines
Something like skipping the check on ns in the above code if parent ==
addr_space_root_offset, and also terminating the for (;;) loop in that function under a similar condition.This would allow for translation to occur for buses other than the CPU's
root MMIO space, yet not attempt to translate across known address space
boundaries (i.e. where address translation is known to be impossible).Quoted 3 lines
To achieve this functionality, it should be enough to take my first patch [1]. And then if no "ranges" is defined, then we have 1:1 translation.
I don't think so; that patch removes all checks on #size-cells rather than only removing/ignoring the check at the root of the address space.
Quoted 8 lines
Quoted 2 lines
I think, that it is safe, but then we will have a different assumptions, than in the Linux - is it acceptable?
Both Linux and U-Boot should conform to the DT specification. So, if there's a difference between the two, there's likely a bug.
Quoted 4 lines
According to your comments with the new parameter, I think that we don't need this. As Simon wrote in one of his reply:
"How would the caller know this root?".
This is a facet of the hardware.
The root of the MMIO address space is the root of the DT.
The root of any other kind of address space is the IO controller that "hosts" the address space, i.e. the I2C or SPI controller.
Every device knows semantically what its address represents, and hence can trivially determine the root node of the address space.
Quoted 6 lines
Device driver writers shouldn't have to care about this, so likely some form of helper function should be provided by I2C/SPI/... subsystems to hide these details. IIRC (although I haven't looked in a while) this is exactly how/why the Linux kernel avoids this kind of issue; the I2C/SPI/... subsystem, handles parsing of reg properties before any device-specific driver is invoked.
Quoted 8 lines
OK, then I suppose we could do this in a uclass
pre_probe()method. But this would be different from how every current driver works (it is the driver's responsibility to calldev_get_addr()).I'm not super-keen on
dev_get_reg()as it adds confusion - why is one reg dealth with differently from another. Perhaps just a different name, likedev_get_bus_addr()?
But there is only one "reg" property per device and I think, that its use-case is actually clearly defined in device-tree specification:
- if parent provides 'ranges' - try to map the address
- if no ranges - then return the reg value only
Quoted 6 lines
Re Linux, can someone trace through the
of_address_to_resource()call and see what it actually does? It seems to callof_translate_address()but presumably does not suffer from this problem. So maybe I am missing something. The S3C I2C driver callsplatform_get_resource()which is presumably set up by a call toof_address_to_resource()?
Quoted 9 lines
There is way too much code there to bring into U-Boot, but we can try to do similar things.
Let's solve this in a general way for the next release.
Regards,
Simon
Please review my new patch:
https://patchwork.ozlabs.org/patch/564246/
If the dev_get_reg() will return what we want with the above patch, then it could be used in each uclass pre_probe() method.
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com
cover dm: add dev_get_reg() for getting device node's reg
In reply to Stephen WarrenHello Stephen,
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 8 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Some time ago I send a patch with such fix:
[1] https://patchwork.ozlabs.org/patch/537372/
Sorry, I didn't add you to the 'CC' list.
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.
Quoted 27 lines
Quoted 8 lines
For this purpose this patch set introduces new core function:
fdt_addr_tdev_get_reg(struct udevice *dev)
which returns the 'reg' value in the same way as previouslydev_get_addr().This fixes s5p gpio driver and booting issue on few Exynos based boards:
- Trats2
- Odroid U3/X2Looking at
arch/arm/dts/exynos4412-trats2.dts, I see the following:i2c at 138d0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; samsung,i2c-max-bus-freq = <100000>; status = "okay"; max77686_pmic at 09 { compatible = "maxim,max77686"; interrupts = <7 0>; reg = <0x09 0 0>;Is that the node you're having problems with? If so, I believe this may simply be due to invalid DT content. In
exynos4.dtsi, that i2c node is defined as:
Quoted 9 lines
i2c at 138d0000 { #address-cells = <1>; #size-cells = <0>;Thus, any reg property in a child of that node must only contain a single cell (the sum of #address-cells and #size-cells in the parent). Does fixing the DT so it's valid solve your issue at all?
Nice hit above! However we don't use DM API yet for the above example, so probably this is why it is still working - currently, the driver uses fdtdec_get_int(), for getting this value.
But for test, after switching it to use of sequence: fdt_getprop() -> fdt_translate_address(), then I can see the warning:
---- cut ----_of_translate_address: Bad cell count for max77686_pmic at 09 ---- cut ----
And for the above issue - applying patch [1] - allows return the right device address: 0x9 - without FDT modifying.
Now, I checked, why the above example compiles by dtc with no warning. It looks, that dtc ignores some child's reg cells-count combination:
---- case 1 -----
parent {
#address-cells = <1>;
#size-cells = <0>;
child {
reg = <0x9>;
};
};This is ok!
---- case 2 -----
parent {
#address-cells = <1>;
#size-cells = <0>;
child {
reg = <0x9 0 0>;
};
};This is ok: (the 2nd and 3rd child's cells are ignored by dtc)
---- case 3 -----
parent {
#address-cells = <1>;
#size-cells = <1>;
child {
reg = <0x9 0 0>;
};
};This is wrong! dtc warning:
Warning (reg_format): "reg" property in /i2c at 138d0000/max77686_pmic has invalid length (12 bytes) (#address-cells == 1, #size-cells == 1)
Now I don't have a time for checking it in dtc code, however we can check in U-Boot, that the dtb is not coherent?
So I can compile my default dts - no dtc warnings, and next in U-Boot I can see:
------------ check i2c node --------------------
Trats2 # fdt list /i2c at 138d0000
i2c at 138d0000 {
#address-cells = <0x00000001>;
#size-cells = <0x00000000>;
compatible = "samsung,s3c2440-i2c";
reg = <0x138d0000 0x00000100>;
interrupts = <0x00000007 0x0000003f 0x00000000>;
samsung,i2c-sda-delay = <0x00000064>;
samsung,i2c-slave-addr = <0x00000010>;
samsung,i2c-max-bus-freq = <0x000186a0>;
status = "okay";
max77686_pmic at 09 {
};
};------------ check pmic node -------------------- Trats2 # fdt list /i2c at 138d0000/max77686_pmic at 09
max77686_pmic at 09 {
compatible = "maxim,max77686";
interrupts = <0x00000007 0x00000000>;
reg = <0x00000009 0x00000000 0x00000000>;
#clock-cells = <0x00000001>;
voltage-regulators {
};
};So, the parent defines the summarized cells count as 1, and the child node can exceed it, because it provides 3 cells.
However it looks that we are still safe, since the code doesn't try exceed the cells count, defined by the parent.
What do you think about this?
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com
cover dm: add dev_get_reg() for getting device node's reg
Quoted 20 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 8 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Quoted 8 lines
Some time ago I send a patch with such fix:
[1] https://patchwork.ozlabs.org/patch/537372/
Sorry, I didn't add you to the 'CC' list.
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
The discussion there does indicate that removing the check on #size-cells would be incorrect.
Quoted 3 lines
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds
dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.
OK; as I mentioned in my other reply, some form of new function or new parameter does seem reasonable here.
...
Quoted 37 lines
Quoted 18 lines
Looking at
arch/arm/dts/exynos4412-trats2.dts, I see the following:i2c at 138d0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; samsung,i2c-max-bus-freq = <100000>; status = "okay"; max77686_pmic at 09 { compatible = "maxim,max77686"; interrupts = <7 0>; reg = <0x09 0 0>;Is that the node you're having problems with? If so, I believe this may simply be due to invalid DT content. In
exynos4.dtsi, that i2c node is defined as:Quoted 7 lines
i2c at 138d0000 { #address-cells = <1>; #size-cells = <0>;Thus, any reg property in a child of that node must only contain a single cell (the sum of #address-cells and #size-cells in the parent). Does fixing the DT so it's valid solve your issue at all?
Nice hit above! However we don't use DM API yet for the above example, so probably this is why it is still working - currently, the driver uses
fdtdec_get_int(), for getting this value.But for test, after switching it to use of sequence:
fdt_getprop()->fdt_translate_address(), then I can see the warning:---- cut ----
_of_translate_address: Bad cell count formax77686_pmicat 09 ---- cut ----
Quoted 5 lines
And for the above issue - applying patch [1] - allows return the right device address:
0x9- without FDT modifying.Now, I checked, why the above example compiles by dtc with no warning. It looks, that dtc ignores some child's reg cells-count combination:
dtc doesn't check that the length of the reg property is *equal* to the sum of #address-cells and #size-cells, but rather that the length is a *multiple* of that value. This is because the reg property can contain multiple addresses.
Quoted 9 lines
---- case 1 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9>; }; };This is ok!
This is "1 * (1 + 0)".
Quoted 9 lines
---- case 2 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9 0 0>; }; };This is ok: (the 2nd and 3rd child's cells are ignored by dtc)
The extra cells aren't ignored; the length is "3 * (1 + 0)".
Quoted 9 lines
---- case 3 -----
parent { #address-cells = <1>; #size-cells = <1>; child { reg = <0x9 0 0>; }; };
Quoted 3 lines
This is wrong! dtc warning:
Warning (reg_format): "reg" property in /i2c at 138d0000/max77686_pmic has invalid length (12 bytes) (#address-cells == 1, #size-cells == 1)
Yes, this is "1.5 * (1 + 1)", yet the "1.5" isn't an integer, hence the warning is triggered.
cover dm: add dev_get_reg() for getting device node's reg
Hi Stephen,
Quoted 30 lines · Stephen Warren
Quoted 28 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 10 lines · Stephen Warren
Quoted 8 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 9 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Some time ago I send a patch with such fix:
Quoted 7 lines
Quoted 4 lines
Sorry, I didn't add you to the 'CC' list.
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
The discussion there does indicate that removing the check on #size-cells would be incorrect.
OK, but since we have a breakage and a release in a week, I'm planning on picking up Przemyslaw's patch. We can revert it immediately afterwards.
Who is going to work out a proper solution (post-release)?
Quoted 92 lines
Quoted 4 lines
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds
dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.OK; as I mentioned in my other reply, some form of new function or new parameter does seem reasonable here.
...
Quoted 38 lines
Quoted 18 lines
Looking at
arch/arm/dts/exynos4412-trats2.dts, I see the following:i2c at 138d0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; samsung,i2c-max-bus-freq = <100000>; status = "okay"; max77686_pmic at 09 { compatible = "maxim,max77686"; interrupts = <7 0>; reg = <0x09 0 0>;Is that the node you're having problems with? If so, I believe this may simply be due to invalid DT content. In
exynos4.dtsi, that i2c node is defined as:Quoted 7 lines
i2c at 138d0000 { #address-cells = <1>; #size-cells = <0>;Thus, any reg property in a child of that node must only contain a single cell (the sum of #address-cells and #size-cells in the parent). Does fixing the DT so it's valid solve your issue at all?
Nice hit above! However we don't use DM API yet for the above example, so probably this is why it is still working - currently, the driver uses
fdtdec_get_int(), for getting this value.But for test, after switching it to use of sequence:
fdt_getprop()->fdt_translate_address(), then I can see the warning:---- cut ----
_of_translate_address: Bad cell count formax77686_pmicat 09 ---- cut ----Quoted 5 lines
And for the above issue - applying patch [1] - allows return the right device address:
0x9- without FDT modifying.Now, I checked, why the above example compiles by dtc with no warning. It looks, that dtc ignores some child's reg cells-count combination:
dtc doesn't check that the length of the reg property is *equal* to the sum of #address-cells and #size-cells, but rather that the length is a *multiple* of that value. This is because the reg property can contain multiple addresses.
Quoted 9 lines
---- case 1 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9>; }; };This is ok!
This is "1 * (1 + 0)".
Quoted 9 lines
---- case 2 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9 0 0>; }; };This is ok: (the 2nd and 3rd child's cells are ignored by dtc)
The extra cells aren't ignored; the length is "3 * (1 + 0)".
Quoted 10 lines
---- case 3 -----
parent { #address-cells = <1>; #size-cells = <1>; child { reg = <0x9 0 0>; }; };
Quoted 6 lines
Quoted 3 lines
This is wrong! dtc warning:
Warning (reg_format): "reg" property in /i2c at 138d0000/max77686_pmic has invalid length (12 bytes) (#address-cells == 1, #size-cells == 1)Yes, this is "1.5 * (1 + 1)", yet the "1.5" isn't an integer, hence the warning is triggered.
Great that you can explain this, thanks.
Regards,
Simon
cover dm: add dev_get_reg() for getting device node's reg
Quoted 39 lines · Simon Glass
Hi Stephen,
Quoted 36 lines · Stephen Warren
Quoted 32 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 10 lines · Stephen Warren
Quoted 8 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 9 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Some time ago I send a patch with such fix:
[1] https://patchwork.ozlabs.org/patch/537372/
Sorry, I didn't add you to the 'CC' list.
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
Quoted 7 lines
Quoted 1 line
The discussion there does indicate that removing the check on #size-cells would be incorrect.
OK, but since we have a breakage and a release in a week, I'm planning on picking up Przemyslaw's patch. We can revert it immediately afterwards.
Who is going to work out a proper solution (post-release)?
I would assume the owner of the affected I2C/SPI controllers, or if the issue is triggered by core/subsystem code, then the owner of that subsystem.
cover dm: add dev_get_reg() for getting device node's reg
In reply to Stephen WarrenHello,
Quoted 25 lines · Stephen Warren
Quoted 24 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 8 lines · Stephen Warren
Quoted 7 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Quoted 8 lines
Quoted 2 lines
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Can you please explain the problem you're seeing in more detail? Without any context, my initial reaction is that this is simply a bug somewhere. That bug should be fixed, rather than introducing new APIs to hide the problem.
Some time ago I send a patch with such fix:
Quoted 8 lines
Quoted 4 lines
Sorry, I didn't add you to the 'CC' list.
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
The discussion there does indicate that removing the check on #size-cells would be incorrect.
Ok, this probably would be good if we assume that dts is always well written, so this is not acceptable.
Quoted 8 lines
Quoted 3 lines
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds
dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.OK; as I mentioned in my other reply, some form of new function or new parameter does seem reasonable here.
...
At this point I can say, that the device-tree files and some compatible drivers are using wrong assumptions.
I think, that adding the new function is not needed, and also that we don't need any new parameter to the function dev_get_reg(), because the right way is to fix the fdt.
For the Exynos GPIO issue, we can use two cases:
- define proper ranges
- move #size-cells=0 to #size-cells=1 and extend the reg property by it's size (actually not too much to do)
This will fix the Exynos boot issue.
Quoted 80 lines
Quoted 37 lines
Quoted 18 lines
Looking at
arch/arm/dts/exynos4412-trats2.dts, I see the following:i2c at 138d0000 { samsung,i2c-sda-delay = <100>; samsung,i2c-slave-addr = <0x10>; samsung,i2c-max-bus-freq = <100000>; status = "okay"; max77686_pmic at 09 { compatible = "maxim,max77686"; interrupts = <7 0>; reg = <0x09 0 0>;Is that the node you're having problems with? If so, I believe this may simply be due to invalid DT content. In
exynos4.dtsi, that i2c node is defined as:Quoted 7 lines
i2c at 138d0000 { #address-cells = <1>; #size-cells = <0>;Thus, any reg property in a child of that node must only contain a single cell (the sum of #address-cells and #size-cells in the parent). Does fixing the DT so it's valid solve your issue at all?
Nice hit above! However we don't use DM API yet for the above example, so probably this is why it is still working - currently, the driver uses
fdtdec_get_int(), for getting this value.But for test, after switching it to use of sequence:
fdt_getprop()->fdt_translate_address(), then I can see the warning:---- cut ----
_of_translate_address: Bad cell count formax77686_pmicat 09 ---- cut ----Quoted 5 lines
And for the above issue - applying patch [1] - allows return the right device address:
0x9- without FDT modifying.Now, I checked, why the above example compiles by dtc with no warning. It looks, that dtc ignores some child's reg cells-count combination:
dtc doesn't check that the length of the reg property is *equal* to the sum of #address-cells and #size-cells, but rather that the length is a *multiple* of that value. This is because the reg property can contain multiple addresses.
Quoted 9 lines
---- case 1 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9>; }; };This is ok!
This is "1 * (1 + 0)".
Quoted 9 lines
---- case 2 -----
parent { #address-cells = <1>; #size-cells = <0>; child { reg = <0x9 0 0>; }; };This is ok: (the 2nd and 3rd child's cells are ignored by dtc)
The extra cells aren't ignored; the length is "3 * (1 + 0)".
Quoted 9 lines
---- case 3 -----
parent { #address-cells = <1>; #size-cells = <1>; child { reg = <0x9 0 0>; }; };
Quoted 8 lines
Quoted 3 lines
This is wrong! dtc warning:
Warning (reg_format): "reg" property in /i2c at 138d0000/max77686_pmic has invalid length (12 bytes) (#address-cells == 1, #size-cells == 1)Yes, this is "1.5 * (1 + 1)", yet the "1.5" isn't an integer, hence the warning is triggered.
Also thank you for the explanation.
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com
cover dm: add dev_get_reg() for getting device node's reg
Quoted 32 lines · Przemyslaw Marczak
Hello,
Quoted 29 lines · Stephen Warren
Quoted 28 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 11 lines · Stephen Warren
Quoted 9 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot, e.g. by I2C uclass or S5P GPIO - the last one is broken at present.
Quoted 7 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Some time ago I send a patch with such fix:
[1] https://patchwork.ozlabs.org/patch/537372/
Sorry, I didn't add you to the 'CC' list.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
The discussion there does indicate that removing the check on #size-cells would be incorrect.
Ok, this probably would be good if we assume that dts is always well written, so this is not acceptable.
Why not?
Certainly it's reasonable to expect code not to blow up in crashy ways in the face of bad DTs. However, I don't think it's reasonable to require that code perform exactly the desired function in the face of arbitrary bad input data.
Besides, the problem here isn't a bad DT. It's perfectly legal for a DT to contain #size-cells=<0>. The problem is bad code, which attempts to translate an address beyond the root of the address space that the address is within. This is a bug in the code, pure and simple.
Quoted 16 lines
Quoted 8 lines
Quoted 3 lines
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds
dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.OK; as I mentioned in my other reply, some form of new function or new parameter does seem reasonable here.
...
At this point I can say, that the device-tree files and some compatible drivers are using wrong assumptions.
I think, that adding the new function is not needed, and also that we don't need any new parameter to the function
dev_get_reg(), because the right way is to fix the fdt.
Quoted 6 lines
For the Exynos GPIO issue, we can use two cases:
- define proper ranges
- move #size-cells=0 to #size-cells=1 and extend the reg property by it's size (actually not too much to do)This will fix the Exynos boot issue.
That may fix/hide the issue, but semantically seems entirely incorrect. I2C addresses cannot logically be mapped into the CPU's MMIO address space, so adding a ranges property that attempts to do that doesn't make sense. I2C addresses don't have a size, so adding one to the DT doesn't make sense.
cover dm: add dev_get_reg() for getting device node's reg
Hello,
Quoted 76 lines · Stephen Warren
Quoted 33 lines · Przemyslaw Marczak
Hello,
Quoted 30 lines · Stephen Warren
Quoted 29 lines · Przemyslaw Marczak
Hello Stephen,
Quoted 12 lines · Stephen Warren
Quoted 10 lines · Przemyslaw Marczak
commit: dm: core: Enable optional use of
fdt_translate_address()enables device's bus/child address translation method, depending on bus 'ranges' property and including child 'reg' property. This change makes impossible to decode the 'reg' for node with '#size-cells' equal to 0.
Such case is possible by the specification and is also used in U-Boot,
e.g. by I2C uclass or S5P GPIO - the last one is broken at present.Quoted 7 lines
Can you please explain the problem you're seeing in more detail? Without
any context, my initial reaction is that this is simply a bug somewhere.
That bug should be fixed, rather than introducing new APIs to hide the problem.Some time ago I send a patch with such fix:
[1] https://patchwork.ozlabs.org/patch/537372/
Sorry, I didn't add you to the 'CC' list.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
However. I checked this in linux, and the code is the same, the size-cells == 0 is not supported also in Linux.
The discussion there does indicate that removing the check on #size-cells would be incorrect.
Ok, this probably would be good if we assume that dts is always well written, so this is not acceptable.
Why not?
Certainly it's reasonable to expect code not to blow up in crashy ways in the face of bad DTs. However, I don't think it's reasonable to require that code perform exactly the desired function in the face of arbitrary bad input data.
Besides, the problem here isn't a bad DT. It's perfectly legal for a DT to contain #size-cells=<0>. The problem is bad code, which attempts to translate an address beyond the root of the address space that the address is within. This is a bug in the code, pure and simple.
Quoted 21 lines
Quoted 8 lines
Quoted 3 lines
So to prevent breaking some consistency in parsing fdt between U-boot and Linux, I sent the patch which adds
dev_get_reg(). And it seem to be useful at least for I2C and Exynos GPIO driver.OK; as I mentioned in my other reply, some form of new function or new parameter does seem reasonable here.
...
At this point I can say, that the device-tree files and some compatible drivers are using wrong assumptions.
I think, that adding the new function is not needed, and also that we don't need any new parameter to the function
dev_get_reg(), because the right way is to fix the fdt.For the Exynos GPIO issue, we can use two cases:
- define proper ranges
- move #size-cells=0 to #size-cells=1 and extend the reg property by it's size (actually not too much to do)
Quoted 9 lines
Quoted 1 line
This will fix the Exynos boot issue.
That may fix/hide the issue, but semantically seems entirely incorrect. I2C addresses cannot logically be mapped into the CPU's MMIO address space, so adding a ranges property that attempts to do that doesn't make sense. I2C addresses don't have a size, so adding one to the DT doesn't make sense.
Agree, then I think my new patch should be suitable for the both cases:
https://patchwork.ozlabs.org/patch/564246/
Best regards,
Signature · 4 lines
Przemyslaw Marczak Samsung R&D Institute Poland Samsung Electronics p.marczak at samsung.com