diff options
Diffstat (limited to 'drivers/serial/serial_pxa.c')
| -rw-r--r-- | drivers/serial/serial_pxa.c | 385 | 
1 files changed, 385 insertions, 0 deletions
| diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c new file mode 100644 index 000000000..9ba457e75 --- /dev/null +++ b/drivers/serial/serial_pxa.c @@ -0,0 +1,385 @@ +/* + * (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, +	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, +	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, +	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 */ |