diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot-sam460ex/drivers/serial | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot-sam460ex/drivers/serial')
35 files changed, 7094 insertions, 0 deletions
diff --git a/roms/u-boot-sam460ex/drivers/serial/Makefile b/roms/u-boot-sam460ex/drivers/serial/Makefile new file mode 100644 index 000000000..c731bfb59 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/Makefile @@ -0,0 +1,76 @@ +# +# (C) Copyright 2006-2009 +# Wolfgang Denk, DENX Software Engineering, wd@denx.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 $(TOPDIR)/config.mk + +LIB := $(obj)libserial.a + +COBJS-$(CONFIG_ALTERA_UART) += altera_uart.o +COBJS-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o +COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o +COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o +COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o +COBJS-$(CONFIG_MCFUART) += mcfuart.o +COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o +COBJS-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o +COBJS-$(CONFIG_SYS_NS16550) += ns16550.o +COBJS-$(CONFIG_DRIVER_S3C4510_UART) += s3c4510b_uart.o +COBJS-$(CONFIG_S3C64XX) += s3c64xx.o +COBJS-$(CONFIG_S5PC1XX) += serial_s5p.o +COBJS-$(CONFIG_SYS_NS16550_SERIAL) += serial.o +COBJS-$(CONFIG_CLPS7111_SERIAL) += serial_clps7111.o +COBJS-$(CONFIG_IMX_SERIAL) += serial_imx.o +COBJS-$(CONFIG_IXP_SERIAL) += serial_ixp.o +COBJS-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o +COBJS-$(CONFIG_LPC2292_SERIAL) += serial_lpc2292.o +COBJS-$(CONFIG_LH7A40X_SERIAL) += serial_lh7a40x.o +COBJS-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o +COBJS-$(CONFIG_MXC_UART) += serial_mxc.o +COBJS-$(CONFIG_NETARM_SERIAL) += serial_netarm.o +COBJS-$(CONFIG_PL010_SERIAL) += serial_pl01x.o +COBJS-$(CONFIG_PL011_SERIAL) += serial_pl01x.o +COBJS-$(CONFIG_PXA_SERIAL) += serial_pxa.o +COBJS-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o +COBJS-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o +COBJS-$(CONFIG_S3C44B0_SERIAL) += serial_s3c44b0.o +COBJS-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o +COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o +COBJS-$(CONFIG_USB_TTY) += usbtty.o + +COBJS := $(sort $(COBJS-y)) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/roms/u-boot-sam460ex/drivers/serial/altera_jtag_uart.c b/roms/u-boot-sam460ex/drivers/serial/altera_jtag_uart.c new file mode 100644 index 000000000..2980e4d07 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/altera_jtag_uart.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------------------------------------------------ + * JTAG acts as the serial port + *-----------------------------------------------------------------*/ +static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; + +void serial_setbrg( void ){ return; } +int serial_init( void ) { return(0);} + +void serial_putc (char c) +{ + while (1) { + unsigned st = readl(&jtag->control); + if (NIOS_JTAG_WSPACE(st)) + break; +#ifdef CONFIG_ALTERA_JTAG_UART_BYPASS + if (!(st & NIOS_JTAG_AC)) /* no connection */ + return; +#endif + WATCHDOG_RESET(); + } + writel ((unsigned char)c, &jtag->data); +} + +void serial_puts (const char *s) +{ + while (*s != 0) + serial_putc (*s++); +} + +int serial_tstc (void) +{ + return ( readl (&jtag->control) & NIOS_JTAG_RRDY); +} + +int serial_getc (void) +{ + int c; + unsigned val; + + while (1) { + WATCHDOG_RESET (); + val = readl (&jtag->data); + if (val & NIOS_JTAG_RVALID) + break; + } + c = val & 0x0ff; + return (c); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/altera_uart.c b/roms/u-boot-sam460ex/drivers/serial/altera_uart.c new file mode 100644 index 000000000..045f1197a --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/altera_uart.c @@ -0,0 +1,94 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------------------------------------------------ + * UART the serial port + *-----------------------------------------------------------------*/ + +static nios_uart_t *uart = (nios_uart_t *) CONFIG_SYS_NIOS_CONSOLE; + +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) + +/* Everything's already setup for fixed-baud PTF + * assignment + */ +void serial_setbrg (void){ return; } +int serial_init (void) { return (0);} + +#else + +void serial_setbrg (void) +{ + unsigned div; + + div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1; + writel (div, &uart->divisor); + return; +} + +int serial_init (void) +{ + serial_setbrg (); + return (0); +} + +#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ + +/*----------------------------------------------------------------------- + * UART CONSOLE + *---------------------------------------------------------------------*/ +void serial_putc (char c) +{ + if (c == '\n') + serial_putc ('\r'); + while ((readl (&uart->status) & NIOS_UART_TRDY) == 0) + WATCHDOG_RESET (); + writel ((unsigned char)c, &uart->txdata); +} + +void serial_puts (const char *s) +{ + while (*s != 0) { + serial_putc (*s++); + } +} + +int serial_tstc (void) +{ + return (readl (&uart->status) & NIOS_UART_RRDY); +} + +int serial_getc (void) +{ + while (serial_tstc () == 0) + WATCHDOG_RESET (); + return (readl (&uart->rxdata) & 0x00ff ); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/arm_dcc.c b/roms/u-boot-sam460ex/drivers/serial/arm_dcc.c new file mode 100644 index 000000000..7b5ecb513 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/arm_dcc.c @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2004-2007 ARM Limited. + * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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 + * + * As a special exception, if other files instantiate templates or use macros + * or inline functions from this file, or you compile this file and link it + * with other works to produce a work based on this file, this file does not + * by itself cause the resulting work to be covered by the GNU General Public + * License. However the source code for this file must still be made available + * in accordance with section (3) of the GNU General Public License. + + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include <common.h> +#include <stdio_dev.h> + +#if defined(CONFIG_CPU_V6) +/* + * ARMV6 + */ +#define DCC_RBIT (1 << 30) +#define DCC_WBIT (1 << 29) + +#define write_dcc(x) \ + __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x)) + +#define read_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x)) + +#define status_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x)) + +#elif defined(CONFIG_CPU_XSCALE) +/* + * XSCALE + */ +#define DCC_RBIT (1 << 31) +#define DCC_WBIT (1 << 28) + +#define write_dcc(x) \ + __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x)) + +#define read_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x)) + +#define status_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x)) + +#else +#define DCC_RBIT (1 << 0) +#define DCC_WBIT (1 << 1) + +#define write_dcc(x) \ + __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x)) + +#define read_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x)) + +#define status_dcc(x) \ + __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x)) + +#endif + +#define can_read_dcc(x) do { \ + status_dcc(x); \ + x &= DCC_RBIT; \ + } while (0); + +#define can_write_dcc(x) do { \ + status_dcc(x); \ + x &= DCC_WBIT; \ + x = (x == 0); \ + } while (0); + +#define TIMEOUT_COUNT 0x4000000 + +#ifndef CONFIG_ARM_DCC_MULTI +#define arm_dcc_init serial_init +void serial_setbrg(void) {} +#define arm_dcc_getc serial_getc +#define arm_dcc_putc serial_putc +#define arm_dcc_puts serial_puts +#define arm_dcc_tstc serial_tstc +#endif + +int arm_dcc_init(void) +{ + return 0; +} + +int arm_dcc_getc(void) +{ + int ch; + register unsigned int reg; + + do { + can_read_dcc(reg); + } while (!reg); + read_dcc(ch); + + return ch; +} + +void arm_dcc_putc(char ch) +{ + register unsigned int reg; + unsigned int timeout_count = TIMEOUT_COUNT; + + while (--timeout_count) { + can_write_dcc(reg); + if (reg) + break; + } + if (timeout_count == 0) + return; + else + write_dcc(ch); +} + +void arm_dcc_puts(const char *s) +{ + while (*s) + arm_dcc_putc(*s++); +} + +int arm_dcc_tstc(void) +{ + register unsigned int reg; + + can_read_dcc(reg); + + return reg; +} + +#ifdef CONFIG_ARM_DCC_MULTI +static struct stdio_dev arm_dcc_dev; + +int drv_arm_dcc_init(void) +{ + int rc; + + /* Device initialization */ + memset(&arm_dcc_dev, 0, sizeof(arm_dcc_dev)); + + strcpy(arm_dcc_dev.name, "dcc"); + arm_dcc_dev.ext = 0; /* No extensions */ + arm_dcc_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; + arm_dcc_dev.tstc = arm_dcc_tstc; /* 'tstc' function */ + arm_dcc_dev.getc = arm_dcc_getc; /* 'getc' function */ + arm_dcc_dev.putc = arm_dcc_putc; /* 'putc' function */ + arm_dcc_dev.puts = arm_dcc_puts; /* 'puts' function */ + + return stdio_register(&arm_dcc_dev); +} +#endif diff --git a/roms/u-boot-sam460ex/drivers/serial/at91rm9200_usart.c b/roms/u-boot-sam460ex/drivers/serial/at91rm9200_usart.c new file mode 100644 index 000000000..05ebbc34c --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/at91rm9200_usart.c @@ -0,0 +1,126 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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> + +#ifndef CONFIG_AT91_LEGACY +#include <asm/io.h> +#include <asm/arch/hardware.h> +#define CONFIG_AT91_LEGACY +#include <asm/arch-at91rm9200/AT91RM9200.h> +#warning Please update to use C structur SoC access ! +#else +#include <asm/arch/AT91RM9200.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) +#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1 +#endif + +/* ggi thunder */ +#ifdef CONFIG_DBGU +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; +#endif +#ifdef CONFIG_USART0 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US0; +#endif +#ifdef CONFIG_USART1 +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US1; +#endif + +void serial_setbrg (void) +{ + int baudrate; + + if ((baudrate = gd->baudrate) <= 0) + baudrate = CONFIG_BAUDRATE; + /* MASTER_CLOCK/(16 * baudrate) */ + us->US_BRGR = (AT91C_MASTER_CLOCK >> 4) / (unsigned)baudrate; +} + +int serial_init (void) +{ + /* make any port initializations specific to this port */ +#ifdef CONFIG_DBGU + *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; /* PA 31 & 30 */ + *AT91C_PMC_PCER = 1 << AT91C_ID_SYS; /* enable clock */ +#endif +#ifdef CONFIG_USART0 + *AT91C_PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART0; /* enable clock */ +#endif +#ifdef CONFIG_USART1 + *AT91C_PIOB_PDR = AT91C_PB21_TXD1 | AT91C_PB20_RXD1; + *AT91C_PMC_PCER |= 1 << AT91C_ID_USART1; /* enable clock */ +#endif + serial_setbrg (); + + us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; + us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; + us->US_MR = + (AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | + AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT); + us->US_IMR = ~0ul; + return (0); +} + +void serial_exit (void) +{ + us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); +} + +void serial_putc (const char c) +{ + if (c == '\n') + serial_putc ('\r'); + while ((us->US_CSR & AT91C_US_TXRDY) == 0); + us->US_THR = c; +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + while ((us->US_CSR & AT91C_US_RXRDY) == 0); + return us->US_RHR; +} + +int serial_tstc (void) +{ + return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/atmel_usart.c b/roms/u-boot-sam460ex/drivers/serial/atmel_usart.c new file mode 100644 index 000000000..cad34122b --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/atmel_usart.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * 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> +#ifndef CONFIG_AT91_LEGACY +#define CONFIG_AT91_LEGACY +#warning Please update to use C structur SoC access ! +#endif +#include <watchdog.h> + +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/memory-map.h> + +#if defined(CONFIG_USART0) +# define USART_ID 0 +# define USART_BASE USART0_BASE +#elif defined(CONFIG_USART1) +# define USART_ID 1 +# define USART_BASE USART1_BASE +#elif defined(CONFIG_USART2) +# define USART_ID 2 +# define USART_BASE USART2_BASE +#elif defined(CONFIG_USART3) +# define USART_ID 3 +# define USART_BASE USART3_BASE +#endif + +#include "atmel_usart.h" + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg(void) +{ + unsigned long divisor; + unsigned long usart_hz; + + /* + * Master Clock + * Baud Rate = -------------- + * 16 * CD + */ + usart_hz = get_usart_clk_rate(USART_ID); + divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; + usart3_writel(BRGR, USART3_BF(CD, divisor)); +} + +int serial_init(void) +{ + usart3_writel(CR, USART3_BIT(RSTRX) | USART3_BIT(RSTTX)); + + serial_setbrg(); + + usart3_writel(CR, USART3_BIT(RXEN) | USART3_BIT(TXEN)); + usart3_writel(MR, (USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL) + | USART3_BF(USCLKS, USART3_USCLKS_MCK) + | USART3_BF(CHRL, USART3_CHRL_8) + | USART3_BF(PAR, USART3_PAR_NONE) + | USART3_BF(NBSTOP, USART3_NBSTOP_1))); + + return 0; +} + +void serial_putc(char c) +{ + if (c == '\n') + serial_putc('\r'); + + while (!(usart3_readl(CSR) & USART3_BIT(TXRDY))) ; + usart3_writel(THR, c); +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} + +int serial_getc(void) +{ + while (!(usart3_readl(CSR) & USART3_BIT(RXRDY))) + WATCHDOG_RESET(); + return usart3_readl(RHR); +} + +int serial_tstc(void) +{ + return (usart3_readl(CSR) & USART3_BIT(RXRDY)) != 0; +} diff --git a/roms/u-boot-sam460ex/drivers/serial/atmel_usart.h b/roms/u-boot-sam460ex/drivers/serial/atmel_usart.h new file mode 100644 index 000000000..af3773a99 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/atmel_usart.h @@ -0,0 +1,314 @@ +/* + * Register definitions for the Atmel USART3 module. + * + * Copyright (C) 2005-2006 Atmel Corporation + * + * 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 + */ +#ifndef __DRIVERS_ATMEL_USART_H__ +#define __DRIVERS_ATMEL_USART_H__ + +/* USART3 register offsets */ +#define USART3_CR 0x0000 +#define USART3_MR 0x0004 +#define USART3_IER 0x0008 +#define USART3_IDR 0x000c +#define USART3_IMR 0x0010 +#define USART3_CSR 0x0014 +#define USART3_RHR 0x0018 +#define USART3_THR 0x001c +#define USART3_BRGR 0x0020 +#define USART3_RTOR 0x0024 +#define USART3_TTGR 0x0028 +#define USART3_FIDI 0x0040 +#define USART3_NER 0x0044 +#define USART3_XXR 0x0048 +#define USART3_IFR 0x004c +#define USART3_RPR 0x0100 +#define USART3_RCR 0x0104 +#define USART3_TPR 0x0108 +#define USART3_TCR 0x010c +#define USART3_RNPR 0x0110 +#define USART3_RNCR 0x0114 +#define USART3_TNPR 0x0118 +#define USART3_TNCR 0x011c +#define USART3_PTCR 0x0120 +#define USART3_PTSR 0x0124 + +/* Bitfields in CR */ +#define USART3_RSTRX_OFFSET 2 +#define USART3_RSTRX_SIZE 1 +#define USART3_RSTTX_OFFSET 3 +#define USART3_RSTTX_SIZE 1 +#define USART3_RXEN_OFFSET 4 +#define USART3_RXEN_SIZE 1 +#define USART3_RXDIS_OFFSET 5 +#define USART3_RXDIS_SIZE 1 +#define USART3_TXEN_OFFSET 6 +#define USART3_TXEN_SIZE 1 +#define USART3_TXDIS_OFFSET 7 +#define USART3_TXDIS_SIZE 1 +#define USART3_RSTSTA_OFFSET 8 +#define USART3_RSTSTA_SIZE 1 +#define USART3_STTBRK_OFFSET 9 +#define USART3_STTBRK_SIZE 1 +#define USART3_STPBRK_OFFSET 10 +#define USART3_STPBRK_SIZE 1 +#define USART3_STTTO_OFFSET 11 +#define USART3_STTTO_SIZE 1 +#define USART3_SENDA_OFFSET 12 +#define USART3_SENDA_SIZE 1 +#define USART3_RSTIT_OFFSET 13 +#define USART3_RSTIT_SIZE 1 +#define USART3_RSTNACK_OFFSET 14 +#define USART3_RSTNACK_SIZE 1 +#define USART3_RETTO_OFFSET 15 +#define USART3_RETTO_SIZE 1 +#define USART3_DTREN_OFFSET 16 +#define USART3_DTREN_SIZE 1 +#define USART3_DTRDIS_OFFSET 17 +#define USART3_DTRDIS_SIZE 1 +#define USART3_RTSEN_OFFSET 18 +#define USART3_RTSEN_SIZE 1 +#define USART3_RTSDIS_OFFSET 19 +#define USART3_RTSDIS_SIZE 1 +#define USART3_COMM_TX_OFFSET 30 +#define USART3_COMM_TX_SIZE 1 +#define USART3_COMM_RX_OFFSET 31 +#define USART3_COMM_RX_SIZE 1 + +/* Bitfields in MR */ +#define USART3_USART_MODE_OFFSET 0 +#define USART3_USART_MODE_SIZE 4 +#define USART3_USCLKS_OFFSET 4 +#define USART3_USCLKS_SIZE 2 +#define USART3_CHRL_OFFSET 6 +#define USART3_CHRL_SIZE 2 +#define USART3_SYNC_OFFSET 8 +#define USART3_SYNC_SIZE 1 +#define USART3_PAR_OFFSET 9 +#define USART3_PAR_SIZE 3 +#define USART3_NBSTOP_OFFSET 12 +#define USART3_NBSTOP_SIZE 2 +#define USART3_CHMODE_OFFSET 14 +#define USART3_CHMODE_SIZE 2 +#define USART3_MSBF_OFFSET 16 +#define USART3_MSBF_SIZE 1 +#define USART3_MODE9_OFFSET 17 +#define USART3_MODE9_SIZE 1 +#define USART3_CLKO_OFFSET 18 +#define USART3_CLKO_SIZE 1 +#define USART3_OVER_OFFSET 19 +#define USART3_OVER_SIZE 1 +#define USART3_INACK_OFFSET 20 +#define USART3_INACK_SIZE 1 +#define USART3_DSNACK_OFFSET 21 +#define USART3_DSNACK_SIZE 1 +#define USART3_MAX_ITERATION_OFFSET 24 +#define USART3_MAX_ITERATION_SIZE 3 +#define USART3_FILTER_OFFSET 28 +#define USART3_FILTER_SIZE 1 + +/* Bitfields in CSR */ +#define USART3_RXRDY_OFFSET 0 +#define USART3_RXRDY_SIZE 1 +#define USART3_TXRDY_OFFSET 1 +#define USART3_TXRDY_SIZE 1 +#define USART3_RXBRK_OFFSET 2 +#define USART3_RXBRK_SIZE 1 +#define USART3_ENDRX_OFFSET 3 +#define USART3_ENDRX_SIZE 1 +#define USART3_ENDTX_OFFSET 4 +#define USART3_ENDTX_SIZE 1 +#define USART3_OVRE_OFFSET 5 +#define USART3_OVRE_SIZE 1 +#define USART3_FRAME_OFFSET 6 +#define USART3_FRAME_SIZE 1 +#define USART3_PARE_OFFSET 7 +#define USART3_PARE_SIZE 1 +#define USART3_TIMEOUT_OFFSET 8 +#define USART3_TIMEOUT_SIZE 1 +#define USART3_TXEMPTY_OFFSET 9 +#define USART3_TXEMPTY_SIZE 1 +#define USART3_ITERATION_OFFSET 10 +#define USART3_ITERATION_SIZE 1 +#define USART3_TXBUFE_OFFSET 11 +#define USART3_TXBUFE_SIZE 1 +#define USART3_RXBUFF_OFFSET 12 +#define USART3_RXBUFF_SIZE 1 +#define USART3_NACK_OFFSET 13 +#define USART3_NACK_SIZE 1 +#define USART3_RIIC_OFFSET 16 +#define USART3_RIIC_SIZE 1 +#define USART3_DSRIC_OFFSET 17 +#define USART3_DSRIC_SIZE 1 +#define USART3_DCDIC_OFFSET 18 +#define USART3_DCDIC_SIZE 1 +#define USART3_CTSIC_OFFSET 19 +#define USART3_CTSIC_SIZE 1 +#define USART3_RI_OFFSET 20 +#define USART3_RI_SIZE 1 +#define USART3_DSR_OFFSET 21 +#define USART3_DSR_SIZE 1 +#define USART3_DCD_OFFSET 22 +#define USART3_DCD_SIZE 1 +#define USART3_CTS_OFFSET 23 +#define USART3_CTS_SIZE 1 + +/* Bitfields in RHR */ +#define USART3_RXCHR_OFFSET 0 +#define USART3_RXCHR_SIZE 9 + +/* Bitfields in THR */ +#define USART3_TXCHR_OFFSET 0 +#define USART3_TXCHR_SIZE 9 + +/* Bitfields in BRGR */ +#define USART3_CD_OFFSET 0 +#define USART3_CD_SIZE 16 + +/* Bitfields in RTOR */ +#define USART3_TO_OFFSET 0 +#define USART3_TO_SIZE 16 + +/* Bitfields in TTGR */ +#define USART3_TG_OFFSET 0 +#define USART3_TG_SIZE 8 + +/* Bitfields in FIDI */ +#define USART3_FI_DI_RATIO_OFFSET 0 +#define USART3_FI_DI_RATIO_SIZE 11 + +/* Bitfields in NER */ +#define USART3_NB_ERRORS_OFFSET 0 +#define USART3_NB_ERRORS_SIZE 8 + +/* Bitfields in XXR */ +#define USART3_XOFF_OFFSET 0 +#define USART3_XOFF_SIZE 8 +#define USART3_XON_OFFSET 8 +#define USART3_XON_SIZE 8 + +/* Bitfields in IFR */ +#define USART3_IRDA_FILTER_OFFSET 0 +#define USART3_IRDA_FILTER_SIZE 8 + +/* Bitfields in RCR */ +#define USART3_RXCTR_OFFSET 0 +#define USART3_RXCTR_SIZE 16 + +/* Bitfields in TCR */ +#define USART3_TXCTR_OFFSET 0 +#define USART3_TXCTR_SIZE 16 + +/* Bitfields in RNCR */ +#define USART3_RXNCR_OFFSET 0 +#define USART3_RXNCR_SIZE 16 + +/* Bitfields in TNCR */ +#define USART3_TXNCR_OFFSET 0 +#define USART3_TXNCR_SIZE 16 + +/* Bitfields in PTCR */ +#define USART3_RXTEN_OFFSET 0 +#define USART3_RXTEN_SIZE 1 +#define USART3_RXTDIS_OFFSET 1 +#define USART3_RXTDIS_SIZE 1 +#define USART3_TXTEN_OFFSET 8 +#define USART3_TXTEN_SIZE 1 +#define USART3_TXTDIS_OFFSET 9 +#define USART3_TXTDIS_SIZE 1 + +/* Constants for USART_MODE */ +#define USART3_USART_MODE_NORMAL 0 +#define USART3_USART_MODE_RS485 1 +#define USART3_USART_MODE_HARDWARE 2 +#define USART3_USART_MODE_MODEM 3 +#define USART3_USART_MODE_ISO7816_T0 4 +#define USART3_USART_MODE_ISO7816_T1 6 +#define USART3_USART_MODE_IRDA 8 + +/* Constants for USCLKS */ +#define USART3_USCLKS_MCK 0 +#define USART3_USCLKS_MCK_DIV 1 +#define USART3_USCLKS_SCK 3 + +/* Constants for CHRL */ +#define USART3_CHRL_5 0 +#define USART3_CHRL_6 1 +#define USART3_CHRL_7 2 +#define USART3_CHRL_8 3 + +/* Constants for PAR */ +#define USART3_PAR_EVEN 0 +#define USART3_PAR_ODD 1 +#define USART3_PAR_SPACE 2 +#define USART3_PAR_MARK 3 +#define USART3_PAR_NONE 4 +#define USART3_PAR_MULTI 6 + +/* Constants for NBSTOP */ +#define USART3_NBSTOP_1 0 +#define USART3_NBSTOP_1_5 1 +#define USART3_NBSTOP_2 2 + +/* Constants for CHMODE */ +#define USART3_CHMODE_NORMAL 0 +#define USART3_CHMODE_ECHO 1 +#define USART3_CHMODE_LOCAL_LOOP 2 +#define USART3_CHMODE_REMOTE_LOOP 3 + +/* Constants for MSBF */ +#define USART3_MSBF_LSBF 0 +#define USART3_MSBF_MSBF 1 + +/* Constants for OVER */ +#define USART3_OVER_X16 0 +#define USART3_OVER_X8 1 + +/* Constants for CD */ +#define USART3_CD_DISABLE 0 +#define USART3_CD_BYPASS 1 + +/* Constants for TO */ +#define USART3_TO_DISABLE 0 + +/* Constants for TG */ +#define USART3_TG_DISABLE 0 + +/* Constants for FI_DI_RATIO */ +#define USART3_FI_DI_RATIO_DISABLE 0 + +/* Bit manipulation macros */ +#define USART3_BIT(name) \ + (1 << USART3_##name##_OFFSET) +#define USART3_BF(name,value) \ + (((value) & ((1 << USART3_##name##_SIZE) - 1)) \ + << USART3_##name##_OFFSET) +#define USART3_BFEXT(name,value) \ + (((value) >> USART3_##name##_OFFSET) \ + & ((1 << USART3_##name##_SIZE) - 1)) +#define USART3_BFINS(name,value,old) \ + (((old) & ~(((1 << USART3_##name##_SIZE) - 1) \ + << USART3_##name##_OFFSET)) \ + | USART3_BF(name,value)) + +/* Register access macros */ +#define usart3_readl(reg) \ + readl((void *)USART_BASE + USART3_##reg) +#define usart3_writel(reg,value) \ + writel((value), (void *)USART_BASE + USART3_##reg) + +#endif /* __DRIVERS_ATMEL_USART_H__ */ diff --git a/roms/u-boot-sam460ex/drivers/serial/mcfuart.c b/roms/u-boot-sam460ex/drivers/serial/mcfuart.c new file mode 100644 index 000000000..d93b24b89 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/mcfuart.c @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2004-2007 Freescale Semiconductor, Inc. + * TsiChung Liew, Tsi-Chung.Liew@freescale.com. + * + * 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 + * + */ + +/* + * Minimal serial functions needed to use one of the uart ports + * as serial console interface. + */ + +#include <common.h> + +#include <asm/immap.h> +#include <asm/uart.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern void uart_port_conf(int port); + +int serial_init(void) +{ + volatile uart_t *uart; + u32 counter; + + uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + + uart_port_conf(CONFIG_SYS_UART_PORT); + + /* write to SICR: SIM2 = uart mode,dcd does not affect rx */ + uart->ucr = UART_UCR_RESET_RX; + uart->ucr = UART_UCR_RESET_TX; + uart->ucr = UART_UCR_RESET_ERROR; + uart->ucr = UART_UCR_RESET_MR; + __asm__("nop"); + + uart->uimr = 0; + + /* write to CSR: RX/TX baud rate from timers */ + uart->ucsr = (UART_UCSR_RCS_SYS_CLK | UART_UCSR_TCS_SYS_CLK); + + uart->umr = (UART_UMR_BC_8 | UART_UMR_PM_NONE); + uart->umr = UART_UMR_SB_STOP_BITS_1; + + /* Setting up BaudRate */ + counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2)); + counter = counter / gd->baudrate; + + /* write to CTUR: divide counter upper byte */ + uart->ubg1 = (u8) ((counter & 0xff00) >> 8); + /* write to CTLR: divide counter lower byte */ + uart->ubg2 = (u8) (counter & 0x00ff); + + uart->ucr = (UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED); + + return (0); +} + +void serial_putc(const char c) +{ + volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + + if (c == '\n') + serial_putc('\r'); + + /* Wait for last character to go. */ + while (!(uart->usr & UART_USR_TXRDY)) ; + + uart->utb = c; +} + +void serial_puts(const char *s) +{ + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) +{ + volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + + /* Wait for a character to arrive. */ + while (!(uart->usr & UART_USR_RXRDY)) ; + return uart->urb; +} + +int serial_tstc(void) +{ + volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + + return (uart->usr & UART_USR_RXRDY); +} + +void serial_setbrg(void) +{ + volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + u32 counter; + + /* Setting up BaudRate */ + counter = (u32) ((gd->bus_clk / 32) + (gd->baudrate / 2)); + counter = counter / gd->baudrate; + + /* write to CTUR: divide counter upper byte */ + uart->ubg1 = ((counter & 0xff00) >> 8); + /* write to CTLR: divide counter lower byte */ + uart->ubg2 = (counter & 0x00ff); + + uart->ucr = UART_UCR_RESET_RX; + uart->ucr = UART_UCR_RESET_TX; + + uart->ucr = UART_UCR_RX_ENABLED | UART_UCR_TX_ENABLED; +} diff --git a/roms/u-boot-sam460ex/drivers/serial/ns16550.c b/roms/u-boot-sam460ex/drivers/serial/ns16550.c new file mode 100644 index 000000000..7e833fde5 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/ns16550.c @@ -0,0 +1,93 @@ +/* + * COM1 NS16550 support + * originally from linux source (arch/powerpc/boot/ns16550.c) + * modified to use CONFIG_SYS_ISA_MEM and new defines + */ + +#include <config.h> +#include <ns16550.h> +#include <watchdog.h> +#include <linux/types.h> +#include <asm/io.h> + +#define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */ +#define UART_MCRVAL (UART_MCR_DTR | \ + UART_MCR_RTS) /* RTS/DTR */ +#define UART_FCRVAL (UART_FCR_FIFO_EN | \ + UART_FCR_RXSR | \ + UART_FCR_TXSR) /* Clear & enable FIFOs */ +#ifdef CONFIG_SYS_NS16550_PORT_MAPPED +#define serial_out(x,y) outb(x,(ulong)y) +#define serial_in(y) inb((ulong)y) +#else +#define serial_out(x,y) writeb(x,y) +#define serial_in(y) readb(y) +#endif + +void NS16550_init (NS16550_t com_port, int baud_divisor) +{ + serial_out(0x00, &com_port->ier); +#if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2) + serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/ +#endif + serial_out(UART_LCR_BKSE | UART_LCRVAL, (ulong)&com_port->lcr); + serial_out(0, &com_port->dll); + serial_out(0, &com_port->dlm); + serial_out(UART_LCRVAL, &com_port->lcr); + serial_out(UART_MCRVAL, &com_port->mcr); + serial_out(UART_FCRVAL, &com_port->fcr); + serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); + serial_out(baud_divisor & 0xff, &com_port->dll); + serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); + serial_out(UART_LCRVAL, &com_port->lcr); +#if defined(CONFIG_OMAP) && !defined(CONFIG_OMAP3_ZOOM2) +#if defined(CONFIG_APTIX) + serial_out(3, &com_port->mdr1); /* /13 mode so Aptix 6MHz can hit 115200 */ +#else + serial_out(0, &com_port->mdr1); /* /16 is proper to hit 115200 with 48MHz */ +#endif +#endif /* CONFIG_OMAP */ +} + +#ifndef CONFIG_NS16550_MIN_FUNCTIONS +void NS16550_reinit (NS16550_t com_port, int baud_divisor) +{ + serial_out(0x00, &com_port->ier); + serial_out(UART_LCR_BKSE | UART_LCRVAL, &com_port->lcr); + serial_out(0, &com_port->dll); + serial_out(0, &com_port->dlm); + serial_out(UART_LCRVAL, &com_port->lcr); + serial_out(UART_MCRVAL, &com_port->mcr); + serial_out(UART_FCRVAL, &com_port->fcr); + serial_out(UART_LCR_BKSE, &com_port->lcr); + serial_out(baud_divisor & 0xff, &com_port->dll); + serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm); + serial_out(UART_LCRVAL, &com_port->lcr); +} +#endif /* CONFIG_NS16550_MIN_FUNCTIONS */ + +void NS16550_putc (NS16550_t com_port, char c) +{ + while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0); + serial_out(c, &com_port->thr); +} + +#ifndef CONFIG_NS16550_MIN_FUNCTIONS +char NS16550_getc (NS16550_t com_port) +{ + while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { +#ifdef CONFIG_USB_TTY + extern void usbtty_poll(void); + usbtty_poll(); +#endif + WATCHDOG_RESET(); + } + return serial_in(&com_port->rbr); +} + +int NS16550_tstc (NS16550_t com_port) +{ + return ((serial_in(&com_port->lsr) & UART_LSR_DR) != 0); +} + +#endif /* CONFIG_NS16550_MIN_FUNCTIONS */ diff --git a/roms/u-boot-sam460ex/drivers/serial/ns9750_serial.c b/roms/u-boot-sam460ex/drivers/serial/ns9750_serial.c new file mode 100644 index 000000000..e9645a053 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/ns9750_serial.c @@ -0,0 +1,210 @@ +/*********************************************************************** + * + * Copyright (C) 2004 by FS Forth-Systeme GmbH. + * All rights reserved. + * + * $Id: ns9750_serial.c,v 1.1 2004/02/16 10:37:20 mpietrek Exp $ + * @Author: Markus Pietrek + * @Descr: Serial driver for the NS9750. Only one UART is supported yet. + * @References: [1] NS9750 Hardware Reference/December 2003 + * @TODO: Implement Character GAP Timer when chip is fixed for PLL bypass + * + * 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 "ns9750_bbus.h" /* for GPIOs */ +#include "ns9750_ser.h" /* for serial configuration */ + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#error "No console index specified." +#endif + +#define CONSOLE CONFIG_CONS_INDEX + +static unsigned int calcBitrateRegister( void ); +static unsigned int calcRxCharGapRegister( void ); + +static char cCharsAvailable; /* Numbers of chars in unCharCache */ +static unsigned int unCharCache; /* unCharCache is only valid if + * cCharsAvailable > 0 */ + +/*********************************************************************** + * @Function: serial_init + * @Return: 0 + * @Descr: configures GPIOs and UART. Requires BBUS Master Reset turned off + ***********************************************************************/ + +int serial_init( void ) +{ + unsigned int aunGPIOTxD[] = { 0, 8, 40, 44 }; + unsigned int aunGPIORxD[] = { 1, 9, 41, 45 }; + + cCharsAvailable = 0; + + /* configure TxD and RxD pins for their special function */ + set_gpio_cfg_reg_val( aunGPIOTxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_OUTPUT ); + set_gpio_cfg_reg_val( aunGPIORxD[ CONSOLE ], + NS9750_GPIO_CFG_FUNC_0 | NS9750_GPIO_CFG_INPUT ); + + /* configure serial engine */ + *get_ser_reg_addr_channel( NS9750_SER_CTRL_A, CONSOLE ) = + NS9750_SER_CTRL_A_CE | + NS9750_SER_CTRL_A_STOP | + NS9750_SER_CTRL_A_WLS_8; + + serial_setbrg(); + + *get_ser_reg_addr_channel( NS9750_SER_CTRL_B, CONSOLE ) = + NS9750_SER_CTRL_B_RCGT; + + return 0; +} + +/*********************************************************************** + * @Function: serial_putc + * @Return: n/a + * @Descr: writes one character to the FIFO. Blocks until FIFO is not full + ***********************************************************************/ + +void serial_putc( const char c ) +{ + if (c == '\n') + serial_putc( '\r' ); + + while (!(*get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE) & + NS9750_SER_STAT_A_TRDY ) ) { + /* do nothing, wait for characters in FIFO sent */ + } + + *(volatile char*) get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE) = c; +} + +/*********************************************************************** + * @Function: serial_puts + * @Return: n/a + * @Descr: writes non-zero string to the FIFO. + ***********************************************************************/ + +void serial_puts( const char *s ) +{ + while (*s) { + serial_putc( *s++ ); + } +} + +/*********************************************************************** + * @Function: serial_getc + * @Return: the character read + * @Descr: performs only 8bit accesses to the FIFO. No error handling + ***********************************************************************/ + +int serial_getc( void ) +{ + int i; + + while (!serial_tstc() ) { + /* do nothing, wait for incoming characters */ + } + + /* at least one character in unCharCache */ + i = (int) (unCharCache & 0xff); + + unCharCache >>= 8; + cCharsAvailable--; + + return i; +} + +/*********************************************************************** + * @Function: serial_tstc + * @Return: 0 if no input available, otherwise != 0 + * @Descr: checks for incoming FIFO not empty. Stores the incoming chars in + * unCharCache and the numbers of characters in cCharsAvailable + ***********************************************************************/ + +int serial_tstc( void ) +{ + unsigned int unRegCache; + + if ( cCharsAvailable ) + return 1; + + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A,CONSOLE ); + if( unRegCache & NS9750_SER_STAT_A_RBC ) { + *get_ser_reg_addr_channel( NS9750_SER_STAT_A, CONSOLE ) = + NS9750_SER_STAT_A_RBC; + unRegCache = *get_ser_reg_addr_channel( NS9750_SER_STAT_A, + CONSOLE ); + } + + if ( unRegCache & NS9750_SER_STAT_A_RRDY ) { + cCharsAvailable = (unRegCache & NS9750_SER_STAT_A_RXFDB_MA)>>20; + if ( !cCharsAvailable ) + cCharsAvailable = 4; + + unCharCache = *get_ser_reg_addr_channel( NS9750_SER_FIFO, + CONSOLE ); + return 1; + } + + /* no chars available */ + return 0; +} + +void serial_setbrg( void ) +{ + *get_ser_reg_addr_channel( NS9750_SER_BITRATE, CONSOLE ) = + calcBitrateRegister(); + *get_ser_reg_addr_channel( NS9750_SER_RX_CHAR_TIMER, CONSOLE ) = + calcRxCharGapRegister(); +} + +/*********************************************************************** + * @Function: calcBitrateRegister + * @Return: value for the serial bitrate register + * @Descr: register value depends on clock frequency and baudrate + ***********************************************************************/ + +static unsigned int calcBitrateRegister( void ) +{ + return ( NS9750_SER_BITRATE_EBIT | + NS9750_SER_BITRATE_CLKMUX_BCLK | + NS9750_SER_BITRATE_TMODE | + NS9750_SER_BITRATE_TCDR_16 | + NS9750_SER_BITRATE_RCDR_16 | + ( ( ( ( CONFIG_SYS_CLK_FREQ / 8 ) / /* BBUS clock,[1] Fig. 38 */ + ( gd->baudrate * 16 ) ) - 1 ) & + NS9750_SER_BITRATE_N_MA ) ); +} + +/*********************************************************************** + * @Function: calcRxCharGapRegister + * @Return: value for the character gap timer register + * @Descr: register value depends on clock frequency and baudrate. Currently 0 + * is used as there is a bug with the gap timer in PLL bypass mode. + ***********************************************************************/ + +static unsigned int calcRxCharGapRegister( void ) +{ + return NS9750_SER_RX_CHAR_TIMER_TRUN; +} diff --git a/roms/u-boot-sam460ex/drivers/serial/opencores_yanu.c b/roms/u-boot-sam460ex/drivers/serial/opencores_yanu.c new file mode 100644 index 000000000..f3830112a --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/opencores_yanu.c @@ -0,0 +1,190 @@ +/* + * Copyright 2010, Renato Andreola <renato.andreola@imagos.it> + * + * 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 <watchdog.h> +#include <asm/io.h> +#include <nios2-yanu.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*-----------------------------------------------------------------*/ +/* YANU Imagos serial port */ +/*-----------------------------------------------------------------*/ + +static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE; + +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) + +/* Everything's already setup for fixed-baud PTF assignment*/ + +void serial_setbrg (void) +{ + int n, k; + const unsigned max_uns = 0xFFFFFFFF; + unsigned best_n, best_m, baud; + + /* compute best N and M couple */ + best_n = YANU_MAX_PRESCALER_N; + for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { + if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= + (unsigned)CONFIG_BAUDRATE) { + best_n = n; + break; + } + } + for (k = 0;; k++) { + if ((unsigned)CONFIG_BAUDRATE <= (max_uns >> (15+n-k))) + break; + } + best_m = + ((unsigned)CONFIG_BAUDRATE * (1 << (15 + n - k))) / + ((unsigned)CONFIG_SYS_CLK_FREQ >> k); + + baud = best_m + best_n * YANU_BAUDE; + writel(baud, &uart->baud); + + return; +} + +#else + +void serial_setbrg (void) +{ + int n, k; + const unsigned max_uns = 0xFFFFFFFF; + unsigned best_n, best_m, baud; + + /* compute best N and M couple */ + best_n = YANU_MAX_PRESCALER_N; + for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { + if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= + gd->baudrate) { + best_n = n; + break; + } + } + for (k = 0;; k++) { + if (gd->baudrate <= (max_uns >> (15+n-k))) + break; + } + best_m = + (gd->baudrate * (1 << (15 + n - k))) / + ((unsigned)CONFIG_SYS_CLK_FREQ >> k); + + baud = best_m + best_n * YANU_BAUDE; + writel(baud, &uart->baud); + + return; +} + + +#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ + +int serial_init (void) +{ + unsigned action,control; + + /* status register cleanup */ + action = YANU_ACTION_RRRDY | + YANU_ACTION_RTRDY | + YANU_ACTION_ROE | + YANU_ACTION_RBRK | + YANU_ACTION_RFE | + YANU_ACTION_RPE | + YANU_ACTION_RFE | YANU_ACTION_RFIFO_CLEAR | YANU_ACTION_TFIFO_CLEAR; + + writel(action, &uart->action); + + /* + * control register cleanup + * no interrupts enabled + * one stop bit + * hardware flow control disabled + * 8 bits + */ + control = (0x7 << YANU_CONTROL_BITS_POS); + /* enven parity just to be clean */ + control |= YANU_CONTROL_PAREVEN; + /* we set threshold for fifo */ + control |= YANU_CONTROL_RDYDLY * YANU_RXFIFO_DLY; + control |= YANU_CONTROL_TXTHR * YANU_TXFIFO_THR; + + writel(control, &uart->control); + + /* to set baud rate */ + serial_setbrg(); + + return (0); +} + + +/*----------------------------------------------------------------------- + * YANU CONSOLE + *---------------------------------------------------------------------*/ +void serial_putc (char c) +{ + int tx_chars; + unsigned status; + + if (c == '\n') + serial_putc ('\r'); + + while (1) { + status = readl(&uart->status); + tx_chars = (status>>YANU_TFIFO_CHARS_POS) + & ((1<<YANU_TFIFO_CHARS_N)-1); + if (tx_chars < YANU_TXFIFO_SIZE-1) + break; + WATCHDOG_RESET (); + } + + writel((unsigned char)c, &uart->data); +} + +void serial_puts (const char *s) +{ + while (*s != 0) { + serial_putc (*s++); + } +} + + +int serial_tstc(void) +{ + unsigned status ; + + status = readl(&uart->status); + return (((status >> YANU_RFIFO_CHARS_POS) & + ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0); +} + +int serial_getc (void) +{ + while (serial_tstc() == 0) + WATCHDOG_RESET (); + + /* first we pull the char */ + writel(YANU_ACTION_RFIFO_PULL, &uart->action); + + return(readl(&uart->data) & YANU_DATA_CHAR_MASK); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.c b/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.c new file mode 100644 index 000000000..aa378e1ac --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) + * Curt Brune <curt@cucy.com> + * + * (C) Copyright 2004 + * DAVE Srl + * http://www.dave-tech.it + * http://www.wawnet.biz + * mailto:info@wawnet.biz + * + * (C) Copyright 2002-2004 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 + * + * MODULE: $Id:$ + * Description: UART/Serial interface for Samsung S3C4510B SoC + * Runtime Env: ARM7TDMI + * Change History: + * 03-02-04 Create (Curt Brune) curt@cucy.com + * + */ + +#include <common.h> + +#include <asm/hardware.h> +#include "s3c4510b_uart.h" + +DECLARE_GLOBAL_DATA_PTR; + +static UART *uart; + +/* flush serial input queue. returns 0 on success or negative error + * number otherwise + */ +static int serial_flush_input(void) +{ + volatile u32 tmp; + + /* keep on reading as long as the receiver is not empty */ + while( uart->m_stat.bf.rxReady) { + tmp = uart->m_rx; + } + + return 0; +} + + +/* flush output queue. returns 0 on success or negative error number + * otherwise + */ +static int serial_flush_output(void) +{ + /* wait until the transmitter is no longer busy */ + while( !uart->m_stat.bf.txBufEmpty); + + return 0; +} + + +void serial_setbrg (void) +{ + UART_LINE_CTRL ulctrl; + UART_CTRL uctrl; + UART_BAUD_DIV ubd; + + serial_flush_output(); + serial_flush_input(); + + /* control register */ + uctrl.ui = 0x0; + uctrl.bf.rxMode = 0x1; + uctrl.bf.rxIrq = 0x0; + uctrl.bf.txMode = 0x1; + uctrl.bf.DSR = 0x0; + uctrl.bf.sendBreak = 0x0; + uctrl.bf.loopBack = 0x0; + uart->m_ctrl.ui = uctrl.ui; + + /* line control register */ + ulctrl.ui = 0x0; + ulctrl.bf.wordLen = 0x3; /* 8 bit data */ + ulctrl.bf.nStop = 0x0; /* 1 stop bit */ + ulctrl.bf.parity = 0x0; /* no parity */ + ulctrl.bf.clk = 0x0; /* internal clock */ + ulctrl.bf.infra_red = 0x0; /* no infra_red */ + uart->m_lineCtrl.ui = ulctrl.ui; + + ubd.ui = 0x0; + + /* see table on page 10-15 in SAMSUNG S3C4510B manual */ + /* get correct divisor */ + switch(gd->baudrate) { + case 1200: ubd.bf.cnt0 = 1301; break; + case 2400: ubd.bf.cnt0 = 650; break; + case 4800: ubd.bf.cnt0 = 324; break; + case 9600: ubd.bf.cnt0 = 162; break; + case 19200: ubd.bf.cnt0 = 80; break; + case 38400: ubd.bf.cnt0 = 40; break; + case 57600: ubd.bf.cnt0 = 26; break; + case 115200: ubd.bf.cnt0 = 13; break; + } + + uart->m_baudDiv.ui = ubd.ui; + uart->m_baudCnt = 0x0; + uart->m_baudClk = 0x0; + +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + +#if CONFIG_SERIAL1 == 1 + uart = (UART *)UART0_BASE; +#elif CONFIG_SERIAL1 == 2 + uart = (UART *)UART1_BASE; +#else +#error CONFIG_SERIAL1 not equal to 1 or 2 +#endif + + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + /* wait for room in the transmit FIFO */ + while( !uart->m_stat.bf.txBufEmpty); + + uart->m_tx = c; + + /* + to be polite with serial console add a line feed + to the carriage return character + */ + if (c=='\n') + serial_putc('\r'); +} + +/* + * Test if an input byte is ready from the serial port. Returns non-zero on + * success, 0 otherwise. + */ +int serial_tstc (void) +{ + return uart->m_stat.bf.rxReady; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + int rv; + + for(;;) { + rv = serial_tstc(); + + if (rv) { + return uart->m_rx & 0xFF; + } + } +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } + + /* busy wait for tx complete */ + while ( !uart->m_stat.bf.txComplete); + + /* clear break */ + uart->m_ctrl.bf.sendBreak = 0; + +} diff --git a/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.h b/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.h new file mode 100644 index 000000000..b06c76d84 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/s3c4510b_uart.h @@ -0,0 +1,109 @@ +#ifndef __UART_H +#define __UART_H + +/* + * Copyright (c) 2004 Cucy Systems (http://www.cucy.com) + * Curt Brune <curt@cucy.com> + * + * 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 + * + * Description: S3C4510B UART register layout + */ + +/* UART LINE CONTROL register */ +typedef struct __BF_UART_LINE_CTRL { + u32 wordLen: 2; + u32 nStop: 1; + u32 parity: 3; + u32 clk: 1; + u32 infra_red: 1; + u32 unused:24; +} BF_UART_LINE_CTRL; + +typedef union _UART_LINE_CTRL { + u32 ui; + BF_UART_LINE_CTRL bf; +} UART_LINE_CTRL; + +/* UART CONTROL register */ +typedef struct __BF_UART_CTRL { + u32 rxMode: 2; + u32 rxIrq: 1; + u32 txMode: 2; + u32 DSR: 1; + u32 sendBreak: 1; + u32 loopBack: 1; + u32 unused:24; +} BF_UART_CTRL; + +typedef union _UART_CTRL { + u32 ui; + BF_UART_CTRL bf; +} UART_CTRL; + +/* UART STATUS register */ +typedef struct __BF_UART_STAT { + u32 overrun: 1; + u32 parity: 1; + u32 frame: 1; + u32 breakIrq: 1; + u32 DTR: 1; + u32 rxReady: 1; + u32 txBufEmpty: 1; + u32 txComplete: 1; + u32 unused:24; +} BF_UART_STAT; + +typedef union _UART_STAT { + u32 ui; + BF_UART_STAT bf; +} UART_STAT; + +/* UART BAUD_DIV register */ +typedef struct __BF_UART_BAUD_DIV { + u32 cnt1: 4; + u32 cnt0:12; + u32 unused:16; +} BF_UART_BAUD_DIV; + +typedef union _UART_BAUD_DIV { + u32 ui; + BF_UART_BAUD_DIV bf; +} UART_BAUD_DIV; + +/* UART register block */ +typedef struct __UART { + volatile UART_LINE_CTRL m_lineCtrl; + volatile UART_CTRL m_ctrl; + volatile UART_STAT m_stat; + volatile u32 m_tx; + volatile u32 m_rx; + volatile UART_BAUD_DIV m_baudDiv; + volatile u32 m_baudCnt; + volatile u32 m_baudClk; +} UART; + +#define NL 0x0A +#define CR 0x0D +#define BSP 0x08 +#define ESC 0x1B +#define CTRLZ 0x1A +#define RUBOUT 0x7F + +#endif diff --git a/roms/u-boot-sam460ex/drivers/serial/s3c64xx.c b/roms/u-boot-sam460ex/drivers/serial/s3c64xx.c new file mode 100644 index 000000000..6d22df7cf --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/s3c64xx.c @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * (C) Copyright 2008 + * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> + * + * 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 <asm/arch/s3c6400.h> + +#ifdef CONFIG_SERIAL1 +#define UART_NR S3C64XX_UART0 + +#elif defined(CONFIG_SERIAL2) +#define UART_NR S3C64XX_UART1 + +#elif defined(CONFIG_SERIAL3) +#define UART_NR S3C64XX_UART2 + +#else +#error "Bad: you didn't configure serial ..." +#endif + +#define barrier() asm volatile("" ::: "memory") + +/* + * The coefficient, used to calculate the baudrate on S3C6400 UARTs is + * calculated as + * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT + * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1, + * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants: + */ +static const int udivslot[] = { + 0, + 0x0080, + 0x0808, + 0x0888, + 0x2222, + 0x4924, + 0x4a52, + 0x54aa, + 0x5555, + 0xd555, + 0xd5d5, + 0xddd5, + 0xdddd, + 0xdfdd, + 0xdfdf, + 0xffdf, +}; + +void serial_setbrg(void) +{ + DECLARE_GLOBAL_DATA_PTR; + s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); + u32 pclk = get_PCLK(); + u32 baudrate = gd->baudrate; + int i; + + i = (pclk / baudrate) % 16; + + uart->UBRDIV = pclk / baudrate / 16 - 1; + uart->UDIVSLOT = udivslot[i]; + + for (i = 0; i < 100; i++) + barrier(); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +int serial_init(void) +{ + s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); + + /* reset and enable FIFOs, set triggers to the maximum */ + uart->UFCON = 0xff; + uart->UMCON = 0; + /* 8N1 */ + uart->ULCON = 3; + /* No interrupts, no DMA, pure polling */ + uart->UCON = 5; + + serial_setbrg(); + + return 0; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc(void) +{ + s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); + + /* wait for character to arrive */ + while (!(uart->UTRSTAT & 0x1)); + + return uart->URXH & 0xff; +} + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet; +void disable_putc(void) +{ + be_quiet = 1; +} + +void enable_putc(void) +{ + be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void serial_putc(const char c) +{ + s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); + +#ifdef CONFIG_MODEM_SUPPORT + if (be_quiet) + return; +#endif + + /* wait for room in the tx FIFO */ + while (!(uart->UTRSTAT & 0x2)); + + uart->UTXH = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc(void) +{ + s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); + + return uart->UTRSTAT & 0x1; +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc(*s++); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial.c b/roms/u-boot-sam460ex/drivers/serial/serial.c new file mode 100644 index 000000000..1073ac0ae --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial.c @@ -0,0 +1,335 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * 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 <ns16550.h> +#ifdef CONFIG_NS87308 +#include <ns87308.h> +#endif +#ifdef CONFIG_KIRKWOOD +#include <asm/arch/kirkwood.h> +#endif +#ifdef CONFIG_ORION5X +#include <asm/arch/orion5x.h> +#endif + +#if defined (CONFIG_SERIAL_MULTI) +#include <serial.h> +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#if defined (CONFIG_SERIAL_MULTI) +/* with CONFIG_SERIAL_MULTI we might have no console + * on these devices + */ +#else +#error "No console index specified." +#endif /* CONFIG_SERIAL_MULTI */ +#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 4) +#error "Invalid console index value." +#endif + +#if CONFIG_CONS_INDEX == 1 && !defined(CONFIG_SYS_NS16550_COM1) +#error "Console port 1 defined but not configured." +#elif CONFIG_CONS_INDEX == 2 && !defined(CONFIG_SYS_NS16550_COM2) +#error "Console port 2 defined but not configured." +#elif CONFIG_CONS_INDEX == 3 && !defined(CONFIG_SYS_NS16550_COM3) +#error "Console port 3 defined but not configured." +#elif CONFIG_CONS_INDEX == 4 && !defined(CONFIG_SYS_NS16550_COM4) +#error "Console port 4 defined but not configured." +#endif + +/* Note: The port number specified in the functions is 1 based. + * the array is 0 based. + */ +static NS16550_t serial_ports[4] = { +#ifdef CONFIG_SYS_NS16550_COM1 + (NS16550_t)CONFIG_SYS_NS16550_COM1, +#else + NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM2 + (NS16550_t)CONFIG_SYS_NS16550_COM2, +#else + NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM3 + (NS16550_t)CONFIG_SYS_NS16550_COM3, +#else + NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM4 + (NS16550_t)CONFIG_SYS_NS16550_COM4 +#else + NULL +#endif +}; + +#define PORT serial_ports[port-1] +#if defined(CONFIG_CONS_INDEX) +#define CONSOLE (serial_ports[CONFIG_CONS_INDEX-1]) +#endif + +#if defined(CONFIG_SERIAL_MULTI) + +/* Multi serial device functions */ +#define DECLARE_ESERIAL_FUNCTIONS(port) \ + int eserial##port##_init (void) {\ + int clock_divisor; \ + clock_divisor = calc_divisor(serial_ports[port-1]); \ + NS16550_init(serial_ports[port-1], clock_divisor); \ + return(0);}\ + void eserial##port##_setbrg (void) {\ + serial_setbrg_dev(port);}\ + int eserial##port##_getc (void) {\ + return serial_getc_dev(port);}\ + int eserial##port##_tstc (void) {\ + return serial_tstc_dev(port);}\ + void eserial##port##_putc (const char c) {\ + serial_putc_dev(port, c);}\ + void eserial##port##_puts (const char *s) {\ + serial_puts_dev(port, s);} + +/* Serial device descriptor */ +#define INIT_ESERIAL_STRUCTURE(port,name,bus) {\ + name,\ + bus,\ + eserial##port##_init,\ + NULL,\ + eserial##port##_setbrg,\ + eserial##port##_getc,\ + eserial##port##_tstc,\ + eserial##port##_putc,\ + eserial##port##_puts, } + +#endif /* CONFIG_SERIAL_MULTI */ + +static int calc_divisor (NS16550_t port) +{ +#ifdef CONFIG_OMAP1510 + /* If can't cleanly clock 115200 set div to 1 */ + if ((CONFIG_SYS_NS16550_CLK == 12000000) && (gd->baudrate == 115200)) { + port->osc_12m_sel = OSC_12M_SEL; /* enable 6.5 * divisor */ + return (1); /* return 1 for base divisor */ + } + port->osc_12m_sel = 0; /* clear if previsouly set */ +#endif +#ifdef CONFIG_OMAP1610 + /* If can't cleanly clock 115200 set div to 1 */ + if ((CONFIG_SYS_NS16550_CLK == 48000000) && (gd->baudrate == 115200)) { + return (26); /* return 26 for base divisor */ + } +#endif + +#ifdef CONFIG_APTIX +#define MODE_X_DIV 13 +#else +#define MODE_X_DIV 16 +#endif + + /* Compute divisor value. Normally, we should simply return: + * CONFIG_SYS_NS16550_CLK) / MODE_X_DIV / gd->baudrate + * but we need to round that value by adding 0.5. + * Rounding is especially important at high baud rates. + */ + return (CONFIG_SYS_NS16550_CLK + (gd->baudrate * (MODE_X_DIV / 2))) / + (MODE_X_DIV * gd->baudrate); +} + +#if !defined(CONFIG_SERIAL_MULTI) +int serial_init (void) +{ + int clock_divisor; + +#ifdef CONFIG_NS87308 + initialise_ns87308(); +#endif + +#ifdef CONFIG_SYS_NS16550_COM1 + clock_divisor = calc_divisor(serial_ports[0]); + NS16550_init(serial_ports[0], clock_divisor); +#endif +#ifdef CONFIG_SYS_NS16550_COM2 + clock_divisor = calc_divisor(serial_ports[1]); + NS16550_init(serial_ports[1], clock_divisor); +#endif +#ifdef CONFIG_SYS_NS16550_COM3 + clock_divisor = calc_divisor(serial_ports[2]); + NS16550_init(serial_ports[2], clock_divisor); +#endif +#ifdef CONFIG_SYS_NS16550_COM4 + clock_divisor = calc_divisor(serial_ports[3]); + NS16550_init(serial_ports[3], clock_divisor); +#endif + + return (0); +} +#endif + +void +_serial_putc(const char c,const int port) +{ + if (c == '\n') + NS16550_putc(PORT, '\r'); + + NS16550_putc(PORT, c); +} + +void +_serial_putc_raw(const char c,const int port) +{ + NS16550_putc(PORT, c); +} + +void +_serial_puts (const char *s,const int port) +{ + while (*s) { + _serial_putc (*s++,port); + } +} + + +int +_serial_getc(const int port) +{ + return NS16550_getc(PORT); +} + +int +_serial_tstc(const int port) +{ + return NS16550_tstc(PORT); +} + +void +_serial_setbrg (const int port) +{ + int clock_divisor; + + clock_divisor = calc_divisor(PORT); + NS16550_reinit(PORT, clock_divisor); +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_putc_dev(unsigned int dev_index,const char c) +{ + _serial_putc(c,dev_index); +} +#else +void +serial_putc(const char c) +{ + _serial_putc(c,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_putc_raw_dev(unsigned int dev_index,const char c) +{ + _serial_putc_raw(c,dev_index); +} +#else +void +serial_putc_raw(const char c) +{ + _serial_putc_raw(c,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_puts_dev(unsigned int dev_index,const char *s) +{ + _serial_puts(s,dev_index); +} +#else +void +serial_puts(const char *s) +{ + _serial_puts(s,CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline int +serial_getc_dev(unsigned int dev_index) +{ + return _serial_getc(dev_index); +} +#else +int +serial_getc(void) +{ + return _serial_getc(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline int +serial_tstc_dev(unsigned int dev_index) +{ + return _serial_tstc(dev_index); +} +#else +int +serial_tstc(void) +{ + return _serial_tstc(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +static inline void +serial_setbrg_dev(unsigned int dev_index) +{ + _serial_setbrg(dev_index); +} +#else +void +serial_setbrg(void) +{ + _serial_setbrg(CONFIG_CONS_INDEX); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) + +DECLARE_ESERIAL_FUNCTIONS(1); +struct serial_device eserial1_device = + INIT_ESERIAL_STRUCTURE(1,"eserial0","EUART1"); +DECLARE_ESERIAL_FUNCTIONS(2); +struct serial_device eserial2_device = + INIT_ESERIAL_STRUCTURE(2,"eserial1","EUART2"); +DECLARE_ESERIAL_FUNCTIONS(3); +struct serial_device eserial3_device = + INIT_ESERIAL_STRUCTURE(3,"eserial2","EUART3"); +DECLARE_ESERIAL_FUNCTIONS(4); +struct serial_device eserial4_device = + INIT_ESERIAL_STRUCTURE(4,"eserial3","EUART4"); +#endif /* CONFIG_SERIAL_MULTI */ diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_clps7111.c b/roms/u-boot-sam460ex/drivers/serial/serial_clps7111.c new file mode 100644 index 000000000..a6aecadd1 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_clps7111.c @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2002-2004 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <clps7111.h> + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + unsigned int reg = 0; + + switch (gd->baudrate) { + case 1200: reg = 191; break; + case 9600: reg = 23; break; + case 19200: reg = 11; break; + case 38400: reg = 5; break; + case 57600: reg = 3; break; + case 115200: reg = 1; break; + default: hang (); break; + } + + /* init serial serial 1,2 */ + IO_SYSCON1 = SYSCON1_UART1EN; + IO_SYSCON2 = SYSCON2_UART2EN; + + reg |= UBRLCR_WRDLEN8; + + IO_UBRLCR1 = reg; + IO_UBRLCR2 = reg; +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + int tmo; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); + + tmo = get_timer (0) + 1 * CONFIG_SYS_HZ; + while (IO_SYSFLG1 & SYSFLG1_UTXFF) + if (get_timer (0) > tmo) + break; + + IO_UARTDR1 = c; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_tstc (void) +{ + return !(IO_SYSFLG1 & SYSFLG1_URXFE); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + while (IO_SYSFLG1 & SYSFLG1_URXFE); + + return IO_UARTDR1 & 0xff; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_imx.c b/roms/u-boot-sam460ex/drivers/serial/serial_imx.c new file mode 100644 index 000000000..b9ca748f6 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_imx.c @@ -0,0 +1,221 @@ +/* + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * 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 <asm/arch/imx-regs.h> + +#if defined CONFIG_IMX_SERIAL1 +#define UART_BASE IMX_UART1_BASE +#elif defined CONFIG_IMX_SERIAL2 +#define UART_BASE IMX_UART2_BASE +#else +#error "define CONFIG_IMX_SERIAL1, CONFIG_IMX_SERIAL2 or CONFIG_IMX_SERIAL_NONE" +#endif + +struct imx_serial { + volatile uint32_t urxd[16]; + volatile uint32_t utxd[16]; + volatile uint32_t ucr1; + volatile uint32_t ucr2; + volatile uint32_t ucr3; + volatile uint32_t ucr4; + volatile uint32_t ufcr; + volatile uint32_t usr1; + volatile uint32_t usr2; + volatile uint32_t uesc; + volatile uint32_t utim; + volatile uint32_t ubir; + volatile uint32_t ubmr; + volatile uint32_t ubrc; + volatile uint32_t bipr[4]; + volatile uint32_t bmpr[4]; + volatile uint32_t uts; +}; + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + serial_init(); +} + +extern void imx_gpio_mode(int gpio_mode); + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + unsigned int ufcr_rfdiv; + unsigned int refclk; + +#ifdef CONFIG_IMX_SERIAL1 + imx_gpio_mode(PC11_PF_UART1_TXD); + imx_gpio_mode(PC12_PF_UART1_RXD); +#else + imx_gpio_mode(PB30_PF_UART2_TXD); + imx_gpio_mode(PB31_PF_UART2_RXD); +#endif + + /* Disable UART */ + base->ucr1 &= ~UCR1_UARTEN; + + /* Set to default POR state */ + + base->ucr1 = 0x00000004; + base->ucr2 = 0x00000000; + base->ucr3 = 0x00000000; + base->ucr4 = 0x00008040; + base->uesc = 0x0000002B; + base->utim = 0x00000000; + base->ubir = 0x00000000; + base->ubmr = 0x00000000; + base->uts = 0x00000000; + /* Set clocks */ + base->ucr4 |= UCR4_REF16; + + /* Configure FIFOs */ + base->ufcr = 0xa81; + + /* set the baud rate. + * + * baud * 16 x + * --------- = - + * refclk y + * + * x - 1 = UBIR + * y - 1 = UBMR + * + * each register is 16 bits wide. refclk max is 96 MHz + * + */ + + ufcr_rfdiv = ((base->ufcr) & UFCR_RFDIV) >> 7; + if (ufcr_rfdiv == 6) + ufcr_rfdiv = 7; + else + ufcr_rfdiv = 6 - ufcr_rfdiv; + + refclk = get_PERCLK1(); + refclk /= ufcr_rfdiv; + + /* Set the numerator value minus one of the BRM ratio */ + base->ubir = (gd->baudrate / 100) - 1; + + /* Set the denominator value minus one of the BRM ratio */ + base->ubmr = (refclk/(16 * 100)) - 1; + + /* Set to 8N1 */ + base->ucr2 &= ~UCR2_PREN; + base->ucr2 |= UCR2_WS; + base->ucr2 &= ~UCR2_STPB; + + /* Ignore RTS */ + base->ucr2 |= UCR2_IRTS; + + /* Enable UART */ + base->ucr1 |= UCR1_UARTEN | UCR1_UARTCLKEN; + + /* Enable FIFOs */ + base->ucr2 |= UCR2_SRST | UCR2_RXEN | UCR2_TXEN; + + /* Clear status flags */ + base->usr2 |= USR2_ADET | + USR2_DTRF | + USR2_IDLE | + USR2_IRINT | + USR2_WAKE | + USR2_RTSF | + USR2_BRCD | + USR2_ORE; + + /* Clear status flags */ + base->usr1 |= USR1_PARITYERR | + USR1_RTSD | + USR1_ESCF | + USR1_FRAMERR | + USR1_AIRINT | + USR1_AWAKE; + return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is successful, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + unsigned char ch; + + while(base->uts & UTS_RXEMPTY); + + ch = (char)base->urxd[0]; + + return ch; +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ +} +#endif + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + + /* Wait for Tx FIFO not full */ + while (base->uts & UTS_TXFULL); + + base->utxd[0] = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ + volatile struct imx_serial* base = (struct imx_serial *)UART_BASE; + + /* If receive fifo is empty, return false */ + if (base->uts & UTS_RXEMPTY) + return 0; + return 1; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_ixp.c b/roms/u-boot-sam460ex/drivers/serial/serial_ixp.c new file mode 100644 index 000000000..dd26af49b --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_ixp.c @@ -0,0 +1,125 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <asm/arch/ixp425.h> + +/* + * 14.7456 MHz + * Baud Rate = -------------- + * 16 x Divisor + */ +#define SERIAL_CLOCK 921600 + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + unsigned int quot = 0; + int uart = CONFIG_SYS_IXP425_CONSOLE; + + if ((gd->baudrate <= SERIAL_CLOCK) && (SERIAL_CLOCK % gd->baudrate == 0)) + quot = SERIAL_CLOCK / gd->baudrate; + else + hang (); + + IER(uart) = 0; /* Disable for now */ + FCR(uart) = 0; /* No fifos enabled */ + + /* set baud rate */ + LCR(uart) = LCR_WLS0 | LCR_WLS1 | LCR_DLAB; + DLL(uart) = quot & 0xff; + DLH(uart) = quot >> 8; + LCR(uart) = LCR_WLS0 | LCR_WLS1; +#ifdef CONFIG_SERIAL_RTS_ACTIVE + MCR(uart) = MCR_RTS; /* set RTS active */ +#else + MCR(uart) = 0; /* set RTS inactive */ +#endif + IER(uart) = IER_UUE; +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + /* wait for room in the tx FIFO on UART */ + while ((LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_TEMT) == 0); + + THR(CONFIG_SYS_IXP425_CONSOLE) = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_tstc (void) +{ + return LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + while (!(LSR(CONFIG_SYS_IXP425_CONSOLE) & LSR_DR)); + + return (char) RBR(CONFIG_SYS_IXP425_CONSOLE) & 0xff; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_ks8695.c b/roms/u-boot-sam460ex/drivers/serial/serial_ks8695.c new file mode 100644 index 000000000..aacd1be63 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_ks8695.c @@ -0,0 +1,117 @@ +/* + * serial.c -- KS8695 serial driver + * + * (C) Copyright 2004, Greg Ungerer <greg.ungerer@opengear.com> + * + * 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 <asm/arch/platform.h> + +#ifndef CONFIG_SERIAL1 +#error "Bad: you didn't configure serial ..." +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Define the UART hardware register access structure. + */ +struct ks8695uart { + unsigned int RX; /* 0x00 - Receive data (r) */ + unsigned int TX; /* 0x04 - Transmit data (w) */ + unsigned int FCR; /* 0x08 - Fifo Control (r/w) */ + unsigned int LCR; /* 0x0c - Line Control (r/w) */ + unsigned int MCR; /* 0x10 - Modem Control (r/w) */ + unsigned int LSR; /* 0x14 - Line Status (r/w) */ + unsigned int MSR; /* 0x18 - Modem Status (r/w) */ + unsigned int BD; /* 0x1c - Baud Rate (r/w) */ + unsigned int SR; /* 0x20 - Status (r/w) */ +}; + +#define KS8695_UART_ADDR ((void *) (KS8695_IO_BASE + KS8695_UART_RX_BUFFER)) +#define KS8695_UART_CLK 25000000 + + +/* + * Under some circumstances we want to be "quiet" and not issue any + * serial output - though we want u-boot to otherwise work and behave + * the same. By default be noisy. + */ +int serial_console = 1; + + +void serial_setbrg(void) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + + /* Set to global baud rate and 8 data bits, no parity, 1 stop bit*/ + uartp->BD = KS8695_UART_CLK / gd->baudrate; + uartp->LCR = KS8695_UART_LINEC_WLEN8; +} + +int serial_init(void) +{ + serial_console = 1; + serial_setbrg(); + return 0; +} + +void serial_raw_putc(const char c) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + int i; + + for (i = 0; (i < 0x100000); i++) { + if (uartp->LSR & KS8695_UART_LINES_TXFE) + break; + } + + uartp->TX = c; +} + +void serial_putc(const char c) +{ + if (serial_console) { + serial_raw_putc(c); + if (c == '\n') + serial_raw_putc('\r'); + } +} + +int serial_tstc(void) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + if (serial_console) + return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0); + return 0; +} + +void serial_puts(const char *s) +{ + char c; + while ((c = *s++) != 0) + serial_putc(c); +} + +int serial_getc(void) +{ + volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + + while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0) + ; + return (uartp->RX); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_lh7a40x.c b/roms/u-boot-sam460ex/drivers/serial/serial_lh7a40x.c new file mode 100644 index 000000000..4767489ae --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_lh7a40x.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * 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 <lh7a40x.h> + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_CONSOLE_UART1) +# define UART_CONSOLE 1 +#elif defined(CONFIG_CONSOLE_UART2) +# define UART_CONSOLE 2 +#elif defined(CONFIG_CONSOLE_UART3) +# define UART_CONSOLE 3 +#else +# error "No console configured ... " +#endif + +void serial_setbrg (void) +{ + lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); + int i; + unsigned int reg = 0; + + /* + * userguide 15.1.2.4 + * + * BAUDDIV is (UART_REF_FREQ/(16 X BAUD))-1 + * + * UART_REF_FREQ = external system clock input / 2 (Hz) + * BAUD is desired baudrate (bits/s) + * + * NOTE: we add (divisor/2) to numerator to round for + * more precision + */ + reg = (((get_PLLCLK()/2) + ((16*gd->baudrate)/2)) / (16 * gd->baudrate)) - 1; + uart->brcon = reg; + + for (i = 0; i < 100; i++); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); + + /* UART must be enabled before writing to any config registers */ + uart->con |= (UART_EN); + +#ifdef CONFIG_CONSOLE_UART1 + /* infrared disabled */ + uart->con |= UART_SIRD; +#endif + /* loopback disabled */ + uart->con &= ~(UART_LBE); + + /* modem lines and tx/rx polarities */ + uart->con &= ~(UART_MXP | UART_TXP | UART_RXP); + + /* FIFO enable, N81 */ + uart->fcon = (UART_WLEN_8 | UART_FEN | UART_STP2_1); + + /* set baudrate */ + serial_setbrg (); + + /* enable rx interrupt */ + uart->inten |= UART_RI; + + return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); + + /* wait for character to arrive */ + while (uart->status & UART_RXFE); + + return(uart->data & 0xff); +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ + switch(on) { + case 0: + default: + break; /* return current */ + case 1: + hwflow = 1; /* turn on */ + break; + case -1: + hwflow = 0; /* turn off */ + break; + } + return hwflow; +} +#endif + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet = 0; +void disable_putc(void) +{ + be_quiet = 1; +} + +void enable_putc(void) +{ + be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); + +#ifdef CONFIG_MODEM_SUPPORT + if (be_quiet) + return; +#endif + + /* wait for room in the tx FIFO */ + while (!(uart->status & UART_TXFE)); + +#ifdef CONFIG_HWFLOW + /* Wait for CTS up */ + while(hwflow && !(uart->status & UART_CTS)); +#endif + + uart->data = c; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ + lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE); + + return(!(uart->status & UART_RXFE)); +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_lpc2292.c b/roms/u-boot-sam460ex/drivers/serial/serial_lpc2292.c new file mode 100644 index 000000000..e3a60b6cb --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_lpc2292.c @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2002-2004 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <asm/arch/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + unsigned short divisor = 0; + + switch (gd->baudrate) { + case 1200: divisor = 3072; break; + case 9600: divisor = 384; break; + case 19200: divisor = 192; break; + case 38400: divisor = 96; break; + case 57600: divisor = 64; break; + case 115200: divisor = 32; break; + default: hang (); break; + } + + /* init serial UART0 */ + PUT8(U0LCR, 0); + PUT8(U0IER, 0); + PUT8(U0LCR, 0x80); /* DLAB=1 */ + PUT8(U0DLL, (unsigned char)(divisor & 0x00FF)); + PUT8(U0DLM, (unsigned char)(divisor >> 8)); + PUT8(U0LCR, 0x03); /* 8N1, DLAB=0 */ + PUT8(U0FCR, 1); /* Enable RX and TX FIFOs */ +} + +int serial_init (void) +{ + unsigned long pinsel0; + + serial_setbrg (); + + pinsel0 = GET32(PINSEL0); + pinsel0 &= ~(0x00000003); + pinsel0 |= 5; + PUT32(PINSEL0, pinsel0); + + return (0); +} + +void serial_putc (const char c) +{ + if (c == '\n') + { + while((GET8(U0LSR) & (1<<5)) == 0); /* Wait for empty U0THR */ + PUT8(U0THR, '\r'); + } + + while((GET8(U0LSR) & (1<<5)) == 0); /* Wait for empty U0THR */ + PUT8(U0THR, c); +} + +int serial_getc (void) +{ + while((GET8(U0LSR) & 1) == 0); + return GET8(U0RBR); +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +/* Test if there is a byte to read */ +int serial_tstc (void) +{ + return (GET8(U0LSR) & 1); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_max3100.c b/roms/u-boot-sam460ex/drivers/serial/serial_max3100.c new file mode 100644 index 000000000..4abc27109 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_max3100.c @@ -0,0 +1,298 @@ +/* + * (C) Copyright 2003 + * + * Pantelis Antoniou <panto@intracom.gr> + * Intracom S.A. + * + * 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 <watchdog.h> + +DECLARE_GLOBAL_DATA_PTR; + +/**************************************************************/ + +/* convienient macros */ +#define MAX3100_SPI_RXD() (MAX3100_SPI_RXD_PORT & MAX3100_SPI_RXD_BIT) + +#define MAX3100_SPI_TXD(x) \ + do { \ + if (x) \ + MAX3100_SPI_TXD_PORT |= MAX3100_SPI_TXD_BIT; \ + else \ + MAX3100_SPI_TXD_PORT &= ~MAX3100_SPI_TXD_BIT; \ + } while(0) + +#define MAX3100_SPI_CLK(x) \ + do { \ + if (x) \ + MAX3100_SPI_CLK_PORT |= MAX3100_SPI_CLK_BIT; \ + else \ + MAX3100_SPI_CLK_PORT &= ~MAX3100_SPI_CLK_BIT; \ + } while(0) + +#define MAX3100_SPI_CLK_TOGGLE() (MAX3100_SPI_CLK_PORT ^= MAX3100_SPI_CLK_BIT) + +#define MAX3100_CS(x) \ + do { \ + if (x) \ + MAX3100_CS_PORT |= MAX3100_CS_BIT; \ + else \ + MAX3100_CS_PORT &= ~MAX3100_CS_BIT; \ + } while(0) + +/**************************************************************/ + +/* MAX3100 definitions */ + +#define MAX3100_WC (3 << 14) /* write configuration */ +#define MAX3100_RC (1 << 14) /* read configuration */ +#define MAX3100_WD (2 << 14) /* write data */ +#define MAX3100_RD (0 << 14) /* read data */ + +/* configuration register bits */ +#define MAX3100_FEN (1 << 13) /* FIFO enable */ +#define MAX3100_SHDN (1 << 12) /* shutdown bit */ +#define MAX3100_TM (1 << 11) /* T bit irq mask */ +#define MAX3100_RM (1 << 10) /* R bit irq mask */ +#define MAX3100_PM (1 << 9) /* P bit irq mask */ +#define MAX3100_RAM (1 << 8) /* mask for RA/FE bit */ +#define MAX3100_IR (1 << 7) /* IRDA timing mode */ +#define MAX3100_ST (1 << 6) /* transmit stop bit */ +#define MAX3100_PE (1 << 5) /* parity enable bit */ +#define MAX3100_L (1 << 4) /* Length bit */ +#define MAX3100_B_MASK (0x000F) /* baud rate bits mask */ +#define MAX3100_B(x) ((x) & 0x000F) /* baud rate select bits */ + +/* data register bits (write) */ +#define MAX3100_TE (1 << 10) /* transmit enable bit (active low) */ +#define MAX3100_RTS (1 << 9) /* request-to-send bit (inverted ~RTS pin) */ + +/* data register bits (read) */ +#define MAX3100_RA (1 << 10) /* receiver activity when in shutdown mode */ +#define MAX3100_FE (1 << 10) /* framing error when in normal mode */ +#define MAX3100_CTS (1 << 9) /* clear-to-send bit (inverted ~CTS pin) */ + +/* data register bits (both directions) */ +#define MAX3100_R (1 << 15) /* receive bit */ +#define MAX3100_T (1 << 14) /* transmit bit */ +#define MAX3100_P (1 << 8) /* parity bit */ +#define MAX3100_D_MASK 0x00FF /* data bits mask */ +#define MAX3100_D(x) ((x) & 0x00FF) /* data bits */ + +/* these definitions are valid only for fOSC = 3.6864MHz */ +#define MAX3100_B_230400 MAX3100_B(0) +#define MAX3100_B_115200 MAX3100_B(1) +#define MAX3100_B_57600 MAX3100_B(2) +#define MAX3100_B_38400 MAX3100_B(9) +#define MAX3100_B_19200 MAX3100_B(10) +#define MAX3100_B_9600 MAX3100_B(11) +#define MAX3100_B_4800 MAX3100_B(12) +#define MAX3100_B_2400 MAX3100_B(13) +#define MAX3100_B_1200 MAX3100_B(14) +#define MAX3100_B_600 MAX3100_B(15) + +/**************************************************************/ + +static inline unsigned int max3100_transfer(unsigned int val) +{ + unsigned int rx; + int b; + + MAX3100_SPI_CLK(0); + MAX3100_CS(0); + + rx = 0; b = 16; + while (--b >= 0) { + MAX3100_SPI_TXD(val & 0x8000); + val <<= 1; + MAX3100_SPI_CLK_TOGGLE(); + udelay(1); + rx <<= 1; + if (MAX3100_SPI_RXD()) + rx |= 1; + MAX3100_SPI_CLK_TOGGLE(); + udelay(1); + } + + MAX3100_SPI_CLK(1); + MAX3100_CS(1); + + return rx; +} + +/**************************************************************/ + +/* must be power of 2 */ +#define RXFIFO_SZ 16 + +static int rxfifo_cnt; +static int rxfifo_in; +static int rxfifo_out; +static unsigned char rxfifo_buf[16]; + +static void max3100_putc(int c) +{ + unsigned int rx; + + while (((rx = max3100_transfer(MAX3100_RC)) & MAX3100_T) == 0) + WATCHDOG_RESET(); + + rx = max3100_transfer(MAX3100_WD | (c & 0xff)); + if ((rx & MAX3100_RD) != 0 && rxfifo_cnt < RXFIFO_SZ) { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + } +} + +static int max3100_getc(void) +{ + int c; + unsigned int rx; + + while (rxfifo_cnt == 0) { + rx = max3100_transfer(MAX3100_RD); + if ((rx & MAX3100_R) != 0) { + do { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + + if (rxfifo_cnt >= RXFIFO_SZ) + break; + } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0); + } + WATCHDOG_RESET(); + } + + rxfifo_cnt--; + c = rxfifo_buf[rxfifo_out++]; + rxfifo_out &= RXFIFO_SZ - 1; + return c; +} + +static int max3100_tstc(void) +{ + unsigned int rx; + + if (rxfifo_cnt > 0) + return 1; + + rx = max3100_transfer(MAX3100_RD); + if ((rx & MAX3100_R) == 0) + return 0; + + do { + rxfifo_cnt++; + rxfifo_buf[rxfifo_in++] = rx & 0xff; + rxfifo_in &= RXFIFO_SZ - 1; + + if (rxfifo_cnt >= RXFIFO_SZ) + break; + } while (((rx = max3100_transfer(MAX3100_RD)) & MAX3100_R) != 0); + + return 1; +} + +int serial_init(void) +{ + unsigned int wconf, rconf; + int i; + + wconf = 0; + + /* Set baud rate */ + switch (gd->baudrate) { + case 1200: + wconf = MAX3100_B_1200; + break; + case 2400: + wconf = MAX3100_B_2400; + break; + case 4800: + wconf = MAX3100_B_4800; + break; + case 9600: + wconf = MAX3100_B_9600; + break; + case 19200: + wconf = MAX3100_B_19200; + break; + case 38400: + wconf = MAX3100_B_38400; + break; + case 57600: + wconf = MAX3100_B_57600; + break; + default: + case 115200: + wconf = MAX3100_B_115200; + break; + case 230400: + wconf = MAX3100_B_230400; + break; + } + + /* try for 10ms, with a 100us gap */ + for (i = 0; i < 10000; i += 100) { + + max3100_transfer(MAX3100_WC | wconf); + rconf = max3100_transfer(MAX3100_RC) & 0x3fff; + + if (rconf == wconf) + break; + udelay(100); + } + + rxfifo_in = rxfifo_out = rxfifo_cnt = 0; + + return (0); +} + +void serial_putc(const char c) +{ + if (c == '\n') + max3100_putc('\r'); + + max3100_putc(c); +} + +void serial_puts(const char *s) +{ + while (*s) + serial_putc (*s++); +} + +int serial_getc(void) +{ + return max3100_getc(); +} + +int serial_tstc(void) +{ + return max3100_tstc(); +} + +/* XXX WTF? */ +void serial_setbrg(void) +{ +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_mxc.c b/roms/u-boot-sam460ex/drivers/serial/serial_mxc.c new file mode 100644 index 000000000..4b93e7b97 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_mxc.c @@ -0,0 +1,253 @@ +/* + * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de> + * + * 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> +#ifdef CONFIG_MX31 +#include <asm/arch/mx31.h> +#else +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#endif + +#define __REG(x) (*((volatile u32 *)(x))) + +#if defined(CONFIG_SYS_MX31_UART1) || defined(CONFIG_SYS_MX25_UART1) +#define UART_PHYS 0x43f90000 +#elif defined(CONFIG_SYS_MX31_UART2) || defined(CONFIG_SYS_MX25_UART2) +#define UART_PHYS 0x43f94000 +#elif defined(CONFIG_SYS_MX31_UART3) || defined(CONFIG_SYS_MX25_UART3) +#define UART_PHYS 0x5000c000 +#elif defined(CONFIG_SYS_MX31_UART4) || defined(CONFIG_SYS_MX25_UART4) +#define UART_PHYS 0x43fb0000 +#elif defined(CONFIG_SYS_MX31_UART5) || defined(CONFIG_SYS_MX25_UART5) +#define UART_PHYS 0x43fb4000 +#elif defined(CONFIG_SYS_MX27_UART1) +#define UART_PHYS 0x1000a000 +#elif defined(CONFIG_SYS_MX27_UART2) +#define UART_PHYS 0x1000b000 +#elif defined(CONFIG_SYS_MX27_UART3) +#define UART_PHYS 0x1000c000 +#elif defined(CONFIG_SYS_MX27_UART4) +#define UART_PHYS 0x1000d000 +#elif defined(CONFIG_SYS_MX27_UART5) +#define UART_PHYS 0x1001b000 +#elif defined(CONFIG_SYS_MX27_UART6) +#define UART_PHYS 0x1001c000 +#elif defined(CONFIG_SYS_MX51_UART1) +#define UART_PHYS UART1_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART2) +#define UART_PHYS UART2_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART3) +#define UART_PHYS UART3_BASE_ADDR +#else +#error "define CONFIG_SYS_MXxx_UARTx to use the MXC UART driver" +#endif + +#ifdef CONFIG_SERIAL_MULTI +#warning "MXC driver does not support MULTI serials." +#endif + +/* Register definitions */ +#define URXD 0x0 /* Receiver Register */ +#define UTXD 0x40 /* Transmitter Register */ +#define UCR1 0x80 /* Control Register 1 */ +#define UCR2 0x84 /* Control Register 2 */ +#define UCR3 0x88 /* Control Register 3 */ +#define UCR4 0x8c /* Control Register 4 */ +#define UFCR 0x90 /* FIFO Control Register */ +#define USR1 0x94 /* Status Register 1 */ +#define USR2 0x98 /* Status Register 2 */ +#define UESC 0x9c /* Escape Character Register */ +#define UTIM 0xa0 /* Escape Timer Register */ +#define UBIR 0xa4 /* BRM Incremental Register */ +#define UBMR 0xa8 /* BRM Modulator Register */ +#define UBRC 0xac /* Baud Rate Count Register */ +#define UTS 0xb4 /* UART Test Register (mx31) */ + +/* UART Control Register Bit Fields.*/ +#define URXD_CHARRDY (1<<15) +#define URXD_ERR (1<<14) +#define URXD_OVRRUN (1<<13) +#define URXD_FRMERR (1<<12) +#define URXD_BRK (1<<11) +#define URXD_PRERR (1<<10) +#define URXD_RX_DATA (0xFF) +#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ +#define UCR1_ADBR (1<<14) /* Auto detect baud rate */ +#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ +#define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ +#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ +#define UCR1_IREN (1<<7) /* Infrared interface enable */ +#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ +#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ +#define UCR1_SNDBRK (1<<4) /* Send break */ +#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ +#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ +#define UCR1_DOZE (1<<1) /* Doze */ +#define UCR1_UARTEN (1<<0) /* UART enabled */ +#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ +#define UCR2_IRTS (1<<14) /* Ignore RTS pin */ +#define UCR2_CTSC (1<<13) /* CTS pin control */ +#define UCR2_CTS (1<<12) /* Clear to send */ +#define UCR2_ESCEN (1<<11) /* Escape enable */ +#define UCR2_PREN (1<<8) /* Parity enable */ +#define UCR2_PROE (1<<7) /* Parity odd/even */ +#define UCR2_STPB (1<<6) /* Stop */ +#define UCR2_WS (1<<5) /* Word size */ +#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */ +#define UCR2_TXEN (1<<2) /* Transmitter enabled */ +#define UCR2_RXEN (1<<1) /* Receiver enabled */ +#define UCR2_SRST (1<<0) /* SW reset */ +#define UCR3_DTREN (1<<13) /* DTR interrupt enable */ +#define UCR3_PARERREN (1<<12) /* Parity enable */ +#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */ +#define UCR3_DSR (1<<10) /* Data set ready */ +#define UCR3_DCD (1<<9) /* Data carrier detect */ +#define UCR3_RI (1<<8) /* Ring indicator */ +#define UCR3_TIMEOUTEN (1<<7) /* Timeout interrupt enable */ +#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */ +#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */ +#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */ +#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */ +#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */ +#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ +#define UCR3_BPEN (1<<0) /* Preset registers enable */ +#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_INVR (1<<9) /* Inverted infrared reception */ +#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ +#define UCR4_WKEN (1<<7) /* Wake interrupt enable */ +#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IRSC (1<<5) /* IR special case */ +#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ +#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ +#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */ +#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ +#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ +#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ +#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ +#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ +#define USR1_RTSS (1<<14) /* RTS pin status */ +#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */ +#define USR1_RTSD (1<<12) /* RTS delta */ +#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */ +#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */ +#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */ +#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */ +#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */ +#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */ +#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */ +#define USR2_ADET (1<<15) /* Auto baud rate detect complete */ +#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */ +#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */ +#define USR2_IDLE (1<<12) /* Idle condition */ +#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */ +#define USR2_WAKE (1<<7) /* Wake */ +#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */ +#define USR2_TXDC (1<<3) /* Transmitter complete */ +#define USR2_BRCD (1<<2) /* Break condition */ +#define USR2_ORE (1<<1) /* Overrun error */ +#define USR2_RDR (1<<0) /* Recv data ready */ +#define UTS_FRCPERR (1<<13) /* Force parity error */ +#define UTS_LOOP (1<<12) /* Loop tx and rx */ +#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ +#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ +#define UTS_TXFULL (1<<4) /* TxFIFO full */ +#define UTS_RXFULL (1<<3) /* RxFIFO full */ +#define UTS_SOFTRST (1<<0) /* Software reset */ + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + u32 clk = imx_get_uartclk(); + + if (!gd->baudrate) + gd->baudrate = CONFIG_BAUDRATE; + + __REG(UART_PHYS + UFCR) = 4 << 7; /* divide input clock by 2 */ + __REG(UART_PHYS + UBIR) = 0xf; + __REG(UART_PHYS + UBMR) = clk / (2 * gd->baudrate); + +} + +int serial_getc (void) +{ + while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY); + return (__REG(UART_PHYS + URXD) & URXD_RX_DATA); /* mask out status from upper word */ +} + +void serial_putc (const char c) +{ + __REG(UART_PHYS + UTXD) = c; + + /* wait for transmitter to be ready */ + while(!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)); + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ + /* If receive fifo is empty, return false */ + if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) + return 0; + return 1; +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + __REG(UART_PHYS + UCR1) = 0x0; + __REG(UART_PHYS + UCR2) = 0x0; + + while (!(__REG(UART_PHYS + UCR2) & UCR2_SRST)); + + __REG(UART_PHYS + UCR3) = 0x0704; + __REG(UART_PHYS + UCR4) = 0x8000; + __REG(UART_PHYS + UESC) = 0x002b; + __REG(UART_PHYS + UTIM) = 0x0; + + __REG(UART_PHYS + UTS) = 0x0; + + serial_setbrg(); + + __REG(UART_PHYS + UCR2) = UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST; + + __REG(UART_PHYS + UCR1) = UCR1_UARTEN; + + return 0; +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_netarm.c b/roms/u-boot-sam460ex/drivers/serial/serial_netarm.c new file mode 100644 index 000000000..2eb539340 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_netarm.c @@ -0,0 +1,195 @@ +/* + * Serial Port stuff - taken from Linux + * + * (C) Copyright 2002 + * MAZeT GmbH <www.mazet.de> + * Stephan Linz <linz@mazet.de>, <linz@li-pro.net> + * + * (c) 2004 + * IMMS gGmbH <www.imms.de> + * Thomas Elste <info@elste.org> + * + * 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 <asm/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define PORTA (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTA)) +#if !defined(CONFIG_NETARM_NS7520) +#define PORTB (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTB)) +#else +#define PORTC (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTC)) +#endif + +/* wait until transmitter is ready for another character */ +#define TXWAITRDY(registers) \ +{ \ + ulong tmo = get_timer(0) + 1 * CONFIG_SYS_HZ; \ + while (((registers)->status_a & NETARM_SER_STATA_TX_RDY) == 0 ) { \ + if (get_timer(0) > tmo) \ + break; \ + } \ +} + + +#ifndef CONFIG_UART1_CONSOLE +volatile netarm_serial_channel_t *serial_reg_ch1 = get_serial_channel(0); +volatile netarm_serial_channel_t *serial_reg_ch2 = get_serial_channel(1); +#else +volatile netarm_serial_channel_t *serial_reg_ch1 = get_serial_channel(1); +volatile netarm_serial_channel_t *serial_reg_ch2 = get_serial_channel(0); +#endif + +extern void _netarm_led_FAIL1(void); + +/* + * Setup both serial i/f with given baudrate + */ +void serial_setbrg (void) +{ + /* set 0 ... make sure pins are configured for serial */ +#if !defined(CONFIG_NETARM_NS7520) + PORTA = PORTB = + NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0); +#else + PORTA = NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0); + PORTC = NETARM_GEN_PORT_CSF (0xef) | NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0); +#endif + + /* first turn em off */ + serial_reg_ch1->ctrl_a = serial_reg_ch2->ctrl_a = 0; + + /* clear match register, we don't need it */ + serial_reg_ch1->rx_match = serial_reg_ch2->rx_match = 0; + + /* setup bit rate generator and rx buffer gap timer (1 byte only) */ + if ((gd->baudrate >= MIN_BAUD_RATE) + && (gd->baudrate <= MAX_BAUD_RATE)) { + serial_reg_ch1->bitrate = serial_reg_ch2->bitrate = + NETARM_SER_BR_X16 (gd->baudrate); + serial_reg_ch1->rx_buf_timer = serial_reg_ch2->rx_buf_timer = + 0; + serial_reg_ch1->rx_char_timer = serial_reg_ch2->rx_char_timer = + NETARM_SER_RXGAP (gd->baudrate); + } else { + hang (); + } + + /* setup port mode */ + serial_reg_ch1->ctrl_b = serial_reg_ch2->ctrl_b = + ( NETARM_SER_CTLB_RCGT_EN | + NETARM_SER_CTLB_UART_MODE); + serial_reg_ch1->ctrl_a = serial_reg_ch2->ctrl_a = + ( NETARM_SER_CTLA_ENABLE | + NETARM_SER_CTLA_P_NONE | + /* see errata */ + NETARM_SER_CTLA_2STOP | + NETARM_SER_CTLA_8BITS | + NETARM_SER_CTLA_DTR_EN | + NETARM_SER_CTLA_RTS_EN); +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +int serial_init (void) +{ + serial_setbrg (); + return 0; +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + volatile unsigned char *fifo; + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); + + fifo = (volatile unsigned char *) &(serial_reg_ch1->fifo); + TXWAITRDY (serial_reg_ch1); + *fifo = c; +} + +/* + * Test of a single byte from the serial port. Returns 1 on success, 0 + * otherwise. + */ +int serial_tstc(void) +{ + return serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. + */ +int serial_getc (void) +{ + unsigned int ch_uint; + volatile unsigned int *fifo; + volatile unsigned char *fifo_char = NULL; + int buf_count = 0; + + while (!(serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY)) + /* NOP */ ; + + fifo = (volatile unsigned int *) &(serial_reg_ch1->fifo); + fifo_char = (unsigned char *) &ch_uint; + ch_uint = *fifo; + + buf_count = NETARM_SER_STATA_RXFDB (serial_reg_ch1->status_a); + switch (buf_count) { + case NETARM_SER_STATA_RXFDB_4BYTES: + buf_count = 4; + break; + case NETARM_SER_STATA_RXFDB_3BYTES: + buf_count = 3; + break; + case NETARM_SER_STATA_RXFDB_2BYTES: + buf_count = 2; + break; + case NETARM_SER_STATA_RXFDB_1BYTES: + buf_count = 1; + break; + default: + /* panic, be never here */ + break; + } + + serial_reg_ch1->status_a |= NETARM_SER_STATA_RX_CLOSED; + + return ch_uint & 0xff; +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.c b/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.c new file mode 100644 index 000000000..c645cef87 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.c @@ -0,0 +1,223 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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 PL010/PL011 UARTs */ + +#include <common.h> +#include <watchdog.h> + +#include "serial_pl01x.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 + * Integrator CP has two UARTs, use the first one, at 38400-8-N-1 + * Versatile PB has four UARTs. + */ +#define CONSOLE_PORT CONFIG_CONS_INDEX +#define baudRate CONFIG_BAUDRATE +static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; +#define NUM_PORTS (sizeof(port)/sizeof(port[0])) + +static void pl01x_putc (int portnum, char c); +static int pl01x_getc (int portnum); +static int pl01x_tstc (int portnum); + +#ifdef CONFIG_PL010_SERIAL + +int serial_init (void) +{ + 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; +} + +#endif /* CONFIG_PL010_SERIAL */ + +#ifdef CONFIG_PL011_SERIAL + +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)) + */ + temp = 16 * baudRate; + divider = CONFIG_PL011_CLOCK / temp; + remainder = CONFIG_PL011_CLOCK % temp; + temp = (8 * remainder) / baudRate; + fraction = (temp >> 1) + (temp & 1); + + 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; +} + +#endif /* CONFIG_PL011_SERIAL */ + +void serial_putc (const char c) +{ + if (c == '\n') + pl01x_putc (CONSOLE_PORT, '\r'); + + pl01x_putc (CONSOLE_PORT, c); +} + +void serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + return pl01x_getc (CONSOLE_PORT); +} + +int serial_tstc (void) +{ + return pl01x_tstc (CONSOLE_PORT); +} + +void serial_setbrg (void) +{ +} + +static void pl01x_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) + WATCHDOG_RESET(); + + /* Send the character */ + IO_WRITE (port[portnum] + UART_PL01x_DR, c); +} + +static int pl01x_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) + WATCHDOG_RESET(); + + 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 pl01x_tstc (int portnum) +{ + WATCHDOG_RESET(); + return !(IO_READ (port[portnum] + UART_PL01x_FR) & + UART_PL01x_FR_RXFE); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.h b/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.h new file mode 100644 index 000000000..5f20fdd10 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_pl01x.h @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2003, 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * 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/roms/u-boot-sam460ex/drivers/serial/serial_pxa.c b/roms/u-boot-sam460ex/drivers/serial/serial_pxa.c new file mode 100644 index 000000000..b74e43957 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_pxa.c @@ -0,0 +1,388 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <watchdog.h> +#include <serial.h> +#include <asm/arch/pxa-regs.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define FFUART_INDEX 0 +#define BTUART_INDEX 1 +#define STUART_INDEX 2 + +#ifndef CONFIG_SERIAL_MULTI +#if defined (CONFIG_FFUART) +#define UART_INDEX FFUART_INDEX +#elif defined (CONFIG_BTUART) +#define UART_INDEX BTUART_INDEX +#elif defined (CONFIG_STUART) +#define UART_INDEX STUART_INDEX +#else +#error "Bad: you didn't configure serial ..." +#endif +#endif + +void pxa_setbrg_dev (unsigned int uart_index) +{ + unsigned int quot = 0; + + if (gd->baudrate == 1200) + quot = 768; + else if (gd->baudrate == 9600) + quot = 96; + else if (gd->baudrate == 19200) + quot = 48; + else if (gd->baudrate == 38400) + quot = 24; + else if (gd->baudrate == 57600) + quot = 16; + else if (gd->baudrate == 115200) + quot = 8; + else + hang (); + + switch (uart_index) { + case FFUART_INDEX: +#ifdef CONFIG_CPU_MONAHANS + CKENA |= CKENA_22_FFUART; +#else + CKEN |= CKEN6_FFUART; +#endif /* CONFIG_CPU_MONAHANS */ + + FFIER = 0; /* Disable for now */ + FFFCR = 0; /* No fifos enabled */ + + /* set baud rate */ + FFLCR = LCR_WLS0 | LCR_WLS1 | LCR_DLAB; + FFDLL = quot & 0xff; + FFDLH = quot >> 8; + FFLCR = LCR_WLS0 | LCR_WLS1; + + FFIER = IER_UUE; /* Enable FFUART */ + break; + + case BTUART_INDEX: +#ifdef CONFIG_CPU_MONAHANS + CKENA |= CKENA_21_BTUART; +#else + CKEN |= CKEN7_BTUART; +#endif /* CONFIG_CPU_MONAHANS */ + + BTIER = 0; + BTFCR = 0; + + /* set baud rate */ + BTLCR = LCR_DLAB; + BTDLL = quot & 0xff; + BTDLH = quot >> 8; + BTLCR = LCR_WLS0 | LCR_WLS1; + + BTIER = IER_UUE; /* Enable BFUART */ + + break; + + case STUART_INDEX: +#ifdef CONFIG_CPU_MONAHANS + CKENA |= CKENA_23_STUART; +#else + CKEN |= CKEN5_STUART; +#endif /* CONFIG_CPU_MONAHANS */ + + STIER = 0; + STFCR = 0; + + /* set baud rate */ + STLCR = LCR_DLAB; + STDLL = quot & 0xff; + STDLH = quot >> 8; + STLCR = LCR_WLS0 | LCR_WLS1; + + STIER = IER_UUE; /* Enable STUART */ + break; + + default: + hang(); + } +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int pxa_init_dev (unsigned int uart_index) +{ + pxa_setbrg_dev (uart_index); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void pxa_putc_dev (unsigned int uart_index,const char c) +{ + switch (uart_index) { + case FFUART_INDEX: + /* wait for room in the tx FIFO on FFUART */ + while ((FFLSR & LSR_TEMT) == 0) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + FFTHR = c; + break; + + case BTUART_INDEX: + while ((BTLSR & LSR_TEMT ) == 0 ) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + BTTHR = c; + break; + + case STUART_INDEX: + while ((STLSR & LSR_TEMT ) == 0 ) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + STTHR = c; + break; + } + + /* If \n, also do \r */ + if (c == '\n') + pxa_putc_dev (uart_index,'\r'); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int pxa_tstc_dev (unsigned int uart_index) +{ + switch (uart_index) { + case FFUART_INDEX: + return FFLSR & LSR_DR; + case BTUART_INDEX: + return BTLSR & LSR_DR; + case STUART_INDEX: + return STLSR & LSR_DR; + } + return -1; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int pxa_getc_dev (unsigned int uart_index) +{ + switch (uart_index) { + case FFUART_INDEX: + while (!(FFLSR & LSR_DR)) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + return (char) FFRBR & 0xff; + + case BTUART_INDEX: + while (!(BTLSR & LSR_DR)) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + return (char) BTRBR & 0xff; + case STUART_INDEX: + while (!(STLSR & LSR_DR)) + WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */ + return (char) STRBR & 0xff; + } + return -1; +} + +void +pxa_puts_dev (unsigned int uart_index,const char *s) +{ + while (*s) { + pxa_putc_dev (uart_index,*s++); + } +} + +#if defined (CONFIG_FFUART) +static int ffuart_init(void) +{ + return pxa_init_dev(FFUART_INDEX); +} + +static void ffuart_setbrg(void) +{ + return pxa_setbrg_dev(FFUART_INDEX); +} + +static void ffuart_putc(const char c) +{ + return pxa_putc_dev(FFUART_INDEX,c); +} + +static void ffuart_puts(const char *s) +{ + return pxa_puts_dev(FFUART_INDEX,s); +} + +static int ffuart_getc(void) +{ + return pxa_getc_dev(FFUART_INDEX); +} + +static int ffuart_tstc(void) +{ + return pxa_tstc_dev(FFUART_INDEX); +} + +struct serial_device serial_ffuart_device = +{ + "serial_ffuart", + "PXA", + ffuart_init, + NULL, + ffuart_setbrg, + ffuart_getc, + ffuart_tstc, + ffuart_putc, + ffuart_puts, +}; +#endif + +#if defined (CONFIG_BTUART) +static int btuart_init(void) +{ + return pxa_init_dev(BTUART_INDEX); +} + +static void btuart_setbrg(void) +{ + return pxa_setbrg_dev(BTUART_INDEX); +} + +static void btuart_putc(const char c) +{ + return pxa_putc_dev(BTUART_INDEX,c); +} + +static void btuart_puts(const char *s) +{ + return pxa_puts_dev(BTUART_INDEX,s); +} + +static int btuart_getc(void) +{ + return pxa_getc_dev(BTUART_INDEX); +} + +static int btuart_tstc(void) +{ + return pxa_tstc_dev(BTUART_INDEX); +} + +struct serial_device serial_btuart_device = +{ + "serial_btuart", + "PXA", + btuart_init, + NULL, + btuart_setbrg, + btuart_getc, + btuart_tstc, + btuart_putc, + btuart_puts, +}; +#endif + +#if defined (CONFIG_STUART) +static int stuart_init(void) +{ + return pxa_init_dev(STUART_INDEX); +} + +static void stuart_setbrg(void) +{ + return pxa_setbrg_dev(STUART_INDEX); +} + +static void stuart_putc(const char c) +{ + return pxa_putc_dev(STUART_INDEX,c); +} + +static void stuart_puts(const char *s) +{ + return pxa_puts_dev(STUART_INDEX,s); +} + +static int stuart_getc(void) +{ + return pxa_getc_dev(STUART_INDEX); +} + +static int stuart_tstc(void) +{ + return pxa_tstc_dev(STUART_INDEX); +} + +struct serial_device serial_stuart_device = +{ + "serial_stuart", + "PXA", + stuart_init, + NULL, + stuart_setbrg, + stuart_getc, + stuart_tstc, + stuart_putc, + stuart_puts, +}; +#endif + + +#ifndef CONFIG_SERIAL_MULTI +inline int serial_init(void) { + return (pxa_init_dev(UART_INDEX)); +} +void serial_setbrg(void) { + pxa_setbrg_dev(UART_INDEX); +} +int serial_getc(void) { + return(pxa_getc_dev(UART_INDEX)); +} +int serial_tstc(void) { + return(pxa_tstc_dev(UART_INDEX)); +} +void serial_putc(const char c) { + pxa_putc_dev(UART_INDEX,c); +} +void serial_puts(const char *s) { + pxa_puts_dev(UART_INDEX,s); +} +#endif /* CONFIG_SERIAL_MULTI */ diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_s3c24x0.c b/roms/u-boot-sam460ex/drivers/serial/serial_s3c24x0.c new file mode 100644 index 000000000..8a3e30209 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_s3c24x0.c @@ -0,0 +1,319 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * 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 <asm/arch/s3c24x0_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SERIAL1 +#define UART_NR S3C24X0_UART0 + +#elif defined(CONFIG_SERIAL2) +# if defined(CONFIG_TRAB) +# error "TRAB supports only CONFIG_SERIAL1" +# endif +#define UART_NR S3C24X0_UART1 + +#elif defined(CONFIG_SERIAL3) +# if defined(CONFIG_TRAB) +# error "TRAB supports only CONFIG_SERIAL1" +# endif +#define UART_NR S3C24X0_UART2 + +#else +#error "Bad: you didn't configure serial ..." +#endif + +#include <asm/io.h> + +#if defined(CONFIG_SERIAL_MULTI) +#include <serial.h> + +/* Multi serial device functions */ +#define DECLARE_S3C_SERIAL_FUNCTIONS(port) \ + int s3serial##port##_init(void) \ + { \ + return serial_init_dev(port); \ + } \ + void s3serial##port##_setbrg(void) \ + { \ + serial_setbrg_dev(port); \ + } \ + int s3serial##port##_getc(void) \ + { \ + return serial_getc_dev(port); \ + } \ + int s3serial##port##_tstc(void) \ + { \ + return serial_tstc_dev(port); \ + } \ + void s3serial##port##_putc(const char c) \ + { \ + serial_putc_dev(port, c); \ + } \ + void s3serial##port##_puts(const char *s) \ + { \ + serial_puts_dev(port, s); \ + } + +#define INIT_S3C_SERIAL_STRUCTURE(port, name, bus) { \ + name, \ + bus, \ + s3serial##port##_init, \ + NULL,\ + s3serial##port##_setbrg, \ + s3serial##port##_getc, \ + s3serial##port##_tstc, \ + s3serial##port##_putc, \ + s3serial##port##_puts, \ +} + +#endif /* CONFIG_SERIAL_MULTI */ + +#ifdef CONFIG_HWFLOW +static int hwflow; +#endif + +void _serial_setbrg(const int dev_index) +{ + struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); + unsigned int reg = 0; + int i; + + /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ + reg = get_PCLK() / (16 * gd->baudrate) - 1; + + writel(reg, &uart->UBRDIV); + for (i = 0; i < 100; i++) + /* Delay */ ; +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline void serial_setbrg_dev(unsigned int dev_index) +{ + _serial_setbrg(dev_index); +} +#else +void serial_setbrg(void) +{ + _serial_setbrg(UART_NR); +} +#endif + + +/* Initialise the serial port. The settings are always 8 data bits, no parity, + * 1 stop bit, no start bits. + */ +static int serial_init_dev(const int dev_index) +{ + struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); + +#ifdef CONFIG_HWFLOW + hwflow = 0; /* turned off by default */ +#endif + + /* FIFO enable, Tx/Rx FIFO clear */ + writel(0x07, &uart->UFCON); + writel(0x0, &uart->UMCON); + + /* Normal,No parity,1 stop,8 bit */ + writel(0x3, &uart->ULCON); + /* + * tx=level,rx=edge,disable timeout int.,enable rx error int., + * normal,interrupt or polling + */ + writel(0x245, &uart->UCON); + +#ifdef CONFIG_HWFLOW + writel(0x1, &uart->UMCON); /* RTS up */ +#endif + + /* FIXME: This is sooooooooooooooooooo ugly */ +#if defined(CONFIG_ARCH_GTA02_v1) || defined(CONFIG_ARCH_GTA02_v2) + /* we need auto hw flow control on the gsm and gps port */ + if (dev_index == 0 || dev_index == 1) + writel(0x10, &uart->UMCON); +#endif + _serial_setbrg(dev_index); + + return (0); +} + +#if !defined(CONFIG_SERIAL_MULTI) +/* Initialise the serial port. The settings are always 8 data bits, no parity, + * 1 stop bit, no start bits. + */ +int serial_init(void) +{ + return serial_init_dev(UART_NR); +} +#endif + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int _serial_getc(const int dev_index) +{ + struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); + + while (!(readl(&uart->UTRSTAT) & 0x1)) + /* wait for character to arrive */ ; + + return readb(&uart->URXH) & 0xff; +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline int serial_getc_dev(unsigned int dev_index) +{ + return _serial_getc(dev_index); +} +#else +int serial_getc(void) +{ + return _serial_getc(UART_NR); +} +#endif + +#ifdef CONFIG_HWFLOW +int hwflow_onoff(int on) +{ + switch (on) { + case 0: + default: + break; /* return current */ + case 1: + hwflow = 1; /* turn on */ + break; + case -1: + hwflow = 0; /* turn off */ + break; + } + return hwflow; +} +#endif + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet = 0; +void disable_putc(void) +{ + be_quiet = 1; +} + +void enable_putc(void) +{ + be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void _serial_putc(const char c, const int dev_index) +{ + struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); +#ifdef CONFIG_MODEM_SUPPORT + if (be_quiet) + return; +#endif + + while (!(readl(&uart->UTRSTAT) & 0x2)) + /* wait for room in the tx FIFO */ ; + +#ifdef CONFIG_HWFLOW + while (hwflow && !(readl(&uart->UMSTAT) & 0x1)) + /* Wait for CTS up */ ; +#endif + + writeb(c, &uart->UTXH); + + /* If \n, also do \r */ + if (c == '\n') + serial_putc('\r'); +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline void serial_putc_dev(unsigned int dev_index, const char c) +{ + _serial_putc(c, dev_index); +} +#else +void serial_putc(const char c) +{ + _serial_putc(c, UART_NR); +} +#endif + + +/* + * Test whether a character is in the RX buffer + */ +int _serial_tstc(const int dev_index) +{ + struct s3c24x0_uart *uart = s3c24x0_get_base_uart(dev_index); + + return readl(&uart->UTRSTAT) & 0x1; +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline int serial_tstc_dev(unsigned int dev_index) +{ + return _serial_tstc(dev_index); +} +#else +int serial_tstc(void) +{ + return _serial_tstc(UART_NR); +} +#endif + +void _serial_puts(const char *s, const int dev_index) +{ + while (*s) { + _serial_putc(*s++, dev_index); + } +} + +#if defined(CONFIG_SERIAL_MULTI) +static inline void serial_puts_dev(int dev_index, const char *s) +{ + _serial_puts(s, dev_index); +} +#else +void serial_puts(const char *s) +{ + _serial_puts(s, UART_NR); +} +#endif + +#if defined(CONFIG_SERIAL_MULTI) +DECLARE_S3C_SERIAL_FUNCTIONS(0); +struct serial_device s3c24xx_serial0_device = +INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0", "S3UART1"); +DECLARE_S3C_SERIAL_FUNCTIONS(1); +struct serial_device s3c24xx_serial1_device = +INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1", "S3UART2"); +DECLARE_S3C_SERIAL_FUNCTIONS(2); +struct serial_device s3c24xx_serial2_device = +INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2", "S3UART3"); +#endif /* CONFIG_SERIAL_MULTI */ diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_s3c44b0.c b/roms/u-boot-sam460ex/drivers/serial/serial_s3c44b0.c new file mode 100644 index 000000000..95d0266c6 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_s3c44b0.c @@ -0,0 +1,218 @@ +/* + * (C) Copyright 2004 + * DAVE Srl + * http://www.dave-tech.it + * http://www.wawnet.biz + * mailto:info@wawnet.biz + * + * (C) Copyright 2002-2004 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <asm/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* flush serial input queue. returns 0 on success or negative error + * number otherwise + */ +static int serial_flush_input(void) +{ + volatile u32 tmp; + + /* keep on reading as long as the receiver is not empty */ + while(UTRSTAT0&0x01) { + tmp = REGB(URXH0); + } + + return 0; +} + + +/* flush output queue. returns 0 on success or negative error number + * otherwise + */ +static int serial_flush_output(void) +{ + /* wait until the transmitter is no longer busy */ + while(!(UTRSTAT0 & 0x02)) { + } + + return 0; +} + + +void serial_setbrg (void) +{ + u32 divisor = 0; + + /* get correct divisor */ + switch(gd->baudrate) { + + case 1200: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 3124; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 3905; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif + break; + + case 9600: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 390; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 487; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif + break; + + case 19200: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 194; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 243; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif + break; + + case 38400: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 97; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 121; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif /* break; */ + + case 57600: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 64; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 80; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif /* break; */ + + case 115200: +#if CONFIG_S3C44B0_CLOCK_SPEED==66 + divisor = 32; +#elif CONFIG_S3C44B0_CLOCK_SPEED==75 + divisor = 40; +#else +# error CONFIG_S3C44B0_CLOCK_SPEED undefined +#endif /* break; */ + } + + serial_flush_output(); + serial_flush_input(); + UFCON0 = 0x0; + ULCON0 = 0x03; + UCON0 = 0x05; + UBRDIV0 = divisor; + + UFCON1 = 0x0; + ULCON1 = 0x03; + UCON1 = 0x05; + UBRDIV1 = divisor; + + for(divisor=0; divisor<100; divisor++) { + /* NOP */ + } +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ + /* wait for room in the transmit FIFO */ + while(!(UTRSTAT0 & 0x02)); + + UTXH0 = (unsigned char)c; + + /* + to be polite with serial console add a line feed + to the carriage return character + */ + if (c=='\n') + serial_putc('\r'); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_tstc (void) +{ + return (UTRSTAT0 & 0x01); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ + int rv; + + for(;;) { + rv = serial_tstc(); + + if(rv > 0) + return URXH0; + } +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_s5p.c b/roms/u-boot-sam460ex/drivers/serial/serial_s5p.c new file mode 100644 index 000000000..9747db372 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_s5p.c @@ -0,0 +1,206 @@ +/* + * (C) Copyright 2009 SAMSUNG Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * Heungjun Kim <riverful.kim@samsung.com> + * + * based on drivers/serial/s3c64xx.c + * + * 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 <asm/io.h> +#include <asm/arch/uart.h> +#include <asm/arch/clk.h> +#include <serial.h> + +static inline struct s5p_uart *s5p_get_base_uart(int dev_index) +{ + u32 offset = dev_index * sizeof(struct s5p_uart); + + if (cpu_is_s5pc100()) + return (struct s5p_uart *)(S5PC100_UART_BASE + offset); + else + return (struct s5p_uart *)(S5PC110_UART_BASE + offset); +} + +/* + * The coefficient, used to calculate the baudrate on S5P UARTs is + * calculated as + * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT + * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1, + * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants: + */ +static const int udivslot[] = { + 0, + 0x0080, + 0x0808, + 0x0888, + 0x2222, + 0x4924, + 0x4a52, + 0x54aa, + 0x5555, + 0xd555, + 0xd5d5, + 0xddd5, + 0xdddd, + 0xdfdd, + 0xdfdf, + 0xffdf, +}; + +void serial_setbrg_dev(const int dev_index) +{ + DECLARE_GLOBAL_DATA_PTR; + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + u32 pclk = get_pclk(); + u32 baudrate = gd->baudrate; + u32 val; + + val = pclk / baudrate; + + writel(val / 16 - 1, &uart->ubrdiv); + writew(udivslot[val % 16], &uart->udivslot); +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +int serial_init_dev(const int dev_index) +{ + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + + /* reset and enable FIFOs, set triggers to the maximum */ + writel(0, &uart->ufcon); + writel(0, &uart->umcon); + /* 8N1 */ + writel(0x3, &uart->ulcon); + /* No interrupts, no DMA, pure polling */ + writel(0x245, &uart->ucon); + + serial_setbrg_dev(dev_index); + + return 0; +} + +static int serial_err_check(const int dev_index, int op) +{ + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + unsigned int mask; + + /* + * UERSTAT + * Break Detect [3] + * Frame Err [2] : receive operation + * Parity Err [1] : receive operation + * Overrun Err [0] : receive operation + */ + if (op) + mask = 0x8; + else + mask = 0xf; + + return readl(&uart->uerstat) & mask; +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc_dev(const int dev_index) +{ + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + + /* wait for character to arrive */ + while (!(readl(&uart->utrstat) & 0x1)) { + if (serial_err_check(dev_index, 0)) + return 0; + } + + return (int)(readl(&uart->urxh) & 0xff); +} + +/* + * Output a single byte to the serial port. + */ +void serial_putc_dev(const char c, const int dev_index) +{ + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + + /* wait for room in the tx FIFO */ + while (!(readl(&uart->utrstat) & 0x2)) { + if (serial_err_check(dev_index, 1)) + return; + } + + writel(c, &uart->utxh); + + /* If \n, also do \r */ + if (c == '\n') + serial_putc('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc_dev(const int dev_index) +{ + struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + + return (int)(readl(&uart->utrstat) & 0x1); +} + +void serial_puts_dev(const char *s, const int dev_index) +{ + while (*s) + serial_putc_dev(*s++, dev_index); +} + +/* Multi serial device functions */ +#define DECLARE_S5P_SERIAL_FUNCTIONS(port) \ +int s5p_serial##port##_init(void) { return serial_init_dev(port); } \ +void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \ +int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \ +int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \ +void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \ +void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); } + +#define INIT_S5P_SERIAL_STRUCTURE(port, name, bus) { \ + name, \ + bus, \ + s5p_serial##port##_init, \ + NULL, \ + s5p_serial##port##_setbrg, \ + s5p_serial##port##_getc, \ + s5p_serial##port##_tstc, \ + s5p_serial##port##_putc, \ + s5p_serial##port##_puts, } + +DECLARE_S5P_SERIAL_FUNCTIONS(0); +struct serial_device s5p_serial0_device = + INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0", "S5PUART0"); +DECLARE_S5P_SERIAL_FUNCTIONS(1); +struct serial_device s5p_serial1_device = + INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1", "S5PUART1"); +DECLARE_S5P_SERIAL_FUNCTIONS(2); +struct serial_device s5p_serial2_device = + INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2", "S5PUART2"); +DECLARE_S5P_SERIAL_FUNCTIONS(3); +struct serial_device s5p_serial3_device = + INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3", "S5PUART3"); diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_sa1100.c b/roms/u-boot-sam460ex/drivers/serial/serial_sa1100.c new file mode 100644 index 000000000..5d1887580 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_sa1100.c @@ -0,0 +1,160 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <SA-1100.h> + +DECLARE_GLOBAL_DATA_PTR; + +void serial_setbrg (void) +{ + unsigned int reg = 0; + + if (gd->baudrate == 1200) + reg = 191; + else if (gd->baudrate == 9600) + reg = 23; + else if (gd->baudrate == 19200) + reg = 11; + else if (gd->baudrate == 38400) + reg = 5; + else if (gd->baudrate == 57600) + reg = 3; + else if (gd->baudrate == 115200) + reg = 1; + else + hang (); + +#ifdef CONFIG_SERIAL1 + /* SA1110 uart function */ + Ser1SDCR0 |= SDCR0_SUS; + + /* Wait until port is ready ... */ + while(Ser1UTSR1 & UTSR1_TBY) {} + + /* init serial serial 1 */ + Ser1UTCR3 = 0x00; + Ser1UTSR0 = 0xff; + Ser1UTCR0 = ( UTCR0_1StpBit | UTCR0_8BitData ); + Ser1UTCR1 = 0; + Ser1UTCR2 = (u32)reg; + Ser1UTCR3 = ( UTCR3_RXE | UTCR3_TXE ); +#elif defined(CONFIG_SERIAL3) + /* Wait until port is ready ... */ + while (Ser3UTSR1 & UTSR1_TBY) { + } + + /* init serial serial 3 */ + Ser3UTCR3 = 0x00; + Ser3UTSR0 = 0xff; + Ser3UTCR0 = (UTCR0_1StpBit | UTCR0_8BitData); + Ser3UTCR1 = 0; + Ser3UTCR2 = (u32) reg; + Ser3UTCR3 = (UTCR3_RXE | UTCR3_TXE); +#else +#error "Bad: you didn't configured serial ..." +#endif +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ +#ifdef CONFIG_SERIAL1 + /* wait for room in the tx FIFO on SERIAL1 */ + while ((Ser1UTSR0 & UTSR0_TFS) == 0); + + Ser1UTDR = c; +#elif defined(CONFIG_SERIAL3) + /* wait for room in the tx FIFO on SERIAL3 */ + while ((Ser3UTSR0 & UTSR0_TFS) == 0); + + Ser3UTDR = c; +#endif + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_tstc (void) +{ +#ifdef CONFIG_SERIAL1 + return Ser1UTSR1 & UTSR1_RNE; +#elif defined(CONFIG_SERIAL3) + return Ser3UTSR1 & UTSR1_RNE; +#endif +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ +#ifdef CONFIG_SERIAL1 + while (!(Ser1UTSR1 & UTSR1_RNE)); + + return (char) Ser1UTDR & 0xff; +#elif defined(CONFIG_SERIAL3) + while (!(Ser3UTSR1 & UTSR1_RNE)); + + return (char) Ser3UTDR & 0xff; +#endif +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_sh.c b/roms/u-boot-sam460ex/drivers/serial/serial_sh.c new file mode 100644 index 000000000..bfdb2ce77 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_sh.c @@ -0,0 +1,239 @@ +/* + * SuperH SCIF device driver. + * Copyright (c) 2007,2008 Nobuhiro Iwamatsu + * + * 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 <asm/io.h> +#include <asm/processor.h> + +#if defined(CONFIG_CONS_SCIF0) +# define SCIF_BASE SCIF0_BASE +#elif defined(CONFIG_CONS_SCIF1) +# define SCIF_BASE SCIF1_BASE +#elif defined(CONFIG_CONS_SCIF2) +# define SCIF_BASE SCIF2_BASE +#elif defined(CONFIG_CONS_SCIF3) +# define SCIF_BASE SCIF3_BASE +#elif defined(CONFIG_CONS_SCIF4) +# define SCIF_BASE SCIF4_BASE +#elif defined(CONFIG_CONS_SCIF5) +# define SCIF_BASE SCIF5_BASE +#else +# error "Default SCIF doesn't set....." +#endif + +/* Base register */ +#define SCSMR (vu_short *)(SCIF_BASE + 0x0) +#define SCBRR (vu_char *)(SCIF_BASE + 0x4) +#define SCSCR (vu_short *)(SCIF_BASE + 0x8) +#define SCFCR (vu_short *)(SCIF_BASE + 0x18) +#define SCFDR (vu_short *)(SCIF_BASE + 0x1C) +#if defined(CONFIG_CPU_SH7720) || \ + (defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A)) +# define SCFSR (vu_short *)(SCIF_BASE + 0x14) /* SCSSR */ +# define SCFTDR (vu_char *)(SCIF_BASE + 0x20) +# define SCFRDR (vu_char *)(SCIF_BASE + 0x24) +#else +# define SCFTDR (vu_char *)(SCIF_BASE + 0xC) +# define SCFSR (vu_short *)(SCIF_BASE + 0x10) +# define SCFRDR (vu_char *)(SCIF_BASE + 0x14) +#endif + +#if defined(CONFIG_CPU_SH7780) || \ + defined(CONFIG_CPU_SH7785) +# define SCRFDR (vu_short *)(SCIF_BASE + 0x20) +# define SCSPTR (vu_short *)(SCIF_BASE + 0x24) +# define SCLSR (vu_short *)(SCIF_BASE + 0x28) +# define SCRER (vu_short *)(SCIF_BASE + 0x2C) +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0xFF +#elif defined(CONFIG_CPU_SH7763) +# if defined(CONFIG_CONS_SCIF2) +# define SCSPTR (vu_short *)(SCIF_BASE + 0x20) +# define SCLSR (vu_short *)(SCIF_BASE + 0x24) +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0x1F +# else +# define SCRFDR (vu_short *)(SCIF_BASE + 0x20) +# define SCSPTR (vu_short *)(SCIF_BASE + 0x24) +# define SCLSR (vu_short *)(SCIF_BASE + 0x28) +# define SCRER (vu_short *)(SCIF_BASE + 0x2C) +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0xFF +# endif +#elif defined(CONFIG_CPU_SH7723) +# if defined(CONFIG_SCIF_A) +# define SCLSR SCFSR +# define LSR_ORER 0x0200 +# define FIFOLEVEL_MASK 0x3F +#else +# define SCLSR (vu_short *)(SCIF_BASE + 0x24) +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0x1F +#endif +#elif defined(CONFIG_CPU_SH7750) || \ + defined(CONFIG_CPU_SH7751) || \ + defined(CONFIG_CPU_SH7722) || \ + defined(CONFIG_CPU_SH7203) +# define SCSPTR (vu_short *)(SCIF_BASE + 0x20) +# define SCLSR (vu_short *)(SCIF_BASE + 0x24) +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0x1F +#elif defined(CONFIG_CPU_SH7720) +# define SCLSR SCFSR +# define LSR_ORER 0x0200 +# define FIFOLEVEL_MASK 0x1F +#elif defined(CONFIG_CPU_SH7710) || \ + defined(CONFIG_CPU_SH7712) +# define SCLSR SCFSR /* SCSSR */ +# define LSR_ORER 1 +# define FIFOLEVEL_MASK 0x1F +#endif + +/* SCBRR register value setting */ +#if defined(CONFIG_CPU_SH7720) +# define SCBRR_VALUE(bps, clk) (((clk * 2) + 16 * bps) / (32 * bps) - 1) +#elif defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A) +/* SH7723 SCIFA use bus clock. So clock *2 */ +# define SCBRR_VALUE(bps, clk) (((clk * 2 * 2) + 16 * bps) / (32 * bps) - 1) +#else /* Generic SuperH */ +# define SCBRR_VALUE(bps, clk) ((clk + 16 * bps) / (32 * bps) - 1) +#endif + +#define SCR_RE (1 << 4) +#define SCR_TE (1 << 5) +#define FCR_RFRST (1 << 1) /* RFCL */ +#define FCR_TFRST (1 << 2) /* TFCL */ +#define FSR_DR (1 << 0) +#define FSR_RDF (1 << 1) +#define FSR_FER (1 << 3) +#define FSR_BRK (1 << 4) +#define FSR_FER (1 << 3) +#define FSR_TEND (1 << 6) +#define FSR_ER (1 << 7) + +/*----------------------------------------------------------------------*/ + +void serial_setbrg(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + writeb(SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ), SCBRR); +} + +int serial_init(void) +{ + writew((SCR_RE | SCR_TE), SCSCR); + writew(0, SCSMR); + writew(0, SCSMR); + writew((FCR_RFRST | FCR_TFRST), SCFCR); + readw(SCFCR); + writew(0, SCFCR); + + serial_setbrg(); + return 0; +} + +static int serial_rx_fifo_level(void) +{ +#if defined(SCRFDR) + return (readw(SCRFDR) >> 0) & FIFOLEVEL_MASK; +#else + return (readw(SCFDR) >> 0) & FIFOLEVEL_MASK; +#endif +} + +void serial_raw_putc(const char c) +{ + unsigned int fsr_bits_to_clear; + + while (1) { + if (readw(SCFSR) & FSR_TEND) { /* Tx fifo is empty */ + fsr_bits_to_clear = FSR_TEND; + break; + } + } + + writeb(c, SCFTDR); + if (fsr_bits_to_clear != 0) + writew(readw(SCFSR) & ~fsr_bits_to_clear, SCFSR); +} + +void serial_putc(const char c) +{ + if (c == '\n') + serial_raw_putc('\r'); + serial_raw_putc(c); +} + +void serial_puts(const char *s) +{ + char c; + while ((c = *s++) != 0) + serial_putc(c); +} + +int serial_tstc(void) +{ + return serial_rx_fifo_level() ? 1 : 0; +} + +#define FSR_ERR_CLEAR 0x0063 +#define RDRF_CLEAR 0x00fc +void handle_error(void) +{ + readw(SCFSR); + writew(FSR_ERR_CLEAR, SCFSR); + readw(SCLSR); + writew(0x00, SCLSR); +} + +int serial_getc_check(void) +{ + unsigned short status; + + status = readw(SCFSR); + + if (status & (FSR_FER | FSR_ER | FSR_BRK)) + handle_error(); + if (readw(SCLSR) & LSR_ORER) + handle_error(); + return status & (FSR_DR | FSR_RDF); +} + +int serial_getc(void) +{ + unsigned short status; + char ch; + + while (!serial_getc_check()) + ; + + ch = readb(SCFRDR); + status = readw(SCFSR); + + writew(RDRF_CLEAR, SCFSR); + + if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK)) + handle_error(); + + if (readw(SCLSR) & LSR_ORER) + handle_error(); + + return ch; +} diff --git a/roms/u-boot-sam460ex/drivers/serial/serial_xuartlite.c b/roms/u-boot-sam460ex/drivers/serial/serial_xuartlite.c new file mode 100644 index 000000000..00d0eaac7 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/serial_xuartlite.c @@ -0,0 +1,77 @@ +/* + * (C) Copyright 2008 Michal Simek <monstr@monstr.eu> + * Clean driver and add xilinx constant from header file + * + * (C) Copyright 2004 Atmark Techno, Inc. + * Yasushi SHOJI <yashi@atmark-techno.com> + * + * 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 <config.h> +#include <asm/io.h> + +#define RX_FIFO_OFFSET 0 /* receive FIFO, read only */ +#define TX_FIFO_OFFSET 4 /* transmit FIFO, write only */ +#define STATUS_REG_OFFSET 8 /* status register, read only */ + +#define SR_TX_FIFO_FULL 0x08 /* transmit FIFO full */ +#define SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */ +#define SR_RX_FIFO_FULL 0x02 /* receive FIFO full */ + +#define UARTLITE_STATUS (CONFIG_SERIAL_BASE + STATUS_REG_OFFSET) +#define UARTLITE_TX_FIFO (CONFIG_SERIAL_BASE + TX_FIFO_OFFSET) +#define UARTLITE_RX_FIFO (CONFIG_SERIAL_BASE + RX_FIFO_OFFSET) + +int serial_init(void) +{ + /* FIXME: Nothing for now. We should initialize fifo, etc */ + return 0; +} + +void serial_setbrg(void) +{ + /* FIXME: what's this for? */ +} + +void serial_putc(const char c) +{ + if (c == '\n') + serial_putc('\r'); + while (in_be32((u32 *) UARTLITE_STATUS) & SR_TX_FIFO_FULL); + out_be32((u32 *) UARTLITE_TX_FIFO, (unsigned char) (c & 0xff)); +} + +void serial_puts(const char * s) +{ + while (*s) { + serial_putc(*s++); + } +} + +int serial_getc(void) +{ + while (!(in_be32((u32 *) UARTLITE_STATUS) & SR_RX_FIFO_VALID_DATA)); + return in_be32((u32 *) UARTLITE_RX_FIFO) & 0xff; +} + +int serial_tstc(void) +{ + return (in_be32((u32 *) UARTLITE_STATUS) & SR_RX_FIFO_VALID_DATA); +} diff --git a/roms/u-boot-sam460ex/drivers/serial/usbtty.c b/roms/u-boot-sam460ex/drivers/serial/usbtty.c new file mode 100644 index 000000000..cffd5a2b2 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/usbtty.c @@ -0,0 +1,1009 @@ +/* + * (C) Copyright 2003 + * Gerry Hamel, geh@ti.com, Texas Instruments + * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie + * + * 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 <config.h> +#include <circbuf.h> +#include <stdio_dev.h> +#include "usbtty.h" +#include "usb_cdc_acm.h" +#include "usbdescriptors.h" + +#ifdef DEBUG +#define TTYDBG(fmt,args...)\ + serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) +#else +#define TTYDBG(fmt,args...) do{}while(0) +#endif + +#if 1 +#define TTYERR(fmt,args...)\ + serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\ + __LINE__,##args) +#else +#define TTYERR(fmt,args...) do{}while(0) +#endif + +/* + * Defines + */ +#define NUM_CONFIGS 1 +#define MAX_INTERFACES 2 +#define NUM_ENDPOINTS 3 +#define ACM_TX_ENDPOINT 3 +#define ACM_RX_ENDPOINT 2 +#define GSERIAL_TX_ENDPOINT 2 +#define GSERIAL_RX_ENDPOINT 1 +#define NUM_ACM_INTERFACES 2 +#define NUM_GSERIAL_INTERFACES 1 +#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface" +#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface" + +/* + * Buffers to hold input and output data + */ +#define USBTTY_BUFFER_SIZE 256 +static circbuf_t usbtty_input; +static circbuf_t usbtty_output; + + +/* + * Instance variables + */ +static struct stdio_dev usbttydev; +static struct usb_device_instance device_instance[1]; +static struct usb_bus_instance bus_instance[1]; +static struct usb_configuration_instance config_instance[NUM_CONFIGS]; +static struct usb_interface_instance interface_instance[MAX_INTERFACES]; +static struct usb_alternate_instance alternate_instance[MAX_INTERFACES]; +/* one extra for control endpoint */ +static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1]; + +/* + * Global flag + */ +int usbtty_configured_flag = 0; + +/* + * Serial number + */ +static char serial_number[16]; + + +/* + * Descriptors, Strings, Local variables. + */ + +/* defined and used by gadget/ep0.c */ +extern struct usb_string_descriptor **usb_strings; + +/* Indicies, References */ +static unsigned short rx_endpoint = 0; +static unsigned short tx_endpoint = 0; +static unsigned short interface_count = 0; +static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; + +/* USB Descriptor Strings */ +static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4}; +static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)]; +static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)]; +static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)]; +static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)]; +static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; +static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)]; + +/* Standard USB Data Structures */ +static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES]; +static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS]; +static struct usb_configuration_descriptor *configuration_descriptor = 0; +static struct usb_device_descriptor device_descriptor = { + .bLength = sizeof(struct usb_device_descriptor), + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = cpu_to_le16(USB_BCD_VERSION), + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, + .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID), + .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE), + .iManufacturer = STR_MANUFACTURER, + .iProduct = STR_PRODUCT, + .iSerialNumber = STR_SERIAL, + .bNumConfigurations = NUM_CONFIGS +}; + + +/* + * Static CDC ACM specific descriptors + */ + +struct acm_config_desc { + struct usb_configuration_descriptor configuration_desc; + + /* Master Interface */ + struct usb_interface_descriptor interface_desc; + + struct usb_class_header_function_descriptor usb_class_header; + struct usb_class_call_management_descriptor usb_class_call_mgt; + struct usb_class_abstract_control_descriptor usb_class_acm; + struct usb_class_union_function_descriptor usb_class_union; + struct usb_endpoint_descriptor notification_endpoint; + + /* Slave Interface */ + struct usb_interface_descriptor data_class_interface; + struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1]; +} __attribute__((packed)); + +static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { + { + .configuration_desc ={ + .bLength = + sizeof(struct usb_configuration_descriptor), + .bDescriptorType = USB_DT_CONFIG, + .wTotalLength = + cpu_to_le16(sizeof(struct acm_config_desc)), + .bNumInterfaces = NUM_ACM_INTERFACES, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG, + .bmAttributes = + BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, + .bMaxPower = USBTTY_MAXPOWER + }, + /* Interface 1 */ + .interface_desc = { + .bLength = sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0x01, + .bInterfaceClass = + COMMUNICATIONS_INTERFACE_CLASS_CONTROL, + .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS, + .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL, + .iInterface = STR_CTRL_INTERFACE, + }, + .usb_class_header = { + .bFunctionLength = + sizeof(struct usb_class_header_function_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_ST_HEADER, + .bcdCDC = cpu_to_le16(110), + }, + .usb_class_call_mgt = { + .bFunctionLength = + sizeof(struct usb_class_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_ST_CMF, + .bmCapabilities = 0x00, + .bDataInterface = 0x01, + }, + .usb_class_acm = { + .bFunctionLength = + sizeof(struct usb_class_abstract_control_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_ST_ACMF, + .bmCapabilities = 0x00, + }, + .usb_class_union = { + .bFunctionLength = + sizeof(struct usb_class_union_function_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_ST_UF, + .bMasterInterface = 0x00, + .bSlaveInterface0 = 0x01, + }, + .notification_endpoint = { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize + = cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), + .bInterval = 0xFF, + }, + + /* Interface 2 */ + .data_class_interface = { + .bLength = + sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0x01, + .bAlternateSetting = 0x00, + .bNumEndpoints = 0x02, + .bInterfaceClass = + COMMUNICATIONS_INTERFACE_CLASS_DATA, + .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE, + .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE, + .iInterface = STR_DATA_INTERFACE, + }, + .data_endpoints = { + { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, + .bmAttributes = + USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = + cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), + .bInterval = 0xFF, + }, + { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, + .bmAttributes = + USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = + cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE), + .bInterval = 0xFF, + }, + }, + }, +}; + +static struct rs232_emu rs232_desc={ + .dter = 115200, + .stop_bits = 0x00, + .parity = 0x00, + .data_bits = 0x08 +}; + + +/* + * Static Generic Serial specific data + */ + + +struct gserial_config_desc { + + struct usb_configuration_descriptor configuration_desc; + struct usb_interface_descriptor interface_desc[NUM_GSERIAL_INTERFACES]; + struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS]; + +} __attribute__((packed)); + +static struct gserial_config_desc +gserial_configuration_descriptors[NUM_CONFIGS] ={ + { + .configuration_desc ={ + .bLength = sizeof(struct usb_configuration_descriptor), + .bDescriptorType = USB_DT_CONFIG, + .wTotalLength = + cpu_to_le16(sizeof(struct gserial_config_desc)), + .bNumInterfaces = NUM_GSERIAL_INTERFACES, + .bConfigurationValue = 1, + .iConfiguration = STR_CONFIG, + .bmAttributes = + BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, + .bMaxPower = USBTTY_MAXPOWER + }, + .interface_desc = { + { + .bLength = + sizeof(struct usb_interface_descriptor), + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = NUM_ENDPOINTS, + .bInterfaceClass = + COMMUNICATIONS_INTERFACE_CLASS_VENDOR, + .bInterfaceSubClass = + COMMUNICATIONS_NO_SUBCLASS, + .bInterfaceProtocol = + COMMUNICATIONS_NO_PROTOCOL, + .iInterface = STR_DATA_INTERFACE + }, + }, + .data_endpoints = { + { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = + cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE), + .bInterval= 0xFF, + }, + { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = + cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE), + .bInterval = 0xFF, + }, + { + .bLength = + sizeof(struct usb_endpoint_descriptor), + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = + cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE), + .bInterval = 0xFF, + }, + }, + }, +}; + +/* + * Static Function Prototypes + */ + +static void usbtty_init_strings (void); +static void usbtty_init_instances (void); +static void usbtty_init_endpoints (void); +static void usbtty_init_terminal_type(short type); +static void usbtty_event_handler (struct usb_device_instance *device, + usb_device_event_t event, int data); +static int usbtty_cdc_setup(struct usb_device_request *request, + struct urb *urb); +static int usbtty_configured (void); +static int write_buffer (circbuf_t * buf); +static int fill_buffer (circbuf_t * buf); + +void usbtty_poll (void); + +/* utility function for converting char* to wide string used by USB */ +static void str2wide (char *str, u16 * wide) +{ + int i; + for (i = 0; i < strlen (str) && str[i]; i++){ + #if defined(__LITTLE_ENDIAN) + wide[i] = (u16) str[i]; + #elif defined(__BIG_ENDIAN) + wide[i] = ((u16)(str[i])<<8); + #else + #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined" + #endif + } +} + +/* + * Test whether a character is in the RX buffer + */ + +int usbtty_tstc (void) +{ + struct usb_endpoint_instance *endpoint = + &endpoint_instance[rx_endpoint]; + + /* If no input data exists, allow more RX to be accepted */ + if(usbtty_input.size <= 0){ + udc_unset_nak(endpoint->endpoint_address&0x03); + } + + usbtty_poll (); + return (usbtty_input.size > 0); +} + +/* + * Read a single byte from the usb client port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ + +int usbtty_getc (void) +{ + char c; + struct usb_endpoint_instance *endpoint = + &endpoint_instance[rx_endpoint]; + + while (usbtty_input.size <= 0) { + udc_unset_nak(endpoint->endpoint_address&0x03); + usbtty_poll (); + } + + buf_pop (&usbtty_input, &c, 1); + udc_set_nak(endpoint->endpoint_address&0x03); + + return c; +} + +/* + * Output a single byte to the usb client port. + */ +void usbtty_putc (const char c) +{ + if (!usbtty_configured ()) + return; + + buf_push (&usbtty_output, &c, 1); + /* If \n, also do \r */ + if (c == '\n') + buf_push (&usbtty_output, "\r", 1); + + /* Poll at end to handle new data... */ + if ((usbtty_output.size + 2) >= usbtty_output.totalsize) { + usbtty_poll (); + } +} + +/* usbtty_puts() helper function for finding the next '\n' in a string */ +static int next_nl_pos (const char *s) +{ + int i; + + for (i = 0; s[i] != '\0'; i++) { + if (s[i] == '\n') + return i; + } + return i; +} + +/* + * Output a string to the usb client port - implementing flow control + */ + +static void __usbtty_puts (const char *str, int len) +{ + int maxlen = usbtty_output.totalsize; + int space, n; + + /* break str into chunks < buffer size, if needed */ + while (len > 0) { + usbtty_poll (); + + space = maxlen - usbtty_output.size; + /* Empty buffer here, if needed, to ensure space... */ + if (space) { + write_buffer (&usbtty_output); + + n = MIN (space, MIN (len, maxlen)); + buf_push (&usbtty_output, str, n); + + str += n; + len -= n; + } + } +} + +void usbtty_puts (const char *str) +{ + int n; + int len; + + if (!usbtty_configured ()) + return; + + len = strlen (str); + /* add '\r' for each '\n' */ + while (len > 0) { + n = next_nl_pos (str); + + if (str[n] == '\n') { + __usbtty_puts (str, n + 1); + __usbtty_puts ("\r", 1); + str += (n + 1); + len -= (n + 1); + } else { + /* No \n found. All done. */ + __usbtty_puts (str, n); + break; + } + } + + /* Poll at end to handle new data... */ + usbtty_poll (); +} + +/* + * Initialize the usb client port. + * + */ +int drv_usbtty_init (void) +{ + int rc; + char * sn; + char * tt; + int snlen; + + /* Ger seiral number */ + if (!(sn = getenv("serial#"))) { + sn = "000000000000"; + } + snlen = strlen(sn); + if (snlen > sizeof(serial_number) - 1) { + printf ("Warning: serial number %s is too long (%d > %lu)\n", + sn, snlen, (ulong)(sizeof(serial_number) - 1)); + snlen = sizeof(serial_number) - 1; + } + memcpy (serial_number, sn, snlen); + serial_number[snlen] = '\0'; + + /* Decide on which type of UDC device to be. + */ + + if(!(tt = getenv("usbtty"))) { + tt = "generic"; + } + usbtty_init_terminal_type(strcmp(tt,"cdc_acm")); + + /* prepare buffers... */ + buf_init (&usbtty_input, USBTTY_BUFFER_SIZE); + buf_init (&usbtty_output, USBTTY_BUFFER_SIZE); + + /* Now, set up USB controller and infrastructure */ + udc_init (); /* Basic USB initialization */ + + usbtty_init_strings (); + usbtty_init_instances (); + + udc_startup_events (device_instance);/* Enable dev, init udc pointers */ + udc_connect (); /* Enable pullup for host detection */ + + usbtty_init_endpoints (); + + /* Device initialization */ + memset (&usbttydev, 0, sizeof (usbttydev)); + + strcpy (usbttydev.name, "usbtty"); + usbttydev.ext = 0; /* No extensions */ + usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; + usbttydev.tstc = usbtty_tstc; /* 'tstc' function */ + usbttydev.getc = usbtty_getc; /* 'getc' function */ + usbttydev.putc = usbtty_putc; /* 'putc' function */ + usbttydev.puts = usbtty_puts; /* 'puts' function */ + + rc = stdio_register (&usbttydev); + + return (rc == 0) ? 1 : rc; +} + +static void usbtty_init_strings (void) +{ + struct usb_string_descriptor *string; + + usbtty_string_table[STR_LANG] = + (struct usb_string_descriptor*)wstrLang; + + string = (struct usb_string_descriptor *) wstrManufacturer; + string->bLength = sizeof(wstrManufacturer); + string->bDescriptorType = USB_DT_STRING; + str2wide (CONFIG_USBD_MANUFACTURER, string->wData); + usbtty_string_table[STR_MANUFACTURER]=string; + + + string = (struct usb_string_descriptor *) wstrProduct; + string->bLength = sizeof(wstrProduct); + string->bDescriptorType = USB_DT_STRING; + str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData); + usbtty_string_table[STR_PRODUCT]=string; + + + string = (struct usb_string_descriptor *) wstrSerial; + string->bLength = sizeof(serial_number); + string->bDescriptorType = USB_DT_STRING; + str2wide (serial_number, string->wData); + usbtty_string_table[STR_SERIAL]=string; + + + string = (struct usb_string_descriptor *) wstrConfiguration; + string->bLength = sizeof(wstrConfiguration); + string->bDescriptorType = USB_DT_STRING; + str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData); + usbtty_string_table[STR_CONFIG]=string; + + + string = (struct usb_string_descriptor *) wstrDataInterface; + string->bLength = sizeof(wstrDataInterface); + string->bDescriptorType = USB_DT_STRING; + str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData); + usbtty_string_table[STR_DATA_INTERFACE]=string; + + string = (struct usb_string_descriptor *) wstrCtrlInterface; + string->bLength = sizeof(wstrCtrlInterface); + string->bDescriptorType = USB_DT_STRING; + str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData); + usbtty_string_table[STR_CTRL_INTERFACE]=string; + + /* Now, initialize the string table for ep0 handling */ + usb_strings = usbtty_string_table; +} + +static void usbtty_init_instances (void) +{ + int i; + + /* initialize device instance */ + memset (device_instance, 0, sizeof (struct usb_device_instance)); + device_instance->device_state = STATE_INIT; + device_instance->device_descriptor = &device_descriptor; + device_instance->event = usbtty_event_handler; + device_instance->cdc_recv_setup = usbtty_cdc_setup; + device_instance->bus = bus_instance; + device_instance->configurations = NUM_CONFIGS; + device_instance->configuration_instance_array = config_instance; + + /* initialize bus instance */ + memset (bus_instance, 0, sizeof (struct usb_bus_instance)); + bus_instance->device = device_instance; + bus_instance->endpoint_array = endpoint_instance; + bus_instance->max_endpoints = 1; + bus_instance->maxpacketsize = 64; + bus_instance->serial_number_str = serial_number; + + /* configuration instance */ + memset (config_instance, 0, + sizeof (struct usb_configuration_instance)); + config_instance->interfaces = interface_count; + config_instance->configuration_descriptor = configuration_descriptor; + config_instance->interface_instance_array = interface_instance; + + /* interface instance */ + memset (interface_instance, 0, + sizeof (struct usb_interface_instance)); + interface_instance->alternates = 1; + interface_instance->alternates_instance_array = alternate_instance; + + /* alternates instance */ + memset (alternate_instance, 0, + sizeof (struct usb_alternate_instance)); + alternate_instance->interface_descriptor = interface_descriptors; + alternate_instance->endpoints = NUM_ENDPOINTS; + alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs; + + /* endpoint instances */ + memset (&endpoint_instance[0], 0, + sizeof (struct usb_endpoint_instance)); + endpoint_instance[0].endpoint_address = 0; + endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE; + endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL; + endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE; + endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL; + udc_setup_ep (device_instance, 0, &endpoint_instance[0]); + + for (i = 1; i <= NUM_ENDPOINTS; i++) { + memset (&endpoint_instance[i], 0, + sizeof (struct usb_endpoint_instance)); + + endpoint_instance[i].endpoint_address = + ep_descriptor_ptrs[i - 1]->bEndpointAddress; + + endpoint_instance[i].rcv_attributes = + ep_descriptor_ptrs[i - 1]->bmAttributes; + + endpoint_instance[i].rcv_packetSize = + le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); + + endpoint_instance[i].tx_attributes = + ep_descriptor_ptrs[i - 1]->bmAttributes; + + endpoint_instance[i].tx_packetSize = + le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize); + + endpoint_instance[i].tx_attributes = + ep_descriptor_ptrs[i - 1]->bmAttributes; + + urb_link_init (&endpoint_instance[i].rcv); + urb_link_init (&endpoint_instance[i].rdy); + urb_link_init (&endpoint_instance[i].tx); + urb_link_init (&endpoint_instance[i].done); + + if (endpoint_instance[i].endpoint_address & USB_DIR_IN) + endpoint_instance[i].tx_urb = + usbd_alloc_urb (device_instance, + &endpoint_instance[i]); + else + endpoint_instance[i].rcv_urb = + usbd_alloc_urb (device_instance, + &endpoint_instance[i]); + } +} + +static void usbtty_init_endpoints (void) +{ + int i; + + bus_instance->max_endpoints = NUM_ENDPOINTS + 1; + for (i = 1; i <= NUM_ENDPOINTS; i++) { + udc_setup_ep (device_instance, i, &endpoint_instance[i]); + } +} + +/* usbtty_init_terminal_type + * + * Do some late binding for our device type. + */ +static void usbtty_init_terminal_type(short type) +{ + switch(type){ + /* CDC ACM */ + case 0: + /* Assign endpoint descriptors */ + ep_descriptor_ptrs[0] = + &acm_configuration_descriptors[0].notification_endpoint; + ep_descriptor_ptrs[1] = + &acm_configuration_descriptors[0].data_endpoints[0]; + ep_descriptor_ptrs[2] = + &acm_configuration_descriptors[0].data_endpoints[1]; + + /* Enumerate Device Descriptor */ + device_descriptor.bDeviceClass = + COMMUNICATIONS_DEVICE_CLASS; + device_descriptor.idProduct = + cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); + + /* Assign endpoint indices */ + tx_endpoint = ACM_TX_ENDPOINT; + rx_endpoint = ACM_RX_ENDPOINT; + + /* Configuration Descriptor */ + configuration_descriptor = + (struct usb_configuration_descriptor*) + &acm_configuration_descriptors; + + /* Interface count */ + interface_count = NUM_ACM_INTERFACES; + break; + + /* BULK IN/OUT & Default */ + case 1: + default: + /* Assign endpoint descriptors */ + ep_descriptor_ptrs[0] = + &gserial_configuration_descriptors[0].data_endpoints[0]; + ep_descriptor_ptrs[1] = + &gserial_configuration_descriptors[0].data_endpoints[1]; + ep_descriptor_ptrs[2] = + &gserial_configuration_descriptors[0].data_endpoints[2]; + + /* Enumerate Device Descriptor */ + device_descriptor.bDeviceClass = 0xFF; + device_descriptor.idProduct = + cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); + + /* Assign endpoint indices */ + tx_endpoint = GSERIAL_TX_ENDPOINT; + rx_endpoint = GSERIAL_RX_ENDPOINT; + + /* Configuration Descriptor */ + configuration_descriptor = + (struct usb_configuration_descriptor*) + &gserial_configuration_descriptors; + + /* Interface count */ + interface_count = NUM_GSERIAL_INTERFACES; + break; + } +} + +/******************************************************************************/ + +static struct urb *next_urb (struct usb_device_instance *device, + struct usb_endpoint_instance *endpoint) +{ + struct urb *current_urb = NULL; + int space; + + /* If there's a queue, then we should add to the last urb */ + if (!endpoint->tx_queue) { + current_urb = endpoint->tx_urb; + } else { + /* Last urb from tx chain */ + current_urb = + p2surround (struct urb, link, endpoint->tx.prev); + } + + /* Make sure this one has enough room */ + space = current_urb->buffer_length - current_urb->actual_length; + if (space > 0) { + return current_urb; + } else { /* No space here */ + /* First look at done list */ + current_urb = first_urb_detached (&endpoint->done); + if (!current_urb) { + current_urb = usbd_alloc_urb (device, endpoint); + } + + urb_append (&endpoint->tx, current_urb); + endpoint->tx_queue++; + } + return current_urb; +} + +static int write_buffer (circbuf_t * buf) +{ + if (!usbtty_configured ()) { + return 0; + } + + struct usb_endpoint_instance *endpoint = + &endpoint_instance[tx_endpoint]; + struct urb *current_urb = NULL; + + current_urb = next_urb (device_instance, endpoint); + /* TX data still exists - send it now + */ + if(endpoint->sent < current_urb->actual_length){ + if(udc_endpoint_write (endpoint)){ + /* Write pre-empted by RX */ + return -1; + } + } + + if (buf->size) { + char *dest; + + int space_avail; + int popnum, popped; + int total = 0; + + /* Break buffer into urb sized pieces, + * and link each to the endpoint + */ + while (buf->size > 0) { + + if (!current_urb) { + TTYERR ("current_urb is NULL, buf->size %d\n", + buf->size); + return total; + } + + dest = (char*)current_urb->buffer + + current_urb->actual_length; + + space_avail = + current_urb->buffer_length - + current_urb->actual_length; + popnum = MIN (space_avail, buf->size); + if (popnum == 0) + break; + + popped = buf_pop (buf, dest, popnum); + if (popped == 0) + break; + current_urb->actual_length += popped; + total += popped; + + /* If endpoint->last == 0, then transfers have + * not started on this endpoint + */ + if (endpoint->last == 0) { + if(udc_endpoint_write (endpoint)){ + /* Write pre-empted by RX */ + return -1; + } + } + + }/* end while */ + return total; + } + + return 0; +} + +static int fill_buffer (circbuf_t * buf) +{ + struct usb_endpoint_instance *endpoint = + &endpoint_instance[rx_endpoint]; + + if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { + unsigned int nb = 0; + char *src = (char *) endpoint->rcv_urb->buffer; + unsigned int rx_avail = buf->totalsize - buf->size; + + if(rx_avail >= endpoint->rcv_urb->actual_length){ + + nb = endpoint->rcv_urb->actual_length; + buf_push (buf, src, nb); + endpoint->rcv_urb->actual_length = 0; + + } + return nb; + } + return 0; +} + +static int usbtty_configured (void) +{ + return usbtty_configured_flag; +} + +/******************************************************************************/ + +static void usbtty_event_handler (struct usb_device_instance *device, + usb_device_event_t event, int data) +{ + switch (event) { + case DEVICE_RESET: + case DEVICE_BUS_INACTIVE: + usbtty_configured_flag = 0; + break; + case DEVICE_CONFIGURED: + usbtty_configured_flag = 1; + break; + + case DEVICE_ADDRESS_ASSIGNED: + usbtty_init_endpoints (); + + default: + break; + } +} + +/******************************************************************************/ + +int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb) +{ + switch (request->bRequest){ + + case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */ + break; + case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */ + break; + case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits + * per character */ + break; + case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */ + break; + case ACM_GET_LINE_ENCODING : /* request DTE rate, + * stop/parity bits */ + memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc)); + urb->actual_length = sizeof(rs232_desc); + + break; + default: + return 1; + } + return 0; +} + +/******************************************************************************/ + +/* + * Since interrupt handling has not yet been implemented, we use this function + * to handle polling. This is called by the tstc,getc,putc,puts routines to + * update the USB state. + */ +void usbtty_poll (void) +{ + /* New interrupts? */ + udc_irq(); + + /* Write any output data to host buffer + * (do this before checking interrupts to avoid missing one) + */ + if (usbtty_configured ()) { + write_buffer (&usbtty_output); + } + + /* New interrupts? */ + udc_irq(); + + /* Check for new data from host.. + * (do this after checking interrupts to get latest data) + */ + if (usbtty_configured ()) { + fill_buffer (&usbtty_input); + } + + /* New interrupts? */ + udc_irq(); + +} diff --git a/roms/u-boot-sam460ex/drivers/serial/usbtty.h b/roms/u-boot-sam460ex/drivers/serial/usbtty.h new file mode 100644 index 000000000..a23169a29 --- /dev/null +++ b/roms/u-boot-sam460ex/drivers/serial/usbtty.h @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2003 + * Gerry Hamel, geh@ti.com, Texas Instruments + * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit + * + * 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 + * + */ + +#ifndef __USB_TTY_H__ +#define __USB_TTY_H__ + +#include <usbdevice.h> +#if defined(CONFIG_PPC) +#include <usb/mpc8xx_udc.h> +#elif defined(CONFIG_OMAP1510) +#include <usb/omap1510_udc.h> +#elif defined(CONFIG_MUSB_UDC) +#include <usb/musb_udc.h> +#elif defined(CONFIG_PXA27X) +#include <usb/pxa27x_udc.h> +#elif defined(CONFIG_SPEAR3XX) || defined(CONFIG_SPEAR600) +#include <usb/spr_udc.h> +#endif + +#include <version_autogenerated.h> + +/* If no VendorID/ProductID is defined in config.h, pretend to be Linux + * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */ + +#ifndef CONFIG_USBD_VENDORID +#define CONFIG_USBD_VENDORID 0x0525 /* Linux/NetChip */ +#endif +#ifndef CONFIG_USBD_PRODUCTID_GSERIAL +#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6 /* gserial */ +#endif +#ifndef CONFIG_USBD_PRODUCTID_CDCACM +#define CONFIG_USBD_PRODUCTID_CDCACM 0xa4a7 /* CDC ACM */ +#endif +#ifndef CONFIG_USBD_MANUFACTURER +#define CONFIG_USBD_MANUFACTURER "Das U-Boot" +#endif +#ifndef CONFIG_USBD_PRODUCT_NAME +#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION +#endif + +#ifndef CONFIG_USBD_CONFIGURATION_STR +#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB" +#endif + +#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT +#define CONFIG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE +#define CONFIG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT +#define CONFIG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE +#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT +#define CONFIG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE +#define CONFIG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE + +#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS + +#define USBTTY_BCD_DEVICE 0x00 +#define USBTTY_MAXPOWER 0x00 + +#define STR_LANG 0x00 +#define STR_MANUFACTURER 0x01 +#define STR_PRODUCT 0x02 +#define STR_SERIAL 0x03 +#define STR_CONFIG 0x04 +#define STR_DATA_INTERFACE 0x05 +#define STR_CTRL_INTERFACE 0x06 +#define STR_COUNT 0x07 + +#endif |