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 <common.h>
11#include <command.h>
12#include <display_options.h>
13#include <asm/io.h>
14
15/* Display values from last command */
16static ulong last_addr, last_size;
17static ulong last_length = 0x40;
18static 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 */
28int 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
94int 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/**************************************************/
120U_BOOT_CMD(iod, 3, 1, do_io_iod,
121	   "IO space display", "[.b, .w, .l] address");
122
123U_BOOT_CMD(iow, 3, 0, do_io_iow,
124	   "IO space modify",
125	   "[.b, .w, .l] address value");
126