[U-Boot] [PATCH 0/2] syscon: update syscon_regmap_lookup_by_phandle

Change the function syscon_regmap_lookup_by_phandle() introduced by commit 6c3af1f24e4b ("syscon: dm: Add a new method to get a regmap from DTS") to have Linux-compatible syscon API and add test for this case: phandle to node with generic "syscon" compatible not bound as syscon UCLASS by default.
Without the patch the added test failed.
And I also update sysreset-syscon driver to use this function and simplify the code, tested on my stm32mp1 board with:
rcc_reboot: rcc-reboot@50000000 { compatible = "syscon-reboot"; regmap = <&rcc>; offset = <0x404>; mask = <0x1>; };
rcc: rcc@50000000 { compatible = "st,stm32mp1-rcc", "syscon"; reg = <0x50000000 0x1000>; #clock-cells = <1>; #reset-cells = <1>; };
PS: compatible st,stm32mp1-rcc is bound to driver drivers/misc/stm32_rcc.c
Patrick Delaunay (2): syscon: update syscon_regmap_lookup_by_phandle sysreset: use syscon_regmap_lookup_by_phandle
arch/sandbox/dts/test.dts | 3 +- drivers/core/syscon-uclass.c | 83 +++++++++++++++++++++++++++----------- drivers/sysreset/sysreset_syscon.c | 15 +------ test/dm/syscon.c | 7 ++++ 4 files changed, 70 insertions(+), 38 deletions(-)

Change the function syscon_regmap_lookup_by_phandle() introduced by commit 6c3af1f24e4b ("syscon: dm: Add a new method to get a regmap from DTS") to have Linux-compatible syscon API.
Same modification than commit e151a1c288bd ("syscon: add Linux-compatible syscon API") solves issue when the node identified by the phandle has several compatibles and is already bound to a dedicated driver.
See Linux commit bdb0066df96e ("mfd: syscon: Decouple syscon interface from platform devices").
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
arch/sandbox/dts/test.dts | 3 +- drivers/core/syscon-uclass.c | 83 +++++++++++++++++++++++++++++++------------- test/dm/syscon.c | 7 ++++ 3 files changed, 68 insertions(+), 25 deletions(-)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 87d8e5b..6d4134c 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -493,6 +493,7 @@ compatible = "denx,u-boot-probe-test"; first-syscon = <&syscon0>; second-sys-ctrl = <&another_system_controller>; + third-syscon = <&syscon2>; }; };
@@ -597,7 +598,7 @@ 0x38 8>; };
- syscon@2 { + syscon2: syscon@2 { compatible = "simple-mfd", "syscon"; reg = <0x40 5 0x48 6 diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c index afac6d6..5bb38e3 100644 --- a/drivers/core/syscon-uclass.c +++ b/drivers/core/syscon-uclass.c @@ -57,18 +57,64 @@ static int syscon_pre_probe(struct udevice *dev) #endif }
+static int syscon_probe_by_ofnode(ofnode node, struct udevice **devp) +{ + struct udevice *dev, *parent; + int ret; + + /* found node with "syscon" compatible, not bounded to SYSCON UCLASS */ + if (!ofnode_device_is_compatible(node, "syscon")) { + dev_dbg(dev, "invalid compatible for syscon device\n"); + return -EINVAL; + } + + /* bound to driver with same ofnode or to root if not found */ + if (device_find_global_by_ofnode(node, &parent)) + parent = dm_root(); + + /* force bound to syscon class */ + ret = device_bind_driver_to_node(parent, "syscon", + ofnode_get_name(node), + node, &dev); + if (ret) { + dev_dbg(dev, "unable to bound syscon device\n"); + return ret; + } + ret = device_probe(dev); + if (ret) { + dev_dbg(dev, "unable to probe syscon device\n"); + return ret; + } + + *devp = dev; + return 0; +} + struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev, const char *name) { struct udevice *syscon; struct regmap *r; + u32 phandle; + ofnode node; int err;
err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, name, &syscon); if (err) { - dev_dbg(dev, "unable to find syscon device\n"); - return ERR_PTR(err); + /* found node with "syscon" compatible, not bounded to SYSCON */ + err = ofnode_read_u32(dev_ofnode(dev), name, &phandle); + if (err) + return ERR_PTR(err); + + node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(node)) { + dev_dbg(dev, "unable to find syscon device\n"); + return ERR_PTR(-EINVAL); + } + err = syscon_probe_by_ofnode(node, &syscon); + if (err) + return ERR_PTR(-ENODEV); }
r = syscon_get_regmap(syscon); @@ -152,29 +198,18 @@ U_BOOT_DRIVER(generic_syscon) = { */ struct regmap *syscon_node_to_regmap(ofnode node) { - struct udevice *dev, *parent; - int ret; - - if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev)) - return syscon_get_regmap(dev); - - if (!ofnode_device_is_compatible(node, "syscon")) - return ERR_PTR(-EINVAL); + struct udevice *dev; + struct regmap *r;
- /* bound to driver with same ofnode or to root if not found */ - if (device_find_global_by_ofnode(node, &parent)) - parent = dm_root(); + if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev)) + if (syscon_probe_by_ofnode(node, &dev)) + return ERR_PTR(-ENODEV);
- /* force bound to syscon class */ - ret = device_bind_driver_to_node(parent, "syscon", - ofnode_get_name(node), - node, &dev); - if (ret) - return ERR_PTR(ret); - - ret = device_probe(dev); - if (ret) - return ERR_PTR(ret); + r = syscon_get_regmap(dev); + if (!r) { + dev_dbg(dev, "unable to find regmap\n"); + return ERR_PTR(-ENODEV); + }
- return syscon_get_regmap(dev); + return r; } diff --git a/test/dm/syscon.c b/test/dm/syscon.c index a294dda..0ff9da7 100644 --- a/test/dm/syscon.c +++ b/test/dm/syscon.c @@ -67,6 +67,13 @@ static int dm_test_syscon_by_phandle(struct unit_test_state *uts) ut_assert(!IS_ERR(map)); ut_asserteq(4, map->range_count);
+ ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, + "third-syscon")); + map = syscon_regmap_lookup_by_phandle(dev, "third-syscon"); + ut_assert(map); + ut_assert(!IS_ERR(map)); + ut_asserteq(4, map->range_count); + ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present")));
return 0;

