1 /*
2  * (C) Copyright 2003
3  * Marc Singer, elf@buici.com
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 /*
9  * Port I/O Functions
10  *
11  * Copied from FADS ROM, Dan Malek (dmalek@jlc.net)
12  */
13 
14 #include <common.h>
15 #include <command.h>
16 
17 /* Display values from last command.
18  * Memory modify remembered values are different from display memory.
19  */
20 static uint in_last_addr, in_last_size;
21 static uint out_last_addr, out_last_size, out_last_value;
22 
23 
do_portio_out(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])24 int do_portio_out (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
25 {
26 	uint addr = out_last_addr;
27 	uint size = out_last_size;
28 	uint value = out_last_value;
29 
30 	if (argc != 3)
31 		return CMD_RET_USAGE;
32 
33 	if ((flag & CMD_FLAG_REPEAT) == 0) {
34 		/*
35 		 * New command specified.  Check for a size specification.
36 		 * Defaults to long if no or incorrect specification.
37 		 */
38 		size = cmd_get_data_size (argv[0], 1);
39 		addr = simple_strtoul (argv[1], NULL, 16);
40 		value = simple_strtoul (argv[2], NULL, 16);
41 	}
42 #if defined (CONFIG_X86)
43 
44 	{
45 		unsigned short port = addr;
46 
47 		switch (size) {
48 		default:
49 		case 1:
50 		    {
51 			unsigned char ch = value;
52 			__asm__ volatile ("out %0, %%dx"::"a" (ch), "d" (port));
53 		    }
54 			break;
55 		case 2:
56 		    {
57 			unsigned short w = value;
58 			__asm__ volatile ("out %0, %%dx"::"a" (w), "d" (port));
59 		    }
60 			break;
61 		case 4:
62 			__asm__ volatile ("out %0, %%dx"::"a" (value), "d" (port));
63 
64 			break;
65 		}
66 	}
67 
68 #endif							/* CONFIG_X86 */
69 
70 	out_last_addr = addr;
71 	out_last_size = size;
72 	out_last_value = value;
73 
74 	return 0;
75 }
76 
77 U_BOOT_CMD(
78 	out,	3,	1,	do_portio_out,
79 	"write datum to IO port",
80 	"[.b, .w, .l] port value\n    - output to IO port"
81 );
82 
do_portio_in(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])83 int do_portio_in (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
84 {
85 	uint addr = in_last_addr;
86 	uint size = in_last_size;
87 
88 	if (argc != 2)
89 		return CMD_RET_USAGE;
90 
91 	if ((flag & CMD_FLAG_REPEAT) == 0) {
92 		/*
93 		 * New command specified.  Check for a size specification.
94 		 * Defaults to long if no or incorrect specification.
95 		 */
96 		size = cmd_get_data_size (argv[0], 1);
97 		addr = simple_strtoul (argv[1], NULL, 16);
98 	}
99 #if defined (CONFIG_X86)
100 
101 	{
102 		unsigned short port = addr;
103 
104 		switch (size) {
105 		default:
106 		case 1:
107 		    {
108 			unsigned char ch;
109 			__asm__ volatile ("in %%dx, %0":"=a" (ch):"d" (port));
110 
111 			printf (" %02x\n", ch);
112 		    }
113 			break;
114 		case 2:
115 		    {
116 			unsigned short w;
117 			__asm__ volatile ("in %%dx, %0":"=a" (w):"d" (port));
118 
119 			printf (" %04x\n", w);
120 		    }
121 			break;
122 		case 4:
123 		    {
124 			unsigned long l;
125 			__asm__ volatile ("in %%dx, %0":"=a" (l):"d" (port));
126 
127 			printf (" %08lx\n", l);
128 		    }
129 			break;
130 		}
131 	}
132 #endif	/* CONFIG_X86 */
133 
134 	in_last_addr = addr;
135 	in_last_size = size;
136 
137 	return 0;
138 }
139 
140 U_BOOT_CMD(
141 	in,	2,	1,	do_portio_in,
142 	"read data from an IO port",
143 	"[.b, .w, .l] port\n"
144 	"    - read datum from IO port"
145 );
146