uboot/test/dm/of_platdata.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2
   3#include <common.h>
   4#include <clk.h>
   5#include <dm.h>
   6#include <dt-structs.h>
   7#include <irq.h>
   8#include <dm/test.h>
   9#include <test/test.h>
  10#include <test/ut.h>
  11#include <asm-generic/gpio.h>
  12#include <asm/global_data.h>
  13
  14/* Test that we can find a device using of-platdata */
  15static int dm_test_of_plat_base(struct unit_test_state *uts)
  16{
  17        struct udevice *dev;
  18
  19        ut_assertok(uclass_first_device_err(UCLASS_SERIAL, &dev));
  20        ut_asserteq_str("sandbox_serial", dev->name);
  21
  22        return 0;
  23}
  24DM_TEST(dm_test_of_plat_base, UT_TESTF_SCAN_PDATA);
  25
  26/* Test that we can read properties from a device */
  27static int dm_test_of_plat_props(struct unit_test_state *uts)
  28{
  29        struct dtd_sandbox_spl_test *plat;
  30        struct udevice *dev;
  31        int i;
  32
  33        ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_spl_test",
  34                                              &dev));
  35
  36        plat = dev_get_plat(dev);
  37        ut_assert(plat->boolval);
  38        ut_asserteq(1, plat->intval);
  39        ut_asserteq(3, ARRAY_SIZE(plat->intarray));
  40        ut_asserteq(2, plat->intarray[0]);
  41        ut_asserteq(3, plat->intarray[1]);
  42        ut_asserteq(4, plat->intarray[2]);
  43        ut_asserteq(5, plat->byteval);
  44        ut_asserteq(1, ARRAY_SIZE(plat->maybe_empty_int));
  45        ut_asserteq(0, plat->maybe_empty_int[0]);
  46        ut_asserteq(3, ARRAY_SIZE(plat->bytearray));
  47        ut_asserteq(6, plat->bytearray[0]);
  48        ut_asserteq(0, plat->bytearray[1]);
  49        ut_asserteq(0, plat->bytearray[2]);
  50        ut_asserteq(9, ARRAY_SIZE(plat->longbytearray));
  51        for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++)
  52                ut_asserteq(9 + i, plat->longbytearray[i]);
  53        ut_asserteq_str("message", plat->stringval);
  54        ut_asserteq(3, ARRAY_SIZE(plat->stringarray));
  55        ut_asserteq_str("multi-word", plat->stringarray[0]);
  56        ut_asserteq_str("message", plat->stringarray[1]);
  57        ut_asserteq_str("", plat->stringarray[2]);
  58
  59        ut_assertok(uclass_next_device_err(&dev));
  60        plat = dev_get_plat(dev);
  61        ut_assert(!plat->boolval);
  62        ut_asserteq(3, plat->intval);
  63        ut_asserteq(5, plat->intarray[0]);
  64        ut_asserteq(0, plat->intarray[1]);
  65        ut_asserteq(0, plat->intarray[2]);
  66        ut_asserteq(8, plat->byteval);
  67        ut_asserteq(3, ARRAY_SIZE(plat->bytearray));
  68        ut_asserteq(1, plat->bytearray[0]);
  69        ut_asserteq(0x23, plat->bytearray[1]);
  70        ut_asserteq(0x34, plat->bytearray[2]);
  71        for (i = 0; i < ARRAY_SIZE(plat->longbytearray); i++)
  72                ut_asserteq(i < 4 ? 9 + i : 0, plat->longbytearray[i]);
  73        ut_asserteq_str("message2", plat->stringval);
  74        ut_asserteq_str("another", plat->stringarray[0]);
  75        ut_asserteq_str("multi-word", plat->stringarray[1]);
  76        ut_asserteq_str("message", plat->stringarray[2]);
  77
  78        ut_assertok(uclass_next_device_err(&dev));
  79        plat = dev_get_plat(dev);
  80        ut_assert(!plat->boolval);
  81        ut_asserteq_str("one", plat->stringarray[0]);
  82        ut_asserteq_str("", plat->stringarray[1]);
  83        ut_asserteq_str("", plat->stringarray[2]);
  84        ut_asserteq(1, plat->maybe_empty_int[0]);
  85
  86        ut_assertok(uclass_next_device_err(&dev));
  87        plat = dev_get_plat(dev);
  88        ut_assert(!plat->boolval);
  89        ut_asserteq_str("spl", plat->stringarray[0]);
  90
  91        ut_asserteq(-ENODEV, uclass_next_device_err(&dev));
  92
  93        return 0;
  94}
  95DM_TEST(dm_test_of_plat_props, UT_TESTF_SCAN_PDATA);
  96
  97/*
  98 * find_driver_info - recursively find the driver_info for a device
  99 *
 100 * This sets found[idx] to true when it finds the driver_info record for a
 101 * device, where idx is the index in the driver_info linker list.
 102 *
 103 * @uts: Test state
 104 * @parent: Parent to search
 105 * @found: bool array to update
 106 * Return: 0 if OK, non-zero on error
 107 */
 108static int find_driver_info(struct unit_test_state *uts, struct udevice *parent,
 109                            bool found[])
 110{
 111        struct udevice *dev;
 112
 113        /* If not the root device, find the entry that caused it to be bound */
 114        if (parent->parent) {
 115                const int n_ents =
 116                        ll_entry_count(struct driver_info, driver_info);
 117                int idx = -1;
 118                int i;
 119
 120                for (i = 0; i < n_ents; i++) {
 121                        const struct driver_rt *drt = gd_dm_driver_rt() + i;
 122
 123                        if (drt->dev == parent) {
 124                                idx = i;
 125                                found[idx] = true;
 126                                break;
 127                        }
 128                }
 129
 130                ut_assert(idx != -1);
 131        }
 132
 133        device_foreach_child(dev, parent) {
 134                int ret;
 135
 136                ret = find_driver_info(uts, dev, found);
 137                if (ret < 0)
 138                        return ret;
 139        }
 140
 141        return 0;
 142}
 143
 144/* Check that every device is recorded in its driver_info struct */
 145static int dm_test_of_plat_dev(struct unit_test_state *uts)
 146{
 147        const int n_ents = ll_entry_count(struct driver_info, driver_info);
 148        bool found[n_ents];
 149        uint i;
 150
 151        /* Skip this test if there is no platform data */
 152        if (!CONFIG_IS_ENABLED(OF_PLATDATA_DRIVER_RT))
 153                return 0;
 154
 155        /* Record the indexes that are found */
 156        memset(found, '\0', sizeof(found));
 157        ut_assertok(find_driver_info(uts, gd->dm_root, found));
 158
 159        /* Make sure that the driver entries without devices have no ->dev */
 160        for (i = 0; i < n_ents; i++) {
 161                const struct driver_rt *drt = gd_dm_driver_rt() + i;
 162                struct udevice *dev;
 163
 164                if (found[i]) {
 165                        /* Make sure we can find it */
 166                        ut_assertnonnull(drt->dev);
 167                        ut_assertok(device_get_by_ofplat_idx(i, &dev));
 168                        ut_asserteq_ptr(dev, drt->dev);
 169                } else {
 170                        ut_assertnull(drt->dev);
 171                        ut_asserteq(-ENOENT, device_get_by_ofplat_idx(i, &dev));
 172                }
 173        }
 174
 175        return 0;
 176}
 177DM_TEST(dm_test_of_plat_dev, UT_TESTF_SCAN_PDATA);
 178
 179/* Test handling of phandles that point to other devices */
 180static int dm_test_of_plat_phandle(struct unit_test_state *uts)
 181{
 182        struct dtd_sandbox_clk_test *plat;
 183        struct udevice *dev, *clk;
 184
 185        ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev));
 186        ut_asserteq_str("sandbox_clk_test", dev->name);
 187        plat = dev_get_plat(dev);
 188
 189        ut_assertok(device_get_by_ofplat_idx(plat->clocks[0].idx, &clk));
 190        ut_asserteq_str("sandbox_fixed_clock", clk->name);
 191
 192        ut_assertok(device_get_by_ofplat_idx(plat->clocks[1].idx, &clk));
 193        ut_asserteq_str("sandbox_clk", clk->name);
 194        ut_asserteq(1, plat->clocks[1].arg[0]);
 195
 196        ut_assertok(device_get_by_ofplat_idx(plat->clocks[2].idx, &clk));
 197        ut_asserteq_str("sandbox_clk", clk->name);
 198        ut_asserteq(0, plat->clocks[2].arg[0]);
 199
 200        ut_assertok(device_get_by_ofplat_idx(plat->clocks[3].idx, &clk));
 201        ut_asserteq_str("sandbox_clk", clk->name);
 202        ut_asserteq(3, plat->clocks[3].arg[0]);
 203
 204        ut_assertok(device_get_by_ofplat_idx(plat->clocks[4].idx, &clk));
 205        ut_asserteq_str("sandbox_clk", clk->name);
 206        ut_asserteq(2, plat->clocks[4].arg[0]);
 207
 208        return 0;
 209}
 210DM_TEST(dm_test_of_plat_phandle, UT_TESTF_SCAN_PDATA);
 211
 212#if CONFIG_IS_ENABLED(OF_PLATDATA_PARENT)
 213/* Test that device parents are correctly set up */
 214static int dm_test_of_plat_parent(struct unit_test_state *uts)
 215{
 216        struct udevice *rtc, *i2c;
 217
 218        ut_assertok(uclass_first_device_err(UCLASS_RTC, &rtc));
 219        ut_assertok(uclass_first_device_err(UCLASS_I2C, &i2c));
 220        ut_asserteq_ptr(i2c, dev_get_parent(rtc));
 221
 222        return 0;
 223}
 224DM_TEST(dm_test_of_plat_parent, UT_TESTF_SCAN_PDATA);
 225#endif
 226
 227/* Test clocks with of-platdata */
 228static int dm_test_of_plat_clk(struct unit_test_state *uts)
 229{
 230        struct dtd_sandbox_clk_test *plat;
 231        struct udevice *dev;
 232        struct clk clk;
 233
 234        ut_assertok(uclass_first_device_err(UCLASS_MISC, &dev));
 235        ut_asserteq_str("sandbox_clk_test", dev->name);
 236        plat = dev_get_plat(dev);
 237
 238        ut_assertok(clk_get_by_phandle(dev, &plat->clocks[0], &clk));
 239        ut_asserteq_str("sandbox_fixed_clock", clk.dev->name);
 240
 241        return 0;
 242}
 243DM_TEST(dm_test_of_plat_clk, UT_TESTF_SCAN_PDATA);
 244
 245/* Test irqs with of-platdata */
 246static int dm_test_of_plat_irq(struct unit_test_state *uts)
 247{
 248        struct dtd_sandbox_irq_test *plat;
 249        struct udevice *dev;
 250        struct irq irq;
 251
 252        ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_irq_test",
 253                                              &dev));
 254        plat = dev_get_plat(dev);
 255
 256        ut_assertok(irq_get_by_phandle(dev, &plat->interrupts_extended[0],
 257                                       &irq));
 258        ut_asserteq_str("sandbox_irq", irq.dev->name);
 259
 260        return 0;
 261}
 262DM_TEST(dm_test_of_plat_irq, UT_TESTF_SCAN_PDATA);
 263
 264/* Test GPIOs with of-platdata */
 265static int dm_test_of_plat_gpio(struct unit_test_state *uts)
 266{
 267        struct dtd_sandbox_gpio_test *plat;
 268        struct udevice *dev;
 269        struct gpio_desc desc;
 270
 271        ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_gpio_test",
 272                                              &dev));
 273        plat = dev_get_plat(dev);
 274
 275        ut_assertok(gpio_request_by_phandle(dev, &plat->test_gpios[0], &desc,
 276                                            GPIOD_IS_OUT));
 277        ut_asserteq_str("sandbox_gpio", desc.dev->name);
 278
 279        return 0;
 280}
 281DM_TEST(dm_test_of_plat_gpio, UT_TESTF_SCAN_PDATA);
 282