diff options
Diffstat (limited to 'cpu/bf537/serial.c')
| -rw-r--r-- | cpu/bf537/serial.c | 194 | 
1 files changed, 194 insertions, 0 deletions
| diff --git a/cpu/bf537/serial.c b/cpu/bf537/serial.c new file mode 100644 index 000000000..dd4f916d5 --- /dev/null +++ b/cpu/bf537/serial.c @@ -0,0 +1,194 @@ +/* + * U-boot - serial.c Serial driver for BF537 + * + * Copyright (c) 2005 blackfin.uclinux.org + * + * This file is based on + * bf537_serial.c: Serial driver for BlackFin BF537 internal UART. + * Copyright (c) 2003	Bas Vermeulen <bas@buyways.nl>, + * 			BuyWays B.V. (www.buyways.nl) + * + * Based heavily on blkfinserial.c + * blkfinserial.c: Serial driver for BlackFin DSP internal USRTs. + * Copyright(c) 2003	Metrowerks	<mwaddel@metrowerks.com> + * Copyright(c)	2001	Tony Z. Kou	<tonyko@arcturusnetworks.com> + * Copyright(c)	2001-2002 Arcturus Networks Inc. <www.arcturusnetworks.com> + * + * Based on code from 68328 version serial driver imlpementation which was: + * Copyright (C) 1995       David S. Miller    <davem@caip.rutgers.edu> + * Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com> + * Copyright (C) 1998, 1999 D. Jeff Dionne     <jeff@uclinux.org> + * Copyright (C) 1999       Vladimir Gurevich  <vgurevic@cisco.com> + * + * (C) Copyright 2000-2004 + * 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 <common.h> +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/segment.h> +#include <asm/bitops.h> +#include <asm/delay.h> +#include <asm/uaccess.h> +#include <asm/io.h> +#include "serial.h" + +unsigned long pll_div_fact; + +void calc_baud(void) +{ +	unsigned char i; +	int temp; +	u_long sclk = get_sclk(); + +	for (i = 0; i < sizeof(baud_table) / sizeof(int); i++) { +		temp = sclk / (baud_table[i] * 8); +		if ((temp & 0x1) == 1) { +			temp++; +		} +		temp = temp / 2; +		hw_baud_table[i].dl_high = (temp >> 8) & 0xFF; +		hw_baud_table[i].dl_low = (temp) & 0xFF; +	} +} + +void serial_setbrg(void) +{ +	int i; +	DECLARE_GLOBAL_DATA_PTR; + +	calc_baud(); + +	for (i = 0; i < sizeof(baud_table) / sizeof(int); i++) { +		if (gd->baudrate == baud_table[i]) +			break; +	} + +	/* Enable UART */ +	*pUART_GCTL |= UART_GCTL_UCEN; +	sync(); + +	/* Set DLAB in LCR to Access DLL and DLH */ +	ACCESS_LATCH; +	sync(); + +	*pUART_DLL = hw_baud_table[i].dl_low; +	sync(); +	*pUART_DLH = hw_baud_table[i].dl_high; +	sync(); + +	/* Clear DLAB in LCR to Access THR RBR IER */ +	ACCESS_PORT_IER; +	sync(); + +	/* Enable  ERBFI and ELSI interrupts +	 * to poll SIC_ISR register*/ +	*pUART_IER = UART_IER_ELSI | UART_IER_ERBFI | UART_IER_ETBEI; +	sync(); + +	/* Set LCR to Word Lengh 8-bit word select */ +	*pUART_LCR = UART_LCR_WLS8; +	sync(); + +	return; +} + +int serial_init(void) +{ +	serial_setbrg(); +	return (0); +} + +void serial_putc(const char c) +{ +	if ((*pUART_LSR) & UART_LSR_TEMT) { +		if (c == '\n') +			serial_putc('\r'); + +		local_put_char(c); +	} + +	while (!((*pUART_LSR) & UART_LSR_TEMT)) +		SYNC_ALL; + +	return; +} + +int serial_tstc(void) +{ +	if (*pUART_LSR & UART_LSR_DR) +		return 1; +	else +		return 0; +} + +int serial_getc(void) +{ +	unsigned short uart_lsr_val, uart_rbr_val; +	unsigned long isr_val; +	int ret; + +	/* Poll for RX Interrupt */ +	while (!((isr_val = +		  *(volatile unsigned long *)SIC_ISR) & IRQ_UART_RX_BIT)) ; +	asm("csync;"); + +	uart_lsr_val = *pUART_LSR;	/* Clear status bit */ +	uart_rbr_val = *pUART_RBR;	/* getc() */ + +	if (isr_val & IRQ_UART_ERROR_BIT) { +		ret = -1; +	} else { +		ret = uart_rbr_val & 0xff; +	} + +	return ret; +} + +void serial_puts(const char *s) +{ +	while (*s) { +		serial_putc(*s++); +	} +} + +static void local_put_char(char ch) +{ +	int flags = 0; +	unsigned long isr_val; + +	save_and_cli(flags); + +	/* Poll for TX Interruput */ +	while (!((isr_val = *pSIC_ISR) & IRQ_UART_TX_BIT)) ; +	asm("csync;"); + +	*pUART_THR = ch;	/* putc() */ + +	if (isr_val & IRQ_UART_ERROR_BIT) { +		printf("?"); +	} + +	restore_flags(flags); + +	return; +} |