summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-07-05 18:20:30 +0300
committerTom Rini <trini@konsulko.com>2021-07-05 18:20:30 +0300
commit6194b45a83bde42cd2f404123823e5b326702001 (patch)
treeeef0284dfb378d20ee3a21577d3f7abb4f127fd5 /cmd
parent840658b093976390e9537724f802281c9c8439f5 (diff)
parent03b61ffe5a780d6e8301df16e4e60b3dcd1d0b66 (diff)
downloadu-boot-6194b45a83bde42cd2f404123823e5b326702001.tar.xz
Merge branch 'next'
Diffstat (limited to 'cmd')
-rw-r--r--cmd/clk.c80
-rw-r--r--cmd/mtd.c9
-rw-r--r--cmd/ti/Kconfig8
-rw-r--r--cmd/ti/Makefile1
-rw-r--r--cmd/ti/pd.c185
5 files changed, 272 insertions, 11 deletions
diff --git a/cmd/clk.c b/cmd/clk.c
index e3c3d2f9bb..7ece2454e0 100644
--- a/cmd/clk.c
+++ b/cmd/clk.c
@@ -18,11 +18,14 @@ static void show_clks(struct udevice *dev, int depth, int last_flag)
{
int i, is_last;
struct udevice *child;
- struct clk *clkp;
+ struct clk *clkp, *parent;
u32 rate;
clkp = dev_get_clk_ptr(dev);
if (device_get_uclass_id(dev) == UCLASS_CLK && clkp) {
+ parent = clk_get_parent(clkp);
+ if (!IS_ERR(parent) && depth == -1)
+ return;
depth++;
rate = clk_get_rate(clkp);
@@ -47,6 +50,9 @@ static void show_clks(struct udevice *dev, int depth, int last_flag)
}
list_for_each_entry(child, &dev->child_head, sibling_node) {
+ if (child == dev)
+ continue;
+
is_last = list_is_last(&child->sibling_node, &dev->child_head);
show_clks(child, depth, (last_flag << 1) | is_last);
}
@@ -54,14 +60,19 @@ static void show_clks(struct udevice *dev, int depth, int last_flag)
int __weak soc_clk_dump(void)
{
- struct udevice *root;
+ struct udevice *dev;
+ struct uclass *uc;
+ int ret;
- root = dm_root();
- if (root) {
- printf(" Rate Usecnt Name\n");
- printf("------------------------------------------\n");
- show_clks(root, -1, 0);
- }
+ ret = uclass_get(UCLASS_CLK, &uc);
+ if (ret)
+ return ret;
+
+ printf(" Rate Usecnt Name\n");
+ printf("------------------------------------------\n");
+
+ uclass_foreach_dev(dev, uc)
+ show_clks(dev, -1, 0);
return 0;
}
@@ -87,8 +98,56 @@ static int do_clk_dump(struct cmd_tbl *cmdtp, int flag, int argc,
return ret;
}
+#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(CLK)
+struct udevice *clk_lookup(const char *name)
+{
+ int i = 0;
+ struct udevice *dev;
+
+ do {
+ uclass_get_device(UCLASS_CLK, i++, &dev);
+ if (!strcmp(name, dev->name))
+ return dev;
+ } while (dev);
+
+ return NULL;
+}
+
+static int do_clk_setfreq(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct clk *clk = NULL;
+ s32 freq;
+ struct udevice *dev;
+
+ freq = simple_strtoul(argv[2], NULL, 10);
+
+ dev = clk_lookup(argv[1]);
+
+ if (dev)
+ clk = dev_get_clk_ptr(dev);
+
+ if (!clk) {
+ printf("clock '%s' not found.\n", argv[1]);
+ return -EINVAL;
+ }
+
+ freq = clk_set_rate(clk, freq);
+ if (freq < 0) {
+ printf("set_rate failed: %d\n", freq);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("set_rate returns %u\n", freq);
+ return 0;
+}
+#endif
+
static struct cmd_tbl cmd_clk_sub[] = {
U_BOOT_CMD_MKENT(dump, 1, 1, do_clk_dump, "", ""),
+#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(CLK)
+ U_BOOT_CMD_MKENT(setfreq, 3, 1, do_clk_setfreq, "", ""),
+#endif
};
static int do_clk(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -113,7 +172,8 @@ static int do_clk(struct cmd_tbl *cmdtp, int flag, int argc,
#ifdef CONFIG_SYS_LONGHELP
static char clk_help_text[] =
- "dump - Print clock frequencies";
+ "dump - Print clock frequencies\n"
+ "setfreq [clk] [freq] - Set clock frequency";
#endif
-U_BOOT_CMD(clk, 2, 1, do_clk, "CLK sub-system", clk_help_text);
+U_BOOT_CMD(clk, 4, 1, do_clk, "CLK sub-system", clk_help_text);
diff --git a/cmd/mtd.c b/cmd/mtd.c
index 485a963bdd..c22478c152 100644
--- a/cmd/mtd.c
+++ b/cmd/mtd.c
@@ -126,6 +126,13 @@ static void mtd_show_device(struct mtd_info *mtd)
printf(" - driver: %s\n", mtd->dev->driver->name);
}
#endif
+ if (IS_ENABLED(CONFIG_OF_CONTROL) && mtd->dev) {
+ char buf[256];
+ int res;
+
+ res = ofnode_get_path(mtd_get_ofnode(mtd), buf, 256);
+ printf(" - path: %s\n", res == 0 ? buf : "unavailable");
+ }
/* MTD device information */
printf(" - type: ");
@@ -535,7 +542,7 @@ static char mtd_help_text[] =
"mtd bad <name>\n"
"\n"
"With:\n"
- "\t<name>: NAND partition/chip name\n"
+ "\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n"
"\t<addr>: user address from/to which data will be retrieved/stored\n"
"\t<off>: offset in <name> in bytes (default: start of the part)\n"
"\t\t* must be block-aligned for erase\n"
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..9e820b84ca
--- /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",
+#if CONFIG_IS_ENABLED(SYS_LONGHELP)
+ "dump - show power domain status\n"
+ "enable [psc] [lpsc] - enable power domain\n"
+ "disable [psc] [lpsc] - disable power domain\n"
+#endif
+);