1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2012 The Chromium OS Authors.
4  */
5 
6 /*
7  * IO space access commands.
8  */
9 
10 #include <command.h>
11 #include <display_options.h>
12 #include <vsprintf.h>
13 #include <asm/io.h>
14 
15 /* Display values from last command */
16 static ulong last_addr, last_size;
17 static ulong last_length = 0x40;
18 static ulong base_address;
19 
20 #define DISP_LINE_LEN	16
21 
22 /*
23  * IO Display
24  *
25  * Syntax:
26  *	iod{.b, .w, .l} {addr}
27  */
do_io_iod(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])28 int do_io_iod(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
29 {
30 	ulong addr, length, bytes;
31 	u8 buf[DISP_LINE_LEN];
32 	int size, todo;
33 
34 	/*
35 	 * We use the last specified parameters, unless new ones are
36 	 * entered.
37 	 */
38 	addr = last_addr;
39 	size = last_size;
40 	length = last_length;
41 
42 	if (argc < 2)
43 		return CMD_RET_USAGE;
44 
45 	if ((flag & CMD_FLAG_REPEAT) == 0) {
46 		/*
47 		 * New command specified.  Check for a size specification.
48 		 * Defaults to long if no or incorrect specification.
49 		 */
50 		size = cmd_get_data_size(argv[0], 4);
51 		if (size < 0)
52 			return 1;
53 
54 		/* Address is specified since argc > 1 */
55 		addr = hextoul(argv[1], NULL);
56 		addr += base_address;
57 
58 		/*
59 		 * If another parameter, it is the length to display.
60 		 * Length is the number of objects, not number of bytes.
61 		 */
62 		if (argc > 2)
63 			length = hextoul(argv[2], NULL);
64 	}
65 
66 	bytes = size * length;
67 
68 	/* Print the lines */
69 	for (; bytes > 0; addr += todo) {
70 		u8 *ptr = buf;
71 		int i;
72 
73 		todo = min(bytes, (ulong)DISP_LINE_LEN);
74 		for (i = 0; i < todo; i += size, ptr += size) {
75 			if (size == 4)
76 				*(u32 *)ptr = inl(addr + i);
77 			else if (size == 2)
78 				*(u16 *)ptr = inw(addr + i);
79 			else
80 				*ptr = inb(addr + i);
81 		}
82 		print_buffer(addr, buf, size, todo / size,
83 			     DISP_LINE_LEN / size);
84 		bytes -= todo;
85 	}
86 
87 	last_addr = addr;
88 	last_length = length;
89 	last_size = size;
90 
91 	return 0;
92 }
93 
do_io_iow(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])94 int do_io_iow(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
95 {
96 	ulong addr, val;
97 	int size;
98 
99 	if (argc != 3)
100 		return CMD_RET_USAGE;
101 
102 	size = cmd_get_data_size(argv[0], 4);
103 	if (size < 0)
104 		return 1;
105 
106 	addr = hextoul(argv[1], NULL);
107 	val = hextoul(argv[2], NULL);
108 
109 	if (size == 4)
110 		outl((u32) val, addr);
111 	else if (size == 2)
112 		outw((u16) val, addr);
113 	else
114 		outb((u8) val, addr);
115 
116 	return 0;
117 }
118 
119 /**************************************************/
120 U_BOOT_CMD(iod, 3, 1, do_io_iod,
121 	   "IO space display", "[.b, .w, .l] address");
122 
123 U_BOOT_CMD(iow, 3, 0, do_io_iow,
124 	   "IO space modify",
125 	   "[.b, .w, .l] address value");
126