1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <common.h>
24#include <ns16550.h>
25#include <stdio_dev.h>
26
27
28#define PWRR 0x20
29#define PWRP 0x21
30#define RESR 0x22
31#define RESP 0x23
32#define AVRINIT 0x33
33#define AVRRESET 0x31
34
35
36#define PWRBLINKSTRT '['
37#define PWRBLINKSTOP 'Z'
38#define HDDLEDON 'W'
39#define HDDLEDOFF 'V'
40#define HDDBLINKSTRT 'Y'
41#define HDDBLINKSTOP 'X'
42
43
44#define PULSETIME 250
45#define LONGPAUSE (5 * PULSETIME)
46
47
48#define PUSHHOLD 1000
49#define NOBUTTON (6 * (LONGPAUSE+PULSETIME))
50
51
52#define MAX_BOOT_CHOICE 3
53
54static char *consoles[] = {
55 "serial",
56#if defined(CONFIG_NETCONSOLE)
57 "nc",
58#endif
59};
60#define MAX_CONS_CHOICE (sizeof(consoles)/sizeof(char *))
61
62#if !defined(CONFIG_NETCONSOLE)
63#define DEF_CONS_CHOICE 0
64#else
65#define DEF_CONS_CHOICE 1
66#endif
67
68#define perror(fmt, args...) printf("%s: " fmt, __FUNCTION__ , ##args)
69
70extern void miconCntl_SendCmd(unsigned char dat);
71extern void miconCntl_DisWDT(void);
72
73static int boot_stop;
74
75static int boot_choice = 1;
76static int cons_choice = DEF_CONS_CHOICE;
77
78static char envbuffer[16];
79
80void init_AVR_DUART (void)
81{
82 NS16550_t AVR_port = (NS16550_t) CONFIG_SYS_NS16550_COM2;
83 int clock_divisor = CONFIG_SYS_NS16550_CLK / 16 / 9600;
84
85
86
87
88
89
90
91 AVR_port->lcr = 0x00;
92 AVR_port->ier = 0x00;
93 AVR_port->lcr = UART_LCR_BKSE;
94 AVR_port->dll = clock_divisor & 0xff;
95 AVR_port->dlm = (clock_divisor >> 8) & 0xff;
96 AVR_port->lcr = UART_LCR_WLS_8 | UART_LCR_PEN | UART_LCR_EPS;
97 AVR_port->mcr = 0x00;
98 AVR_port->fcr = UART_FCR_FIFO_EN | UART_FCR_RXSR | UART_FCR_TXSR;
99
100 miconCntl_DisWDT();
101
102 boot_stop = 0;
103 miconCntl_SendCmd(PWRBLINKSTRT);
104}
105
106static inline int avr_tstc(void)
107{
108 return (NS16550_tstc((NS16550_t)CONFIG_SYS_NS16550_COM2));
109}
110
111static inline char avr_getc(void)
112{
113 return (NS16550_getc((NS16550_t)CONFIG_SYS_NS16550_COM2));
114}
115
116static int push_timeout(char button_code)
117{
118 ulong push_start = get_timer(0);
119 while (get_timer(push_start) <= PUSHHOLD)
120 if (avr_tstc() && avr_getc() == button_code)
121 return 0;
122 return 1;
123}
124
125static void next_boot_choice(void)
126{
127 ulong return_start;
128 ulong pulse_start;
129 int on_times;
130 int button_on;
131 int led_state;
132 char c;
133
134 button_on = 0;
135 return_start = get_timer(0);
136
137 on_times = boot_choice;
138 led_state = 0;
139 miconCntl_SendCmd(HDDLEDOFF);
140 pulse_start = get_timer(0);
141
142 while (get_timer(return_start) <= NOBUTTON || button_on) {
143 if (avr_tstc()) {
144 c = avr_getc();
145 if (c == PWRP)
146 button_on = 1;
147 else if (c == PWRR) {
148 button_on = 0;
149 return_start = get_timer(0);
150 if (++boot_choice > MAX_BOOT_CHOICE)
151 boot_choice = 1;
152 sprintf(envbuffer, "bootcmd%d", boot_choice);
153 if (getenv(envbuffer)) {
154 sprintf(envbuffer, "run bootcmd%d", boot_choice);
155 setenv("bootcmd", envbuffer);
156 }
157 on_times = boot_choice;
158 led_state = 1;
159 miconCntl_SendCmd(HDDLEDON);
160 pulse_start = get_timer(0);
161 } else {
162 perror("Unexpected code: 0x%02X\n", c);
163 }
164 }
165 if (on_times && get_timer(pulse_start) > PULSETIME) {
166 if (led_state == 1) {
167 --on_times;
168 led_state = 0;
169 miconCntl_SendCmd(HDDLEDOFF);
170 } else {
171 led_state = 1;
172 miconCntl_SendCmd(HDDLEDON);
173 }
174 pulse_start = get_timer(0);
175 }
176 if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
177 on_times = boot_choice;
178 led_state = 1;
179 miconCntl_SendCmd(HDDLEDON);
180 pulse_start = get_timer(0);
181 }
182 }
183 if (led_state)
184 miconCntl_SendCmd(HDDLEDOFF);
185}
186
187void next_cons_choice(int console)
188{
189 ulong return_start;
190 ulong pulse_start;
191 int on_times;
192 int button_on;
193 int led_state;
194 char c;
195
196 button_on = 0;
197 cons_choice = console;
198 return_start = get_timer(0);
199
200 on_times = cons_choice+1;
201 led_state = 1;
202 miconCntl_SendCmd(HDDLEDON);
203 pulse_start = get_timer(0);
204
205 while (get_timer(return_start) <= NOBUTTON || button_on) {
206 if (avr_tstc()) {
207 c = avr_getc();
208 if (c == RESP)
209 button_on = 1;
210 else if (c == RESR) {
211 button_on = 0;
212 return_start = get_timer(0);
213 cons_choice = (cons_choice + 1) % MAX_CONS_CHOICE;
214 console_assign(stdin, consoles[cons_choice]);
215 console_assign(stdout, consoles[cons_choice]);
216 console_assign(stderr, consoles[cons_choice]);
217 on_times = cons_choice+1;
218 led_state = 0;
219 miconCntl_SendCmd(HDDLEDOFF);
220 pulse_start = get_timer(0);
221 } else {
222 perror("Unexpected code: 0x%02X\n", c);
223 }
224 }
225 if (on_times && get_timer(pulse_start) > PULSETIME) {
226 if (led_state == 0) {
227 --on_times;
228 led_state = 1;
229 miconCntl_SendCmd(HDDLEDON);
230 } else {
231 led_state = 0;
232 miconCntl_SendCmd(HDDLEDOFF);
233 }
234 pulse_start = get_timer(0);
235 }
236 if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
237 on_times = cons_choice+1;
238 led_state = 0;
239 miconCntl_SendCmd(HDDLEDOFF);
240 pulse_start = get_timer(0);
241 }
242 }
243 if (led_state);
244 miconCntl_SendCmd(HDDLEDOFF);
245}
246
247int avr_input(void)
248{
249 char avr_button;
250
251 if (!avr_tstc())
252 return 0;
253
254 avr_button = avr_getc();
255 switch (avr_button) {
256 case PWRP:
257 if (push_timeout(PWRR)) {
258
259 boot_stop = ~boot_stop;
260 if (boot_stop)
261 miconCntl_SendCmd(PWRBLINKSTOP);
262 else
263 miconCntl_SendCmd(PWRBLINKSTRT);
264
265 while (avr_getc() != PWRR)
266 ;
267 } else
268
269 next_boot_choice();
270 break;
271 case RESP:
272
273 while (avr_getc() != RESR)
274 ;
275 next_cons_choice(cons_choice);
276 break;
277 case AVRINIT:
278 return 0;
279 default:
280 perror("Unexpected code: 0x%02X\n", avr_button);
281 return 0;
282 }
283 if (boot_stop)
284 return (-3);
285 else
286 return (-2);
287}
288
289void avr_StopBoot(void)
290{
291 boot_stop = ~0;
292 miconCntl_SendCmd(PWRBLINKSTOP);
293}
294