From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jaehoon Chung Date: Wed, 12 May 2021 07:44:57 +0900 Subject: [PATCHv4 15/26] cmd: ti: pd: Add debug command for K3 power domains In-Reply-To: <20210511083104.10868-16-kristo@kernel.org> References: <20210511083104.10868-1-kristo@kernel.org> <20210511083104.10868-16-kristo@kernel.org> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de On 5/11/21 5:30 PM, Tero Kristo wrote: > From: Tero Kristo > > Add support command for debugging K3 power domains. This is useful with > the HSM rearch setup, where power domains are directly controlled by SPL > instead of going through the TI SCI layer. The debugging support is only > available in the u-boot codebase though, so the raw register access > power domain layer must be enabled on u-boot side for this to work. By > default, u-boot side uses the TI SCI layer, and R5 SPL only uses the > direct access methods. > > Signed-off-by: Tero Kristo > Signed-off-by: Tero Kristo Reviewed-by: Jaehoon Chung Best Regards, Jaehoon Chung > --- > cmd/ti/Kconfig | 8 ++ > cmd/ti/Makefile | 1 + > cmd/ti/pd.c | 185 +++++++++++++++++++++++++ > drivers/power/domain/ti-power-domain.c | 6 +- > include/k3-dev.h | 9 ++ > 5 files changed, 206 insertions(+), 3 deletions(-) > create mode 100644 cmd/ti/pd.c > > diff --git a/cmd/ti/Kconfig b/cmd/ti/Kconfig > index efeff0d482..db557445a8 100644 > --- a/cmd/ti/Kconfig > +++ b/cmd/ti/Kconfig > @@ -7,4 +7,12 @@ config CMD_DDR3 > supports memory verification, memory comapre and ecc > verification if supported. > > +config CMD_PD > + bool "command for verifying power domains" > + depends on TI_POWER_DOMAIN > + help > + Debug command for K3 power domains. For this to work, the > + K3 power domain driver must be enabled for the u-boot; by > + default it is only enabled for SPL. > + > endmenu > diff --git a/cmd/ti/Makefile b/cmd/ti/Makefile > index 16fbade9ed..045593396b 100644 > --- a/cmd/ti/Makefile > +++ b/cmd/ti/Makefile > @@ -5,4 +5,5 @@ obj- += dummy.o > > ifndef CONFIG_SPL_BUILD > obj-$(CONFIG_CMD_DDR3) += ddr3.o > +obj-$(CONFIG_CMD_PD) += pd.o > endif > diff --git a/cmd/ti/pd.c b/cmd/ti/pd.c > new file mode 100644 > index 0000000000..a53ccdcc40 > --- /dev/null > +++ b/cmd/ti/pd.c > @@ -0,0 +1,185 @@ > +// 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 = simple_strtoul(argv[1], NULL, 10); > + lpsc_id = simple_strtoul(argv[2], NULL, 10); > + > + 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", > +#ifdef CONFIG_SYS_LONGHELP > + "dump - show power domain status\n" > + "enable [psc] [lpsc] - enable power domain\n" > + "disable [psc] [lpsc] - disable power domain\n" > +#endif > +); > diff --git a/drivers/power/domain/ti-power-domain.c b/drivers/power/domain/ti-power-domain.c > index e418a7b996..567e7e1e8e 100644 > --- a/drivers/power/domain/ti-power-domain.c > +++ b/drivers/power/domain/ti-power-domain.c > @@ -132,7 +132,7 @@ static void ti_pd_transition(struct ti_pd *pd) > psc_write(BIT(pd->id), pd->psc, PSC_PTCMD); > } > > -static u8 ti_pd_state(struct ti_pd *pd) > +u8 ti_pd_state(struct ti_pd *pd) > { > return pd_read(pd, PSC_PDCTL) & PDCTL_STATE_MASK; > } > @@ -227,12 +227,12 @@ static int ti_lpsc_wait(struct ti_lpsc *lpsc) > return ret; > } > > -static u8 lpsc_get_state(struct ti_lpsc *lpsc) > +u8 lpsc_get_state(struct ti_lpsc *lpsc) > { > return lpsc_read(lpsc, PSC_MDCTL) & MDSTAT_STATE_MASK; > } > > -static int ti_lpsc_transition(struct ti_lpsc *lpsc, u8 state) > +int ti_lpsc_transition(struct ti_lpsc *lpsc, u8 state) > { > struct ti_pd *psc_pd; > int ret; > diff --git a/include/k3-dev.h b/include/k3-dev.h > index de3a8bdf9e..55c5057db3 100644 > --- a/include/k3-dev.h > +++ b/include/k3-dev.h > @@ -22,6 +22,11 @@ > #define PSC_PD_ALWAYSON BIT(1) > #define PSC_PD_DEPENDS BIT(2) > > +#define MDSTAT_STATE_MASK 0x3f > +#define MDSTAT_BUSY_MASK 0x30 > +#define MDSTAT_STATE_SWRSTDISABLE 0x0 > +#define MDSTAT_STATE_ENABLE 0x3 > + > struct ti_psc { > int id; > void __iomem *base; > @@ -73,4 +78,8 @@ struct ti_k3_pd_platdata { > extern const struct ti_k3_pd_platdata j721e_pd_platdata; > extern const struct ti_k3_pd_platdata j7200_pd_platdata; > > +u8 ti_pd_state(struct ti_pd *pd); > +u8 lpsc_get_state(struct ti_lpsc *lpsc); > +int ti_lpsc_transition(struct ti_lpsc *lpsc, u8 state); > + > #endif >