1 /*
2  * (C) Copyright 2001
3  * Erik Theisen,  Wave 7 Optics, etheisen@mindspring.com.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 /*
25  * AMCC 4XX DCR Functions
26  */
27 
28 #include <common.h>
29 #include <config.h>
30 #include <command.h>
31 
32 unsigned long get_dcr (unsigned short);
33 unsigned long set_dcr (unsigned short, unsigned long);
34 
35 /* =======================================================================
36  * Interpreter command to retrieve an AMCC PPC 4xx Device Control Register
37  * =======================================================================
38  */
do_getdcr(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])39 int do_getdcr ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[] )
40 {
41 	unsigned short dcrn;	/* Device Control Register Num */
42 	unsigned long value;	/* DCR's value */
43 
44 	unsigned long get_dcr (unsigned short);
45 
46 	/* Validate arguments */
47 	if (argc < 2) {
48 		cmd_usage(cmdtp);
49 		return 1;
50 	}
51 
52 	/* Get a DCR */
53 	dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16);
54 	value = get_dcr (dcrn);
55 
56 	printf ("%04x: %08lx\n", dcrn, value);
57 
58 	return 0;
59 }
60 
61 
62 /* ======================================================================
63  * Interpreter command to set an AMCC PPC 4xx Device Control Register
64  * ======================================================================
65 */
do_setdcr(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])66 int do_setdcr (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
67 {
68 	unsigned short dcrn;	/* Device Control Register Num */
69 	unsigned long value;
70 
71 	/* DCR's value */
72 	int nbytes;
73 	extern char console_buffer[];
74 
75 	/* Validate arguments */
76 	if (argc < 2) {
77 		cmd_usage(cmdtp);
78 		return 1;
79 	}
80 
81 	/* Set a DCR */
82 	dcrn = (unsigned short) simple_strtoul (argv[1], NULL, 16);
83 	do {
84 		value = get_dcr (dcrn);
85 		printf ("%04x: %08lx", dcrn, value);
86 		nbytes = readline (" ? ");
87 		if (nbytes == 0) {
88 			/*
89 			 * <CR> pressed as only input, don't modify current
90 			 * location and exit command.
91 			 */
92 			nbytes = 1;
93 			return 0;
94 		} else {
95 			unsigned long i;
96 			char *endp;
97 
98 			i = simple_strtoul (console_buffer, &endp, 16);
99 			nbytes = endp - console_buffer;
100 			if (nbytes)
101 				set_dcr (dcrn, i);
102 		}
103 	} while (nbytes);
104 
105 	return 0;
106 }
107 
108 /* =======================================================================
109  * Interpreter command to retrieve an register value through AMCC PPC 4xx
110  * Device Control Register inderect addressing.
111  * =======================================================================
112  */
do_getidcr(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])113 int do_getidcr (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
114 {
115 	unsigned short adr_dcrn;	/* Device Control Register Num for Address */
116 	unsigned short dat_dcrn;	/* Device Control Register Num for Data */
117 	unsigned short offset;		/* Register's offset */
118 	unsigned long value;		/* Register's value */
119 	char *ptr = NULL;
120 	char buf[80];
121 
122 	/* Validate arguments */
123 	if (argc < 3) {
124 		cmd_usage(cmdtp);
125 		return 1;
126 	}
127 
128 	/* Find out whether ther is '.' (dot) symbol in the first parameter. */
129 	strncpy (buf, argv[1], sizeof(buf)-1);
130 	buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */
131 	ptr = strchr (buf, '.');
132 
133 	if (ptr != NULL) {
134 		/* First parameter has format adr_dcrn.dat_dcrn */
135 		*ptr++ = 0; /* erase '.', create zero-end string */
136 		adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16);
137 		dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16);
138 	} else {
139 		/*
140 		 * First parameter has format adr_dcrn; dat_dcrn will be
141 		 * calculated as adr_dcrn+1.
142 		 */
143 		adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16);
144 		dat_dcrn = adr_dcrn+1;
145 	}
146 
147 	/* Register's offset */
148 	offset = (unsigned short) simple_strtoul (argv[2], NULL, 16);
149 
150 	/* Disable interrupts */
151 	disable_interrupts ();
152 	/* Set offset */
153 	set_dcr (adr_dcrn, offset);
154 	/* get data */
155 	value = get_dcr (dat_dcrn);
156 	/* Enable interrupts */
157 	enable_interrupts ();
158 
159 	printf ("%04x.%04x-%04x Read  %08lx\n", adr_dcrn, dat_dcrn, offset, value);
160 
161 	return 0;
162 }
163 
164 /* =======================================================================
165  * Interpreter command to update an register value through AMCC PPC 4xx
166  * Device Control Register inderect addressing.
167  * =======================================================================
168  */
do_setidcr(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])169 int do_setidcr (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
170 {
171 	unsigned short adr_dcrn;	/* Device Control Register Num for Address */
172 	unsigned short dat_dcrn;	/* Device Control Register Num for Data */
173 	unsigned short offset;		/* Register's offset */
174 	unsigned long value;		/* Register's value */
175 	char *ptr = NULL;
176 	char buf[80];
177 
178 	/* Validate arguments */
179 	if (argc < 4) {
180 		cmd_usage(cmdtp);
181 		return 1;
182 	}
183 
184 	/* Find out whether ther is '.' (dot) symbol in the first parameter. */
185 	strncpy (buf, argv[1], sizeof(buf)-1);
186 	buf[sizeof(buf)-1] = 0; /* will guarantee zero-end string */
187 	ptr = strchr (buf, '.');
188 
189 	if (ptr != NULL) {
190 		/* First parameter has format adr_dcrn.dat_dcrn */
191 		*ptr++ = 0;	/* erase '.', create zero-end string */
192 		adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16);
193 		dat_dcrn = (unsigned short) simple_strtoul (ptr, NULL, 16);
194 	} else {
195 		/*
196 		 * First parameter has format adr_dcrn; dat_dcrn will be
197 		 * calculated as adr_dcrn+1.
198 		 */
199 		adr_dcrn = (unsigned short) simple_strtoul (buf, NULL, 16);
200 		dat_dcrn = adr_dcrn+1;
201 	}
202 
203 	/* Register's offset */
204 	offset = (unsigned short) simple_strtoul (argv[2], NULL, 16);
205 	/* New value */
206 	value  = (unsigned  long) simple_strtoul (argv[3], NULL, 16);
207 
208 	/* Disable interrupts */
209 	disable_interrupts ();
210 	/* Set offset */
211 	set_dcr (adr_dcrn, offset);
212 	/* set data */
213 	set_dcr (dat_dcrn, value);
214 	/* Enable interrupts */
215 	enable_interrupts ();
216 
217 	printf ("%04x.%04x-%04x Write %08lx\n", adr_dcrn, dat_dcrn, offset, value);
218 
219 	return 0;
220 }
221 
222 /***************************************************/
223 
224 U_BOOT_CMD(
225 	getdcr,	2,	1,	do_getdcr,
226 	"Get an AMCC PPC 4xx DCR's value",
227 	"dcrn - return a DCR's value."
228 );
229 U_BOOT_CMD(
230 	setdcr,	2,	1,	do_setdcr,
231 	"Set an AMCC PPC 4xx DCR's value",
232 	"dcrn - set a DCR's value."
233 );
234 
235 U_BOOT_CMD(
236 	getidcr,	3,	1,	do_getidcr,
237 	"Get a register value via indirect DCR addressing",
238 	"adr_dcrn[.dat_dcrn] offset - write offset to adr_dcrn, read value from dat_dcrn."
239 );
240 
241 U_BOOT_CMD(
242 	setidcr,	4,	1,	do_setidcr,
243 	"Set a register value via indirect DCR addressing",
244 	"adr_dcrn[.dat_dcrn] offset value - write offset to adr_dcrn, write value to dat_dcrn."
245 );
246