On Thu, 7 Mar 2019 at 01:57, Patrick Delaunay patrick.delaunay@st.com wrote:
Change the function syscon_regmap_lookup_by_phandle() introduced by commit 6c3af1f24e4b ("syscon: dm: Add a new method to get a regmap from DTS") to have Linux-compatible syscon API.
Same modification than commit e151a1c288bd ("syscon: add Linux-compatible syscon API") solves issue when the node identified by the phandle has several compatibles and is already bound to a dedicated driver.
See Linux commit bdb0066df96e ("mfd: syscon: Decouple syscon interface from platform devices").
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com
arch/sandbox/dts/test.dts | 3 +- drivers/core/syscon-uclass.c | 83 +++++++++++++++++++++++++++++++------------- test/dm/syscon.c | 7 ++++ 3 files changed, 68 insertions(+), 25 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Use the new function syscon_regmap_lookup_by_phandle() to simplify the code.
Signed-off-by: Patrick Delaunay patrick.delaunay@st.com ---
drivers/sysreset/sysreset_syscon.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
diff --git a/drivers/sysreset/sysreset_syscon.c b/drivers/sysreset/sysreset_syscon.c index 3450640..3fb39b9 100644 --- a/drivers/sysreset/sysreset_syscon.c +++ b/drivers/sysreset/sysreset_syscon.c @@ -36,20 +36,9 @@ static struct sysreset_ops syscon_reboot_ops = { int syscon_reboot_probe(struct udevice *dev) { struct syscon_reboot_priv *priv = dev_get_priv(dev); - int err; - u32 phandle; - ofnode node;
- err = ofnode_read_u32(dev_ofnode(dev), "regmap", &phandle); - if (err) - return err; - - node = ofnode_get_by_phandle(phandle); - if (!ofnode_valid(node)) - return -EINVAL; - - priv->regmap = syscon_node_to_regmap(node); - if (!priv->regmap) { + priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap"); + if (IS_ERR(priv->regmap)) { pr_err("unable to find regmap\n"); return -ENODEV; }
participants (2)
-
Patrick Delaunay
-
Simon Glass