]>
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 * 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.
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.
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,
27 /* Button codes from the AVR */
28 #define PWRR 0x20 /* Power button release */
29 #define PWRP 0x21 /* Power button push */
30 #define RESR 0x22 /* Reset button release */
31 #define RESP 0x23 /* Reset button push */
32 #define AVRINIT 0x33 /* Init complete */
33 #define AVRRESET 0x31 /* Reset request */
36 #define PWRBLINKSTRT '[' /* Blink power LED */
37 #define PWRBLINKSTOP 'Z' /* Solid power LED */
38 #define HDDLEDON 'W' /* HDD LED on */
39 #define HDDLEDOFF 'V' /* HDD LED off */
40 #define HDDBLINKSTRT 'Y' /* HDD LED start blink */
41 #define HDDBLINKSTOP 'X' /* HDD LED stop blink */
43 /* Timings for LEDs blinking to show choice */
44 #define PULSETIME 250 /* msecs */
45 #define LONGPAUSE (5 * PULSETIME)
47 /* Button press times */
48 #define PUSHHOLD 1000 /* msecs */
49 #define NOBUTTON (6 * (LONGPAUSE+PULSETIME))
51 /* Boot and console choices */
52 #define MAX_BOOT_CHOICE 3
54 static char *consoles
[] = {
56 #if defined(CONFIG_NETCONSOLE)
60 #define MAX_CONS_CHOICE (sizeof(consoles)/sizeof(char *))
62 #if !defined(CONFIG_NETCONSOLE)
63 #define DEF_CONS_CHOICE 0
65 #define DEF_CONS_CHOICE 1
68 #define perror(fmt, args...) printf("%s: " fmt, __FUNCTION__ , ##args)
70 extern void miconCntl_SendCmd(unsigned char dat
);
71 extern void miconCntl_DisWDT(void);
75 static int boot_choice
= 1;
76 static int cons_choice
= DEF_CONS_CHOICE
;
78 static char envbuffer
[16];
80 void init_AVR_DUART (void)
82 NS16550_t AVR_port
= (NS16550_t
) CFG_NS16550_COM2
;
83 int clock_divisor
= CFG_NS16550_CLK
/ 16 / 9600;
86 * AVR port init sequence taken from
87 * the original Linkstation init code
88 * Normal U-Boot serial reinit doesn't
89 * work because the AVR uses even parity
93 AVR_port
->lcr
= LCR_BKSE
;
94 AVR_port
->dll
= clock_divisor
& 0xff;
95 AVR_port
->dlm
= (clock_divisor
>> 8) & 0xff;
96 AVR_port
->lcr
= LCR_WLS_8
| LCR_PEN
| LCR_EPS
;
98 AVR_port
->fcr
= FCR_FIFO_EN
| FCR_RXSR
| FCR_TXSR
;
103 miconCntl_SendCmd(PWRBLINKSTRT
);
106 static inline int avr_tstc(void)
108 return (NS16550_tstc((NS16550_t
)CFG_NS16550_COM2
));
111 static inline char avr_getc(void)
113 return (NS16550_getc((NS16550_t
)CFG_NS16550_COM2
));
116 static int push_timeout(char button_code
)
118 ulong push_start
= get_timer(0);
119 while (get_timer(push_start
) <= PUSHHOLD
)
120 if (avr_tstc() && avr_getc() == button_code
)
125 static void next_boot_choice(void)
135 return_start
= get_timer(0);
137 on_times
= boot_choice
;
139 miconCntl_SendCmd(HDDLEDOFF
);
140 pulse_start
= get_timer(0);
142 while (get_timer(return_start
) <= NOBUTTON
|| button_on
) {
147 else if (c
== PWRR
) {
149 return_start
= get_timer(0);
150 if (++boot_choice
> MAX_BOOT_CHOICE
)
152 sprintf(envbuffer
, "bootcmd%d", boot_choice
);
153 if (getenv(envbuffer
)) {
154 sprintf(envbuffer
, "run bootcmd%d", boot_choice
);
155 setenv("bootcmd", envbuffer
);
157 on_times
= boot_choice
;
159 miconCntl_SendCmd(HDDLEDON
);
160 pulse_start
= get_timer(0);
162 perror("Unexpected code: 0x%02X\n", c
);
165 if (on_times
&& get_timer(pulse_start
) > PULSETIME
) {
166 if (led_state
== 1) {
169 miconCntl_SendCmd(HDDLEDOFF
);
172 miconCntl_SendCmd(HDDLEDON
);
174 pulse_start
= get_timer(0);
176 if (!on_times
&& get_timer(pulse_start
) > LONGPAUSE
) {
177 on_times
= boot_choice
;
179 miconCntl_SendCmd(HDDLEDON
);
180 pulse_start
= get_timer(0);
184 miconCntl_SendCmd(HDDLEDOFF
);
187 void next_cons_choice(int console
)
197 cons_choice
= console
;
198 return_start
= get_timer(0);
200 on_times
= cons_choice
+1;
202 miconCntl_SendCmd(HDDLEDON
);
203 pulse_start
= get_timer(0);
205 while (get_timer(return_start
) <= NOBUTTON
|| button_on
) {
210 else if (c
== RESR
) {
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;
219 miconCntl_SendCmd(HDDLEDOFF
);
220 pulse_start
= get_timer(0);
222 perror("Unexpected code: 0x%02X\n", c
);
225 if (on_times
&& get_timer(pulse_start
) > PULSETIME
) {
226 if (led_state
== 0) {
229 miconCntl_SendCmd(HDDLEDON
);
232 miconCntl_SendCmd(HDDLEDOFF
);
234 pulse_start
= get_timer(0);
236 if (!on_times
&& get_timer(pulse_start
) > LONGPAUSE
) {
237 on_times
= cons_choice
+1;
239 miconCntl_SendCmd(HDDLEDOFF
);
240 pulse_start
= get_timer(0);
244 miconCntl_SendCmd(HDDLEDOFF
);
254 avr_button
= avr_getc();
255 switch (avr_button
) {
257 if (push_timeout(PWRR
)) {
258 /* Timeout before power button release */
259 boot_stop
= ~boot_stop
;
261 miconCntl_SendCmd(PWRBLINKSTOP
);
263 miconCntl_SendCmd(PWRBLINKSTRT
);
264 /* Wait for power button release */
265 while (avr_getc() != PWRR
)
268 /* Power button released */
272 /* Wait for Reset button release */
273 while (avr_getc() != RESR
)
275 next_cons_choice(cons_choice
);
280 perror("Unexpected code: 0x%02X\n", avr_button
);
289 void avr_StopBoot(void)
292 miconCntl_SendCmd(PWRBLINKSTOP
);