uboot/test/dm/phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
   4 * Written by Jean-Jacques Hiblot  <jjhiblot@ti.com>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <generic-phy.h>
  10#include <log.h>
  11#include <dm/test.h>
  12#include <test/test.h>
  13#include <test/ut.h>
  14
  15/* Base test of the phy uclass */
  16static int dm_test_phy_base(struct unit_test_state *uts)
  17{
  18        struct udevice *dev;
  19        struct phy phy1_method1;
  20        struct phy phy1_method2;
  21        struct phy phy2;
  22        struct phy phy3;
  23        struct udevice *parent;
  24
  25        /* Get the device using the phy device*/
  26        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
  27                                              "gen_phy_user", &parent));
  28        /*
  29         * Get the same phy port in 2 different ways and compare.
  30         */
  31        ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method1))
  32        ut_assertok(generic_phy_get_by_index(parent, 0, &phy1_method2))
  33        ut_asserteq(phy1_method1.id, phy1_method2.id);
  34
  35        /*
  36         * Get the second phy port. Check that the same phy provider (device)
  37         * provides this 2nd phy port, but that the IDs are different
  38         */
  39        ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2))
  40        ut_asserteq_ptr(phy1_method2.dev, phy2.dev);
  41        ut_assert(phy1_method1.id != phy2.id);
  42
  43        /*
  44         * Get the third phy port. Check that the phy provider is different
  45         */
  46        ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3))
  47        ut_assert(phy2.dev != phy3.dev);
  48
  49        /* Try to get a non-existing phy */
  50        ut_asserteq(-ENODEV, uclass_get_device(UCLASS_PHY, 4, &dev));
  51        ut_asserteq(-ENODATA, generic_phy_get_by_name(parent,
  52                                        "phy_not_existing", &phy1_method1));
  53
  54        return 0;
  55}
  56DM_TEST(dm_test_phy_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
  57
  58/* Test of the phy uclass using the sandbox phy driver operations */
  59static int dm_test_phy_ops(struct unit_test_state *uts)
  60{
  61        struct phy phy1;
  62        struct phy phy2;
  63        struct phy phy3;
  64        struct udevice *parent;
  65
  66        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
  67                                              "gen_phy_user", &parent));
  68
  69        ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1));
  70        ut_asserteq(0, phy1.id);
  71        ut_assertok(generic_phy_get_by_name(parent, "phy2", &phy2));
  72        ut_asserteq(1, phy2.id);
  73        ut_assertok(generic_phy_get_by_name(parent, "phy3", &phy3));
  74        ut_asserteq(0, phy3.id);
  75
  76        /* test normal operations */
  77        ut_assertok(generic_phy_init(&phy1));
  78        ut_assertok(generic_phy_power_on(&phy1));
  79        ut_assertok(generic_phy_power_off(&phy1));
  80
  81        /*
  82         * Test power_on() failure after exit().
  83         * The sandbox phy driver does not allow power-on/off after
  84         * exit, but the uclass counts power-on/init calls and skips
  85         * calling the driver's ops when e.g. powering off an already
  86         * powered-off phy.
  87         */
  88        ut_assertok(generic_phy_exit(&phy1));
  89        ut_assert(generic_phy_power_on(&phy1) != 0);
  90        ut_assertok(generic_phy_power_off(&phy1));
  91
  92        /*
  93         * test normal operations again (after re-init)
  94         */
  95        ut_assertok(generic_phy_init(&phy1));
  96        ut_assertok(generic_phy_power_on(&phy1));
  97        ut_assertok(generic_phy_power_off(&phy1));
  98
  99        /*
 100         * test calling unimplemented feature.
 101         * The call is expected to succeed
 102         */
 103        ut_assertok(generic_phy_reset(&phy1));
 104
 105        /*
 106         * Test power_off() failure after exit().
 107         * For this we need to call exit() while the phy is powered-on,
 108         * so that the uclass actually calls the driver's power-off()
 109         * and reports the resulting failure.
 110         */
 111        ut_assertok(generic_phy_power_on(&phy1));
 112        ut_assertok(generic_phy_exit(&phy1));
 113        ut_assert(generic_phy_power_off(&phy1) != 0);
 114        ut_assertok(generic_phy_power_on(&phy1));
 115
 116        /* PHY2 has a known problem with power off */
 117        ut_assertok(generic_phy_init(&phy2));
 118        ut_assertok(generic_phy_power_on(&phy2));
 119        ut_asserteq(-EIO, generic_phy_power_off(&phy2));
 120
 121        /* PHY3 has a known problem with power off and power on */
 122        ut_assertok(generic_phy_init(&phy3));
 123        ut_asserteq(-EIO, generic_phy_power_on(&phy3));
 124        ut_assertok(generic_phy_power_off(&phy3));
 125
 126        return 0;
 127}
 128DM_TEST(dm_test_phy_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 129
 130static int dm_test_phy_bulk(struct unit_test_state *uts)
 131{
 132        struct phy_bulk phys;
 133        struct udevice *parent;
 134
 135        /* test normal operations */
 136        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
 137                                              "gen_phy_user1", &parent));
 138
 139        ut_assertok(generic_phy_get_bulk(parent, &phys));
 140        ut_asserteq(2, phys.count);
 141
 142        ut_asserteq(0, generic_phy_init_bulk(&phys));
 143        ut_asserteq(0, generic_phy_power_on_bulk(&phys));
 144        ut_asserteq(0, generic_phy_power_off_bulk(&phys));
 145        ut_asserteq(0, generic_phy_exit_bulk(&phys));
 146
 147        /* has a known problem phy */
 148        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
 149                                              "gen_phy_user", &parent));
 150
 151        ut_assertok(generic_phy_get_bulk(parent, &phys));
 152        ut_asserteq(3, phys.count);
 153
 154        ut_asserteq(0, generic_phy_init_bulk(&phys));
 155        ut_asserteq(-EIO, generic_phy_power_on_bulk(&phys));
 156        ut_asserteq(-EIO, generic_phy_power_off_bulk(&phys));
 157        ut_asserteq(0, generic_phy_exit_bulk(&phys));
 158
 159        return 0;
 160}
 161DM_TEST(dm_test_phy_bulk, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 162
 163static int dm_test_phy_multi_exit(struct unit_test_state *uts)
 164{
 165        struct phy phy1_method1;
 166        struct phy phy1_method2;
 167        struct phy phy1_method3;
 168        struct udevice *parent;
 169
 170        /* Get the same phy instance in 3 different ways. */
 171        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
 172                                              "gen_phy_user", &parent));
 173        ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method1));
 174        ut_asserteq(0, phy1_method1.id);
 175        ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method2));
 176        ut_asserteq(0, phy1_method2.id);
 177        ut_asserteq_ptr(phy1_method1.dev, phy1_method1.dev);
 178
 179        ut_assertok(uclass_get_device_by_name(UCLASS_SIMPLE_BUS,
 180                                              "gen_phy_user1", &parent));
 181        ut_assertok(generic_phy_get_by_name(parent, "phy1", &phy1_method3));
 182        ut_asserteq(0, phy1_method3.id);
 183        ut_asserteq_ptr(phy1_method1.dev, phy1_method3.dev);
 184
 185        /*
 186         * Test using the same PHY from different handles.
 187         * In non-test code these could be in different drivers.
 188         */
 189
 190        /*
 191         * These must only call the driver's ops at the first init()
 192         * and power_on().
 193         */
 194        ut_assertok(generic_phy_init(&phy1_method1));
 195        ut_assertok(generic_phy_init(&phy1_method2));
 196        ut_assertok(generic_phy_power_on(&phy1_method1));
 197        ut_assertok(generic_phy_power_on(&phy1_method2));
 198        ut_assertok(generic_phy_init(&phy1_method3));
 199        ut_assertok(generic_phy_power_on(&phy1_method3));
 200
 201        /*
 202         * These must not call the driver's ops as other handles still
 203         * want the PHY powered-on and initialized.
 204         */
 205        ut_assertok(generic_phy_power_off(&phy1_method3));
 206        ut_assertok(generic_phy_exit(&phy1_method3));
 207
 208        /*
 209         * We would get an error here if the generic_phy_exit() above
 210         * actually called the driver's exit(), as the sandbox driver
 211         * doesn't allow power-off() after exit().
 212         */
 213        ut_assertok(generic_phy_power_off(&phy1_method1));
 214        ut_assertok(generic_phy_power_off(&phy1_method2));
 215        ut_assertok(generic_phy_exit(&phy1_method1));
 216        ut_assertok(generic_phy_exit(&phy1_method2));
 217
 218        return 0;
 219}
 220DM_TEST(dm_test_phy_multi_exit, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
 221