Commit f262d4ca4b2bf8a99acb37c6151c54cd80251566

Authored by Simon Glass
1 parent bd933bfd83

dm: core: Add a way to read platdata for all child devices

When generating ACPI tables we need to make sure that all devices have
read their platform data, so that they can generate the tables correctly.

Rather than adding this code in ACPI, create a core function to handle it.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 4 changed files with 99 additions and 1 deletions Side-by-side Diff

drivers/core/device.c
... ... @@ -792,6 +792,42 @@
792 792 return -ENODEV;
793 793 }
794 794  
  795 +int device_first_child_ofdata_err(struct udevice *parent, struct udevice **devp)
  796 +{
  797 + struct udevice *dev;
  798 + int ret;
  799 +
  800 + device_find_first_child(parent, &dev);
  801 + if (!dev)
  802 + return -ENODEV;
  803 +
  804 + ret = device_ofdata_to_platdata(dev);
  805 + if (ret)
  806 + return ret;
  807 +
  808 + *devp = dev;
  809 +
  810 + return 0;
  811 +}
  812 +
  813 +int device_next_child_ofdata_err(struct udevice **devp)
  814 +{
  815 + struct udevice *dev = *devp;
  816 + int ret;
  817 +
  818 + device_find_next_child(&dev);
  819 + if (!dev)
  820 + return -ENODEV;
  821 +
  822 + ret = device_ofdata_to_platdata(dev);
  823 + if (ret)
  824 + return ret;
  825 +
  826 + *devp = dev;
  827 +
  828 + return 0;
  829 +}
  830 +
795 831 struct udevice *dev_get_parent(const struct udevice *child)
796 832 {
797 833 return child->parent;
... ... @@ -578,6 +578,31 @@
578 578 struct udevice **devp);
579 579  
580 580 /**
  581 + * device_first_child_ofdata_err() - Find the first child and reads its platdata
  582 + *
  583 + * The ofdata_to_platdata() method is called on the child before it is returned,
  584 + * but the child is not probed.
  585 + *
  586 + * @parent: Parent to check
  587 + * @devp: Returns child that was found, if any
  588 + * @return 0 on success, -ENODEV if no children, other -ve on error
  589 + */
  590 +int device_first_child_ofdata_err(struct udevice *parent,
  591 + struct udevice **devp);
  592 +
  593 +/*
  594 + * device_next_child_ofdata_err() - Find the next child and read its platdata
  595 + *
  596 + * The ofdata_to_platdata() method is called on the child before it is returned,
  597 + * but the child is not probed.
  598 + *
  599 + * @devp: On entry, points to the previous child; on exit returns the child that
  600 + * was found, if any
  601 + * @return 0 on success, -ENODEV if no children, other -ve on error
  602 + */
  603 +int device_next_child_ofdata_err(struct udevice **devp);
  604 +
  605 +/**
581 606 * device_has_children() - check if a device has any children
582 607 *
583 608 * @dev: Device to check
... ... @@ -705,6 +730,23 @@
705 730 */
706 731 #define device_foreach_child(pos, parent) \
707 732 list_for_each_entry(pos, &parent->child_head, sibling_node)
  733 +
  734 +/**
  735 + * device_foreach_child_ofdata_to_platdata() - iterate through children
  736 + *
  737 + * This stops when it gets an error, with @pos set to the device that failed to
  738 + * read ofdata.
  739 +
  740 + * This creates a for() loop which works through the available children of
  741 + * a device in order from start to end. Device ofdata is read by calling
  742 + * device_ofdata_to_platdata() on each one. The devices are not probed.
  743 + *
  744 + * @pos: struct udevice * for the current device
  745 + * @parent: parent device to scan
  746 + */
  747 +#define device_foreach_child_ofdata_to_platdata(pos, parent) \
  748 + for (int _ret = device_first_child_ofdata_err(parent, &dev); !_ret; \
  749 + _ret = device_next_child_ofdata_err(&dev))
708 750  
709 751 /**
710 752 * dm_scan_fdt_dev() - Bind child device in a the device tree
... ... @@ -844,7 +844,8 @@
844 844 }
845 845  
846 846 static inline const uint8_t *dev_read_u8_array_ptr(const struct udevice *dev,
847   - const char *propname, size_t sz)
  847 + const char *propname,
  848 + size_t sz)
848 849 {
849 850 return ofnode_read_u8_array_ptr(dev_ofnode(dev), propname, sz);
850 851 }
... ... @@ -872,4 +872,23 @@
872 872 return 0;
873 873 }
874 874 DM_TEST(dm_test_read_int, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  875 +
  876 +/* Test device_first_child_ofdata_err(), etc. */
  877 +static int dm_test_child_ofdata(struct unit_test_state *uts)
  878 +{
  879 + struct udevice *bus, *dev;
  880 + int count;
  881 +
  882 + ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &bus));
  883 + count = 0;
  884 + device_foreach_child_ofdata_to_platdata(dev, bus) {
  885 + ut_assert(dev->flags & DM_FLAG_PLATDATA_VALID);
  886 + ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
  887 + count++;
  888 + }
  889 + ut_asserteq(3, count);
  890 +
  891 + return 0;
  892 +}
  893 +DM_TEST(dm_test_child_ofdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);