123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*
- * avr.c
- *
- * AVR functions
- *
- * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
- #include <common.h>
- #include <ns16550.h>
- #include <console.h>
- /* Button codes from the AVR */
- #define PWRR 0x20 /* Power button release */
- #define PWRP 0x21 /* Power button push */
- #define RESR 0x22 /* Reset button release */
- #define RESP 0x23 /* Reset button push */
- #define AVRINIT 0x33 /* Init complete */
- #define AVRRESET 0x31 /* Reset request */
- /* LED commands */
- #define PWRBLINKSTRT '[' /* Blink power LED */
- #define PWRBLINKSTOP 'Z' /* Solid power LED */
- #define HDDLEDON 'W' /* HDD LED on */
- #define HDDLEDOFF 'V' /* HDD LED off */
- #define HDDBLINKSTRT 'Y' /* HDD LED start blink */
- #define HDDBLINKSTOP 'X' /* HDD LED stop blink */
- /* Timings for LEDs blinking to show choice */
- #define PULSETIME 250 /* msecs */
- #define LONGPAUSE (5 * PULSETIME)
- /* Button press times */
- #define PUSHHOLD 1000 /* msecs */
- #define NOBUTTON (6 * (LONGPAUSE+PULSETIME))
- /* Boot and console choices */
- #define MAX_BOOT_CHOICE 3
- static char *consoles[] = {
- "serial",
- #if defined(CONFIG_NETCONSOLE)
- "nc",
- #endif
- };
- #define MAX_CONS_CHOICE (sizeof(consoles)/sizeof(char *))
- #if !defined(CONFIG_NETCONSOLE)
- #define DEF_CONS_CHOICE 0
- #else
- #define DEF_CONS_CHOICE 1
- #endif
- #define perror(fmt, args...) printf("%s: " fmt, __FUNCTION__ , ##args)
- extern void miconCntl_SendCmd(unsigned char dat);
- extern void miconCntl_DisWDT(void);
- static int boot_stop;
- static int boot_choice = 1;
- static int cons_choice = DEF_CONS_CHOICE;
- static char envbuffer[16];
- void init_AVR_DUART (void)
- {
- NS16550_t AVR_port = (NS16550_t) CONFIG_SYS_NS16550_COM2;
- int clock_divisor = CONFIG_SYS_NS16550_CLK / 16 / 9600;
- /*
- * AVR port init sequence taken from
- * the original Linkstation init code
- * Normal U-Boot serial reinit doesn't
- * work because the AVR uses even parity
- */
- AVR_port->lcr = 0x00;
- AVR_port->ier = 0x00;
- AVR_port->lcr = UART_LCR_BKSE;
- AVR_port->dll = clock_divisor & 0xff;
- AVR_port->dlm = (clock_divisor >> 8) & 0xff;
- AVR_port->lcr = UART_LCR_WLS_8 | UART_LCR_PEN | UART_LCR_EPS;
- AVR_port->mcr = 0x00;
- AVR_port->fcr = UART_FCR_FIFO_EN | UART_FCR_RXSR | UART_FCR_TXSR;
- miconCntl_DisWDT();
- boot_stop = 0;
- miconCntl_SendCmd(PWRBLINKSTRT);
- }
- static inline int avr_tstc(void)
- {
- return (NS16550_tstc((NS16550_t)CONFIG_SYS_NS16550_COM2));
- }
- static inline char avr_getc(void)
- {
- return (NS16550_getc((NS16550_t)CONFIG_SYS_NS16550_COM2));
- }
- static int push_timeout(char button_code)
- {
- ulong push_start = get_timer(0);
- while (get_timer(push_start) <= PUSHHOLD)
- if (avr_tstc() && avr_getc() == button_code)
- return 0;
- return 1;
- }
- static void next_boot_choice(void)
- {
- ulong return_start;
- ulong pulse_start;
- int on_times;
- int button_on;
- int led_state;
- char c;
- button_on = 0;
- return_start = get_timer(0);
- on_times = boot_choice;
- led_state = 0;
- miconCntl_SendCmd(HDDLEDOFF);
- pulse_start = get_timer(0);
- while (get_timer(return_start) <= NOBUTTON || button_on) {
- if (avr_tstc()) {
- c = avr_getc();
- if (c == PWRP)
- button_on = 1;
- else if (c == PWRR) {
- button_on = 0;
- return_start = get_timer(0);
- if (++boot_choice > MAX_BOOT_CHOICE)
- boot_choice = 1;
- sprintf(envbuffer, "bootcmd%d", boot_choice);
- if (getenv(envbuffer)) {
- sprintf(envbuffer, "run bootcmd%d", boot_choice);
- setenv("bootcmd", envbuffer);
- }
- on_times = boot_choice;
- led_state = 1;
- miconCntl_SendCmd(HDDLEDON);
- pulse_start = get_timer(0);
- } else {
- perror("Unexpected code: 0x%02X\n", c);
- }
- }
- if (on_times && get_timer(pulse_start) > PULSETIME) {
- if (led_state == 1) {
- --on_times;
- led_state = 0;
- miconCntl_SendCmd(HDDLEDOFF);
- } else {
- led_state = 1;
- miconCntl_SendCmd(HDDLEDON);
- }
- pulse_start = get_timer(0);
- }
- if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
- on_times = boot_choice;
- led_state = 1;
- miconCntl_SendCmd(HDDLEDON);
- pulse_start = get_timer(0);
- }
- }
- if (led_state)
- miconCntl_SendCmd(HDDLEDOFF);
- }
- void next_cons_choice(int console)
- {
- ulong return_start;
- ulong pulse_start;
- int on_times;
- int button_on;
- int led_state;
- char c;
- button_on = 0;
- cons_choice = console;
- return_start = get_timer(0);
- on_times = cons_choice+1;
- led_state = 1;
- miconCntl_SendCmd(HDDLEDON);
- pulse_start = get_timer(0);
- while (get_timer(return_start) <= NOBUTTON || button_on) {
- if (avr_tstc()) {
- c = avr_getc();
- if (c == RESP)
- button_on = 1;
- else if (c == RESR) {
- button_on = 0;
- return_start = get_timer(0);
- cons_choice = (cons_choice + 1) % MAX_CONS_CHOICE;
- console_assign(stdin, consoles[cons_choice]);
- console_assign(stdout, consoles[cons_choice]);
- console_assign(stderr, consoles[cons_choice]);
- on_times = cons_choice+1;
- led_state = 0;
- miconCntl_SendCmd(HDDLEDOFF);
- pulse_start = get_timer(0);
- } else {
- perror("Unexpected code: 0x%02X\n", c);
- }
- }
- if (on_times && get_timer(pulse_start) > PULSETIME) {
- if (led_state == 0) {
- --on_times;
- led_state = 1;
- miconCntl_SendCmd(HDDLEDON);
- } else {
- led_state = 0;
- miconCntl_SendCmd(HDDLEDOFF);
- }
- pulse_start = get_timer(0);
- }
- if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
- on_times = cons_choice+1;
- led_state = 0;
- miconCntl_SendCmd(HDDLEDOFF);
- pulse_start = get_timer(0);
- }
- }
- if (led_state);
- miconCntl_SendCmd(HDDLEDOFF);
- }
- int avr_input(void)
- {
- char avr_button;
- if (!avr_tstc())
- return 0;
- avr_button = avr_getc();
- switch (avr_button) {
- case PWRP:
- if (push_timeout(PWRR)) {
- /* Timeout before power button release */
- boot_stop = ~boot_stop;
- if (boot_stop)
- miconCntl_SendCmd(PWRBLINKSTOP);
- else
- miconCntl_SendCmd(PWRBLINKSTRT);
- /* Wait for power button release */
- while (avr_getc() != PWRR)
- ;
- } else
- /* Power button released */
- next_boot_choice();
- break;
- case RESP:
- /* Wait for Reset button release */
- while (avr_getc() != RESR)
- ;
- next_cons_choice(cons_choice);
- break;
- case AVRINIT:
- return 0;
- default:
- perror("Unexpected code: 0x%02X\n", avr_button);
- return 0;
- }
- if (boot_stop)
- return (-3);
- else
- return (-2);
- }
- void avr_StopBoot(void)
- {
- boot_stop = ~0;
- miconCntl_SendCmd(PWRBLINKSTOP);
- }
|