]>
git.ipfire.org Git - people/ms/u-boot.git/blob - board/linkstation/avr.c
6 * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
8 * SPDX-License-Identifier: GPL-2.0+
12 #include <stdio_dev.h>
14 /* Button codes from the AVR */
15 #define PWRR 0x20 /* Power button release */
16 #define PWRP 0x21 /* Power button push */
17 #define RESR 0x22 /* Reset button release */
18 #define RESP 0x23 /* Reset button push */
19 #define AVRINIT 0x33 /* Init complete */
20 #define AVRRESET 0x31 /* Reset request */
23 #define PWRBLINKSTRT '[' /* Blink power LED */
24 #define PWRBLINKSTOP 'Z' /* Solid power LED */
25 #define HDDLEDON 'W' /* HDD LED on */
26 #define HDDLEDOFF 'V' /* HDD LED off */
27 #define HDDBLINKSTRT 'Y' /* HDD LED start blink */
28 #define HDDBLINKSTOP 'X' /* HDD LED stop blink */
30 /* Timings for LEDs blinking to show choice */
31 #define PULSETIME 250 /* msecs */
32 #define LONGPAUSE (5 * PULSETIME)
34 /* Button press times */
35 #define PUSHHOLD 1000 /* msecs */
36 #define NOBUTTON (6 * (LONGPAUSE+PULSETIME))
38 /* Boot and console choices */
39 #define MAX_BOOT_CHOICE 3
41 static char *consoles
[] = {
43 #if defined(CONFIG_NETCONSOLE)
47 #define MAX_CONS_CHOICE (sizeof(consoles)/sizeof(char *))
49 #if !defined(CONFIG_NETCONSOLE)
50 #define DEF_CONS_CHOICE 0
52 #define DEF_CONS_CHOICE 1
55 #define perror(fmt, args...) printf("%s: " fmt, __FUNCTION__ , ##args)
57 extern void miconCntl_SendCmd(unsigned char dat
);
58 extern void miconCntl_DisWDT(void);
62 static int boot_choice
= 1;
63 static int cons_choice
= DEF_CONS_CHOICE
;
65 static char envbuffer
[16];
67 void init_AVR_DUART (void)
69 NS16550_t AVR_port
= (NS16550_t
) CONFIG_SYS_NS16550_COM2
;
70 int clock_divisor
= CONFIG_SYS_NS16550_CLK
/ 16 / 9600;
73 * AVR port init sequence taken from
74 * the original Linkstation init code
75 * Normal U-Boot serial reinit doesn't
76 * work because the AVR uses even parity
80 AVR_port
->lcr
= UART_LCR_BKSE
;
81 AVR_port
->dll
= clock_divisor
& 0xff;
82 AVR_port
->dlm
= (clock_divisor
>> 8) & 0xff;
83 AVR_port
->lcr
= UART_LCR_WLS_8
| UART_LCR_PEN
| UART_LCR_EPS
;
85 AVR_port
->fcr
= UART_FCR_FIFO_EN
| UART_FCR_RXSR
| UART_FCR_TXSR
;
90 miconCntl_SendCmd(PWRBLINKSTRT
);
93 static inline int avr_tstc(void)
95 return (NS16550_tstc((NS16550_t
)CONFIG_SYS_NS16550_COM2
));
98 static inline char avr_getc(void)
100 return (NS16550_getc((NS16550_t
)CONFIG_SYS_NS16550_COM2
));
103 static int push_timeout(char button_code
)
105 ulong push_start
= get_timer(0);
106 while (get_timer(push_start
) <= PUSHHOLD
)
107 if (avr_tstc() && avr_getc() == button_code
)
112 static void next_boot_choice(void)
122 return_start
= get_timer(0);
124 on_times
= boot_choice
;
126 miconCntl_SendCmd(HDDLEDOFF
);
127 pulse_start
= get_timer(0);
129 while (get_timer(return_start
) <= NOBUTTON
|| button_on
) {
134 else if (c
== PWRR
) {
136 return_start
= get_timer(0);
137 if (++boot_choice
> MAX_BOOT_CHOICE
)
139 sprintf(envbuffer
, "bootcmd%d", boot_choice
);
140 if (getenv(envbuffer
)) {
141 sprintf(envbuffer
, "run bootcmd%d", boot_choice
);
142 setenv("bootcmd", envbuffer
);
144 on_times
= boot_choice
;
146 miconCntl_SendCmd(HDDLEDON
);
147 pulse_start
= get_timer(0);
149 perror("Unexpected code: 0x%02X\n", c
);
152 if (on_times
&& get_timer(pulse_start
) > PULSETIME
) {
153 if (led_state
== 1) {
156 miconCntl_SendCmd(HDDLEDOFF
);
159 miconCntl_SendCmd(HDDLEDON
);
161 pulse_start
= get_timer(0);
163 if (!on_times
&& get_timer(pulse_start
) > LONGPAUSE
) {
164 on_times
= boot_choice
;
166 miconCntl_SendCmd(HDDLEDON
);
167 pulse_start
= get_timer(0);
171 miconCntl_SendCmd(HDDLEDOFF
);
174 void next_cons_choice(int console
)
184 cons_choice
= console
;
185 return_start
= get_timer(0);
187 on_times
= cons_choice
+1;
189 miconCntl_SendCmd(HDDLEDON
);
190 pulse_start
= get_timer(0);
192 while (get_timer(return_start
) <= NOBUTTON
|| button_on
) {
197 else if (c
== RESR
) {
199 return_start
= get_timer(0);
200 cons_choice
= (cons_choice
+ 1) % MAX_CONS_CHOICE
;
201 console_assign(stdin
, consoles
[cons_choice
]);
202 console_assign(stdout
, consoles
[cons_choice
]);
203 console_assign(stderr
, consoles
[cons_choice
]);
204 on_times
= cons_choice
+1;
206 miconCntl_SendCmd(HDDLEDOFF
);
207 pulse_start
= get_timer(0);
209 perror("Unexpected code: 0x%02X\n", c
);
212 if (on_times
&& get_timer(pulse_start
) > PULSETIME
) {
213 if (led_state
== 0) {
216 miconCntl_SendCmd(HDDLEDON
);
219 miconCntl_SendCmd(HDDLEDOFF
);
221 pulse_start
= get_timer(0);
223 if (!on_times
&& get_timer(pulse_start
) > LONGPAUSE
) {
224 on_times
= cons_choice
+1;
226 miconCntl_SendCmd(HDDLEDOFF
);
227 pulse_start
= get_timer(0);
231 miconCntl_SendCmd(HDDLEDOFF
);
241 avr_button
= avr_getc();
242 switch (avr_button
) {
244 if (push_timeout(PWRR
)) {
245 /* Timeout before power button release */
246 boot_stop
= ~boot_stop
;
248 miconCntl_SendCmd(PWRBLINKSTOP
);
250 miconCntl_SendCmd(PWRBLINKSTRT
);
251 /* Wait for power button release */
252 while (avr_getc() != PWRR
)
255 /* Power button released */
259 /* Wait for Reset button release */
260 while (avr_getc() != RESR
)
262 next_cons_choice(cons_choice
);
267 perror("Unexpected code: 0x%02X\n", avr_button
);
276 void avr_StopBoot(void)
279 miconCntl_SendCmd(PWRBLINKSTOP
);