uboot/cmd/ti/pd.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Power Domain test commands
   4 *
   5 * Copyright (C) 2020 Texas Instruments Incorporated, <www.ti.com>
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <dm.h>
  11#include <k3-dev.h>
  12
  13static const struct udevice_id ti_pd_of_match[] = {
  14        { .compatible = "ti,sci-pm-domain" },
  15        { /* sentinel */ }
  16};
  17
  18static struct ti_k3_pd_platdata *ti_pd_find_data(void)
  19{
  20        struct udevice *dev;
  21        int i = 0;
  22
  23        while (1) {
  24                uclass_get_device(UCLASS_POWER_DOMAIN, i++, &dev);
  25                if (!dev)
  26                        return NULL;
  27
  28                if (device_is_compatible(dev,
  29                                         ti_pd_of_match[0].compatible))
  30                        return  dev_get_priv(dev);
  31        }
  32
  33        return NULL;
  34}
  35
  36static void dump_lpsc(struct ti_k3_pd_platdata *data, struct ti_pd *pd)
  37{
  38        int i;
  39        struct ti_lpsc *lpsc;
  40        u8 state;
  41        static const char * const lpsc_states[] = {
  42                "swrstdis", "syncrst", "disable", "enable", "autosleep",
  43                "autowake", "unknown",
  44        };
  45
  46        for (i = 0; i < data->num_lpsc; i++) {
  47                lpsc = &data->lpsc[i];
  48                if (lpsc->pd != pd)
  49                        continue;
  50                state = lpsc_get_state(lpsc);
  51                if (state > ARRAY_SIZE(lpsc_states))
  52                        state = ARRAY_SIZE(lpsc_states) - 1;
  53                printf("    LPSC%d: state=%s, usecount=%d\n",
  54                       lpsc->id, lpsc_states[state], lpsc->usecount);
  55        }
  56}
  57
  58static void dump_pd(struct ti_k3_pd_platdata *data, struct ti_psc *psc)
  59{
  60        int i;
  61        struct ti_pd *pd;
  62        u8 state;
  63        static const char * const pd_states[] = {
  64                "off", "on", "unknown"
  65        };
  66
  67        for (i = 0; i < data->num_pd; i++) {
  68                pd = &data->pd[i];
  69                if (pd->psc != psc)
  70                        continue;
  71                state = ti_pd_state(pd);
  72                if (state > ARRAY_SIZE(pd_states))
  73                        state = ARRAY_SIZE(pd_states) - 1;
  74                printf("  PD%d: state=%s, usecount=%d:\n",
  75                       pd->id, pd_states[state], pd->usecount);
  76                dump_lpsc(data, pd);
  77        }
  78}
  79
  80static void dump_psc(struct ti_k3_pd_platdata *data)
  81{
  82        int i;
  83        struct ti_psc *psc;
  84
  85        for (i = 0; i < data->num_psc; i++) {
  86                psc = &data->psc[i];
  87                printf("PSC%d [%p]:\n", psc->id, psc->base);
  88                dump_pd(data, psc);
  89        }
  90}
  91
  92static int do_pd_dump(struct cmd_tbl *cmdtp, int flag, int argc,
  93                      char *const argv[])
  94{
  95        struct ti_k3_pd_platdata *data;
  96
  97        data = ti_pd_find_data();
  98        if (!data)
  99                return CMD_RET_FAILURE;
 100
 101        dump_psc(data);
 102
 103        return 0;
 104}
 105
 106static int do_pd_endis(int argc, char *const argv[], u8 state)
 107{
 108        u32 psc_id;
 109        u32 lpsc_id;
 110        int i;
 111        struct ti_k3_pd_platdata *data;
 112        struct ti_lpsc *lpsc;
 113        int ret;
 114
 115        if (argc < 3)
 116                return CMD_RET_FAILURE;
 117
 118        data = ti_pd_find_data();
 119        if (!data)
 120                return CMD_RET_FAILURE;
 121
 122        psc_id = dectoul(argv[1], NULL);
 123        lpsc_id = dectoul(argv[2], NULL);
 124
 125        for (i = 0; i < data->num_lpsc; i++) {
 126                lpsc = &data->lpsc[i];
 127                if (lpsc->pd->psc->id != psc_id)
 128                        continue;
 129                if (lpsc->id != lpsc_id)
 130                        continue;
 131                printf("%s pd [PSC:%d,LPSC:%d]...\n",
 132                       state == MDSTAT_STATE_ENABLE ? "Enabling" : "Disabling",
 133                       psc_id, lpsc_id);
 134                ret = ti_lpsc_transition(lpsc, state);
 135                if (ret)
 136                        return CMD_RET_FAILURE;
 137                else
 138                        return 0;
 139        }
 140
 141        printf("No matching psc/lpsc found.\n");
 142
 143        return CMD_RET_FAILURE;
 144}
 145
 146static int do_pd_enable(struct cmd_tbl *cmdtp, int flag, int argc,
 147                        char *const argv[])
 148{
 149        return do_pd_endis(argc, argv, MDSTAT_STATE_ENABLE);
 150}
 151
 152static int do_pd_disable(struct cmd_tbl *cmdtp, int flag, int argc,
 153                         char *const argv[])
 154{
 155        return do_pd_endis(argc, argv, MDSTAT_STATE_SWRSTDISABLE);
 156}
 157
 158static struct cmd_tbl cmd_pd[] = {
 159        U_BOOT_CMD_MKENT(dump, 1, 0, do_pd_dump, "", ""),
 160        U_BOOT_CMD_MKENT(enable, 3, 0, do_pd_enable, "", ""),
 161        U_BOOT_CMD_MKENT(disable, 3, 0, do_pd_disable, "", ""),
 162};
 163
 164static int ti_do_pd(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
 165{
 166        struct cmd_tbl *c;
 167
 168        argc--;
 169        argv++;
 170
 171        c = find_cmd_tbl(argv[0], cmd_pd, ARRAY_SIZE(cmd_pd));
 172        if (c)
 173                return c->cmd(cmdtp, flag, argc, argv);
 174        else
 175                return CMD_RET_USAGE;
 176}
 177
 178U_BOOT_CMD(pd, 4, 1, ti_do_pd,
 179           "TI power domain control",
 180#if IS_ENABLED(CONFIG_SYS_LONGHELP)
 181           "dump                 - show power domain status\n"
 182           "enable [psc] [lpsc]  - enable power domain\n"
 183           "disable [psc] [lpsc] - disable power domain\n"
 184#endif
 185);
 186