// SPDX-License-Identifier: GPL-2.0+ /* * Power Domain test commands * * Copyright (C) 2020 Texas Instruments Incorporated, */ #include #include #include #include static const struct udevice_id ti_pd_of_match[] = { { .compatible = "ti,sci-pm-domain" }, { /* sentinel */ } }; static struct ti_k3_pd_platdata *ti_pd_find_data(void) { struct udevice *dev; int i = 0; while (1) { uclass_get_device(UCLASS_POWER_DOMAIN, i++, &dev); if (!dev) return NULL; if (device_is_compatible(dev, ti_pd_of_match[0].compatible)) return dev_get_priv(dev); } return NULL; } static void dump_lpsc(struct ti_k3_pd_platdata *data, struct ti_pd *pd) { int i; struct ti_lpsc *lpsc; u8 state; static const char * const lpsc_states[] = { "swrstdis", "syncrst", "disable", "enable", "autosleep", "autowake", "unknown", }; for (i = 0; i < data->num_lpsc; i++) { lpsc = &data->lpsc[i]; if (lpsc->pd != pd) continue; state = lpsc_get_state(lpsc); if (state > ARRAY_SIZE(lpsc_states)) state = ARRAY_SIZE(lpsc_states) - 1; printf(" LPSC%d: state=%s, usecount=%d\n", lpsc->id, lpsc_states[state], lpsc->usecount); } } static void dump_pd(struct ti_k3_pd_platdata *data, struct ti_psc *psc) { int i; struct ti_pd *pd; u8 state; static const char * const pd_states[] = { "off", "on", "unknown" }; for (i = 0; i < data->num_pd; i++) { pd = &data->pd[i]; if (pd->psc != psc) continue; state = ti_pd_state(pd); if (state > ARRAY_SIZE(pd_states)) state = ARRAY_SIZE(pd_states) - 1; printf(" PD%d: state=%s, usecount=%d:\n", pd->id, pd_states[state], pd->usecount); dump_lpsc(data, pd); } } static void dump_psc(struct ti_k3_pd_platdata *data) { int i; struct ti_psc *psc; for (i = 0; i < data->num_psc; i++) { psc = &data->psc[i]; printf("PSC%d [%p]:\n", psc->id, psc->base); dump_pd(data, psc); } } static int do_pd_dump(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct ti_k3_pd_platdata *data; data = ti_pd_find_data(); if (!data) return CMD_RET_FAILURE; dump_psc(data); return 0; } static int do_pd_endis(int argc, char *const argv[], u8 state) { u32 psc_id; u32 lpsc_id; int i; struct ti_k3_pd_platdata *data; struct ti_lpsc *lpsc; int ret; if (argc < 3) return CMD_RET_FAILURE; data = ti_pd_find_data(); if (!data) return CMD_RET_FAILURE; psc_id = dectoul(argv[1], NULL); lpsc_id = dectoul(argv[2], NULL); for (i = 0; i < data->num_lpsc; i++) { lpsc = &data->lpsc[i]; if (lpsc->pd->psc->id != psc_id) continue; if (lpsc->id != lpsc_id) continue; printf("%s pd [PSC:%d,LPSC:%d]...\n", state == MDSTAT_STATE_ENABLE ? "Enabling" : "Disabling", psc_id, lpsc_id); ret = ti_lpsc_transition(lpsc, state); if (ret) return CMD_RET_FAILURE; else return 0; } printf("No matching psc/lpsc found.\n"); return CMD_RET_FAILURE; } static int do_pd_enable(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_pd_endis(argc, argv, MDSTAT_STATE_ENABLE); } static int do_pd_disable(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { return do_pd_endis(argc, argv, MDSTAT_STATE_SWRSTDISABLE); } static struct cmd_tbl cmd_pd[] = { U_BOOT_CMD_MKENT(dump, 1, 0, do_pd_dump, "", ""), U_BOOT_CMD_MKENT(enable, 3, 0, do_pd_enable, "", ""), U_BOOT_CMD_MKENT(disable, 3, 0, do_pd_disable, "", ""), }; static int ti_do_pd(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) { struct cmd_tbl *c; argc--; argv++; c = find_cmd_tbl(argv[0], cmd_pd, ARRAY_SIZE(cmd_pd)); if (c) return c->cmd(cmdtp, flag, argc, argv); else return CMD_RET_USAGE; } U_BOOT_CMD(pd, 4, 1, ti_do_pd, "TI power domain control", #if IS_ENABLED(CONFIG_SYS_LONGHELP) "dump - show power domain status\n" "enable [psc] [lpsc] - enable power domain\n" "disable [psc] [lpsc] - disable power domain\n" #endif );