diff options
Diffstat (limited to 'drivers/serial/serial_blackfin.c')
-rw-r--r-- | drivers/serial/serial_blackfin.c | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/drivers/serial/serial_blackfin.c b/drivers/serial/serial_blackfin.c new file mode 100644 index 0000000000..105e3493c9 --- /dev/null +++ b/drivers/serial/serial_blackfin.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2005 + * Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> + * + * 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 + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/blackfin.h> + +#define UART_IER_ERBFI 0x01 +#define UART_IER_ETBEI 0x02 +#define UART_IER_ELSI 0x04 +#define UART_IER_EDDSI 0x08 + +#define UART_IIR_NOINT 0x01 +#define UART_IIR_STATUS 0x06 +#define UART_IIR_LSR 0x06 +#define UART_IIR_RBR 0x04 +#define UART_IIR_THR 0x02 +#define UART_IIR_MSR 0x00 + +#define UART_LCR_WLS5 0 +#define UART_LCR_WLS6 0x01 +#define UART_LCR_WLS7 0x02 +#define UART_LCR_WLS8 0x03 +#define UART_LCR_STB 0x04 +#define UART_LCR_PEN 0x08 +#define UART_LCR_EPS 0x10 +#define UART_LCR_SP 0x20 +#define UART_LCR_SB 0x40 +#define UART_LCR_DLAB 0x80 + +#define UART_LSR_DR 0x01 +#define UART_LSR_OE 0x02 +#define UART_LSR_PE 0x04 +#define UART_LSR_FE 0x08 +#define UART_LSR_BI 0x10 +#define UART_LSR_THRE 0x20 +#define UART_LSR_TEMT 0x40 + +#define UART_GCTL_UCEN 0x01 + +static int blackfin_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + int divisor, oldlcr; + + oldlcr = readw(UART_LCR); + + divisor = get_sclk() / (baudrate * 16); + + /* Set DLAB in LCR to Access DLL and DLH */ + writew(UART_LCR_DLAB, UART_LCR); + + writew(divisor & 0xff, UART_DLL); + writew((divisor >> 8) & 0xff, UART_DLH); + + /* Clear DLAB in LCR to Access THR RBR IER */ + writew(oldlcr, UART_LCR); + + return 0; +} + +static int blackfin_serial_init_port(struct console_device *cdev) +{ + /* Enable UART */ + writew(UART_GCTL_UCEN, UART_GCTL); + + /* Set LCR to Word Lengh 8-bit word select */ + writew(UART_LCR_WLS8, UART_LCR); + + return 0; +} + +static void blackfin_serial_putc(struct console_device *cdev, char c) +{ + while (!(readw(UART_LSR) & UART_LSR_TEMT)); + + writew(c, UART_THR); +} + +static int blackfin_serial_getc(struct console_device *cdev) +{ + while (!(readw(UART_LSR) & UART_LSR_DR)); + + return readw(UART_RBR); +} + +static int blackfin_serial_tstc(struct console_device *cdev) +{ + return (readw(UART_LSR) & UART_LSR_DR) ? 1 : 0; +} + +static int blackfin_serial_probe(struct device_d *dev) +{ + struct console_device *cdev; + + cdev = malloc(sizeof(struct console_device)); + dev->type_data = cdev; + cdev->dev = dev; + cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR; + cdev->tstc = blackfin_serial_tstc; + cdev->putc = blackfin_serial_putc; + cdev->getc = blackfin_serial_getc; + cdev->setbrg = blackfin_serial_setbaudrate; + + blackfin_serial_init_port(cdev); + + console_register(cdev); + + return 0; +} + +static struct driver_d blackfin_serial_driver = { + .name = "blackfin_serial", + .probe = blackfin_serial_probe, + .type = DEVICE_TYPE_CONSOLE, +}; + +static int blackfin_serial_init(void) +{ + register_driver(&blackfin_serial_driver); + return 0; +} + +console_initcall(blackfin_serial_init); + |