From 661d9afe1429e28adcaacd277ab9f28e3790e93f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 29 May 2020 19:22:41 +0200 Subject: power: pmic: Add SPL Kconfig entry for PFUZE100 Add Kconfig entry for the PFUZE PMIC, SPL variant. Signed-off-by: Marek Vasut Cc: Fabio Estevam Cc: Jaehoon Chung Cc: Peng Fan Cc: Stefano Babic Reviewed-by: Jaehoon Chung --- drivers/power/pmic/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index ef8bf49d495..a62aa38054c 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -105,6 +105,13 @@ config DM_PMIC_PFUZE100 This config enables implementation of driver-model pmic uclass features for PMIC PFUZE100. The driver implements read/write operations. +config SPL_DM_PMIC_PFUZE100 + bool "Enable Driver Model for PMIC PFUZE100 in SPL" + depends on DM_PMIC + ---help--- + This config enables implementation of driver-model pmic uclass features + for PMIC PFUZE100 in SPL. The driver implements read/write operations. + config DM_PMIC_MAX77686 bool "Enable Driver Model for PMIC MAX77686" depends on DM_PMIC -- cgit v1.3.1 From b59889bf344dd261b50d69a5eacfa2874573c7cd Mon Sep 17 00:00:00 2001 From: Pratyush Yadav Date: Tue, 26 May 2020 17:35:57 +0530 Subject: regmap: Check for out-of-range offsets before mapping them In regmap_raw_{read,write}_range(), offsets are checked to make sure they aren't out of range. But this check happens _after_ the address is mapped from physical memory. Input should be sanity-checked before using it. Mapping the address before validating it leaves the door open to passing an invalid address to map_physmem(). So check for out of range offsets _before_ mapping them. This fixes a segmentation fault in sandbox when -1 is used as an offset to regmap_{read,write}(). Signed-off-by: Pratyush Yadav --- drivers/core/regmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index 4a214eff7cc..a67a237b88f 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -310,13 +310,13 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, } range = &map->ranges[range_num]; - ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); - if (offset + val_len > range->size) { debug("%s: offset/size combination invalid\n", __func__); return -ERANGE; } + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + switch (val_len) { case REGMAP_SIZE_8: *((u8 *)valp) = __read_8(ptr, map->endianness); @@ -419,13 +419,13 @@ int regmap_raw_write_range(struct regmap *map, uint range_num, uint offset, } range = &map->ranges[range_num]; - ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); - if (offset + val_len > range->size) { debug("%s: offset/size combination invalid\n", __func__); return -ERANGE; } + ptr = map_physmem(range->start + offset, val_len, MAP_NOCACHE); + switch (val_len) { case REGMAP_SIZE_8: __write_8(ptr, val, map->endianness); -- cgit v1.3.1 From c03b7612ea346ad7454086d1623fb57098faf315 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 2 Jun 2020 01:47:07 +0200 Subject: usb: provide a device tree node to USB devices It is possible to specify a device tree node for an USB device. This is useful if you have a static USB setup and want to use aliases which point to these nodes, like on the Raspberry Pi. The nodes are matched against their hub port number, the compatible strings are not matched for now. Signed-off-by: Michael Walle Reviewed-by: Marek Vasut Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 9 +++++++++ drivers/usb/host/usb-uclass.c | 41 ++++++++++++++++++++++++++++++++++++----- test/dm/usb.c | 22 ++++++++++++++++++++++ 3 files changed, 67 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 5ce5e284764..b9255e4593e 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -810,6 +810,8 @@ hub { compatible = "usb-hub"; usb,device-class = <9>; + #address-cells = <1>; + #size-cells = <0>; hub-emul { compatible = "sandbox,usb-hub"; #address-cells = <1>; @@ -838,6 +840,13 @@ }; }; + + usbstor@1 { + reg = <1>; + }; + usbstor@3 { + reg = <3>; + }; }; }; diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c index cb79dfbbd5b..f42c0625cbf 100644 --- a/drivers/usb/host/usb-uclass.c +++ b/drivers/usb/host/usb-uclass.c @@ -494,6 +494,35 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, return usb_match_one_id_intf(desc, int_desc, id); } +static ofnode usb_get_ofnode(struct udevice *hub, int port) +{ + ofnode node; + u32 reg; + + if (!dev_has_of_node(hub)) + return ofnode_null(); + + /* + * The USB controller and its USB hub are two different udevices, + * but the device tree has only one node for both. Thus we are + * assigning this node to both udevices. + * If port is zero, the controller scans its root hub, thus we + * are using the same ofnode as the controller here. + */ + if (!port) + return dev_ofnode(hub); + + ofnode_for_each_subnode(node, dev_ofnode(hub)) { + if (ofnode_read_u32(node, "reg", ®)) + continue; + + if (reg == port) + return node; + } + + return ofnode_null(); +} + /** * usb_find_and_bind_driver() - Find and bind the right USB driver * @@ -502,13 +531,14 @@ static int usb_match_one_id(struct usb_device_descriptor *desc, static int usb_find_and_bind_driver(struct udevice *parent, struct usb_device_descriptor *desc, struct usb_interface_descriptor *iface, - int bus_seq, int devnum, + int bus_seq, int devnum, int port, struct udevice **devp) { struct usb_driver_entry *start, *entry; int n_ents; int ret; char name[30], *str; + ofnode node = usb_get_ofnode(parent, port); *devp = NULL; debug("%s: Searching for driver\n", __func__); @@ -533,8 +563,8 @@ static int usb_find_and_bind_driver(struct udevice *parent, * find another driver. For now this doesn't seem * necesssary, so just bind the first match. */ - ret = device_bind(parent, drv, drv->name, NULL, -1, - &dev); + ret = device_bind_ofnode(parent, drv, drv->name, NULL, + node, &dev); if (ret) goto error; debug("%s: Match found: %s\n", __func__, drv->name); @@ -651,9 +681,10 @@ int usb_scan_device(struct udevice *parent, int port, if (ret) { if (ret != -ENOENT) return ret; - ret = usb_find_and_bind_driver(parent, &udev->descriptor, iface, + ret = usb_find_and_bind_driver(parent, &udev->descriptor, + iface, udev->controller_dev->seq, - udev->devnum, &dev); + udev->devnum, port, &dev); if (ret) return ret; created = true; diff --git a/test/dm/usb.c b/test/dm/usb.c index a25c2c14820..b273a515efd 100644 --- a/test/dm/usb.c +++ b/test/dm/usb.c @@ -78,6 +78,28 @@ static int dm_test_usb_multi(struct unit_test_state *uts) } DM_TEST(dm_test_usb_multi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +/* test that we have an associated ofnode with the usb device */ +static int dm_test_usb_fdt_node(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode node; + + state_set_skip_delays(true); + ut_assertok(usb_init()); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@1"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev)); + ut_asserteq(1, ofnode_equal(ofnode_null(), dev_ofnode(dev))); + ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev)); + node = ofnode_path("/usb@1/hub/usbstor@3"); + ut_asserteq(1, ofnode_equal(node, dev_ofnode(dev))); + ut_assertok(usb_stop()); + + return 0; +} +DM_TEST(dm_test_usb_fdt_node, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + static int count_usb_devices(void) { struct udevice *hub; -- cgit v1.3.1 From be1a6e94254af205bd67d69e3bdb26b161ccd72f Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 2 Jun 2020 01:47:09 +0200 Subject: dm: uclass: don't assign aliased seq numbers If there are aliases for an uclass, set the base for the "dynamically" allocated numbers next to the highest alias. Please note, that this might lead to holes in the sequences, depending on the device tree. For example if there is only an alias "ethernet1", the next device seq number would be 2. In particular this fixes a problem with boards which are using ethernet aliases but also might have network add-in cards like the E1000. If the board is started with the add-in card and depending on the order of the drivers, the E1000 might occupy the first ethernet device and mess up all the hardware addresses, because the devices are now shifted by one. Also adapt the test cases to the new handling and add test cases checking the holes in the seq numbers. Signed-off-by: Michael Walle Reviewed-by: Alex Marginean Tested-by: Alex Marginean Acked-by: Vladimir Oltean Reviewed-by: Simon Glass Tested-by: Michal Simek [on zcu102-revA] --- arch/sandbox/dts/test.dts | 4 ++-- drivers/core/uclass.c | 21 +++++++++++++++------ include/configs/sandbox.h | 6 +++--- test/dm/eth.c | 14 +++++++------- test/dm/test-fdt.c | 22 +++++++++++++++++----- 5 files changed, 44 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b9255e4593e..a6e2bfd082f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -23,8 +23,8 @@ pci0 = &pci0; pci1 = &pci1; pci2 = &pci2; - remoteproc1 = &rproc_1; - remoteproc2 = &rproc_2; + remoteproc0 = &rproc_1; + remoteproc1 = &rproc_2; rtc0 = &rtc_0; rtc1 = &rtc_1; spi0 = "/spi@0"; diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 2ab419cfe4d..c3f1b73cd6b 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -689,13 +689,14 @@ int uclass_unbind_device(struct udevice *dev) int uclass_resolve_seq(struct udevice *dev) { + struct uclass *uc = dev->uclass; + struct uclass_driver *uc_drv = uc->uc_drv; struct udevice *dup; - int seq; + int seq = 0; int ret; assert(dev->seq == -1); - ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, dev->req_seq, - false, &dup); + ret = uclass_find_device_by_seq(uc_drv->id, dev->req_seq, false, &dup); if (!ret) { dm_warn("Device '%s': seq %d is in use by '%s'\n", dev->name, dev->req_seq, dup->name); @@ -707,9 +708,17 @@ int uclass_resolve_seq(struct udevice *dev) return ret; } - for (seq = 0; seq < DM_MAX_SEQ; seq++) { - ret = uclass_find_device_by_seq(dev->uclass->uc_drv->id, seq, - false, &dup); + if (CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(DM_SEQ_ALIAS) && + (uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) { + /* + * dev_read_alias_highest_id() will return -1 if there no + * alias. Thus we can always add one. + */ + seq = dev_read_alias_highest_id(uc_drv->name) + 1; + } + + for (; seq < DM_MAX_SEQ; seq++) { + ret = uclass_find_device_by_seq(uc_drv->id, seq, false, &dup); if (ret == -ENODEV) break; if (ret) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 2a81f3a9bc0..528187e1a68 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -94,9 +94,9 @@ #endif #define SANDBOX_ETH_SETTINGS "ethaddr=00:00:11:22:33:44\0" \ - "eth1addr=00:00:11:22:33:45\0" \ - "eth3addr=00:00:11:22:33:46\0" \ - "eth5addr=00:00:11:22:33:47\0" \ + "eth3addr=00:00:11:22:33:45\0" \ + "eth5addr=00:00:11:22:33:46\0" \ + "eth6addr=00:00:11:22:33:47\0" \ "ipaddr=1.2.3.4\0" #define MEM_LAYOUT_ENV_SETTINGS \ diff --git a/test/dm/eth.c b/test/dm/eth.c index 1fddcaabb09..b58c9640a27 100644 --- a/test/dm/eth.c +++ b/test/dm/eth.c @@ -48,7 +48,7 @@ static int dm_test_eth_alias(struct unit_test_state *uts) ut_assertok(net_loop(PING)); ut_asserteq_str("eth@10002000", env_get("ethact")); - env_set("ethact", "eth1"); + env_set("ethact", "eth6"); ut_assertok(net_loop(PING)); ut_asserteq_str("eth@10004000", env_get("ethact")); @@ -105,7 +105,7 @@ static int dm_test_eth_act(struct unit_test_state *uts) const char *ethname[DM_TEST_ETH_NUM] = {"eth@10002000", "eth@10003000", "sbe5", "eth@10004000"}; const char *addrname[DM_TEST_ETH_NUM] = {"ethaddr", "eth5addr", - "eth3addr", "eth1addr"}; + "eth3addr", "eth6addr"}; char ethaddr[DM_TEST_ETH_NUM][18]; int i; @@ -188,15 +188,15 @@ static int dm_test_eth_rotate(struct unit_test_state *uts) /* Invalidate eth1's MAC address */ memset(ethaddr, '\0', sizeof(ethaddr)); - strncpy(ethaddr, env_get("eth1addr"), 17); - /* Must disable access protection for eth1addr before clearing */ - env_set(".flags", "eth1addr"); - env_set("eth1addr", NULL); + strncpy(ethaddr, env_get("eth6addr"), 17); + /* Must disable access protection for eth6addr before clearing */ + env_set(".flags", "eth6addr"); + env_set("eth6addr", NULL); retval = _dm_test_eth_rotate1(uts); /* Restore the env */ - env_set("eth1addr", ethaddr); + env_set("eth6addr", ethaddr); env_set("ethrotate", NULL); if (!retval) { diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 4fcae03dc5b..51f25474094 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -361,20 +361,32 @@ static int dm_test_fdt_uclass_seq(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev)); ut_asserteq_str("d-test", dev->name); - /* d-test actually gets 0 */ - ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev)); + /* + * d-test actually gets 9, because thats the next free one after the + * aliases. + */ + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 9, &dev)); ut_asserteq_str("d-test", dev->name); - /* initially no one wants seq 1 */ - ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, + /* initially no one wants seq 10 */ + ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 10, &dev)); ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev)); /* But now that it is probed, we can find it */ - ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev)); + ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 10, &dev)); ut_asserteq_str("f-test", dev->name); + /* + * And we should still have holes in our sequence numbers, that is 2 + * and 4 should not be used. + */ + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 2, + true, &dev)); + ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 4, + true, &dev)); + return 0; } DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -- cgit v1.3.1