return dm_priv_to_rw(dev->parent_priv_);
}
+void *dev_get_attach_ptr(const struct udevice *dev, enum dm_tag_t tag)
+{
+ switch (tag) {
+ case DM_TAG_PLAT:
+ return dev_get_plat(dev);
+ case DM_TAG_PARENT_PLAT:
+ return dev_get_parent_plat(dev);
+ case DM_TAG_UC_PLAT:
+ return dev_get_uclass_plat(dev);
+ case DM_TAG_PRIV:
+ return dev_get_priv(dev);
+ case DM_TAG_PARENT_PRIV:
+ return dev_get_parent_priv(dev);
+ case DM_TAG_UC_PRIV:
+ return dev_get_uclass_priv(dev);
+ default:
+ return NULL;
+ }
+}
+
+int dev_get_attach_size(const struct udevice *dev, enum dm_tag_t tag)
+{
+ const struct udevice *parent = dev_get_parent(dev);
+ const struct uclass *uc = dev->uclass;
+ const struct uclass_driver *uc_drv = uc->uc_drv;
+ const struct driver *parent_drv = NULL;
+ int size = 0;
+
+ if (parent)
+ parent_drv = parent->driver;
+
+ switch (tag) {
+ case DM_TAG_PLAT:
+ size = dev->driver->plat_auto;
+ break;
+ case DM_TAG_PARENT_PLAT:
+ if (parent) {
+ size = parent_drv->per_child_plat_auto;
+ if (!size)
+ size = parent->uclass->uc_drv->per_child_plat_auto;
+ }
+ break;
+ case DM_TAG_UC_PLAT:
+ size = uc_drv->per_device_plat_auto;
+ break;
+ case DM_TAG_PRIV:
+ size = dev->driver->priv_auto;
+ break;
+ case DM_TAG_PARENT_PRIV:
+ if (parent) {
+ size = parent_drv->per_child_auto;
+ if (!size)
+ size = parent->uclass->uc_drv->per_child_auto;
+ }
+ break;
+ case DM_TAG_UC_PRIV:
+ size = uc_drv->per_device_auto;
+ break;
+ default:
+ break;
+ }
+
+ return size;
+}
+
static int device_get_device_tail(struct udevice *dev, int ret,
struct udevice **devp)
{
#define _DM_DEVICE_H
#include <dm/ofnode.h>
+#include <dm/tag.h>
#include <dm/uclass-id.h>
#include <fdtdec.h>
#include <linker_lists.h>
*/
void *dev_get_uclass_priv(const struct udevice *dev);
+/**
+ * dev_get_attach_ptr() - Get the value of an attached pointed tag
+ *
+ * The tag is assumed to hold a pointer, if it exists
+ *
+ * @dev: Device to look at
+ * @tag: Tag to access
+ * @return value of tag, or NULL if there is no tag of this type
+ */
+void *dev_get_attach_ptr(const struct udevice *dev, enum dm_tag_t tag);
+
+/**
+ * dev_get_attach_size() - Get the size of an attached tag
+ *
+ * Core tags have an automatic-allocation mechanism where the allocated size is
+ * defined by the device, parent or uclass. This returns the size associated
+ * with a particular tag
+ *
+ * @dev: Device to look at
+ * @tag: Tag to access
+ * @return size of auto-allocated data, 0 if none
+ */
+int dev_get_attach_size(const struct udevice *dev, enum dm_tag_t tag);
+
/**
* dev_get_parent() - Get the parent of a device
*
return 0;
}
DM_TEST(dm_test_uclass_find_device, UT_TESTF_SCAN_FDT);
+
+/* Test getting information about tags attached to devices */
+static int dm_test_dev_get_attach(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ ut_assertok(uclass_first_device_err(UCLASS_TEST_FDT, &dev));
+ ut_asserteq_str("a-test", dev->name);
+
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PLAT));
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PRIV));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_UC_PRIV));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_UC_PLAT));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PLAT));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PRIV));
+
+ ut_asserteq(sizeof(struct dm_test_pdata),
+ dev_get_attach_size(dev, DM_TAG_PLAT));
+ ut_asserteq(sizeof(struct dm_test_priv),
+ dev_get_attach_size(dev, DM_TAG_PRIV));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_UC_PRIV));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_UC_PLAT));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PLAT));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PRIV));
+
+ return 0;
+}
+DM_TEST(dm_test_dev_get_attach, UT_TESTF_SCAN_FDT);
+
+/* Test getting information about tags attached to bus devices */
+static int dm_test_dev_get_attach_bus(struct unit_test_state *uts)
+{
+ struct udevice *dev, *child;
+
+ ut_assertok(uclass_first_device_err(UCLASS_TEST_BUS, &dev));
+ ut_asserteq_str("some-bus", dev->name);
+
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PLAT));
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_PRIV));
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_UC_PRIV));
+ ut_assertnonnull(dev_get_attach_ptr(dev, DM_TAG_UC_PLAT));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PLAT));
+ ut_assertnull(dev_get_attach_ptr(dev, DM_TAG_PARENT_PRIV));
+
+ ut_asserteq(sizeof(struct dm_test_pdata),
+ dev_get_attach_size(dev, DM_TAG_PLAT));
+ ut_asserteq(sizeof(struct dm_test_priv),
+ dev_get_attach_size(dev, DM_TAG_PRIV));
+ ut_asserteq(sizeof(struct dm_test_uclass_priv),
+ dev_get_attach_size(dev, DM_TAG_UC_PRIV));
+ ut_asserteq(sizeof(struct dm_test_uclass_plat),
+ dev_get_attach_size(dev, DM_TAG_UC_PLAT));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PLAT));
+ ut_asserteq(0, dev_get_attach_size(dev, DM_TAG_PARENT_PRIV));
+
+ /* Now try the child of the bus */
+ ut_assertok(device_first_child_err(dev, &child));
+ ut_asserteq_str("c-test@5", child->name);
+
+ ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PLAT));
+ ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PRIV));
+ ut_assertnull(dev_get_attach_ptr(child, DM_TAG_UC_PRIV));
+ ut_assertnull(dev_get_attach_ptr(child, DM_TAG_UC_PLAT));
+ ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PARENT_PLAT));
+ ut_assertnonnull(dev_get_attach_ptr(child, DM_TAG_PARENT_PRIV));
+
+ ut_asserteq(sizeof(struct dm_test_pdata),
+ dev_get_attach_size(child, DM_TAG_PLAT));
+ ut_asserteq(sizeof(struct dm_test_priv),
+ dev_get_attach_size(child, DM_TAG_PRIV));
+ ut_asserteq(0, dev_get_attach_size(child, DM_TAG_UC_PRIV));
+ ut_asserteq(0, dev_get_attach_size(child, DM_TAG_UC_PLAT));
+ ut_asserteq(sizeof(struct dm_test_parent_plat),
+ dev_get_attach_size(child, DM_TAG_PARENT_PLAT));
+ ut_asserteq(sizeof(struct dm_test_parent_data),
+ dev_get_attach_size(child, DM_TAG_PARENT_PRIV));
+
+ return 0;
+}
+DM_TEST(dm_test_dev_get_attach_bus, UT_TESTF_SCAN_FDT);