Commit f262d4ca4b2bf8a99acb37c6151c54cd80251566
1 parent
bd933bfd83
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
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; |
include/dm/device.h
... | ... | @@ -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 |
include/dm/read.h
... | ... | @@ -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 | } |
test/dm/test-fdt.c
... | ... | @@ -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); |
-
mentioned in commit 3cfc04