From 3d3befa754fedb320f779320ac0ab11deb0a6275 Mon Sep 17 00:00:00 2001 From: wdenk Date: Sun, 14 Mar 2004 15:06:13 +0000 Subject: * Patch by Philippe Robin, 09 Mar 2004: Added ARM Integrator AP, CP and Versatile PB926EJ-S Reference Platform support. * Patch by Masami Komiya, 08 Mar 2004: Don't overwrite server IP address or boot file name when the boot server does not return values * Patch by listmember@orkun.us, 5 Mar 2004: Removed compile time restriction on CFG_I2C_SPEED for DS1338 RTC --- drivers/Makefile | 3 +- drivers/serial_pl010.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial_pl011.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/serial_pl011.h | 137 ++++++++++++++++++++++++++++++++++++++ drivers/smc91111.c | 20 +++--- 5 files changed, 499 insertions(+), 13 deletions(-) create mode 100644 drivers/serial_pl010.c create mode 100644 drivers/serial_pl011.c create mode 100644 drivers/serial_pl011.h (limited to 'drivers') diff --git a/drivers/Makefile b/drivers/Makefile index 32a6a0607e..33b9ab4b7c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -38,7 +38,8 @@ OBJS = 3c589.o 5701rls.o ali512x.o \ pcnet.o plb2800_eth.o \ ps2ser.o ps2mult.o pc_keyb.o keyboard.o \ rtl8019.o rtl8139.o \ - s3c24x0_i2c.o sed13806.o serial.o serial_max3100.o \ + s3c24x0_i2c.o sed13806.o \ + serial.o serial_max3100.o serial_pl011.o serial_pl010.o \ smc91111.o smiLynxEM.o status_led.o sym53c8xx.o \ ti_pci1410a.o tigon3.o w83c553f.o omap1510_i2c.o \ usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o diff --git a/drivers/serial_pl010.c b/drivers/serial_pl010.c new file mode 100644 index 0000000000..01b5f0aafd --- /dev/null +++ b/drivers/serial_pl010.c @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ +/* Should be fairly simple to make it work with the PL010 as well */ + +#include + +#ifdef CFG_PL010_SERIAL + +#include "serial_pl011.h" + +#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) +#define IO_READ(addr) (*(volatile unsigned int *)(addr)) + +/* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 */ +#define NUM_PORTS 2 +#define CONSOLE_PORT CONFIG_CONS_INDEX +#define baudRate CONFIG_BAUDRATE +static volatile unsigned char * const port[NUM_PORTS] = {(void*)(CFG_SERIAL0), + (void*)(CFG_SERIAL1)}; + + +static void pl010_putc(int portnum, char c); +static int pl010_getc(int portnum); +static int pl010_tstc(int portnum); + + +int serial_init (void) +{ + unsigned int temp; + unsigned int divisor; + + /* + ** First, disable everything. + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL010_CR, 0x0); + + /* + ** Set baud rate + ** + */ + switch (baudRate) { + case 9600: + divisor = UART_PL010_BAUD_9600; + break; + + case 19200: + divisor = UART_PL010_BAUD_9600; + break; + + case 38400: + divisor = UART_PL010_BAUD_38400; + break; + + case 57600: + divisor = UART_PL010_BAUD_57600; + break; + + case 115200: + divisor = UART_PL010_BAUD_115200; + break; + + default: + divisor = UART_PL010_BAUD_38400; + } + + IO_WRITE(port[CONSOLE_PORT] + UART_PL010_LCRM, ((divisor & 0xf00) >> 8)); + IO_WRITE(port[CONSOLE_PORT] + UART_PL010_LCRL, (divisor & 0xff)); + + /* + ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL010_LCRH, + (UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN)); + + /* + ** Finally, enable the UART + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL010_CR, (UART_PL010_CR_UARTEN)); + + return (0); +} + +void +serial_putc(const char c) +{ + if (c == '\n') + pl010_putc(CONSOLE_PORT, '\r'); + + pl010_putc(CONSOLE_PORT, c); +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int +serial_getc(void) +{ + return pl010_getc(CONSOLE_PORT); +} + +int +serial_tstc(void) +{ + return pl010_tstc(CONSOLE_PORT); +} + +void +serial_setbrg (void) +{ +} + +static void pl010_putc(int portnum, char c) +{ + /* Wait until there is space in the FIFO */ + while (IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF); + + /* Send the character */ + IO_WRITE(port[portnum] + UART_PL01x_DR, c); +} + +static int pl010_getc(int portnum) +{ + unsigned int data; + + /* Wait until there is data in the FIFO */ + while (IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); + + data = IO_READ(port[portnum] + UART_PL01x_DR); + + /* Check for an error flag */ + if (data & 0xFFFFFF00) + { + /* Clear the error */ + IO_WRITE(port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF); + return -1; + } + + return (int)data; +} + +static int pl010_tstc(int portnum) +{ + return !(IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); +} + +#endif diff --git a/drivers/serial_pl011.c b/drivers/serial_pl011.c new file mode 100644 index 0000000000..60fcc9132a --- /dev/null +++ b/drivers/serial_pl011.c @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* Simple U-Boot driver for the PrimeCell PL011 UARTs on the IntegratorCP */ +/* Should be fairly simple to make it work with the PL010 as well */ + +#include + +#ifdef CFG_PL011_SERIAL + +#include "serial_pl011.h" + +#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val)) +#define IO_READ(addr) (*(volatile unsigned int *)(addr)) + +/* + * IntegratorCP has two UARTs, use the first one, at 38400-8-N-1 + * Versatile PB has four UARTs. + */ +#define NUM_PORTS 2 +#define CONSOLE_PORT CONFIG_CONS_INDEX +#define baudRate CONFIG_BAUDRATE +static volatile unsigned char * const port[NUM_PORTS] = {(void*)(CFG_SERIAL0), + (void*)(CFG_SERIAL1)}; + + +static void pl011_putc(int portnum, char c); +static int pl011_getc(int portnum); +static int pl011_tstc(int portnum); + + +int serial_init (void) +{ + unsigned int temp; + unsigned int divider; + unsigned int remainder; + unsigned int fraction; + + /* + ** First, disable everything. + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL011_CR, 0x0); + + /* + ** Set baud rate + ** + ** IBRD = UART_CLK / (16 * BAUD_RATE) + ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE)) + */ +#ifdef CONFIG_VERSATILE + temp = 16 * baudRate; + divider = 24000000 / temp; + remainder = 24000000 % temp; + temp = (8 * remainder) / baudRate; + fraction = (temp >> 1) + (temp & 1); +#endif +#ifdef CONFIG_INTEGRATOR + temp = 16 * baudRate; + divider = 14745600 / temp; + remainder = 14745600 % temp; + temp = (8 * remainder) / baudRate; + fraction = (temp >> 1) + (temp & 1); +#endif + + IO_WRITE(port[CONSOLE_PORT] + UART_PL011_IBRD, divider); + IO_WRITE(port[CONSOLE_PORT] + UART_PL011_FBRD, fraction); + + /* + ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled. + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL011_LCRH, + (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN)); + + /* + ** Finally, enable the UART + */ + IO_WRITE(port[CONSOLE_PORT] + UART_PL011_CR, + (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE)); + + return (0); +} + +void +serial_putc(const char c) +{ + if (c == '\n') + pl011_putc(CONSOLE_PORT, '\r'); + + pl011_putc(CONSOLE_PORT, c); +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int +serial_getc(void) +{ + return pl011_getc(CONSOLE_PORT); +} + +int +serial_tstc(void) +{ + return pl011_tstc(CONSOLE_PORT); +} + +void +serial_setbrg (void) +{ +} + +static void pl011_putc(int portnum, char c) +{ + /* Wait until there is space in the FIFO */ + while (IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF); + + /* Send the character */ + IO_WRITE(port[portnum] + UART_PL01x_DR, c); +} + +static int pl011_getc(int portnum) +{ + unsigned int data; + + /* Wait until there is data in the FIFO */ + while (IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); + + data = IO_READ(port[portnum] + UART_PL01x_DR); + + /* Check for an error flag */ + if (data & 0xFFFFFF00) + { + /* Clear the error */ + IO_WRITE(port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF); + return -1; + } + + return (int)data; +} + +static int pl011_tstc(int portnum) +{ + return !(IO_READ(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE); +} + +#endif diff --git a/drivers/serial_pl011.h b/drivers/serial_pl011.h new file mode 100644 index 0000000000..2117848c9c --- /dev/null +++ b/drivers/serial_pl011.h @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2003, 2004 + * ARM Ltd. + * Philippe Robin, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * ARM PrimeCell UART's (PL010 & PL011) + * ------------------------------------ + * + * Definitions common to both PL010 & PL011 + * + */ +#define UART_PL01x_DR 0x00 /* Data read or written from the interface. */ +#define UART_PL01x_RSR 0x04 /* Receive status register (Read). */ +#define UART_PL01x_ECR 0x04 /* Error clear register (Write). */ +#define UART_PL01x_FR 0x18 /* Flag register (Read only). */ + +#define UART_PL01x_RSR_OE 0x08 +#define UART_PL01x_RSR_BE 0x04 +#define UART_PL01x_RSR_PE 0x02 +#define UART_PL01x_RSR_FE 0x01 + +#define UART_PL01x_FR_TXFE 0x80 +#define UART_PL01x_FR_RXFF 0x40 +#define UART_PL01x_FR_TXFF 0x20 +#define UART_PL01x_FR_RXFE 0x10 +#define UART_PL01x_FR_BUSY 0x08 +#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY) + +/* + * PL010 definitions + * + */ +#define UART_PL010_LCRH 0x08 /* Line control register, high byte. */ +#define UART_PL010_LCRM 0x0C /* Line control register, middle byte. */ +#define UART_PL010_LCRL 0x10 /* Line control register, low byte. */ +#define UART_PL010_CR 0x14 /* Control register. */ +#define UART_PL010_IIR 0x1C /* Interrupt indentification register (Read). */ +#define UART_PL010_ICR 0x1C /* Interrupt clear register (Write). */ +#define UART_PL010_ILPR 0x20 /* IrDA low power counter register. */ + +#define UART_PL010_CR_LPE (1 << 7) +#define UART_PL010_CR_RTIE (1 << 6) +#define UART_PL010_CR_TIE (1 << 5) +#define UART_PL010_CR_RIE (1 << 4) +#define UART_PL010_CR_MSIE (1 << 3) +#define UART_PL010_CR_IIRLP (1 << 2) +#define UART_PL010_CR_SIREN (1 << 1) +#define UART_PL010_CR_UARTEN (1 << 0) + +#define UART_PL010_LCRH_WLEN_8 (3 << 5) +#define UART_PL010_LCRH_WLEN_7 (2 << 5) +#define UART_PL010_LCRH_WLEN_6 (1 << 5) +#define UART_PL010_LCRH_WLEN_5 (0 << 5) +#define UART_PL010_LCRH_FEN (1 << 4) +#define UART_PL010_LCRH_STP2 (1 << 3) +#define UART_PL010_LCRH_EPS (1 << 2) +#define UART_PL010_LCRH_PEN (1 << 1) +#define UART_PL010_LCRH_BRK (1 << 0) + + +#define UART_PL010_BAUD_460800 1 +#define UART_PL010_BAUD_230400 3 +#define UART_PL010_BAUD_115200 7 +#define UART_PL010_BAUD_57600 15 +#define UART_PL010_BAUD_38400 23 +#define UART_PL010_BAUD_19200 47 +#define UART_PL010_BAUD_14400 63 +#define UART_PL010_BAUD_9600 95 +#define UART_PL010_BAUD_4800 191 +#define UART_PL010_BAUD_2400 383 +#define UART_PL010_BAUD_1200 767 +/* + * PL011 definitions + * + */ +#define UART_PL011_IBRD 0x24 +#define UART_PL011_FBRD 0x28 +#define UART_PL011_LCRH 0x2C +#define UART_PL011_CR 0x30 +#define UART_PL011_IMSC 0x38 +#define UART_PL011_PERIPH_ID0 0xFE0 + +#define UART_PL011_LCRH_SPS (1 << 7) +#define UART_PL011_LCRH_WLEN_8 (3 << 5) +#define UART_PL011_LCRH_WLEN_7 (2 << 5) +#define UART_PL011_LCRH_WLEN_6 (1 << 5) +#define UART_PL011_LCRH_WLEN_5 (0 << 5) +#define UART_PL011_LCRH_FEN (1 << 4) +#define UART_PL011_LCRH_STP2 (1 << 3) +#define UART_PL011_LCRH_EPS (1 << 2) +#define UART_PL011_LCRH_PEN (1 << 1) +#define UART_PL011_LCRH_BRK (1 << 0) + +#define UART_PL011_CR_CTSEN (1 << 15) +#define UART_PL011_CR_RTSEN (1 << 14) +#define UART_PL011_CR_OUT2 (1 << 13) +#define UART_PL011_CR_OUT1 (1 << 12) +#define UART_PL011_CR_RTS (1 << 11) +#define UART_PL011_CR_DTR (1 << 10) +#define UART_PL011_CR_RXE (1 << 9) +#define UART_PL011_CR_TXE (1 << 8) +#define UART_PL011_CR_LPE (1 << 7) +#define UART_PL011_CR_IIRLP (1 << 2) +#define UART_PL011_CR_SIREN (1 << 1) +#define UART_PL011_CR_UARTEN (1 << 0) + +#define UART_PL011_IMSC_OEIM (1 << 10) +#define UART_PL011_IMSC_BEIM (1 << 9) +#define UART_PL011_IMSC_PEIM (1 << 8) +#define UART_PL011_IMSC_FEIM (1 << 7) +#define UART_PL011_IMSC_RTIM (1 << 6) +#define UART_PL011_IMSC_TXIM (1 << 5) +#define UART_PL011_IMSC_RXIM (1 << 4) +#define UART_PL011_IMSC_DSRMIM (1 << 3) +#define UART_PL011_IMSC_DCDMIM (1 << 2) +#define UART_PL011_IMSC_CTSMIM (1 << 1) +#define UART_PL011_IMSC_RIMIM (1 << 0) diff --git a/drivers/smc91111.c b/drivers/smc91111.c index 6c3a0b753c..486c11cd09 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -1313,7 +1313,6 @@ static void smc_phy_configure () #if SMC_DEBUG > 2 static void print_packet( byte * buf, int length ) { -#if 0 int i; int remainder; int lines; @@ -1345,7 +1344,6 @@ static void print_packet( byte * buf, int length ) } printf("\n"); #endif -#endif } #endif @@ -1423,28 +1421,26 @@ int smc_get_ethaddr (bd_t * bd) } memcpy (bd->bi_enetaddr, v_mac, 6); /* update global address to match env (allows env changing) */ smc_set_mac_addr (v_mac); /* use old function to update smc default */ + PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1], + v_mac[2], v_mac[3], v_mac[4], v_mac[5]); return (0); } int get_rom_mac (char *v_rom_mac) { - int is_rom_present = 0; - #ifdef HARDCODE_MAC /* used for testing or to supress run time warnings */ char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 }; memcpy (v_rom_mac, hw_mac_addr, 6); return (1); #else - if (is_rom_present) { - /* if eeprom contents are valid - * extract mac address into hw_mac_addr, 8 or 16 bit accesses - * memcpy (v_rom_mac, hc_mac_addr, 6); - * return(1); - */ + int i; + SMC_SELECT_BANK (1); + for (i=0; i<6; i++) + { + v_rom_mac[i] = SMC_inb (ADDR0_REG + i); } - memset (v_rom_mac, 0, 6); - return (0); + return (1); #endif } #endif /* CONFIG_DRIVER_SMC91111 */ -- cgit