diff --git a/drivers/w1-eeprom/ds24xxx.c b/drivers/w1-eeprom/ds24xxx.c index d12fd5754e..4be378b43d 100644 --- a/drivers/w1-eeprom/ds24xxx.c +++ b/drivers/w1-eeprom/ds24xxx.c @@ -53,3 +53,10 @@ U_BOOT_DRIVER(ds24xxx) = { .ops = &ds24xxx_ops, .probe = ds24xxx_probe, }; + +u8 family_supported[] = { + W1_FAMILY_DS24B33, + W1_FAMILY_DS2431, +}; + +U_BOOT_W1_DEVICE(ds24xxx, family_supported); diff --git a/drivers/w1-eeprom/ds2502.c b/drivers/w1-eeprom/ds2502.c index b3d68d7f05..a67f5edd0f 100644 --- a/drivers/w1-eeprom/ds2502.c +++ b/drivers/w1-eeprom/ds2502.c @@ -243,3 +243,9 @@ U_BOOT_DRIVER(ds2502) = { .ops = &ds2502_ops, .probe = ds2502_probe, }; + +u8 family_supported[] = { + W1_FAMILY_DS2502, +}; + +U_BOOT_W1_DEVICE(ds2502, family_supported); diff --git a/drivers/w1-eeprom/w1-eeprom-uclass.c b/drivers/w1-eeprom/w1-eeprom-uclass.c index 97a9d43b03..7a02af3dd6 100644 --- a/drivers/w1-eeprom/w1-eeprom-uclass.c +++ b/drivers/w1-eeprom/w1-eeprom-uclass.c @@ -37,37 +37,6 @@ int w1_eeprom_read_buf(struct udevice *dev, unsigned int offset, return ops->read_buf(dev, offset, buf, count); } -int w1_eeprom_register_new_device(u64 id) -{ - u8 family = id & 0xff; - int ret; - struct udevice *dev; - - for (ret = uclass_first_device(UCLASS_W1_EEPROM, &dev); - !ret && dev; - uclass_next_device(&dev)) { - if (ret || !dev) { - debug("cannot find w1 eeprom dev\n"); - return ret; - } - if (dev_get_driver_data(dev) == family) { - struct w1_device *w1; - - w1 = dev_get_parent_plat(dev); - if (w1->id) /* device already in use */ - continue; - w1->id = id; - debug("%s: Match found: %s:%s %llx\n", __func__, - dev->name, dev->driver->name, id); - return 0; - } - } - - debug("%s: No matches found: error %d\n", __func__, ret); - - return ret; -} - int w1_eeprom_get_id(struct udevice *dev, u64 *id) { struct w1_device *w1 = dev_get_parent_plat(dev); diff --git a/drivers/w1/w1-uclass.c b/drivers/w1/w1-uclass.c index 8bc6cb13f4..b98927389f 100644 --- a/drivers/w1/w1-uclass.c +++ b/drivers/w1/w1-uclass.c @@ -4,9 +4,11 @@ * Copyright (c) 2015 Free Electrons * Copyright (c) 2015 NextThing Co. * Copyright (c) 2018 Microchip Technology, Inc. + * Copyright (c) 2021 Bootlin * * Maxime Ripard * Eugen Hristev + * Kory Maincent * */ @@ -26,6 +28,76 @@ struct w1_bus { u64 search_id; }; +int w1_bus_find_dev(const struct udevice *bus, u64 id, struct udevice +**devp) +{ + struct udevice *dev; + u8 family = id & 0xff; + int ret; + + for (ret = uclass_first_device(UCLASS_W1_EEPROM, &dev); + !ret && dev; + uclass_next_device(&dev)) { + if (ret || !dev) { + debug("cannot find w1 eeprom dev\n"); + return -ENODEV; + } + + if (dev_get_driver_data(dev) == family) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + +int w1_register_new_device(u64 id, struct udevice *bus) +{ + u8 family = id & 0xff; + int n_ents, ret = 0; + struct udevice *dev; + + struct w1_driver_entry *start, *entry; + + start = ll_entry_start(struct w1_driver_entry, w1_driver_entry); + n_ents = ll_entry_count(struct w1_driver_entry, w1_driver_entry); + + for (entry = start; entry != start + n_ents; entry++) { + const u8 *match_family; + const struct driver *drv; + struct w1_device *w1; + + for (match_family = entry->family; match_family; + match_family++) { + if (*match_family != family) + continue; + + ret = w1_bus_find_dev(bus, id, &dev); + + /* If nothing in the device tree, bind a device */ + if (ret == -ENODEV) { + drv = entry->driver; + ret = device_bind(bus, drv, drv->name, + NULL, ofnode_null(), &dev); + if (ret) + return ret; + } + + device_probe(dev); + + w1 = dev_get_parent_plat(dev); + w1->id = id; + + return 0; + } + } + + debug("%s: No matches found: error %d\n", __func__, ret); + + return ret; +} + static int w1_enumerate(struct udevice *bus) { const struct w1_ops *ops = device_get_ops(bus); @@ -97,8 +169,8 @@ static int w1_enumerate(struct udevice *bus) debug("%s: Detected new device 0x%llx (family 0x%x)\n", bus->name, rn, (u8)(rn & 0xff)); - /* attempt to register as w1-eeprom device */ - w1_eeprom_register_new_device(rn); + /* attempt to register as w1 device */ + w1_register_new_device(rn, bus); } } diff --git a/include/w1-eeprom.h b/include/w1-eeprom.h index 22337368b4..b3cf77a81e 100644 --- a/include/w1-eeprom.h +++ b/include/w1-eeprom.h @@ -27,7 +27,5 @@ int w1_eeprom_read_buf(struct udevice *dev, unsigned int offset, int w1_eeprom_dm_init(void); -int w1_eeprom_register_new_device(u64 id); - int w1_eeprom_get_id(struct udevice *dev, u64 *id); #endif diff --git a/include/w1.h b/include/w1.h index 77f439e587..b18078ba15 100644 --- a/include/w1.h +++ b/include/w1.h @@ -15,6 +15,23 @@ struct udevice; #define W1_FAMILY_DS2502 0x09 #define W1_FAMILY_EEP_SANDBOX 0xfe +struct w1_driver_entry { + struct driver *driver; + u8 *family; +}; + +/* U_BOOT_W1_DEVICE() tells U-Boot to create a one-wire device. + * + * @__name: Device name (C identifier, not a string. E.g. gpio7_at_ff7e0000) + * @__driver: Driver name (C identifier, not a string. E.g. gpio7_at_ff7e0000) + * @__family: Family code number of the one-wire + */ +#define U_BOOT_W1_DEVICE(__name, __family) \ + ll_entry_declare(struct w1_driver_entry, __name, w1_driver_entry) = { \ + .driver = llsym(struct driver, __name, driver), \ + .family = __family, \ + } + struct w1_device { u64 id; };