1737e1216SJoseph Chen /*
2737e1216SJoseph Chen * SPDX-License-Identifier: GPL-2.0+
3737e1216SJoseph Chen *
4737e1216SJoseph Chen * (C) Copyright 2018 Rockchip Electronics Co., Ltd
5737e1216SJoseph Chen *
6737e1216SJoseph Chen */
7737e1216SJoseph Chen
8737e1216SJoseph Chen #include <asm/io.h>
9737e1216SJoseph Chen #include <common.h>
10737e1216SJoseph Chen #include <dm.h>
11737e1216SJoseph Chen #include <fdtdec.h>
12737e1216SJoseph Chen
13fe2fac95SJoseph Chen enum ops {
14fe2fac95SJoseph Chen SEARCH_NAME,
15fe2fac95SJoseph Chen SEARCH_COMP,
16fe2fac95SJoseph Chen };
17fe2fac95SJoseph Chen
iomem_show(const char * label,unsigned long base,size_t start,size_t end)18737e1216SJoseph Chen void iomem_show(const char *label, unsigned long base, size_t start, size_t end)
19737e1216SJoseph Chen {
20737e1216SJoseph Chen unsigned long val, offset = start, nr = 0;
21737e1216SJoseph Chen
22737e1216SJoseph Chen if (label)
23737e1216SJoseph Chen printf("%s:\n", label);
24737e1216SJoseph Chen
25737e1216SJoseph Chen printf("%08lx: ", base + offset);
26737e1216SJoseph Chen for (offset = start; offset <= end; offset += 0x04) {
27737e1216SJoseph Chen if (nr >= 4) {
28737e1216SJoseph Chen printf("\n%08lx: ", base + offset);
29737e1216SJoseph Chen nr = 0;
30737e1216SJoseph Chen }
31737e1216SJoseph Chen val = readl((void __iomem *)base + offset);
32737e1216SJoseph Chen printf("%08lx ", val);
33737e1216SJoseph Chen nr++;
34737e1216SJoseph Chen }
35737e1216SJoseph Chen printf("\n");
36737e1216SJoseph Chen }
37737e1216SJoseph Chen
iomem_show_by_match(enum ops op,const char * search,size_t start,size_t end)38fe2fac95SJoseph Chen static int iomem_show_by_match(enum ops op, const char *search,
39fe2fac95SJoseph Chen size_t start, size_t end)
40737e1216SJoseph Chen {
41737e1216SJoseph Chen const void *fdt = gd->fdt_blob;
42fe2fac95SJoseph Chen const char *name;
43737e1216SJoseph Chen fdt_addr_t addr;
44fe2fac95SJoseph Chen int found = 0;
45737e1216SJoseph Chen int offset;
46737e1216SJoseph Chen
47737e1216SJoseph Chen for (offset = fdt_next_node(fdt, 0, NULL);
48737e1216SJoseph Chen offset >= 0;
49737e1216SJoseph Chen offset = fdt_next_node(fdt, offset, NULL)) {
50fe2fac95SJoseph Chen if (op == SEARCH_COMP)
51fe2fac95SJoseph Chen name = fdt_getprop(fdt, offset, "compatible", NULL);
52fe2fac95SJoseph Chen else if (op == SEARCH_NAME)
53fe2fac95SJoseph Chen name = fdt_get_name(fdt, offset, NULL);
54fe2fac95SJoseph Chen else
55fe2fac95SJoseph Chen goto out;
56fe2fac95SJoseph Chen
57fe2fac95SJoseph Chen if (!name)
58737e1216SJoseph Chen continue;
59737e1216SJoseph Chen
60fe2fac95SJoseph Chen if (strstr(name, search)) {
61737e1216SJoseph Chen addr = fdtdec_get_addr_size_auto_noparent(fdt, offset,
62737e1216SJoseph Chen "reg", 0, NULL, false);
63fe2fac95SJoseph Chen if (addr == FDT_ADDR_T_NONE)
64fe2fac95SJoseph Chen goto out;
65fe2fac95SJoseph Chen
66fe2fac95SJoseph Chen iomem_show(name, addr, start, end);
67fe2fac95SJoseph Chen found = 1;
68737e1216SJoseph Chen break;
69737e1216SJoseph Chen }
70737e1216SJoseph Chen }
71737e1216SJoseph Chen printf("\n");
72fe2fac95SJoseph Chen
73fe2fac95SJoseph Chen out:
74fe2fac95SJoseph Chen return found;
75737e1216SJoseph Chen }
76737e1216SJoseph Chen
iomem_show_by_compatible(const char * compat,size_t start,size_t end)77fe2fac95SJoseph Chen void iomem_show_by_compatible(const char *compat, size_t start, size_t end)
78fe2fac95SJoseph Chen {
79fe2fac95SJoseph Chen iomem_show_by_match(SEARCH_COMP, compat, start, end);
80fe2fac95SJoseph Chen }
81fe2fac95SJoseph Chen
do_iomem_by_match(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])82fe2fac95SJoseph Chen static int do_iomem_by_match(cmd_tbl_t *cmdtp, int flag,
83fe2fac95SJoseph Chen int argc, char *const argv[])
84737e1216SJoseph Chen {
85737e1216SJoseph Chen size_t start, end;
86fe2fac95SJoseph Chen const char *search;
87737e1216SJoseph Chen
88737e1216SJoseph Chen if (argc != 4)
89737e1216SJoseph Chen return CMD_RET_USAGE;
90737e1216SJoseph Chen
91fe2fac95SJoseph Chen search = argv[1];
92737e1216SJoseph Chen start = simple_strtoul(argv[2], NULL, 0);
93737e1216SJoseph Chen end = simple_strtoul(argv[3], NULL, 0);
94*d035dcf8SJoseph Chen if (start > end) {
95*d035dcf8SJoseph Chen printf("Invalid: 0x%lx > 0x%lx\n", (ulong)start, (ulong)end);
96*d035dcf8SJoseph Chen return CMD_RET_FAILURE;
97*d035dcf8SJoseph Chen }
98737e1216SJoseph Chen
99fe2fac95SJoseph Chen if (!iomem_show_by_match(SEARCH_COMP, search, start, end))
100fe2fac95SJoseph Chen iomem_show_by_match(SEARCH_NAME, search, start, end);
101737e1216SJoseph Chen
102737e1216SJoseph Chen return 0;
103737e1216SJoseph Chen }
104737e1216SJoseph Chen
105737e1216SJoseph Chen U_BOOT_CMD(
106fe2fac95SJoseph Chen iomem, 4, 1, do_iomem_by_match,
107fe2fac95SJoseph Chen "Show iomem data by device compatible(high priority) or node name",
108fe2fac95SJoseph Chen "iomem <compatible or node name> <start offset> <end offset>\n"
109737e1216SJoseph Chen " eg: iomem -grf 0x0 0x200"
110fe2fac95SJoseph Chen " eg: iomem gpio3 0x0 0x200"
111737e1216SJoseph Chen );
112