mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-30 08:03:32 +08:00
syscon: update syscon_regmap_lookup_by_phandle
Change the function syscon_regmap_lookup_by_phandle() introduced by commit6c3af1f24e
("syscon: dm: Add a new method to get a regmap from DTS") to have Linux-compatible syscon API. Same modification than commite151a1c288
("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> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
1ceb10b4d8
commit
a442e61e24
@ -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
|
||||
|
@ -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");
|
||||
/* 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;
|
||||
struct udevice *dev;
|
||||
struct regmap *r;
|
||||
|
||||
if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
|
||||
return syscon_get_regmap(dev);
|
||||
if (uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
|
||||
if (syscon_probe_by_ofnode(node, &dev))
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
if (!ofnode_device_is_compatible(node, "syscon"))
|
||||
return ERR_PTR(-EINVAL);
|
||||
r = syscon_get_regmap(dev);
|
||||
if (!r) {
|
||||
dev_dbg(dev, "unable to find regmap\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = device_probe(dev);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return syscon_get_regmap(dev);
|
||||
return r;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user