[PATCHv4 15/26] cmd: ti: pd: Add debug command for K3 power domains

Jaehoon Chung jh80.chung at samsung.com
Wed May 12 00:44:57 CEST 2021


On 5/11/21 5:30 PM, Tero Kristo wrote:
> From: Tero Kristo <t-kristo at ti.com>
> 
> 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 <t-kristo at ti.com>
> Signed-off-by: Tero Kristo <kristo at kernel.org>

Reviewed-by: Jaehoon Chung <jh80.chung at samsung.com>

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, <www.ti.com>
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <dm.h>
> +#include <k3-dev.h>
> +
> +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
> 



More information about the U-Boot mailing list