1 /*
2 * SPDX-License-Identifier: GPL-2.0+
3 *
4 * (C) Copyright 2018 Rockchip Electronics Co., Ltd
5 *
6 */
7
8 #include <asm/io.h>
9 #include <common.h>
10 #include <dm.h>
11 #include <fdtdec.h>
12
13 enum ops {
14 SEARCH_NAME,
15 SEARCH_COMP,
16 };
17
iomem_show(const char * label,unsigned long base,size_t start,size_t end)18 void iomem_show(const char *label, unsigned long base, size_t start, size_t end)
19 {
20 unsigned long val, offset = start, nr = 0;
21
22 if (label)
23 printf("%s:\n", label);
24
25 printf("%08lx: ", base + offset);
26 for (offset = start; offset <= end; offset += 0x04) {
27 if (nr >= 4) {
28 printf("\n%08lx: ", base + offset);
29 nr = 0;
30 }
31 val = readl((void __iomem *)base + offset);
32 printf("%08lx ", val);
33 nr++;
34 }
35 printf("\n");
36 }
37
iomem_show_by_match(enum ops op,const char * search,size_t start,size_t end)38 static int iomem_show_by_match(enum ops op, const char *search,
39 size_t start, size_t end)
40 {
41 const void *fdt = gd->fdt_blob;
42 const char *name;
43 fdt_addr_t addr;
44 int found = 0;
45 int offset;
46
47 for (offset = fdt_next_node(fdt, 0, NULL);
48 offset >= 0;
49 offset = fdt_next_node(fdt, offset, NULL)) {
50 if (op == SEARCH_COMP)
51 name = fdt_getprop(fdt, offset, "compatible", NULL);
52 else if (op == SEARCH_NAME)
53 name = fdt_get_name(fdt, offset, NULL);
54 else
55 goto out;
56
57 if (!name)
58 continue;
59
60 if (strstr(name, search)) {
61 addr = fdtdec_get_addr_size_auto_noparent(fdt, offset,
62 "reg", 0, NULL, false);
63 if (addr == FDT_ADDR_T_NONE)
64 goto out;
65
66 iomem_show(name, addr, start, end);
67 found = 1;
68 break;
69 }
70 }
71 printf("\n");
72
73 out:
74 return found;
75 }
76
iomem_show_by_compatible(const char * compat,size_t start,size_t end)77 void iomem_show_by_compatible(const char *compat, size_t start, size_t end)
78 {
79 iomem_show_by_match(SEARCH_COMP, compat, start, end);
80 }
81
do_iomem_by_match(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])82 static int do_iomem_by_match(cmd_tbl_t *cmdtp, int flag,
83 int argc, char *const argv[])
84 {
85 size_t start, end;
86 const char *search;
87
88 if (argc != 4)
89 return CMD_RET_USAGE;
90
91 search = argv[1];
92 start = simple_strtoul(argv[2], NULL, 0);
93 end = simple_strtoul(argv[3], NULL, 0);
94 if (start > end) {
95 printf("Invalid: 0x%lx > 0x%lx\n", (ulong)start, (ulong)end);
96 return CMD_RET_FAILURE;
97 }
98
99 if (!iomem_show_by_match(SEARCH_COMP, search, start, end))
100 iomem_show_by_match(SEARCH_NAME, search, start, end);
101
102 return 0;
103 }
104
105 U_BOOT_CMD(
106 iomem, 4, 1, do_iomem_by_match,
107 "Show iomem data by device compatible(high priority) or node name",
108 "iomem <compatible or node name> <start offset> <end offset>\n"
109 " eg: iomem -grf 0x0 0x200"
110 " eg: iomem gpio3 0x0 0x200"
111 );
112