diff options
| author | fishsoupisgood <github@madingley.org> | 2019-04-29 01:17:54 +0100 | 
|---|---|---|
| committer | fishsoupisgood <github@madingley.org> | 2019-05-27 03:43:43 +0100 | 
| commit | 3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch) | |
| tree | 65ca85f13617aee1dce474596800950f266a456c /roms/u-boot/drivers/serial | |
| download | qemu-master.tar.gz qemu-master.tar.bz2 qemu-master.zip  | |
Diffstat (limited to 'roms/u-boot/drivers/serial')
33 files changed, 7826 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/serial/Makefile b/roms/u-boot/drivers/serial/Makefile new file mode 100644 index 00000000..571c18fa --- /dev/null +++ b/roms/u-boot/drivers/serial/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2006-2009 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y += serial.o + +obj-$(CONFIG_ALTERA_UART) += altera_uart.o +obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o +obj-$(CONFIG_ARM_DCC) += arm_dcc.o +obj-$(CONFIG_ATMEL_USART) += atmel_usart.o +obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o +obj-$(CONFIG_MCFUART) += mcfuart.o +obj-$(CONFIG_OPENCORES_YANU) += opencores_yanu.o +obj-$(CONFIG_SYS_NS16550) += ns16550.o +obj-$(CONFIG_S5P) += serial_s5p.o +obj-$(CONFIG_SYS_NS16550_SERIAL) += serial_ns16550.o +obj-$(CONFIG_IMX_SERIAL) += serial_imx.o +obj-$(CONFIG_KS8695_SERIAL) += serial_ks8695.o +obj-$(CONFIG_MAX3100_SERIAL) += serial_max3100.o +obj-$(CONFIG_MXC_UART) += serial_mxc.o +obj-$(CONFIG_PL010_SERIAL) += serial_pl01x.o +obj-$(CONFIG_PL011_SERIAL) += serial_pl01x.o +obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o +obj-$(CONFIG_SA1100_SERIAL) += serial_sa1100.o +obj-$(CONFIG_S3C24X0_SERIAL) += serial_s3c24x0.o +obj-$(CONFIG_XILINX_UARTLITE) += serial_xuartlite.o +obj-$(CONFIG_SANDBOX_SERIAL) += sandbox.o +obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o +obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o +obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o +obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o +obj-$(CONFIG_MXS_AUART) += mxs_auart.o +obj-$(CONFIG_ARC_SERIAL) += serial_arc.o + +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_USB_TTY) += usbtty.o +endif diff --git a/roms/u-boot/drivers/serial/altera_jtag_uart.c b/roms/u-boot/drivers/serial/altera_jtag_uart.c new file mode 100644 index 00000000..0573c7a9 --- /dev/null +++ b/roms/u-boot/drivers/serial/altera_jtag_uart.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> +#include <linux/compiler.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*------------------------------------------------------------------ + * JTAG acts as the serial port + *-----------------------------------------------------------------*/ +static nios_jtag_t *jtag = (nios_jtag_t *)CONFIG_SYS_NIOS_CONSOLE; + +static void altera_jtag_serial_setbrg(void) +{ +} + +static int altera_jtag_serial_init(void) +{ +	return 0; +} + +static void altera_jtag_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); +} + +static int altera_jtag_serial_tstc(void) +{ +	return ( readl (&jtag->control) & NIOS_JTAG_RRDY); +} + +static int altera_jtag_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); +} + +static struct serial_device altera_jtag_serial_drv = { +	.name	= "altera_jtag_uart", +	.start	= altera_jtag_serial_init, +	.stop	= NULL, +	.setbrg	= altera_jtag_serial_setbrg, +	.putc	= altera_jtag_serial_putc, +	.puts	= default_serial_puts, +	.getc	= altera_jtag_serial_getc, +	.tstc	= altera_jtag_serial_tstc, +}; + +void altera_jtag_serial_initialize(void) +{ +	serial_register(&altera_jtag_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &altera_jtag_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/altera_uart.c b/roms/u-boot/drivers/serial/altera_uart.c new file mode 100644 index 00000000..d620528e --- /dev/null +++ b/roms/u-boot/drivers/serial/altera_uart.c @@ -0,0 +1,100 @@ +/* + * (C) Copyright 2004, Psyent Corporation <www.psyent.com> + * Scott McNutt <smcnutt@psyent.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <nios2-io.h> +#include <linux/compiler.h> +#include <serial.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 + */ +static void altera_serial_setbrg(void) +{ +} + +static int altera_serial_init(void) +{ +	return 0; +} + +#else + +static void altera_serial_setbrg(void) +{ +	unsigned div; + +	div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1; +	writel (div, &uart->divisor); +} + +static int altera_serial_init(void) +{ +	serial_setbrg(); +	return 0; +} + +#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ + +/*----------------------------------------------------------------------- + * UART CONSOLE + *---------------------------------------------------------------------*/ +static void altera_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); +} + +static int altera_serial_tstc(void) +{ +	return (readl (&uart->status) & NIOS_UART_RRDY); +} + +static int altera_serial_getc(void) +{ +	while (serial_tstc () == 0) +		WATCHDOG_RESET (); +	return (readl (&uart->rxdata) & 0x00ff ); +} + +static struct serial_device altera_serial_drv = { +	.name	= "altera_serial", +	.start	= altera_serial_init, +	.stop	= NULL, +	.setbrg	= altera_serial_setbrg, +	.putc	= altera_serial_putc, +	.puts	= default_serial_puts, +	.getc	= altera_serial_getc, +	.tstc	= altera_serial_tstc, +}; + +void altera_serial_initialize(void) +{ +	serial_register(&altera_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &altera_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/arm_dcc.c b/roms/u-boot/drivers/serial/arm_dcc.c new file mode 100644 index 00000000..5dfb02f4 --- /dev/null +++ b/roms/u-boot/drivers/serial/arm_dcc.c @@ -0,0 +1,158 @@ +/* + * 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 <serial.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 + +static int arm_dcc_init(void) +{ +	return 0; +} + +static int arm_dcc_getc(void) +{ +	int ch; +	register unsigned int reg; + +	do { +		can_read_dcc(reg); +	} while (!reg); +	read_dcc(ch); + +	return ch; +} + +static 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); +} + +static int arm_dcc_tstc(void) +{ +	register unsigned int reg; + +	can_read_dcc(reg); + +	return reg; +} + +static void arm_dcc_setbrg(void) +{ +} + +static struct serial_device arm_dcc_drv = { +	.name	= "arm_dcc", +	.start	= arm_dcc_init, +	.stop	= NULL, +	.setbrg	= arm_dcc_setbrg, +	.putc	= arm_dcc_putc, +	.puts	= default_serial_puts, +	.getc	= arm_dcc_getc, +	.tstc	= arm_dcc_tstc, +}; + +void arm_dcc_initialize(void) +{ +	serial_register(&arm_dcc_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &arm_dcc_drv; +} diff --git a/roms/u-boot/drivers/serial/atmel_usart.c b/roms/u-boot/drivers/serial/atmel_usart.c new file mode 100644 index 00000000..8f0e3489 --- /dev/null +++ b/roms/u-boot/drivers/serial/atmel_usart.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004-2006 Atmel Corporation + * + * Modified to support C structur SoC access by + * Andreas Bießmann <biessmann@corscience.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#include <common.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h> + +#include <asm/io.h> +#include <asm/arch/clk.h> +#include <asm/arch/hardware.h> + +#include "atmel_usart.h" + +DECLARE_GLOBAL_DATA_PTR; + +static void atmel_serial_setbrg(void) +{ +	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; +	unsigned long divisor; +	unsigned long usart_hz; + +	/* +	 *              Master Clock +	 * Baud Rate = -------------- +	 *                16 * CD +	 */ +	usart_hz = get_usart_clk_rate(CONFIG_USART_ID); +	divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate; +	writel(USART3_BF(CD, divisor), &usart->brgr); +} + +static int atmel_serial_init(void) +{ +	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + +	/* +	 * Just in case: drain transmitter register +	 * 1000us is enough for baudrate >= 9600 +	 */ +	if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY))) +		__udelay(1000); + +	writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr); + +	serial_setbrg(); + +	writel((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)), +			   &usart->mr); +	writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr); +	/* 100us is enough for the new settings to be settled */ +	__udelay(100); + +	return 0; +} + +static void atmel_serial_putc(char c) +{ +	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + +	if (c == '\n') +		serial_putc('\r'); + +	while (!(readl(&usart->csr) & USART3_BIT(TXRDY))); +	writel(c, &usart->thr); +} + +static int atmel_serial_getc(void) +{ +	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; + +	while (!(readl(&usart->csr) & USART3_BIT(RXRDY))) +		 WATCHDOG_RESET(); +	return readl(&usart->rhr); +} + +static int atmel_serial_tstc(void) +{ +	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE; +	return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0; +} + +static struct serial_device atmel_serial_drv = { +	.name	= "atmel_serial", +	.start	= atmel_serial_init, +	.stop	= NULL, +	.setbrg	= atmel_serial_setbrg, +	.putc	= atmel_serial_putc, +	.puts	= default_serial_puts, +	.getc	= atmel_serial_getc, +	.tstc	= atmel_serial_tstc, +}; + +void atmel_serial_initialize(void) +{ +	serial_register(&atmel_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &atmel_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/atmel_usart.h b/roms/u-boot/drivers/serial/atmel_usart.h new file mode 100644 index 00000000..7f919a29 --- /dev/null +++ b/roms/u-boot/drivers/serial/atmel_usart.h @@ -0,0 +1,294 @@ +/* + * Register definitions for the Atmel USART3 module. + * + * Copyright (C) 2005-2006 Atmel Corporation + * + * Modified to support C structure SoC access by + * Andreas Bießmann <biessmann@corscience.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#ifndef __DRIVERS_ATMEL_USART_H__ +#define __DRIVERS_ATMEL_USART_H__ + +/* USART3 register footprint */ +typedef struct atmel_usart3 { +	u32	cr; +	u32	mr; +	u32	ier; +	u32	idr; +	u32	imr; +	u32	csr; +	u32	rhr; +	u32	thr; +	u32	brgr; +	u32	rtor; +	u32	ttgr; +	u32	reserved0[5]; +	u32	fidi; +	u32	ner; +	u32	reserved1; +	u32	ifr; +	u32	man; +	u32	reserved2[54]; /* version and PDC not needed */ +} atmel_usart3_t; + +/* 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)) + +#endif /* __DRIVERS_ATMEL_USART_H__ */ diff --git a/roms/u-boot/drivers/serial/lpc32xx_hsuart.c b/roms/u-boot/drivers/serial/lpc32xx_hsuart.c new file mode 100644 index 00000000..c8926a89 --- /dev/null +++ b/roms/u-boot/drivers/serial/lpc32xx_hsuart.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 Vladimir Zapolskiy <vz@mleia.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/clk.h> +#include <asm/arch/uart.h> +#include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct hsuart_regs *hsuart = (struct hsuart_regs *)HS_UART_BASE; + +static void lpc32xx_serial_setbrg(void) +{ +	u32 div; + +	/* UART rate = PERIPH_CLK / ((HSU_RATE + 1) x 14) */ +	div = (get_serial_clock() / 14 + gd->baudrate / 2) / gd->baudrate - 1; +	if (div > 255) +		div = 255; + +	writel(div, &hsuart->rate); +} + +static int lpc32xx_serial_getc(void) +{ +	while (!(readl(&hsuart->level) & HSUART_LEVEL_RX)) +		/* NOP */; + +	return readl(&hsuart->rx) & HSUART_RX_DATA; +} + +static void lpc32xx_serial_putc(const char c) +{ +	if (c == '\n') +		serial_putc('\r'); + +	writel(c, &hsuart->tx); + +	/* Wait for character to be sent */ +	while (readl(&hsuart->level) & HSUART_LEVEL_TX) +		/* NOP */; +} + +static int lpc32xx_serial_tstc(void) +{ +	if (readl(&hsuart->level) & HSUART_LEVEL_RX) +		return 1; + +	return 0; +} + +static int lpc32xx_serial_init(void) +{ +	lpc32xx_serial_setbrg(); + +	/* Disable hardware RTS and CTS flow control, set up RX and TX FIFO */ +	writel(HSUART_CTRL_TMO_16 | HSUART_CTRL_HSU_OFFSET(20) | +	       HSUART_CTRL_HSU_RX_TRIG_32 | HSUART_CTRL_HSU_TX_TRIG_0, +	       &hsuart->ctrl); +	return 0; +} + +static struct serial_device lpc32xx_serial_drv = { +	.name	= "lpc32xx_serial", +	.start	= lpc32xx_serial_init, +	.stop	= NULL, +	.setbrg	= lpc32xx_serial_setbrg, +	.putc	= lpc32xx_serial_putc, +	.puts	= default_serial_puts, +	.getc	= lpc32xx_serial_getc, +	.tstc	= lpc32xx_serial_tstc, +}; + +void lpc32xx_serial_initialize(void) +{ +	serial_register(&lpc32xx_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &lpc32xx_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/mcfuart.c b/roms/u-boot/drivers/serial/mcfuart.c new file mode 100644 index 00000000..407354fc --- /dev/null +++ b/roms/u-boot/drivers/serial/mcfuart.c @@ -0,0 +1,130 @@ +/* + * (C) Copyright 2004-2007 Freescale Semiconductor, Inc. + * TsiChung Liew, Tsi-Chung.Liew@freescale.com. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * Minimal serial functions needed to use one of the uart ports + * as serial console interface. + */ + +#include <common.h> +#include <serial.h> +#include <linux/compiler.h> + +#include <asm/immap.h> +#include <asm/uart.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern void uart_port_conf(int port); + +static int mcf_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); +} + +static void mcf_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; +} + +static int mcf_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; +} + +static int mcf_serial_tstc(void) +{ +	volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE); + +	return (uart->usr & UART_USR_RXRDY); +} + +static void mcf_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; +} + +static struct serial_device mcf_serial_drv = { +	.name	= "mcf_serial", +	.start	= mcf_serial_init, +	.stop	= NULL, +	.setbrg	= mcf_serial_setbrg, +	.putc	= mcf_serial_putc, +	.puts	= default_serial_puts, +	.getc	= mcf_serial_getc, +	.tstc	= mcf_serial_tstc, +}; + +void mcf_serial_initialize(void) +{ +	serial_register(&mcf_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &mcf_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/mxs_auart.c b/roms/u-boot/drivers/serial/mxs_auart.c new file mode 100644 index 00000000..fc0fa96a --- /dev/null +++ b/roms/u-boot/drivers/serial/mxs_auart.c @@ -0,0 +1,151 @@ +/* + * Freescale i.MX23/i.MX28 AUART driver + * + * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com> + * + * Based on the MXC serial driver: + * + * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de> + * + * Further based on the Linux mxs-auart.c driver: + * + * Freescale STMP37XX/STMP38X Application UART drkiver + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ +#include <common.h> +#include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h> +#include <asm/arch/regs-base.h> +#include <asm/arch/regs-uartapp.h> +#include <asm/arch/sys_proto.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_MXS_AUART_BASE +#error "CONFIG_MXS_AUART_BASE must be set to the base UART to use" +#endif + +/* AUART clock always supplied by XTAL and always 24MHz */ +#define MXS_AUART_CLK 24000000 + +static struct mxs_uartapp_regs *get_uartapp_registers(void) +{ +	return (struct mxs_uartapp_regs *)CONFIG_MXS_AUART_BASE; +} + +/** + * Sets the baud rate and settings. + * The settings are: 8 data bits, no parit and 1 stop bit. + */ +static void mxs_auart_setbrg(void) +{ +	u32 div; +	u32 linectrl = 0; +	struct mxs_uartapp_regs *regs = get_uartapp_registers(); + +	if (!gd->baudrate) +		gd->baudrate = CONFIG_BAUDRATE; + +	/* +	 * From i.MX28 datasheet: +	 * div is calculated by calculating UARTCLK*32/baudrate, rounded to int +	 * div must be between 0xEC and 0x003FFFC0 inclusive +	 * Lowest 6 bits of div goes in BAUD_DIVFRAC part of LINECTRL register +	 * Next 16 bits goes in BAUD_DIVINT part of LINECTRL register +	 */ +	div = (MXS_AUART_CLK * 32) / gd->baudrate; +	if (div < 0xEC || div > 0x003FFFC0) +		return; + +	linectrl |= ((div & UARTAPP_LINECTRL_EXTRACT_BAUD_DIVFRAC_MASK) << +		UARTAPP_LINECTRL_BAUD_DIVFRAC_OFFSET) & +		UARTAPP_LINECTRL_BAUD_DIVFRAC_MASK; +	linectrl |= ((div >> UARTAPP_LINECTRL_EXTRACT_BAUD_DIVINT_OFFSET) << +		UARTAPP_LINECTRL_BAUD_DIVINT_OFFSET) & +		UARTAPP_LINECTRL_BAUD_DIVINT_MASK; + +	/* Word length: 8 bits */ +	linectrl |= UARTAPP_LINECTRL_WLEN_8BITS; + +	/* Enable FIFOs. */ +	linectrl |= UARTAPP_LINECTRL_FEN_MASK; + +	/* Write above settings, no parity, 1 stop bit */ +	writel(linectrl, ®s->hw_uartapp_linectrl); +} + +static int mxs_auart_init(void) +{ +	struct mxs_uartapp_regs *regs = get_uartapp_registers(); +	/* Reset everything */ +	mxs_reset_block(®s->hw_uartapp_ctrl0_reg); +	/* Disable interrupts */ +	writel(0, ®s->hw_uartapp_intr); +	/* Set baud rate and settings */ +	serial_setbrg(); +	/* Disable RTS and CTS, ignore LINECTRL2 register */ +	writel(UARTAPP_CTRL2_RTSEN_MASK | +			UARTAPP_CTRL2_CTSEN_MASK | +			UARTAPP_CTRL2_USE_LCR2_MASK, +			®s->hw_uartapp_ctrl2_clr); +	/* Enable receiver, transmitter and UART */ +	writel(UARTAPP_CTRL2_RXE_MASK | +			UARTAPP_CTRL2_TXE_MASK | +			UARTAPP_CTRL2_UARTEN_MASK, +			®s->hw_uartapp_ctrl2_set); +	return 0; +} + +static void mxs_auart_putc(const char c) +{ +	struct mxs_uartapp_regs *regs = get_uartapp_registers(); +	/* Wait in loop while the transmit FIFO is full */ +	while (readl(®s->hw_uartapp_stat) & UARTAPP_STAT_TXFF_MASK) +		; + +	writel(c, ®s->hw_uartapp_data); + +	if (c == '\n') +		mxs_auart_putc('\r'); +} + +static int mxs_auart_tstc(void) +{ +	struct mxs_uartapp_regs *regs = get_uartapp_registers(); +	/* Checks if receive FIFO is empty */ +	return !(readl(®s->hw_uartapp_stat) & UARTAPP_STAT_RXFE_MASK); +} + +static int mxs_auart_getc(void) +{ +	struct mxs_uartapp_regs *regs = get_uartapp_registers(); +	/* Wait until a character is available to read */ +	while (!mxs_auart_tstc()) +		; +	/* Read the character from the data register */ +	return readl(®s->hw_uartapp_data) & 0xFF; +} + +static struct serial_device mxs_auart_drv = { +	.name = "mxs_auart_serial", +	.start = mxs_auart_init, +	.stop = NULL, +	.setbrg = mxs_auart_setbrg, +	.putc = mxs_auart_putc, +	.puts = default_serial_puts, +	.getc = mxs_auart_getc, +	.tstc = mxs_auart_tstc, +}; + +void mxs_auart_initialize(void) +{ +	serial_register(&mxs_auart_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &mxs_auart_drv; +} diff --git a/roms/u-boot/drivers/serial/ns16550.c b/roms/u-boot/drivers/serial/ns16550.c new file mode 100644 index 00000000..f26979db --- /dev/null +++ b/roms/u-boot/drivers/serial/ns16550.c @@ -0,0 +1,147 @@ +/* + * 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) +#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0) +#define serial_out(x, y)	out_be32(y, x) +#define serial_in(y)		in_be32(y) +#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0) +#define serial_out(x, y)	out_le32(y, x) +#define serial_in(y)		in_le32(y) +#else +#define serial_out(x, y)	writeb(x, y) +#define serial_in(y)		readb(y) +#endif + +#if defined(CONFIG_K2HK_EVM) +#define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE   0 +#define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0)) +#undef UART_MCRVAL +#ifdef CONFIG_SERIAL_HW_FLOW_CONTROL +#define UART_MCRVAL             (UART_MCR_RTS | UART_MCR_AFE) +#else +#define UART_MCRVAL             (UART_MCR_RTS) +#endif +#endif + +#ifndef CONFIG_SYS_NS16550_IER +#define CONFIG_SYS_NS16550_IER  0x00 +#endif /* CONFIG_SYS_NS16550_IER */ + +void NS16550_init(NS16550_t com_port, int baud_divisor) +{ +#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_OMAP34XX)) +	/* +	 * On some OMAP3 devices when UART3 is configured for boot mode before +	 * SPL starts only THRE bit is set. We have to empty the transmitter +	 * before initialization starts. +	 */ +	if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE)) +	     == UART_LSR_THRE) { +		serial_out(UART_LCR_DLAB, &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); +		serial_out(0, &com_port->mdr1); +	} +#endif + +	while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT)) +		; + +	serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier); +#if defined(CONFIG_OMAP) || defined(CONFIG_AM33XX) || \ +			defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) +	serial_out(0x7, &com_port->mdr1);	/* mode select reset TL16C750*/ +#endif +	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 | 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)) || \ +	defined(CONFIG_AM33XX) || defined(CONFIG_SOC_DA8XX) || \ +	defined(CONFIG_TI81XX) || defined(CONFIG_AM43XX) + +	/* /16 is proper to hit 115200 with 48MHz */ +	serial_out(0, &com_port->mdr1); +#endif /* CONFIG_OMAP */ +#if defined(CONFIG_K2HK_EVM) +	serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC); +#endif +} + +#ifndef CONFIG_NS16550_MIN_FUNCTIONS +void NS16550_reinit(NS16550_t com_port, int baud_divisor) +{ +	serial_out(CONFIG_SYS_NS16550_IER, &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); + +	/* +	 * Call watchdog_reset() upon newline. This is done here in putc +	 * since the environment code uses a single puts() to print the complete +	 * environment upon "printenv". So we can't put this watchdog call +	 * in puts(). +	 */ +	if (c == '\n') +		WATCHDOG_RESET(); +} + +#ifndef CONFIG_NS16550_MIN_FUNCTIONS +char NS16550_getc(NS16550_t com_port) +{ +	while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { +#if !defined(CONFIG_SPL_BUILD) && defined(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/drivers/serial/opencores_yanu.c b/roms/u-boot/drivers/serial/opencores_yanu.c new file mode 100644 index 00000000..d4ed60c3 --- /dev/null +++ b/roms/u-boot/drivers/serial/opencores_yanu.c @@ -0,0 +1,157 @@ +/* + * Copyright 2010, Renato Andreola <renato.andreola@imagos.it> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <nios2-yanu.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +/*-----------------------------------------------------------------*/ +/* YANU Imagos serial port */ +/*-----------------------------------------------------------------*/ + +static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE; + +static void oc_serial_setbrg(void) +{ +	int n, k; +	const unsigned max_uns = 0xFFFFFFFF; +	unsigned best_n, best_m, baud; +	unsigned baudrate; + +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) +	/* Everything's already setup for fixed-baud PTF assignment */ +	baudrate = CONFIG_BAUDRATE; +#else +	baudrate = gd->baudrate; +#endif +	/* 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)) >= +		    baudrate) { +			best_n = n; +			break; +		} +	} +	for (k = 0;; k++) { +		if (baudrate <= (max_uns >> (15+n-k))) +			break; +	} +	best_m = +	    (baudrate * (1 << (15 + n - k))) / +	    ((unsigned)CONFIG_SYS_CLK_FREQ >> k); + +	baud = best_m + best_n * YANU_BAUDE; +	writel(baud, &uart->baud); + +	return; +} + +static int oc_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 + *---------------------------------------------------------------------*/ +static void oc_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); +} + +static int oc_serial_tstc(void) +{ +	unsigned status ; + +	status = readl(&uart->status); +	return (((status >> YANU_RFIFO_CHARS_POS) & +		 ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0); +} + +static int oc_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); +} + +static struct serial_device oc_serial_drv = { +	.name	= "oc_serial", +	.start	= oc_serial_init, +	.stop	= NULL, +	.setbrg	= oc_serial_setbrg, +	.putc	= oc_serial_putc, +	.puts	= default_serial_puts, +	.getc	= oc_serial_getc, +	.tstc	= oc_serial_tstc, +}; + +void oc_serial_initialize(void) +{ +	serial_register(&oc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &oc_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/sandbox.c b/roms/u-boot/drivers/serial/sandbox.c new file mode 100644 index 00000000..51fd871d --- /dev/null +++ b/roms/u-boot/drivers/serial/sandbox.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * This provide a test serial port. It provides an emulated serial port where + * a test program and read out the serial output and inject serial input for + * U-Boot. + */ + +#include <common.h> +#include <lcd.h> +#include <os.h> +#include <serial.h> +#include <linux/compiler.h> +#include <asm/state.h> + +/* + * + *   serial_buf: A buffer that holds keyboard characters for the + *		 Sandbox U-boot. + * + * invariants: + *   serial_buf_write		 == serial_buf_read -> empty buffer + *   (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer + */ +static char serial_buf[16]; +static unsigned int serial_buf_write; +static unsigned int serial_buf_read; + +static int sandbox_serial_init(void) +{ +	struct sandbox_state *state = state_get_current(); + +	if (state->term_raw != STATE_TERM_COOKED) +		os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS); +	return 0; +} + +static void sandbox_serial_setbrg(void) +{ +} + +static void sandbox_serial_putc(const char ch) +{ +	os_write(1, &ch, 1); +} + +static void sandbox_serial_puts(const char *str) +{ +	os_write(1, str, strlen(str)); +} + +static unsigned int increment_buffer_index(unsigned int index) +{ +	return (index + 1) % ARRAY_SIZE(serial_buf); +} + +static int sandbox_serial_tstc(void) +{ +	const unsigned int next_index = +		increment_buffer_index(serial_buf_write); +	ssize_t count; + +	os_usleep(100); +#ifdef CONFIG_LCD +	lcd_sync(); +#endif +	if (next_index == serial_buf_read) +		return 1;	/* buffer full */ + +	count = os_read_no_block(0, &serial_buf[serial_buf_write], 1); +	if (count == 1) +		serial_buf_write = next_index; +	return serial_buf_write != serial_buf_read; +} + +static int sandbox_serial_getc(void) +{ +	int result; + +	while (!sandbox_serial_tstc()) +		;	/* buffer empty */ + +	result = serial_buf[serial_buf_read]; +	serial_buf_read = increment_buffer_index(serial_buf_read); +	return result; +} + +static struct serial_device sandbox_serial_drv = { +	.name	= "sandbox_serial", +	.start	= sandbox_serial_init, +	.stop	= NULL, +	.setbrg	= sandbox_serial_setbrg, +	.putc	= sandbox_serial_putc, +	.puts	= sandbox_serial_puts, +	.getc	= sandbox_serial_getc, +	.tstc	= sandbox_serial_tstc, +}; + +void sandbox_serial_initialize(void) +{ +	serial_register(&sandbox_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sandbox_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial.c b/roms/u-boot/drivers/serial/serial.c new file mode 100644 index 00000000..fd61a5e5 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial.c @@ -0,0 +1,577 @@ +/* + * (C) Copyright 2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <environment.h> +#include <serial.h> +#include <stdio_dev.h> +#include <post.h> +#include <linux/compiler.h> +#include <errno.h> + +DECLARE_GLOBAL_DATA_PTR; + +static struct serial_device *serial_devices; +static struct serial_device *serial_current; +/* + * Table with supported baudrates (defined in config_xyz.h) + */ +static const unsigned long baudrate_table[] = CONFIG_SYS_BAUDRATE_TABLE; + +/** + * serial_null() - Void registration routine of a serial driver + * + * This routine implements a void registration routine of a serial + * driver. The registration routine of a particular driver is aliased + * to this empty function in case the driver is not compiled into + * U-Boot. + */ +static void serial_null(void) +{ +} + +/** + * on_baudrate() - Update the actual baudrate when the env var changes + * + * This will check for a valid baudrate and only apply it if valid. + */ +static int on_baudrate(const char *name, const char *value, enum env_op op, +	int flags) +{ +	int i; +	int baudrate; + +	switch (op) { +	case env_op_create: +	case env_op_overwrite: +		/* +		 * Switch to new baudrate if new baudrate is supported +		 */ +		baudrate = simple_strtoul(value, NULL, 10); + +		/* Not actually changing */ +		if (gd->baudrate == baudrate) +			return 0; + +		for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) { +			if (baudrate == baudrate_table[i]) +				break; +		} +		if (i == ARRAY_SIZE(baudrate_table)) { +			if ((flags & H_FORCE) == 0) +				printf("## Baudrate %d bps not supported\n", +					baudrate); +			return 1; +		} +		if ((flags & H_INTERACTIVE) != 0) { +			printf("## Switch baudrate to %d" +				" bps and press ENTER ...\n", baudrate); +			udelay(50000); +		} + +		gd->baudrate = baudrate; + +		serial_setbrg(); + +		udelay(50000); + +		if ((flags & H_INTERACTIVE) != 0) +			while (1) { +				if (getc() == '\r') +					break; +			} + +		return 0; +	case env_op_delete: +		printf("## Baudrate may not be deleted\n"); +		return 1; +	default: +		return 0; +	} +} +U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); + +/** + * serial_initfunc() - Forward declare of driver registration routine + * @name:	Name of the real driver registration routine. + * + * This macro expands onto forward declaration of a driver registration + * routine, which is then used below in serial_initialize() function. + * The declaration is made weak and aliases to serial_null() so in case + * the driver is not compiled in, the function is still declared and can + * be used, but aliases to serial_null() and thus is optimized away. + */ +#define serial_initfunc(name)					\ +	void name(void)						\ +		__attribute__((weak, alias("serial_null"))); + +serial_initfunc(mpc8xx_serial_initialize); +serial_initfunc(ns16550_serial_initialize); +serial_initfunc(pxa_serial_initialize); +serial_initfunc(s3c24xx_serial_initialize); +serial_initfunc(s5p_serial_initialize); +serial_initfunc(zynq_serial_initialize); +serial_initfunc(bfin_serial_initialize); +serial_initfunc(bfin_jtag_initialize); +serial_initfunc(mpc512x_serial_initialize); +serial_initfunc(uartlite_serial_initialize); +serial_initfunc(au1x00_serial_initialize); +serial_initfunc(asc_serial_initialize); +serial_initfunc(jz_serial_initialize); +serial_initfunc(mpc5xx_serial_initialize); +serial_initfunc(mpc8260_scc_serial_initialize); +serial_initfunc(mpc8260_smc_serial_initialize); +serial_initfunc(mpc85xx_serial_initialize); +serial_initfunc(iop480_serial_initialize); +serial_initfunc(leon2_serial_initialize); +serial_initfunc(leon3_serial_initialize); +serial_initfunc(marvell_serial_initialize); +serial_initfunc(amirix_serial_initialize); +serial_initfunc(bmw_serial_initialize); +serial_initfunc(cogent_serial_initialize); +serial_initfunc(cpci750_serial_initialize); +serial_initfunc(evb64260_serial_initialize); +serial_initfunc(ml2_serial_initialize); +serial_initfunc(sconsole_serial_initialize); +serial_initfunc(p3mx_serial_initialize); +serial_initfunc(altera_jtag_serial_initialize); +serial_initfunc(altera_serial_initialize); +serial_initfunc(atmel_serial_initialize); +serial_initfunc(lpc32xx_serial_initialize); +serial_initfunc(mcf_serial_initialize); +serial_initfunc(oc_serial_initialize); +serial_initfunc(sandbox_serial_initialize); +serial_initfunc(clps7111_serial_initialize); +serial_initfunc(imx_serial_initialize); +serial_initfunc(ks8695_serial_initialize); +serial_initfunc(lh7a40x_serial_initialize); +serial_initfunc(max3100_serial_initialize); +serial_initfunc(mxc_serial_initialize); +serial_initfunc(pl01x_serial_initialize); +serial_initfunc(sa1100_serial_initialize); +serial_initfunc(sh_serial_initialize); +serial_initfunc(arm_dcc_initialize); +serial_initfunc(mxs_auart_initialize); +serial_initfunc(arc_serial_initialize); + +/** + * serial_register() - Register serial driver with serial driver core + * @dev:	Pointer to the serial driver structure + * + * This function registers the serial driver supplied via @dev with + * serial driver core, thus making U-Boot aware of it and making it + * available for U-Boot to use. On platforms that still require manual + * relocation of constant variables, relocation of the supplied structure + * is performed. + */ +void serial_register(struct serial_device *dev) +{ +#ifdef CONFIG_NEEDS_MANUAL_RELOC +	if (dev->start) +		dev->start += gd->reloc_off; +	if (dev->stop) +		dev->stop += gd->reloc_off; +	if (dev->setbrg) +		dev->setbrg += gd->reloc_off; +	if (dev->getc) +		dev->getc += gd->reloc_off; +	if (dev->tstc) +		dev->tstc += gd->reloc_off; +	if (dev->putc) +		dev->putc += gd->reloc_off; +	if (dev->puts) +		dev->puts += gd->reloc_off; +#endif + +	dev->next = serial_devices; +	serial_devices = dev; +} + +/** + * serial_initialize() - Register all compiled-in serial port drivers + * + * This function registers all serial port drivers that are compiled + * into the U-Boot binary with the serial core, thus making them + * available to U-Boot to use. Lastly, this function assigns a default + * serial port to the serial core. That serial port is then used as a + * default output. + */ +void serial_initialize(void) +{ +	mpc8xx_serial_initialize(); +	ns16550_serial_initialize(); +	pxa_serial_initialize(); +	s3c24xx_serial_initialize(); +	s5p_serial_initialize(); +	mpc512x_serial_initialize(); +	bfin_serial_initialize(); +	bfin_jtag_initialize(); +	uartlite_serial_initialize(); +	zynq_serial_initialize(); +	au1x00_serial_initialize(); +	asc_serial_initialize(); +	jz_serial_initialize(); +	mpc5xx_serial_initialize(); +	mpc8260_scc_serial_initialize(); +	mpc8260_smc_serial_initialize(); +	mpc85xx_serial_initialize(); +	iop480_serial_initialize(); +	leon2_serial_initialize(); +	leon3_serial_initialize(); +	marvell_serial_initialize(); +	amirix_serial_initialize(); +	bmw_serial_initialize(); +	cogent_serial_initialize(); +	cpci750_serial_initialize(); +	evb64260_serial_initialize(); +	ml2_serial_initialize(); +	sconsole_serial_initialize(); +	p3mx_serial_initialize(); +	altera_jtag_serial_initialize(); +	altera_serial_initialize(); +	atmel_serial_initialize(); +	lpc32xx_serial_initialize(); +	mcf_serial_initialize(); +	oc_serial_initialize(); +	sandbox_serial_initialize(); +	clps7111_serial_initialize(); +	imx_serial_initialize(); +	ks8695_serial_initialize(); +	lh7a40x_serial_initialize(); +	max3100_serial_initialize(); +	mxc_serial_initialize(); +	pl01x_serial_initialize(); +	sa1100_serial_initialize(); +	sh_serial_initialize(); +	arm_dcc_initialize(); +	mxs_auart_initialize(); +	arc_serial_initialize(); + +	serial_assign(default_serial_console()->name); +} + +/** + * serial_stdio_init() - Register serial ports with STDIO core + * + * This function generates a proxy driver for each serial port driver. + * These proxy drivers then register with the STDIO core, making the + * serial drivers available as STDIO devices. + */ +void serial_stdio_init(void) +{ +	struct stdio_dev dev; +	struct serial_device *s = serial_devices; + +	while (s) { +		memset(&dev, 0, sizeof(dev)); + +		strcpy(dev.name, s->name); +		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; + +		dev.start = s->start; +		dev.stop = s->stop; +		dev.putc = s->putc; +		dev.puts = s->puts; +		dev.getc = s->getc; +		dev.tstc = s->tstc; + +		stdio_register(&dev); + +		s = s->next; +	} +} + +/** + * serial_assign() - Select the serial output device by name + * @name:	Name of the serial driver to be used as default output + * + * This function configures the serial output multiplexing by + * selecting which serial device will be used as default. In case + * the STDIO "serial" device is selected as stdin/stdout/stderr, + * the serial device previously configured by this function will be + * used for the particular operation. + * + * Returns 0 on success, negative on error. + */ +int serial_assign(const char *name) +{ +	struct serial_device *s; + +	for (s = serial_devices; s; s = s->next) { +		if (strcmp(s->name, name)) +			continue; +		serial_current = s; +		return 0; +	} + +	return -EINVAL; +} + +/** + * serial_reinit_all() - Reinitialize all compiled-in serial ports + * + * This function reinitializes all serial ports that are compiled + * into U-Boot by calling their serial_start() functions. + */ +void serial_reinit_all(void) +{ +	struct serial_device *s; + +	for (s = serial_devices; s; s = s->next) +		s->start(); +} + +/** + * get_current() - Return pointer to currently selected serial port + * + * This function returns a pointer to currently selected serial port. + * The currently selected serial port is altered by serial_assign() + * function. + * + * In case this function is called before relocation or before any serial + * port is configured, this function calls default_serial_console() to + * determine the serial port. Otherwise, the configured serial port is + * returned. + * + * Returns pointer to the currently selected serial port on success, + * NULL on error. + */ +static struct serial_device *get_current(void) +{ +	struct serial_device *dev; + +	if (!(gd->flags & GD_FLG_RELOC)) +		dev = default_serial_console(); +	else if (!serial_current) +		dev = default_serial_console(); +	else +		dev = serial_current; + +	/* We must have a console device */ +	if (!dev) { +#ifdef CONFIG_SPL_BUILD +		puts("Cannot find console\n"); +		hang(); +#else +		panic("Cannot find console\n"); +#endif +	} + +	return dev; +} + +/** + * serial_init() - Initialize currently selected serial port + * + * This function initializes the currently selected serial port. This + * usually involves setting up the registers of that particular port, + * enabling clock and such. This function uses the get_current() call + * to determine which port is selected. + * + * Returns 0 on success, negative on error. + */ +int serial_init(void) +{ +	return get_current()->start(); +} + +/** + * serial_setbrg() - Configure baud-rate of currently selected serial port + * + * This function configures the baud-rate of the currently selected + * serial port. The baud-rate is retrieved from global data within + * the serial port driver. This function uses the get_current() call + * to determine which port is selected. + * + * Returns 0 on success, negative on error. + */ +void serial_setbrg(void) +{ +	get_current()->setbrg(); +} + +/** + * serial_getc() - Read character from currently selected serial port + * + * This function retrieves a character from currently selected serial + * port. In case there is no character waiting on the serial port, + * this function will block and wait for the character to appear. This + * function uses the get_current() call to determine which port is + * selected. + * + * Returns the character on success, negative on error. + */ +int serial_getc(void) +{ +	return get_current()->getc(); +} + +/** + * serial_tstc() - Test if data is available on currently selected serial port + * + * This function tests if one or more characters are available on + * currently selected serial port. This function never blocks. This + * function uses the get_current() call to determine which port is + * selected. + * + * Returns positive if character is available, zero otherwise. + */ +int serial_tstc(void) +{ +	return get_current()->tstc(); +} + +/** + * serial_putc() - Output character via currently selected serial port + * @c:	Single character to be output from the serial port. + * + * This function outputs a character via currently selected serial + * port. This character is passed to the serial port driver responsible + * for controlling the hardware. The hardware may still be in process + * of transmitting another character, therefore this function may block + * for a short amount of time. This function uses the get_current() + * call to determine which port is selected. + */ +void serial_putc(const char c) +{ +	get_current()->putc(c); +} + +/** + * serial_puts() - Output string via currently selected serial port + * @s:	Zero-terminated string to be output from the serial port. + * + * This function outputs a zero-terminated string via currently + * selected serial port. This function behaves as an accelerator + * in case the hardware can queue multiple characters for transfer. + * The whole string that is to be output is available to the function + * implementing the hardware manipulation. Transmitting the whole + * string may take some time, thus this function may block for some + * amount of time. This function uses the get_current() call to + * determine which port is selected. + */ +void serial_puts(const char *s) +{ +	get_current()->puts(s); +} + +/** + * default_serial_puts() - Output string by calling serial_putc() in loop + * @s:	Zero-terminated string to be output from the serial port. + * + * This function outputs a zero-terminated string by calling serial_putc() + * in a loop. Most drivers do not support queueing more than one byte for + * transfer, thus this function precisely implements their serial_puts(). + * + * To optimize the number of get_current() calls, this function only + * calls get_current() once and then directly accesses the putc() call + * of the &struct serial_device . + */ +void default_serial_puts(const char *s) +{ +	struct serial_device *dev = get_current(); +	while (*s) +		dev->putc(*s++); +} + +#if CONFIG_POST & CONFIG_SYS_POST_UART +static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE; + +/** + * uart_post_test() - Test the currently selected serial port using POST + * @flags:	POST framework flags + * + * Do a loopback test of the currently selected serial port. This + * function is only useful in the context of the POST testing framwork. + * The serial port is firstly configured into loopback mode and then + * characters are sent through it. + * + * Returns 0 on success, value otherwise. + */ +/* Mark weak until post/cpu/.../uart.c migrate over */ +__weak +int uart_post_test(int flags) +{ +	unsigned char c; +	int ret, saved_baud, b; +	struct serial_device *saved_dev, *s; + +	/* Save current serial state */ +	ret = 0; +	saved_dev = serial_current; +	saved_baud = gd->baudrate; + +	for (s = serial_devices; s; s = s->next) { +		/* If this driver doesn't support loop back, skip it */ +		if (!s->loop) +			continue; + +		/* Test the next device */ +		serial_current = s; + +		ret = serial_init(); +		if (ret) +			goto done; + +		/* Consume anything that happens to be queued */ +		while (serial_tstc()) +			serial_getc(); + +		/* Enable loop back */ +		s->loop(1); + +		/* Test every available baud rate */ +		for (b = 0; b < ARRAY_SIZE(bauds); ++b) { +			gd->baudrate = bauds[b]; +			serial_setbrg(); + +			/* +			 * Stick to printable chars to avoid issues: +			 *  - terminal corruption +			 *  - serial program reacting to sequences and sending +			 *    back random extra data +			 *  - most serial drivers add in extra chars (like \r\n) +			 */ +			for (c = 0x20; c < 0x7f; ++c) { +				/* Send it out */ +				serial_putc(c); + +				/* Make sure it's the same one */ +				ret = (c != serial_getc()); +				if (ret) { +					s->loop(0); +					goto done; +				} + +				/* Clean up the output in case it was sent */ +				serial_putc('\b'); +				ret = ('\b' != serial_getc()); +				if (ret) { +					s->loop(0); +					goto done; +				} +			} +		} + +		/* Disable loop back */ +		s->loop(0); + +		/* XXX: There is no serial_stop() !? */ +		if (s->stop) +			s->stop(); +	} + + done: +	/* Restore previous serial state */ +	serial_current = saved_dev; +	gd->baudrate = saved_baud; +	serial_reinit_all(); +	serial_setbrg(); + +	return ret; +} +#endif diff --git a/roms/u-boot/drivers/serial/serial_arc.c b/roms/u-boot/drivers/serial/serial_arc.c new file mode 100644 index 00000000..2ddbf32a --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_arc.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.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. + * + */ + +#include <common.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct arc_serial_regs { +	unsigned int id0; +	unsigned int id1; +	unsigned int id2; +	unsigned int id3; +	unsigned int data; +	unsigned int status; +	unsigned int baudl; +	unsigned int baudh; +}; + +/* Bit definitions of STATUS register */ +#define UART_RXEMPTY		(1 << 5) +#define UART_OVERFLOW_ERR	(1 << 1) +#define UART_TXEMPTY		(1 << 7) + +struct arc_serial_regs *regs; + +static void arc_serial_setbrg(void) +{ +	int arc_console_baud; + +	if (!gd->baudrate) +		gd->baudrate = CONFIG_BAUDRATE; + +	arc_console_baud = gd->cpu_clk / (gd->baudrate * 4) - 1; +	writeb(arc_console_baud & 0xff, ®s->baudl); + +#ifdef CONFIG_ARC +	/* +	 * UART ISS(Instruction Set simulator) emulation has a subtle bug: +	 * A existing value of Baudh = 0 is used as a indication to startup +	 * it's internal state machine. +	 * Thus if baudh is set to 0, 2 times, it chokes. +	 * This happens with BAUD=115200 and the formaula above +	 * Until that is fixed, when running on ISS, we will set baudh to !0 +	 */ +	if (gd->arch.running_on_hw) +		writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh); +	else +		writeb(1, ®s->baudh); +#else +	writeb((arc_console_baud & 0xff00) >> 8, ®s->baudh); +#endif +} + +static int arc_serial_init(void) +{ +	regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE; +	serial_setbrg(); +	return 0; +} + +static void arc_serial_putc(const char c) +{ +	if (c == '\n') +		arc_serial_putc('\r'); + +	while (!(readb(®s->status) & UART_TXEMPTY)) +		; + +	writeb(c, ®s->data); +} + +static int arc_serial_tstc(void) +{ +	return !(readb(®s->status) & UART_RXEMPTY); +} + +static int arc_serial_getc(void) +{ +	while (!arc_serial_tstc()) +		; + +	/* Check for overflow errors */ +	if (readb(®s->status) & UART_OVERFLOW_ERR) +		return 0; + +	return readb(®s->data) & 0xFF; +} + +static struct serial_device arc_serial_drv = { +	.name	= "arc_serial", +	.start	= arc_serial_init, +	.stop	= NULL, +	.setbrg	= arc_serial_setbrg, +	.putc	= arc_serial_putc, +	.puts	= default_serial_puts, +	.getc	= arc_serial_getc, +	.tstc	= arc_serial_tstc, +}; + +void arc_serial_initialize(void) +{ +	serial_register(&arc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &arc_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_bfin.c b/roms/u-boot/drivers/serial/serial_bfin.c new file mode 100644 index 00000000..0443b842 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_bfin.c @@ -0,0 +1,411 @@ +/* + * U-boot - serial.c Blackfin Serial Driver + * + * Copyright (c) 2005-2008 Analog Devices Inc. + * + * Copyright (c) 2003	Bas Vermeulen <bas@buyways.nl>, + *			BuyWays B.V. (www.buyways.nl) + * + * Based heavily on: + * 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. + * + * Licensed under the GPL-2 or later. + */ + +/* Anomaly notes: + *  05000086 - we don't support autobaud + *  05000099 - we only use DR bit, so losing others is not a problem + *  05000100 - we don't use the UART_IIR register + *  05000215 - we poll the uart (no dma/interrupts) + *  05000225 - no workaround possible, but this shouldnt cause errors ... + *  05000230 - we tweak the baud rate calculation slightly + *  05000231 - we always use 1 stop bit + *  05000309 - we always enable the uart before we modify it in anyway + *  05000350 - we always enable the uart regardless of boot mode + *  05000363 - we don't support break signals, so don't generate one + */ + +#include <common.h> +#include <post.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/compiler.h> +#include <asm/blackfin.h> +#include <asm/serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_UART_CONSOLE + +#ifdef CONFIG_DEBUG_SERIAL +static uart_lsr_t cached_lsr[256]; +static uart_lsr_t cached_rbr[256]; +static size_t cache_count; + +/* The LSR is read-to-clear on some parts, so we have to make sure status + * bits aren't inadvertently lost when doing various tests.  This also + * works around anomaly 05000099 at the same time by keeping a cumulative + * tally of all the status bits. + */ +static uart_lsr_t uart_lsr_save; +static uart_lsr_t uart_lsr_read(uint32_t uart_base) +{ +	uart_lsr_t lsr = _lsr_read(pUART); +	uart_lsr_save |= (lsr & (OE|PE|FE|BI)); +	return lsr | uart_lsr_save; +} +/* Just do the clear for everyone since it can't hurt. */ +static void uart_lsr_clear(uint32_t uart_base) +{ +	uart_lsr_save = 0; +	_lsr_write(pUART, -1); +} +#else +/* When debugging is disabled, we only care about the DR bit, so if other + * bits get set/cleared, we don't really care since we don't read them + * anyways (and thus anomaly 05000099 is irrelevant). + */ +static inline uart_lsr_t uart_lsr_read(uint32_t uart_base) +{ +	return _lsr_read(pUART); +} +static void uart_lsr_clear(uint32_t uart_base) +{ +	_lsr_write(pUART, -1); +} +#endif + +static void uart_putc(uint32_t uart_base, const char c) +{ +	/* send a \r for compatibility */ +	if (c == '\n') +		serial_putc('\r'); + +	WATCHDOG_RESET(); + +	/* wait for the hardware fifo to clear up */ +	while (!(uart_lsr_read(uart_base) & THRE)) +		continue; + +	/* queue the character for transmission */ +	bfin_write(&pUART->thr, c); +	SSYNC(); + +	WATCHDOG_RESET(); +} + +static int uart_tstc(uint32_t uart_base) +{ +	WATCHDOG_RESET(); +	return (uart_lsr_read(uart_base) & DR) ? 1 : 0; +} + +static int uart_getc(uint32_t uart_base) +{ +	uint16_t uart_rbr_val; + +	/* wait for data ! */ +	while (!uart_tstc(uart_base)) +		continue; + +	/* grab the new byte */ +	uart_rbr_val = bfin_read(&pUART->rbr); + +#ifdef CONFIG_DEBUG_SERIAL +	/* grab & clear the LSR */ +	uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base); + +	cached_lsr[cache_count] = uart_lsr_val; +	cached_rbr[cache_count] = uart_rbr_val; +	cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr); + +	if (uart_lsr_val & (OE|PE|FE|BI)) { +		printf("\n[SERIAL ERROR]\n"); +		do { +			--cache_count; +			printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count, +				cached_rbr[cache_count], cached_lsr[cache_count]); +		} while (cache_count > 0); +		return -1; +	} +#endif +	uart_lsr_clear(uart_base); + +	return uart_rbr_val; +} + +#if CONFIG_POST & CONFIG_SYS_POST_UART +# define LOOP(x) x +#else +# define LOOP(x) +#endif + +#if BFIN_UART_HW_VER < 4 + +LOOP( +static void uart_loop(uint32_t uart_base, int state) +{ +	u16 mcr; + +	/* Drain the TX fifo first so bytes don't come back */ +	while (!(uart_lsr_read(uart_base) & TEMT)) +		continue; + +	mcr = bfin_read(&pUART->mcr); +	if (state) +		mcr |= LOOP_ENA | MRTS; +	else +		mcr &= ~(LOOP_ENA | MRTS); +	bfin_write(&pUART->mcr, mcr); +} +) + +#else + +LOOP( +static void uart_loop(uint32_t uart_base, int state) +{ +	u32 control; + +	/* Drain the TX fifo first so bytes don't come back */ +	while (!(uart_lsr_read(uart_base) & TEMT)) +		continue; + +	control = bfin_read(&pUART->control); +	if (state) +		control |= LOOP_ENA | MRTS; +	else +		control &= ~(LOOP_ENA | MRTS); +	bfin_write(&pUART->control, control); +} +) + +#endif + +static inline void __serial_set_baud(uint32_t uart_base, uint32_t baud) +{ +#ifdef CONFIG_DEBUG_EARLY_SERIAL +	serial_early_set_baud(uart_base, baud); +#else +	uint16_t divisor = (get_uart_clk() + (baud * 8)) / (baud * 16) +			- ANOMALY_05000230; + +	/* Program the divisor to get the baud rate we want */ +	serial_set_divisor(uart_base, divisor); +#endif +} + +static void uart_puts(uint32_t uart_base, const char *s) +{ +	while (*s) +		uart_putc(uart_base, *s++); +} + +#define DECL_BFIN_UART(n) \ +static int uart##n##_init(void) \ +{ \ +	const unsigned short pins[] = { _P_UART(n, RX), _P_UART(n, TX), 0, }; \ +	peripheral_request_list(pins, "bfin-uart"); \ +	uart_init(MMR_UART(n)); \ +	__serial_set_baud(MMR_UART(n), gd->baudrate); \ +	uart_lsr_clear(MMR_UART(n)); \ +	return 0; \ +} \ +\ +static int uart##n##_uninit(void) \ +{ \ +	return serial_early_uninit(MMR_UART(n)); \ +} \ +\ +static void uart##n##_setbrg(void) \ +{ \ +	__serial_set_baud(MMR_UART(n), gd->baudrate); \ +} \ +\ +static int uart##n##_getc(void) \ +{ \ +	return uart_getc(MMR_UART(n)); \ +} \ +\ +static int uart##n##_tstc(void) \ +{ \ +	return uart_tstc(MMR_UART(n)); \ +} \ +\ +static void uart##n##_putc(const char c) \ +{ \ +	uart_putc(MMR_UART(n), c); \ +} \ +\ +static void uart##n##_puts(const char *s) \ +{ \ +	uart_puts(MMR_UART(n), s); \ +} \ +\ +LOOP( \ +static void uart##n##_loop(int state) \ +{ \ +	uart_loop(MMR_UART(n), state); \ +} \ +) \ +\ +struct serial_device bfin_serial##n##_device = { \ +	.name   = "bfin_uart"#n, \ +	.start  = uart##n##_init, \ +	.stop   = uart##n##_uninit, \ +	.setbrg = uart##n##_setbrg, \ +	.getc   = uart##n##_getc, \ +	.tstc   = uart##n##_tstc, \ +	.putc   = uart##n##_putc, \ +	.puts   = uart##n##_puts, \ +	LOOP(.loop = uart##n##_loop) \ +}; + +#ifdef UART0_RBR +DECL_BFIN_UART(0) +#endif +#ifdef UART1_RBR +DECL_BFIN_UART(1) +#endif +#ifdef UART2_RBR +DECL_BFIN_UART(2) +#endif +#ifdef UART3_RBR +DECL_BFIN_UART(3) +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_UART_CONSOLE == 0 +	return &bfin_serial0_device; +#elif CONFIG_UART_CONSOLE == 1 +	return &bfin_serial1_device; +#elif CONFIG_UART_CONSOLE == 2 +	return &bfin_serial2_device; +#elif CONFIG_UART_CONSOLE == 3 +	return &bfin_serial3_device; +#endif +} + +void bfin_serial_initialize(void) +{ +#ifdef UART0_RBR +	serial_register(&bfin_serial0_device); +#endif +#ifdef UART1_RBR +	serial_register(&bfin_serial1_device); +#endif +#ifdef UART2_RBR +	serial_register(&bfin_serial2_device); +#endif +#ifdef UART3_RBR +	serial_register(&bfin_serial3_device); +#endif +} + +#ifdef CONFIG_DEBUG_EARLY_SERIAL +inline void uart_early_putc(uint32_t uart_base, const char c) +{ +	/* send a \r for compatibility */ +	if (c == '\n') +		uart_early_putc(uart_base, '\r'); + +	/* wait for the hardware fifo to clear up */ +	while (!(_lsr_read(pUART) & THRE)) +		continue; + +	/* queue the character for transmission */ +	bfin_write(&pUART->thr, c); +	SSYNC(); +} + +void uart_early_puts(const char *s) +{ +	while (*s) +		uart_early_putc(UART_BASE, *s++); +} + +/* Symbol for our assembly to call. */ +void _serial_early_set_baud(uint32_t baud) +{ +	serial_early_set_baud(UART_BASE, baud); +} + +/* Symbol for our assembly to call. */ +void _serial_early_init(void) +{ +	serial_early_init(UART_BASE); +} +#endif + +#elif defined(CONFIG_UART_MEM) + +char serial_logbuf[CONFIG_UART_MEM]; +char *serial_logbuf_head = serial_logbuf; + +int serial_mem_init(void) +{ +	serial_logbuf_head = serial_logbuf; +	return 0; +} + +void serial_mem_setbrg(void) +{ +} + +int serial_mem_tstc(void) +{ +	return 0; +} + +int serial_mem_getc(void) +{ +	return 0; +} + +void serial_mem_putc(const char c) +{ +	*serial_logbuf_head = c; +	if (++serial_logbuf_head == serial_logbuf + CONFIG_UART_MEM) +		serial_logbuf_head = serial_logbuf; +} + +void serial_mem_puts(const char *s) +{ +	while (*s) +		serial_putc(*s++); +} + +struct serial_device bfin_serial_mem_device = { +	.name   = "bfin_uart_mem", +	.start  = serial_mem_init, +	.setbrg = serial_mem_setbrg, +	.getc   = serial_mem_getc, +	.tstc   = serial_mem_tstc, +	.putc   = serial_mem_putc, +	.puts   = serial_mem_puts, +}; + + +__weak struct serial_device *default_serial_console(void) +{ +	return &bfin_serial_mem_device; +} + +void bfin_serial_initialize(void) +{ +	serial_register(&bfin_serial_mem_device); +} +#endif /* CONFIG_UART_MEM */ diff --git a/roms/u-boot/drivers/serial/serial_imx.c b/roms/u-boot/drivers/serial/serial_imx.c new file mode 100644 index 00000000..d43a5fed --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_imx.c @@ -0,0 +1,223 @@ +/* + * (c) 2004 Sascha Hauer <sascha@saschahauer.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <serial.h> +#include <linux/compiler.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; + +static void imx_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. + * + */ +static int imx_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. + */ +static int imx_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. + */ +static void imx_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 + */ +static int imx_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; +} + +static struct serial_device imx_serial_drv = { +	.name	= "imx_serial", +	.start	= imx_serial_init, +	.stop	= NULL, +	.setbrg	= imx_serial_setbrg, +	.putc	= imx_serial_putc, +	.puts	= default_serial_puts, +	.getc	= imx_serial_getc, +	.tstc	= imx_serial_tstc, +}; + +void imx_serial_initialize(void) +{ +	serial_register(&imx_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &imx_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_ks8695.c b/roms/u-boot/drivers/serial/serial_ks8695.c new file mode 100644 index 00000000..13adabd1 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_ks8695.c @@ -0,0 +1,121 @@ +/* + * serial.c -- KS8695 serial driver + * + * (C) Copyright 2004, Greg Ungerer <greg.ungerer@opengear.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/platform.h> +#include <serial.h> +#include <linux/compiler.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; + + +static void ks8695_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; +} + +static int ks8695_serial_init(void) +{ +	serial_console = 1; +	serial_setbrg(); +	return 0; +} + +static void ks8695_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; +} + +static void ks8695_serial_putc(const char c) +{ +	if (serial_console) { +		ks8695_serial_raw_putc(c); +		if (c == '\n') +			ks8695_serial_raw_putc('\r'); +	} +} + +static int ks8695_serial_tstc(void) +{ +	volatile struct ks8695uart *uartp = KS8695_UART_ADDR; +	if (serial_console) +		return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0); +	return 0; +} + +static int ks8695_serial_getc(void) +{ +	volatile struct ks8695uart *uartp = KS8695_UART_ADDR; + +	while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0) +		; +	return (uartp->RX); +} + +static struct serial_device ks8695_serial_drv = { +	.name	= "ks8695_serial", +	.start	= ks8695_serial_init, +	.stop	= NULL, +	.setbrg	= ks8695_serial_setbrg, +	.putc	= ks8695_serial_putc, +	.puts	= default_serial_puts, +	.getc	= ks8695_serial_getc, +	.tstc	= ks8695_serial_tstc, +}; + +void ks8695_serial_initialize(void) +{ +	serial_register(&ks8695_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &ks8695_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_lpuart.c b/roms/u-boot/drivers/serial/serial_lpuart.c new file mode 100644 index 00000000..da5f9a21 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_lpuart.c @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +#define US1_TDRE        (1 << 7) +#define US1_RDRF        (1 << 5) +#define UC2_TE          (1 << 3) +#define UC2_RE          (1 << 2) + +DECLARE_GLOBAL_DATA_PTR; + +struct lpuart_fsl *base = (struct lpuart_fsl *)LPUART_BASE; + +static void lpuart_serial_setbrg(void) +{ +	u32 clk = mxc_get_clock(MXC_UART_CLK); +	u16 sbr; + +	if (!gd->baudrate) +		gd->baudrate = CONFIG_BAUDRATE; + +	sbr = (u16)(clk / (16 * gd->baudrate)); +	/* place adjustment later - n/32 BRFA */ + +	__raw_writeb(sbr >> 8, &base->ubdh); +	__raw_writeb(sbr & 0xff, &base->ubdl); +} + +static int lpuart_serial_getc(void) +{ +	u8 status; + +	while (!(__raw_readb(&base->us1) & US1_RDRF)) +		WATCHDOG_RESET(); + +	status = __raw_readb(&base->us1); +	status |= US1_RDRF; +	__raw_writeb(status, &base->us1); + +	return __raw_readb(&base->ud); +} + +static void lpuart_serial_putc(const char c) +{ +	if (c == '\n') +		serial_putc('\r'); + +	while (!(__raw_readb(&base->us1) & US1_TDRE)) +		WATCHDOG_RESET(); + +	__raw_writeb(c, &base->ud); +} + +/* + * Test whether a character is in the RX buffer + */ +static int lpuart_serial_tstc(void) +{ +	if (__raw_readb(&base->urcfifo) == 0) +		return 0; + +	return 1; +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + */ +static int lpuart_serial_init(void) +{ +	u8 ctrl; + +	ctrl = __raw_readb(&base->uc2); +	ctrl &= ~UC2_RE; +	ctrl &= ~UC2_TE; +	__raw_writeb(ctrl, &base->uc2); + +	__raw_writeb(0, &base->umodem); +	__raw_writeb(0, &base->uc1); + +	/* provide data bits, parity, stop bit, etc */ + +	serial_setbrg(); + +	__raw_writeb(UC2_RE | UC2_TE, &base->uc2); + +	return 0; +} + +static struct serial_device lpuart_serial_drv = { +	.name = "lpuart_serial", +	.start = lpuart_serial_init, +	.stop = NULL, +	.setbrg = lpuart_serial_setbrg, +	.putc = lpuart_serial_putc, +	.puts = default_serial_puts, +	.getc = lpuart_serial_getc, +	.tstc = lpuart_serial_tstc, +}; + +void lpuart_serial_initialize(void) +{ +	serial_register(&lpuart_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &lpuart_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_max3100.c b/roms/u-boot/drivers/serial/serial_max3100.c new file mode 100644 index 00000000..027d9194 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_max3100.c @@ -0,0 +1,294 @@ +/* + * (C) Copyright 2003 + * + * Pantelis Antoniou <panto@intracom.gr> + * Intracom S.A. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <serial.h> +#include <linux/compiler.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_serial_putc_raw(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_serial_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_serial_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; +} + +static int max3100_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); +} + +static void max3100_serial_putc(const char c) +{ +	if (c == '\n') +		max3100_serial_putc_raw('\r'); + +	max3100_serial_putc_raw(c); +} + +static void max3100_serial_puts(const char *s) +{ +	while (*s) +		max3100_serial_putc_raw(*s++); +} + +static void max3100_serial_setbrg(void) +{ +} + +static struct serial_device max3100_serial_drv = { +	.name	= "max3100_serial", +	.start	= max3100_serial_init, +	.stop	= NULL, +	.setbrg	= max3100_serial_setbrg, +	.putc	= max3100_serial_putc, +	.puts	= max3100_serial_puts, +	.getc	= max3100_serial_getc, +	.tstc	= max3100_serial_tstc, +}; + +void max3100_serial_initialize(void) +{ +	serial_register(&max3100_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &max3100_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_mxc.c b/roms/u-boot/drivers/serial/serial_mxc.c new file mode 100644 index 00000000..56bee552 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_mxc.c @@ -0,0 +1,224 @@ +/* + * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <serial.h> +#include <linux/compiler.h> + +#define __REG(x)     (*((volatile u32 *)(x))) + +#ifndef CONFIG_MXC_UART_BASE +#error "define CONFIG_MXC_UART_BASE to use the MXC UART driver" +#endif + +#define UART_PHYS	CONFIG_MXC_UART_BASE + +/* 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; + +static void mxc_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); + +} + +static int mxc_serial_getc(void) +{ +	while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) +		WATCHDOG_RESET(); +	return (__REG(UART_PHYS + URXD) & URXD_RX_DATA); /* mask out status from upper word */ +} + +static void mxc_serial_putc(const char c) +{ +	__REG(UART_PHYS + UTXD) = c; + +	/* wait for transmitter to be ready */ +	while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY)) +		WATCHDOG_RESET(); + +	/* If \n, also do \r */ +	if (c == '\n') +		serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +static int mxc_serial_tstc(void) +{ +	/* If receive fifo is empty, return false */ +	if (__REG(UART_PHYS + UTS) & UTS_RXEMPTY) +		return 0; +	return 1; +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +static int mxc_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; +} + +static struct serial_device mxc_serial_drv = { +	.name	= "mxc_serial", +	.start	= mxc_serial_init, +	.stop	= NULL, +	.setbrg	= mxc_serial_setbrg, +	.putc	= mxc_serial_putc, +	.puts	= default_serial_puts, +	.getc	= mxc_serial_getc, +	.tstc	= mxc_serial_tstc, +}; + +void mxc_serial_initialize(void) +{ +	serial_register(&mxc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &mxc_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_ns16550.c b/roms/u-boot/drivers/serial/serial_ns16550.c new file mode 100644 index 00000000..ba68d469 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_ns16550.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <linux/compiler.h> + +#include <ns16550.h> +#ifdef CONFIG_NS87308 +#include <ns87308.h> +#endif + +#include <serial.h> + +#ifndef CONFIG_NS16550_MIN_FUNCTIONS + +DECLARE_GLOBAL_DATA_PTR; + +#if !defined(CONFIG_CONS_INDEX) +#elif (CONFIG_CONS_INDEX < 1) || (CONFIG_CONS_INDEX > 6) +#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." +#elif CONFIG_CONS_INDEX == 5 && !defined(CONFIG_SYS_NS16550_COM5) +#error	"Console port 5 defined but not configured." +#elif CONFIG_CONS_INDEX == 6 && !defined(CONFIG_SYS_NS16550_COM6) +#error	"Console port 6 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[6] = { +#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 +#ifdef CONFIG_SYS_NS16550_COM5 +	(NS16550_t)CONFIG_SYS_NS16550_COM5, +#else +	NULL, +#endif +#ifdef CONFIG_SYS_NS16550_COM6 +	(NS16550_t)CONFIG_SYS_NS16550_COM6 +#else +	NULL +#endif +}; + +#define PORT	serial_ports[port-1] + +/* Multi serial device functions */ +#define DECLARE_ESERIAL_FUNCTIONS(port) \ +	static 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 ; \ +	} \ +	static void eserial##port##_setbrg(void) \ +	{ \ +		serial_setbrg_dev(port); \ +	} \ +	static int  eserial##port##_getc(void) \ +	{ \ +		return serial_getc_dev(port); \ +	} \ +	static int  eserial##port##_tstc(void) \ +	{ \ +		return serial_tstc_dev(port); \ +	} \ +	static void eserial##port##_putc(const char c) \ +	{ \ +		serial_putc_dev(port, c); \ +	} \ +	static void eserial##port##_puts(const char *s) \ +	{ \ +		serial_puts_dev(port, s); \ +	} + +/* Serial device descriptor */ +#define INIT_ESERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,			\ +	.start	= eserial##port##_init,		\ +	.stop	= NULL,				\ +	.setbrg	= eserial##port##_setbrg,	\ +	.getc	= eserial##port##_getc,		\ +	.tstc	= eserial##port##_tstc,		\ +	.putc	= eserial##port##_putc,		\ +	.puts	= eserial##port##_puts,		\ +} + +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 + +#define MODE_X_DIV 16 +	/* 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); +} + +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); +} + +static inline void +serial_putc_dev(unsigned int dev_index,const char c) +{ +	_serial_putc(c,dev_index); +} + +static inline void +serial_putc_raw_dev(unsigned int dev_index,const char c) +{ +	_serial_putc_raw(c,dev_index); +} + +static inline void +serial_puts_dev(unsigned int dev_index,const char *s) +{ +	_serial_puts(s,dev_index); +} + +static inline int +serial_getc_dev(unsigned int dev_index) +{ +	return _serial_getc(dev_index); +} + +static inline int +serial_tstc_dev(unsigned int dev_index) +{ +	return _serial_tstc(dev_index); +} + +static inline void +serial_setbrg_dev(unsigned int dev_index) +{ +	_serial_setbrg(dev_index); +} + +#if defined(CONFIG_SYS_NS16550_COM1) +DECLARE_ESERIAL_FUNCTIONS(1); +struct serial_device eserial1_device = +	INIT_ESERIAL_STRUCTURE(1, "eserial0"); +#endif +#if defined(CONFIG_SYS_NS16550_COM2) +DECLARE_ESERIAL_FUNCTIONS(2); +struct serial_device eserial2_device = +	INIT_ESERIAL_STRUCTURE(2, "eserial1"); +#endif +#if defined(CONFIG_SYS_NS16550_COM3) +DECLARE_ESERIAL_FUNCTIONS(3); +struct serial_device eserial3_device = +	INIT_ESERIAL_STRUCTURE(3, "eserial2"); +#endif +#if defined(CONFIG_SYS_NS16550_COM4) +DECLARE_ESERIAL_FUNCTIONS(4); +struct serial_device eserial4_device = +	INIT_ESERIAL_STRUCTURE(4, "eserial3"); +#endif +#if defined(CONFIG_SYS_NS16550_COM5) +DECLARE_ESERIAL_FUNCTIONS(5); +struct serial_device eserial5_device = +	INIT_ESERIAL_STRUCTURE(5, "eserial4"); +#endif +#if defined(CONFIG_SYS_NS16550_COM6) +DECLARE_ESERIAL_FUNCTIONS(6); +struct serial_device eserial6_device = +	INIT_ESERIAL_STRUCTURE(6, "eserial5"); +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_CONS_INDEX == 1 +	return &eserial1_device; +#elif CONFIG_CONS_INDEX == 2 +	return &eserial2_device; +#elif CONFIG_CONS_INDEX == 3 +	return &eserial3_device; +#elif CONFIG_CONS_INDEX == 4 +	return &eserial4_device; +#elif CONFIG_CONS_INDEX == 5 +	return &eserial5_device; +#elif CONFIG_CONS_INDEX == 6 +	return &eserial6_device; +#else +#error "Bad CONFIG_CONS_INDEX." +#endif +} + +void ns16550_serial_initialize(void) +{ +#if defined(CONFIG_SYS_NS16550_COM1) +	serial_register(&eserial1_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM2) +	serial_register(&eserial2_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM3) +	serial_register(&eserial3_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM4) +	serial_register(&eserial4_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM5) +	serial_register(&eserial5_device); +#endif +#if defined(CONFIG_SYS_NS16550_COM6) +	serial_register(&eserial6_device); +#endif +} + +#endif /* !CONFIG_NS16550_MIN_FUNCTIONS */ diff --git a/roms/u-boot/drivers/serial/serial_pl01x.c b/roms/u-boot/drivers/serial/serial_pl01x.c new file mode 100644 index 00000000..dfb610e1 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_pl01x.c @@ -0,0 +1,252 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */ + +#include <common.h> +#include <watchdog.h> +#include <asm/io.h> +#include <serial.h> +#include <linux/compiler.h> +#include "serial_pl01x.h" + +/* + * 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 +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); +unsigned int baudrate = CONFIG_BAUDRATE; +DECLARE_GLOBAL_DATA_PTR; + +static struct pl01x_regs *pl01x_get_regs(int portnum) +{ +	return (struct pl01x_regs *) port[portnum]; +} + +#ifdef CONFIG_PL010_SERIAL + +static int pl01x_serial_init(void) +{ +	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); +	unsigned int divisor; + +	/* First, disable everything */ +	writel(0, ®s->pl010_cr); + +	/* 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; +	} + +	writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm); +	writel(divisor & 0xff, ®s->pl010_lcrl); + +	/* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */ +	writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, ®s->pl010_lcrh); + +	/* Finally, enable the UART */ +	writel(UART_PL010_CR_UARTEN, ®s->pl010_cr); + +	return 0; +} + +#endif /* CONFIG_PL010_SERIAL */ + +#ifdef CONFIG_PL011_SERIAL + +static int pl01x_serial_init(void) +{ +	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); +	unsigned int temp; +	unsigned int divider; +	unsigned int remainder; +	unsigned int fraction; +	unsigned int lcr; + +#ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT +	/* Empty RX fifo if necessary */ +	if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) { +		while (!(readl(®s->fr) & UART_PL01x_FR_RXFE)) +			readl(®s->dr); +	} +#endif + +	/* First, disable everything */ +	writel(0, ®s->pl011_cr); + +	/* +	 * Set baud rate +	 * +	 * IBRD = UART_CLK / (16 * BAUD_RATE) +	 * FBRD = RND((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); + +	writel(divider, ®s->pl011_ibrd); +	writel(fraction, ®s->pl011_fbrd); + +	/* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */ +	lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; +	writel(lcr, ®s->pl011_lcrh); + +#ifdef CONFIG_PL011_SERIAL_RLCR +	{ +		int i; + +		/* +		 * Program receive line control register after waiting +		 * 10 bus cycles.  Delay be writing to readonly register +		 * 10 times +		 */ +		for (i = 0; i < 10; i++) +			writel(lcr, ®s->fr); + +		writel(lcr, ®s->pl011_rlcr); +		/* lcrh needs to be set again for change to be effective */ +		writel(lcr, ®s->pl011_lcrh); +	} +#endif +	/* Finally, enable the UART */ +	writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE | +	       UART_PL011_CR_RTS, ®s->pl011_cr); + +	return 0; +} + +#endif /* CONFIG_PL011_SERIAL */ + +static void pl01x_serial_putc(const char c) +{ +	if (c == '\n') +		pl01x_putc (CONSOLE_PORT, '\r'); + +	pl01x_putc (CONSOLE_PORT, c); +} + +static int pl01x_serial_getc(void) +{ +	return pl01x_getc (CONSOLE_PORT); +} + +static int pl01x_serial_tstc(void) +{ +	return pl01x_tstc (CONSOLE_PORT); +} + +static void pl01x_serial_setbrg(void) +{ +	struct pl01x_regs *regs = pl01x_get_regs(CONSOLE_PORT); + +	baudrate = gd->baudrate; +	/* +	 * Flush FIFO and wait for non-busy before changing baudrate to avoid +	 * crap in console +	 */ +	while (!(readl(®s->fr) & UART_PL01x_FR_TXFE)) +		WATCHDOG_RESET(); +	while (readl(®s->fr) & UART_PL01x_FR_BUSY) +		WATCHDOG_RESET(); +	serial_init(); +} + +static void pl01x_putc (int portnum, char c) +{ +	struct pl01x_regs *regs = pl01x_get_regs(portnum); + +	/* Wait until there is space in the FIFO */ +	while (readl(®s->fr) & UART_PL01x_FR_TXFF) +		WATCHDOG_RESET(); + +	/* Send the character */ +	writel(c, ®s->dr); +} + +static int pl01x_getc (int portnum) +{ +	struct pl01x_regs *regs = pl01x_get_regs(portnum); +	unsigned int data; + +	/* Wait until there is data in the FIFO */ +	while (readl(®s->fr) & UART_PL01x_FR_RXFE) +		WATCHDOG_RESET(); + +	data = readl(®s->dr); + +	/* Check for an error flag */ +	if (data & 0xFFFFFF00) { +		/* Clear the error */ +		writel(0xFFFFFFFF, ®s->ecr); +		return -1; +	} + +	return (int) data; +} + +static int pl01x_tstc (int portnum) +{ +	struct pl01x_regs *regs = pl01x_get_regs(portnum); + +	WATCHDOG_RESET(); +	return !(readl(®s->fr) & UART_PL01x_FR_RXFE); +} + +static struct serial_device pl01x_serial_drv = { +	.name	= "pl01x_serial", +	.start	= pl01x_serial_init, +	.stop	= NULL, +	.setbrg	= pl01x_serial_setbrg, +	.putc	= pl01x_serial_putc, +	.puts	= default_serial_puts, +	.getc	= pl01x_serial_getc, +	.tstc	= pl01x_serial_tstc, +}; + +void pl01x_serial_initialize(void) +{ +	serial_register(&pl01x_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &pl01x_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_pl01x.h b/roms/u-boot/drivers/serial/serial_pl01x.h new file mode 100644 index 00000000..288a4f19 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_pl01x.h @@ -0,0 +1,128 @@ +/* + * (C) Copyright 2003, 2004 + * ARM Ltd. + * Philippe Robin, <philippe.robin@arm.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +/* + * ARM PrimeCell UART's (PL010 & PL011) + * ------------------------------------ + * + *  Definitions common to both PL010 & PL011 + * + */ + +#ifndef __ASSEMBLY__ +/* + * We can use a combined structure for PL010 and PL011, because they overlap + * only in common registers. + */ +struct pl01x_regs { +	u32	dr;		/* 0x00 Data register */ +	u32	ecr;		/* 0x04 Error clear register (Write) */ +	u32	pl010_lcrh;	/* 0x08 Line control register, high byte */ +	u32	pl010_lcrm;	/* 0x0C Line control register, middle byte */ +	u32	pl010_lcrl;	/* 0x10 Line control register, low byte */ +	u32	pl010_cr;	/* 0x14 Control register */ +	u32	fr;		/* 0x18 Flag register (Read only) */ +#ifdef CONFIG_PL011_SERIAL_RLCR +	u32	pl011_rlcr;	/* 0x1c Receive line control register */ +#else +	u32	reserved; +#endif +	u32	ilpr;		/* 0x20 IrDA low-power counter register */ +	u32	pl011_ibrd;	/* 0x24 Integer baud rate register */ +	u32	pl011_fbrd;	/* 0x28 Fractional baud rate register */ +	u32	pl011_lcrh;	/* 0x2C Line control register */ +	u32	pl011_cr;	/* 0x30 Control register */ +}; +#endif + +#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_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_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/drivers/serial/serial_pxa.c b/roms/u-boot/drivers/serial/serial_pxa.c new file mode 100644 index 00000000..d5140045 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_pxa.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> + * + * (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) + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <watchdog.h> +#include <serial.h> +#include <asm/arch/pxa-regs.h> +#include <asm/arch/regs-uart.h> +#include <asm/io.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * The numbering scheme differs here for PXA25x, PXA27x and PXA3xx so we can + * easily handle enabling of clock. + */ +#ifdef	CONFIG_CPU_MONAHANS +#define	UART_CLK_BASE	CKENA_21_BTUART +#define	UART_CLK_REG	CKENA +#define	BTUART_INDEX	0 +#define	FFUART_INDEX	1 +#define	STUART_INDEX	2 +#elif	CONFIG_CPU_PXA25X +#define	UART_CLK_BASE	(1 << 4)	/* HWUART */ +#define	UART_CLK_REG	CKEN +#define	HWUART_INDEX	0 +#define	STUART_INDEX	1 +#define	FFUART_INDEX	2 +#define	BTUART_INDEX	3 +#else	/* PXA27x */ +#define	UART_CLK_BASE	CKEN5_STUART +#define	UART_CLK_REG	CKEN +#define	STUART_INDEX	0 +#define	FFUART_INDEX	1 +#define	BTUART_INDEX	2 +#endif + +/* + * Only PXA250 has HWUART, to avoid poluting the code with more macros, + * artificially introduce this. + */ +#ifndef	CONFIG_CPU_PXA25X +#define	HWUART_INDEX	0xff +#endif + +static uint32_t pxa_uart_get_baud_divider(void) +{ +	if (gd->baudrate == 1200) +		return 768; +	else if (gd->baudrate == 9600) +		return 96; +	else if (gd->baudrate == 19200) +		return 48; +	else if (gd->baudrate == 38400) +		return 24; +	else if (gd->baudrate == 57600) +		return 16; +	else if (gd->baudrate == 115200) +		return 8; +	else	/* Unsupported baudrate */ +		return 0; +} + +static struct pxa_uart_regs *pxa_uart_index_to_regs(uint32_t uart_index) +{ +	switch (uart_index) { +	case FFUART_INDEX: return (struct pxa_uart_regs *)FFUART_BASE; +	case BTUART_INDEX: return (struct pxa_uart_regs *)BTUART_BASE; +	case STUART_INDEX: return (struct pxa_uart_regs *)STUART_BASE; +	case HWUART_INDEX: return (struct pxa_uart_regs *)HWUART_BASE; +	default: +		return NULL; +	} +} + +static void pxa_uart_toggle_clock(uint32_t uart_index, int enable) +{ +	uint32_t clk_reg, clk_offset, reg; + +	clk_reg = UART_CLK_REG; +	clk_offset = UART_CLK_BASE << uart_index; + +	reg = readl(clk_reg); + +	if (enable) +		reg |= clk_offset; +	else +		reg &= ~clk_offset; + +	writel(reg, clk_reg); +} + +/* + * Enable clock and set baud rate, parity etc. + */ +void pxa_setbrg_dev(uint32_t uart_index) +{ +	uint32_t divider = 0; +	struct pxa_uart_regs *uart_regs; + +	divider = pxa_uart_get_baud_divider(); +	if (!divider) +		hang(); + +	uart_regs = pxa_uart_index_to_regs(uart_index); +	if (!uart_regs) +		hang(); + +	pxa_uart_toggle_clock(uart_index, 1); + +	/* Disable interrupts and FIFOs */ +	writel(0, &uart_regs->ier); +	writel(0, &uart_regs->fcr); + +	/* Set baud rate */ +	writel(LCR_WLS0 | LCR_WLS1 | LCR_DLAB, &uart_regs->lcr); +	writel(divider & 0xff, &uart_regs->dll); +	writel(divider >> 8, &uart_regs->dlh); +	writel(LCR_WLS0 | LCR_WLS1, &uart_regs->lcr); + +	/* Enable UART */ +	writel(IER_UUE, &uart_regs->ier); +} + +/* + * 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) +{ +	struct pxa_uart_regs *uart_regs; + +	uart_regs = pxa_uart_index_to_regs(uart_index); +	if (!uart_regs) +		hang(); + +	while (!(readl(&uart_regs->lsr) & LSR_TEMT)) +		WATCHDOG_RESET(); +	writel(c, &uart_regs->thr); + +	/* 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) +{ +	struct pxa_uart_regs *uart_regs; + +	uart_regs = pxa_uart_index_to_regs(uart_index); +	if (!uart_regs) +		return -1; + +	return readl(&uart_regs->lsr) & 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 pxa_getc_dev(unsigned int uart_index) +{ +	struct pxa_uart_regs *uart_regs; + +	uart_regs = pxa_uart_index_to_regs(uart_index); +	if (!uart_regs) +		return -1; + +	while (!(readl(&uart_regs->lsr) & LSR_DR)) +		WATCHDOG_RESET(); +	return readl(&uart_regs->rbr) & 0xff; +} + +void pxa_puts_dev(unsigned int uart_index, const char *s) +{ +	while (*s) +		pxa_putc_dev(uart_index, *s++); +} + +#define	pxa_uart(uart, UART)						\ +	int uart##_init(void)						\ +	{								\ +		return pxa_init_dev(UART##_INDEX);			\ +	}								\ +									\ +	void uart##_setbrg(void)					\ +	{								\ +		return pxa_setbrg_dev(UART##_INDEX);			\ +	}								\ +									\ +	void uart##_putc(const char c)					\ +	{								\ +		return pxa_putc_dev(UART##_INDEX, c);			\ +	}								\ +									\ +	void uart##_puts(const char *s)					\ +	{								\ +		return pxa_puts_dev(UART##_INDEX, s);			\ +	}								\ +									\ +	int uart##_getc(void)						\ +	{								\ +		return pxa_getc_dev(UART##_INDEX);			\ +	}								\ +									\ +	int uart##_tstc(void)						\ +	{								\ +		return pxa_tstc_dev(UART##_INDEX);			\ +	}								\ + +#define	pxa_uart_desc(uart)						\ +	struct serial_device serial_##uart##_device =			\ +	{								\ +		.name	= "serial_"#uart,				\ +		.start	= uart##_init,					\ +		.stop	= NULL,						\ +		.setbrg	= uart##_setbrg,				\ +		.getc	= uart##_getc,					\ +		.tstc	= uart##_tstc,					\ +		.putc	= uart##_putc,					\ +		.puts	= uart##_puts,					\ +	}; + +#define	pxa_uart_multi(uart, UART)					\ +	pxa_uart(uart, UART)						\ +	pxa_uart_desc(uart) + +#if defined(CONFIG_HWUART) +	pxa_uart_multi(hwuart, HWUART) +#endif +#if defined(CONFIG_STUART) +	pxa_uart_multi(stuart, STUART) +#endif +#if defined(CONFIG_FFUART) +	pxa_uart_multi(ffuart, FFUART) +#endif +#if defined(CONFIG_BTUART) +	pxa_uart_multi(btuart, BTUART) +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#if CONFIG_CONS_INDEX == 1 +	return &serial_hwuart_device; +#elif CONFIG_CONS_INDEX == 2 +	return &serial_stuart_device; +#elif CONFIG_CONS_INDEX == 3 +	return &serial_ffuart_device; +#elif CONFIG_CONS_INDEX == 4 +	return &serial_btuart_device; +#else +#error "Bad CONFIG_CONS_INDEX." +#endif +} + +void pxa_serial_initialize(void) +{ +#if defined(CONFIG_FFUART) +	serial_register(&serial_ffuart_device); +#endif +#if defined(CONFIG_BTUART) +	serial_register(&serial_btuart_device); +#endif +#if defined(CONFIG_STUART) +	serial_register(&serial_stuart_device); +#endif +} diff --git a/roms/u-boot/drivers/serial/serial_s3c24x0.c b/roms/u-boot/drivers/serial/serial_s3c24x0.c new file mode 100644 index 00000000..c07f4c9b --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_s3c24x0.c @@ -0,0 +1,267 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <linux/compiler.h> +#include <asm/arch/s3c24x0_cpu.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SERIAL1 +#define UART_NR	S3C24X0_UART0 + +#elif defined(CONFIG_SERIAL2) +#define UART_NR	S3C24X0_UART1 + +#elif defined(CONFIG_SERIAL3) +#define UART_NR	S3C24X0_UART2 + +#else +#error "Bad: you didn't configure serial ..." +#endif + +#include <asm/io.h> +#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) {	\ +	.name	= __name,				\ +	.start	= s3serial##port##_init,		\ +	.stop	= NULL,					\ +	.setbrg	= s3serial##port##_setbrg,		\ +	.getc	= s3serial##port##_getc,		\ +	.tstc	= s3serial##port##_tstc,		\ +	.putc	= s3serial##port##_putc,		\ +	.puts	= s3serial##port##_puts,		\ +} + +#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 */ ; +} + +static inline void serial_setbrg_dev(unsigned int dev_index) +{ +	_serial_setbrg(dev_index); +} + +/* 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); +} + +/* + * 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; +} + +static inline int serial_getc_dev(unsigned int dev_index) +{ +	return _serial_getc(dev_index); +} + +#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'); +} + +static inline void serial_putc_dev(unsigned int dev_index, const char c) +{ +	_serial_putc(c, dev_index); +} + +/* + * 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; +} + +static inline int serial_tstc_dev(unsigned int dev_index) +{ +	return _serial_tstc(dev_index); +} + +void _serial_puts(const char *s, const int dev_index) +{ +	while (*s) { +		_serial_putc(*s++, dev_index); +	} +} + +static inline void serial_puts_dev(int dev_index, const char *s) +{ +	_serial_puts(s, dev_index); +} + +DECLARE_S3C_SERIAL_FUNCTIONS(0); +struct serial_device s3c24xx_serial0_device = +INIT_S3C_SERIAL_STRUCTURE(0, "s3ser0"); +DECLARE_S3C_SERIAL_FUNCTIONS(1); +struct serial_device s3c24xx_serial1_device = +INIT_S3C_SERIAL_STRUCTURE(1, "s3ser1"); +DECLARE_S3C_SERIAL_FUNCTIONS(2); +struct serial_device s3c24xx_serial2_device = +INIT_S3C_SERIAL_STRUCTURE(2, "s3ser2"); + +__weak struct serial_device *default_serial_console(void) +{ +#if defined(CONFIG_SERIAL1) +	return &s3c24xx_serial0_device; +#elif defined(CONFIG_SERIAL2) +	return &s3c24xx_serial1_device; +#elif defined(CONFIG_SERIAL3) +	return &s3c24xx_serial2_device; +#else +#error "CONFIG_SERIAL? missing." +#endif +} + +void s3c24xx_serial_initialize(void) +{ +	serial_register(&s3c24xx_serial0_device); +	serial_register(&s3c24xx_serial1_device); +	serial_register(&s3c24xx_serial2_device); +} diff --git a/roms/u-boot/drivers/serial/serial_s5p.c b/roms/u-boot/drivers/serial/serial_s5p.c new file mode 100644 index 00000000..98c62b4c --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_s5p.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2009 SAMSUNG Electronics + * Minkyu Kang <mk7.kang@samsung.com> + * Heungjun Kim <riverful.kim@samsung.com> + * + * based on drivers/serial/s3c64xx.c + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <linux/compiler.h> +#include <asm/io.h> +#include <asm/arch/uart.h> +#include <asm/arch/clk.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define RX_FIFO_COUNT_MASK	0xff +#define RX_FIFO_FULL_MASK	(1 << 8) +#define TX_FIFO_FULL_MASK	(1 << 24) + +/* Information about a serial port */ +struct fdt_serial { +	u32 base_addr;  /* address of registers in physical memory */ +	u8 port_id;     /* uart port number */ +	u8 enabled;     /* 1 if enabled, 0 if disabled */ +} config __attribute__ ((section(".data"))); + +static inline struct s5p_uart *s5p_get_base_uart(int dev_index) +{ +#ifdef CONFIG_OF_CONTROL +	return (struct s5p_uart *)(config.base_addr); +#else +	u32 offset = dev_index * sizeof(struct s5p_uart); +	return (struct s5p_uart *)(samsung_get_base_uart() + offset); +#endif +} + +/* + * 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, +}; + +static void serial_setbrg_dev(const int dev_index) +{ +	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); +	u32 uclk = get_uart_clk(dev_index); +	u32 baudrate = gd->baudrate; +	u32 val; + +#if defined(CONFIG_SILENT_CONSOLE) && \ +		defined(CONFIG_OF_CONTROL) && \ +		!defined(CONFIG_SPL_BUILD) +	if (fdtdec_get_config_int(gd->fdt_blob, "silent_console", 0)) +		gd->flags |= GD_FLG_SILENT; +#endif + +	if (!config.enabled) +		return; + +	val = uclk / baudrate; + +	writel(val / 16 - 1, &uart->ubrdiv); + +	if (s5p_uart_divslot()) +		writew(udivslot[val % 16], &uart->rest.slot); +	else +		writeb(val % 16, &uart->rest.value); +} + +/* + * Initialise the serial port with the given baudrate. 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 s5p_uart *const uart = s5p_get_base_uart(dev_index); + +	/* enable FIFOs, auto clear Rx FIFO */ +	writel(0x3, &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. + */ +static int serial_getc_dev(const int dev_index) +{ +	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + +	if (!config.enabled) +		return 0; + +	/* wait for character to arrive */ +	while (!(readl(&uart->ufstat) & (RX_FIFO_COUNT_MASK | +					 RX_FIFO_FULL_MASK))) { +		if (serial_err_check(dev_index, 0)) +			return 0; +	} + +	return (int)(readb(&uart->urxh) & 0xff); +} + +/* + * Output a single byte to the serial port. + */ +static void serial_putc_dev(const char c, const int dev_index) +{ +	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + +	if (!config.enabled) +		return; + +	/* wait for room in the tx FIFO */ +	while ((readl(&uart->ufstat) & TX_FIFO_FULL_MASK)) { +		if (serial_err_check(dev_index, 1)) +			return; +	} + +	writeb(c, &uart->utxh); + +	/* If \n, also do \r */ +	if (c == '\n') +		serial_putc('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +static int serial_tstc_dev(const int dev_index) +{ +	struct s5p_uart *const uart = s5p_get_base_uart(dev_index); + +	if (!config.enabled) +		return 0; + +	return (int)(readl(&uart->utrstat) & 0x1); +} + +static 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) \ +static int s5p_serial##port##_init(void) { return serial_init_dev(port); } \ +static void s5p_serial##port##_setbrg(void) { serial_setbrg_dev(port); } \ +static int s5p_serial##port##_getc(void) { return serial_getc_dev(port); } \ +static int s5p_serial##port##_tstc(void) { return serial_tstc_dev(port); } \ +static void s5p_serial##port##_putc(const char c) { serial_putc_dev(c, port); } \ +static void s5p_serial##port##_puts(const char *s) { serial_puts_dev(s, port); } + +#define INIT_S5P_SERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,				\ +	.start	= s5p_serial##port##_init,		\ +	.stop	= NULL,					\ +	.setbrg	= s5p_serial##port##_setbrg,		\ +	.getc	= s5p_serial##port##_getc,		\ +	.tstc	= s5p_serial##port##_tstc,		\ +	.putc	= s5p_serial##port##_putc,		\ +	.puts	= s5p_serial##port##_puts,		\ +} + +DECLARE_S5P_SERIAL_FUNCTIONS(0); +struct serial_device s5p_serial0_device = +	INIT_S5P_SERIAL_STRUCTURE(0, "s5pser0"); +DECLARE_S5P_SERIAL_FUNCTIONS(1); +struct serial_device s5p_serial1_device = +	INIT_S5P_SERIAL_STRUCTURE(1, "s5pser1"); +DECLARE_S5P_SERIAL_FUNCTIONS(2); +struct serial_device s5p_serial2_device = +	INIT_S5P_SERIAL_STRUCTURE(2, "s5pser2"); +DECLARE_S5P_SERIAL_FUNCTIONS(3); +struct serial_device s5p_serial3_device = +	INIT_S5P_SERIAL_STRUCTURE(3, "s5pser3"); + +#ifdef CONFIG_OF_CONTROL +int fdtdec_decode_console(int *index, struct fdt_serial *uart) +{ +	const void *blob = gd->fdt_blob; +	int node; + +	node = fdt_path_offset(blob, "console"); +	if (node < 0) +		return node; + +	uart->base_addr = fdtdec_get_addr(blob, node, "reg"); +	if (uart->base_addr == FDT_ADDR_T_NONE) +		return -FDT_ERR_NOTFOUND; + +	uart->port_id = fdtdec_get_int(blob, node, "id", -1); +	uart->enabled = fdtdec_get_is_enabled(blob, node); + +	return 0; +} +#endif + +__weak struct serial_device *default_serial_console(void) +{ +#ifdef CONFIG_OF_CONTROL +	int index = 0; + +	if ((!config.base_addr) && (fdtdec_decode_console(&index, &config))) { +		debug("Cannot decode default console node\n"); +		return NULL; +	} + +	switch (config.port_id) { +	case 0: +		return &s5p_serial0_device; +	case 1: +		return &s5p_serial1_device; +	case 2: +		return &s5p_serial2_device; +	case 3: +		return &s5p_serial3_device; +	default: +		debug("Unknown config.port_id: %d", config.port_id); +		break; +	} + +	return NULL; +#else +	config.enabled = 1; +#if defined(CONFIG_SERIAL0) +	return &s5p_serial0_device; +#elif defined(CONFIG_SERIAL1) +	return &s5p_serial1_device; +#elif defined(CONFIG_SERIAL2) +	return &s5p_serial2_device; +#elif defined(CONFIG_SERIAL3) +	return &s5p_serial3_device; +#else +#error "CONFIG_SERIAL? missing." +#endif +#endif +} + +void s5p_serial_initialize(void) +{ +	serial_register(&s5p_serial0_device); +	serial_register(&s5p_serial1_device); +	serial_register(&s5p_serial2_device); +	serial_register(&s5p_serial3_device); +} diff --git a/roms/u-boot/drivers/serial/serial_sa1100.c b/roms/u-boot/drivers/serial/serial_sa1100.c new file mode 100644 index 00000000..78f241d8 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_sa1100.c @@ -0,0 +1,162 @@ +/* + * (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) + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <SA-1100.h> +#include <serial.h> +#include <linux/compiler.h> + +DECLARE_GLOBAL_DATA_PTR; + +static void sa1100_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. + * + */ +static int sa1100_serial_init(void) +{ +	serial_setbrg (); + +	return (0); +} + + +/* + * Output a single byte to the serial port. + */ +static void sa1100_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. + */ +static int sa1100_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. + */ +static int sa1100_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 +} + +static struct serial_device sa1100_serial_drv = { +	.name	= "sa1100_serial", +	.start	= sa1100_serial_init, +	.stop	= NULL, +	.setbrg	= sa1100_serial_setbrg, +	.putc	= sa1100_serial_putc, +	.puts	= default_serial_puts, +	.getc	= sa1100_serial_getc, +	.tstc	= sa1100_serial_tstc, +}; + +void sa1100_serial_initialize(void) +{ +	serial_register(&sa1100_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sa1100_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_sh.c b/roms/u-boot/drivers/serial/serial_sh.c new file mode 100644 index 00000000..0826d59a --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_sh.c @@ -0,0 +1,202 @@ +/* + * SuperH SCIF device driver. + * Copyright (C) 2013  Renesas Electronics Corporation + * Copyright (C) 2007,2008,2010 Nobuhiro Iwamatsu + * Copyright (C) 2002 - 2008  Paul Mundt + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/processor.h> +#include "serial_sh.h" +#include <serial.h> +#include <linux/compiler.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 +#elif defined(CONFIG_CONS_SCIF6) +# define SCIF_BASE	SCIF6_BASE +#elif defined(CONFIG_CONS_SCIF7) +# define SCIF_BASE	SCIF7_BASE +#else +# error "Default SCIF doesn't set....." +#endif + +#if defined(CONFIG_SCIF_A) +	#define SCIF_BASE_PORT	PORT_SCIFA +#else +	#define SCIF_BASE_PORT	PORT_SCIF +#endif + +static struct uart_port sh_sci = { +	.membase	= (unsigned char*)SCIF_BASE, +	.mapbase	= SCIF_BASE, +	.type		= SCIF_BASE_PORT, +}; + +static void sh_serial_setbrg(void) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	sci_out(&sh_sci, SCBRR, +		SCBRR_VALUE(gd->baudrate, CONFIG_SH_SCIF_CLK_FREQ)); +} + +static int sh_serial_init(void) +{ +	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); +	sci_out(&sh_sci, SCSCR , SCSCR_INIT(&sh_sci)); +	sci_out(&sh_sci, SCSMR, 0); +	sci_out(&sh_sci, SCSMR, 0); +	sci_out(&sh_sci, SCFCR, SCFCR_RFRST|SCFCR_TFRST); +	sci_in(&sh_sci, SCFCR); +	sci_out(&sh_sci, SCFCR, 0); + +	serial_setbrg(); +	return 0; +} + +#if defined(CONFIG_CPU_SH7760) || \ +	defined(CONFIG_CPU_SH7780) || \ +	defined(CONFIG_CPU_SH7785) || \ +	defined(CONFIG_CPU_SH7786) +static int scif_rxfill(struct uart_port *port) +{ +	return sci_in(port, SCRFDR) & 0xff; +} +#elif defined(CONFIG_CPU_SH7763) +static int scif_rxfill(struct uart_port *port) +{ +	if ((port->mapbase == 0xffe00000) || +		(port->mapbase == 0xffe08000)) { +		/* SCIF0/1*/ +		return sci_in(port, SCRFDR) & 0xff; +	} else { +		/* SCIF2 */ +		return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; +	} +} +#elif defined(CONFIG_ARCH_SH7372) +static int scif_rxfill(struct uart_port *port) +{ +	if (port->type == PORT_SCIFA) +		return sci_in(port, SCFDR) & SCIF_RFDC_MASK; +	else +		return sci_in(port, SCRFDR); +} +#else +static int scif_rxfill(struct uart_port *port) +{ +	return sci_in(port, SCFDR) & SCIF_RFDC_MASK; +} +#endif + +static int serial_rx_fifo_level(void) +{ +	return scif_rxfill(&sh_sci); +} + +static void handle_error(void) +{ +	sci_in(&sh_sci, SCxSR); +	sci_out(&sh_sci, SCxSR, SCxSR_ERROR_CLEAR(&sh_sci)); +	sci_in(&sh_sci, SCLSR); +	sci_out(&sh_sci, SCLSR, 0x00); +} + +void serial_raw_putc(const char c) +{ +	while (1) { +		/* Tx fifo is empty */ +		if (sci_in(&sh_sci, SCxSR) & SCxSR_TEND(&sh_sci)) +			break; +	} + +	sci_out(&sh_sci, SCxTDR, c); +	sci_out(&sh_sci, SCxSR, sci_in(&sh_sci, SCxSR) & ~SCxSR_TEND(&sh_sci)); +} + +static void sh_serial_putc(const char c) +{ +	if (c == '\n') +		serial_raw_putc('\r'); +	serial_raw_putc(c); +} + +static int sh_serial_tstc(void) +{ +	if (sci_in(&sh_sci, SCxSR) & SCIF_ERRORS) { +		handle_error(); +		return 0; +	} + +	return serial_rx_fifo_level() ? 1 : 0; +} + + +int serial_getc_check(void) +{ +	unsigned short status; + +	status = sci_in(&sh_sci, SCxSR); + +	if (status & SCIF_ERRORS) +		handle_error(); +	if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) +		handle_error(); +	return status & (SCIF_DR | SCxSR_RDxF(&sh_sci)); +} + +static int sh_serial_getc(void) +{ +	unsigned short status; +	char ch; + +	while (!serial_getc_check()) +		; + +	ch = sci_in(&sh_sci, SCxRDR); +	status = sci_in(&sh_sci, SCxSR); + +	sci_out(&sh_sci, SCxSR, SCxSR_RDxF_CLEAR(&sh_sci)); + +	if (status & SCIF_ERRORS) +			handle_error(); + +	if (sci_in(&sh_sci, SCLSR) & SCxSR_ORER(&sh_sci)) +		handle_error(); +	return ch; +} + +static struct serial_device sh_serial_drv = { +	.name	= "sh_serial", +	.start	= sh_serial_init, +	.stop	= NULL, +	.setbrg	= sh_serial_setbrg, +	.putc	= sh_serial_putc, +	.puts	= default_serial_puts, +	.getc	= sh_serial_getc, +	.tstc	= sh_serial_tstc, +}; + +void sh_serial_initialize(void) +{ +	serial_register(&sh_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ +	return &sh_serial_drv; +} diff --git a/roms/u-boot/drivers/serial/serial_sh.h b/roms/u-boot/drivers/serial/serial_sh.h new file mode 100644 index 00000000..f5e9854d --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_sh.h @@ -0,0 +1,740 @@ +/* + * Copy and modify from linux/drivers/serial/sh-sci.h + */ + +struct uart_port { +	unsigned long	iobase;		/* in/out[bwl] */ +	unsigned char	*membase;	/* read/write[bwl] */ +	unsigned long	mapbase;	/* for ioremap */ +	unsigned int	type;		/* port type */ +}; + +#define PORT_SCI	52 +#define PORT_SCIF	53 +#define PORT_SCIFA	83 +#define PORT_SCIFB	93 + +#if defined(CONFIG_H83007) || defined(CONFIG_H83068) +#include <asm/regs306x.h> +#endif +#if defined(CONFIG_H8S2678) +#include <asm/regs267x.h> +#endif + +#if defined(CONFIG_CPU_SH7706) || \ +	defined(CONFIG_CPU_SH7707) || \ +	defined(CONFIG_CPU_SH7708) || \ +	defined(CONFIG_CPU_SH7709) +# define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */ +# define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */ +# define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ +#elif defined(CONFIG_CPU_SH7705) +# define SCIF0		0xA4400000 +# define SCIF2		0xA4410000 +# define SCSMR_Ir	0xA44A0000 +# define IRDA_SCIF	SCIF0 +# define SCPCR 0xA4000116 +# define SCPDR 0xA4000136 + +/* Set the clock source, + * SCIF2 (0xA4410000) -> External clock, SCK pin used as clock input + * SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output + */ +# define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 +#elif defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_SH73A0) || \ +	defined(CONFIG_R8A7740) +# define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define PORT_PTCR	   0xA405011EUL +# define PORT_PVCR	   0xA4050122UL +# define SCIF_ORER	   0x0200   /* overrun error bit */ +#elif defined(CONFIG_SH_RTS7751R2D) +# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */ +# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001   /* overrun error bit */ +# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7750)  || \ +	defined(CONFIG_CPU_SH7750R) || \ +	defined(CONFIG_CPU_SH7750S) || \ +	defined(CONFIG_CPU_SH7091)  || \ +	defined(CONFIG_CPU_SH7751)  || \ +	defined(CONFIG_CPU_SH7751R) +# define SCSPTR1 0xffe0001c /* 8  bit SCI */ +# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001   /* overrun error bit */ +# define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \ +	0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ +	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */) +#elif defined(CONFIG_CPU_SH7760) +# define SCSPTR0 0xfe600024 /* 16 bit SCIF */ +# define SCSPTR1 0xfe610024 /* 16 bit SCIF */ +# define SCSPTR2 0xfe620024 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)          0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7710) || defined(CONFIG_CPU_SH7712) +# define SCSPTR0 0xA4400000	  /* 16 bit SCIF */ +# define SCIF_ORER 0x0001   /* overrun error bit */ +# define PACR 0xa4050100 +# define PBCR 0xa4050102 +# define SCSCR_INIT(port)          0x3B +#elif defined(CONFIG_CPU_SH7343) +# define SCSPTR0 0xffe00010	/* 16 bit SCIF */ +# define SCSPTR1 0xffe10010	/* 16 bit SCIF */ +# define SCSPTR2 0xffe20010	/* 16 bit SCIF */ +# define SCSPTR3 0xffe30010	/* 16 bit SCIF */ +# define SCSCR_INIT(port) 0x32	/* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ +#elif defined(CONFIG_CPU_SH7722) +# define PADR			0xA4050120 +# undef PSDR +# define PSDR			0xA405013e +# define PWDR			0xA4050166 +# define PSCR			0xA405011E +# define SCIF_ORER		0x0001	/* overrun error bit */ +# define SCSCR_INIT(port)	0x0038	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7366) +# define SCPDR0			0xA405013E      /* 16 bit SCIF0 PSDR */ +# define SCSPTR0		SCPDR0 +# define SCIF_ORER		0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)	0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7723) +# define SCSPTR0                0xa4050160 +# define SCSPTR1                0xa405013e +# define SCSPTR2                0xa4050160 +# define SCSPTR3                0xa405013e +# define SCSPTR4                0xa4050128 +# define SCSPTR5                0xa4050128 +# define SCIF_ORER              0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)       0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7724) +# define SCIF_ORER              0x0001  /* overrun error bit */ +# define SCSCR_INIT(port) ((port)->type == PORT_SCIFA ? \ +	0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ +	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */) +#elif defined(CONFIG_CPU_SH7734) +# define SCSPTR0 0xFFE40020 +# define SCSPTR1 0xFFE41020 +# define SCSPTR2 0xFFE42020 +# define SCSPTR3 0xFFE43020 +# define SCSPTR4 0xFFE44020 +# define SCSPTR5 0xFFE45020 +# define SCIF_ORER 0x0001  /* overrun error bit */ +# define SCSCR_INIT(port) 0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH4_202) +# define SCSPTR2 0xffe80020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001   /* overrun error bit */ +# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH5_101) || defined(CONFIG_CPU_SH5_103) +# define SCIF_BASE_ADDR    0x01030000 +# define SCIF_ADDR_SH5     (PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR) +# define SCIF_PTR2_OFFS    0x0000020 +# define SCIF_LSR2_OFFS    0x0000024 +# define SCSPTR\ +		((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ +# define SCLSR2\ +		((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ +# define SCSCR_INIT(port)  0x38		/* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_H83007) || defined(CONFIG_H83068) +# define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define H8300_SCI_DR(ch) (*(volatile char *)(P1DR + h8300_sci_pins[ch].port)) +#elif defined(CONFIG_H8S2678) +# define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define H8300_SCI_DR(ch) (*(volatile char *)(P1DR + h8300_sci_pins[ch].port)) +#elif defined(CONFIG_CPU_SH7757) || \ +	defined(CONFIG_CPU_SH7752) || \ +	defined(CONFIG_CPU_SH7753) +# define SCSPTR0 0xfe4b0020 +# define SCSPTR1 0xfe4b0020 +# define SCSPTR2 0xfe4b0020 +# define SCIF_ORER 0x0001 +# define SCSCR_INIT(port)	0x38 +# define SCIF_ONLY +#elif defined(CONFIG_CPU_SH7763) +# define SCSPTR0 0xffe00024 /* 16 bit SCIF */ +# define SCSPTR1 0xffe08024 /* 16 bit SCIF */ +# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ +# define SCIF_ORER 0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)	0x38	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7770) +# define SCSPTR0 0xff923020 /* 16 bit SCIF */ +# define SCSPTR1 0xff924020 /* 16 bit SCIF */ +# define SCSPTR2 0xff925020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)	0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */ +#elif defined(CONFIG_CPU_SH7780) +# define SCSPTR0	0xffe00024	/* 16 bit SCIF */ +# define SCSPTR1	0xffe10024	/* 16 bit SCIF */ +# define SCIF_ORER	0x0001		/* Overrun error bit */ + +#if defined(CONFIG_SH_SH2007) +/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */ +# define SCSCR_INIT(port)	0x38 +#else +/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */ +# define SCSCR_INIT(port)	0x3a +#endif + +#elif defined(CONFIG_CPU_SH7785) || \ +	defined(CONFIG_CPU_SH7786) +# define SCSPTR0	0xffea0024	/* 16 bit SCIF */ +# define SCSPTR1	0xffeb0024	/* 16 bit SCIF */ +# define SCSPTR2	0xffec0024	/* 16 bit SCIF */ +# define SCSPTR3	0xffed0024	/* 16 bit SCIF */ +# define SCSPTR4	0xffee0024	/* 16 bit SCIF */ +# define SCSPTR5	0xffef0024	/* 16 bit SCIF */ +# define SCIF_ORER	0x0001		/* Overrun error bit */ +# define SCSCR_INIT(port)	0x3a	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7201) || \ +	defined(CONFIG_CPU_SH7203) || \ +	defined(CONFIG_CPU_SH7206) || \ +	defined(CONFIG_CPU_SH7263) || \ +	defined(CONFIG_CPU_SH7264) +# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ +# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ +# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ +# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ +# if defined(CONFIG_CPU_SH7201) +#  define SCSPTR4 0xfffeA020 /* 16 bit SCIF */ +#  define SCSPTR5 0xfffeA820 /* 16 bit SCIF */ +#  define SCSPTR6 0xfffeB020 /* 16 bit SCIF */ +#  define SCSPTR7 0xfffeB820 /* 16 bit SCIF */ +# endif +# define SCSCR_INIT(port)	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7269) +# define SCSPTR0 0xe8007020 /* 16 bit SCIF */ +# define SCSPTR1 0xe8007820 /* 16 bit SCIF */ +# define SCSPTR2 0xe8008020 /* 16 bit SCIF */ +# define SCSPTR3 0xe8008820 /* 16 bit SCIF */ +# define SCSPTR4 0xe8009020 /* 16 bit SCIF */ +# define SCSPTR5 0xe8009820 /* 16 bit SCIF */ +# define SCSPTR6 0xe800a020 /* 16 bit SCIF */ +# define SCSPTR7 0xe800a820 /* 16 bit SCIF */ +# define SCSCR_INIT(port)	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SH7619) +# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ +# define SCSPTR1 0xf8410020 /* 16 bit SCIF */ +# define SCSPTR2 0xf8420020 /* 16 bit SCIF */ +# define SCIF_ORER 0x0001  /* overrun error bit */ +# define SCSCR_INIT(port)	0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_CPU_SHX3) +# define SCSPTR0 0xffc30020		/* 16 bit SCIF */ +# define SCSPTR1 0xffc40020		/* 16 bit SCIF */ +# define SCSPTR2 0xffc50020		/* 16 bit SCIF */ +# define SCSPTR3 0xffc60020		/* 16 bit SCIF */ +# define SCIF_ORER 0x0001		/* Overrun error bit */ +# define SCSCR_INIT(port)	0x38	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +# define SCIF_ORER	0x0001 +# define SCSCR_INIT(port)	0x32	/* TIE=0,RIE=0,TE=1,RE=1,REIE=0, */ +#else +# error CPU subtype not defined +#endif + +/* SCSCR */ +#define SCI_CTRL_FLAGS_TIE  0x80 /* all */ +#define SCI_CTRL_FLAGS_RIE  0x40 /* all */ +#define SCI_CTRL_FLAGS_TE   0x20 /* all */ +#define SCI_CTRL_FLAGS_RE   0x10 /* all */ +#if defined(CONFIG_CPU_SH7750)  || \ +	defined(CONFIG_CPU_SH7091)  || \ +	defined(CONFIG_CPU_SH7750R) || \ +	defined(CONFIG_CPU_SH7722)  || \ +	defined(CONFIG_CPU_SH7734)  || \ +	defined(CONFIG_CPU_SH7750S) || \ +	defined(CONFIG_CPU_SH7751)  || \ +	defined(CONFIG_CPU_SH7751R) || \ +	defined(CONFIG_CPU_SH7763)  || \ +	defined(CONFIG_CPU_SH7780)  || \ +	defined(CONFIG_CPU_SH7785)  || \ +	defined(CONFIG_CPU_SH7786)  || \ +	defined(CONFIG_CPU_SHX3) +#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ +#elif defined(CONFIG_CPU_SH7724) +#define SCI_CTRL_FLAGS_REIE ((port)->type == PORT_SCIFA ? 0 : 8) +#else +#define SCI_CTRL_FLAGS_REIE 0 +#endif +/*		SCI_CTRL_FLAGS_MPIE 0x08  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/*		SCI_CTRL_FLAGS_TEIE 0x04  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/*		SCI_CTRL_FLAGS_CKE1 0x02  * all */ +/*		SCI_CTRL_FLAGS_CKE0 0x01  * 7707 SCI/SCIF, 7708 SCI, 7709 SCI/SCIF, 7750 SCI */ + +/* SCxSR SCI */ +#define SCI_TDRE  0x80 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_RDRF  0x40 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_ORER  0x20 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_FER   0x10 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_PER   0x08 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +#define SCI_TEND  0x04 /* 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/*      SCI_MPB   0x02  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ +/*      SCI_MPBT  0x01  * 7707 SCI, 7708 SCI, 7709 SCI, 7750 SCI */ + +#define SCI_ERRORS ( SCI_PER | SCI_FER | SCI_ORER) + +/* SCxSR SCIF */ +#define SCIF_ER    0x0080 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TEND  0x0040 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_TDFE  0x0020 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_BRK   0x0010 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_FER   0x0008 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_PER   0x0004 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_RDF   0x0002 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ +#define SCIF_DR    0x0001 /* 7705 SCIF, 7707 SCIF, 7709 SCIF, 7750 SCIF */ + +#if defined(CONFIG_CPU_SH7705) || \ +	defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_SH73A0) || \ +	defined(CONFIG_R8A7740) +# define SCIF_ORER    0x0200 +# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK | SCIF_ORER) +# define SCIF_RFDC_MASK 0x007f +# define SCIF_TXROOM_MAX 64 +#elif defined(CONFIG_CPU_SH7763) +# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) +# define SCIF_RFDC_MASK 0x007f +# define SCIF_TXROOM_MAX 64 +/* SH7763 SCIF2 support */ +# define SCIF2_RFDC_MASK 0x001f +# define SCIF2_TXROOM_MAX 16 +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) +# define SCIF_RFDC_MASK	0x003f +#else +# define SCIF_ERRORS (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) +# define SCIF_RFDC_MASK 0x001f +# define SCIF_TXROOM_MAX 16 +#endif + +#ifndef SCIF_ORER +#define SCIF_ORER	0x0000 +#endif + +#define SCxSR_TEND(port)\ +		(((port)->type == PORT_SCI) ? SCI_TEND	: SCIF_TEND) +#define SCxSR_ERRORS(port)\ +		(((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS) +#define SCxSR_RDxF(port)\ +		(((port)->type == PORT_SCI) ? SCI_RDRF	: SCIF_RDF) +#define SCxSR_TDxE(port)\ +		(((port)->type == PORT_SCI) ? SCI_TDRE	: SCIF_TDFE) +#define SCxSR_FER(port)\ +		(((port)->type == PORT_SCI) ? SCI_FER	: SCIF_FER) +#define SCxSR_PER(port)\ +		(((port)->type == PORT_SCI) ? SCI_PER	: SCIF_PER) +#define SCxSR_BRK(port)\ +		((port)->type == PORT_SCI) ? 0x00		: SCIF_BRK) +#define SCxSR_ORER(port)\ +		(((port)->type == PORT_SCI) ? SCI_ORER	: SCIF_ORER) + +#if defined(CONFIG_CPU_SH7705) || \ +	defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_SH73A0) || \ +	defined(CONFIG_R8A7740) +# define SCxSR_RDxF_CLEAR(port)	 (sci_in(port, SCxSR) & 0xfffc) +# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) +# define SCxSR_TDxE_CLEAR(port)	 (sci_in(port, SCxSR) & 0xffdf) +# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3) +#else +# define SCxSR_RDxF_CLEAR(port)	 (((port)->type == PORT_SCI) ? 0xbc : 0x00fc) +# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073) +# define SCxSR_TDxE_CLEAR(port)  (((port)->type == PORT_SCI) ? 0x78 : 0x00df) +# define SCxSR_BREAK_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x00e3) +#endif + +/* SCFCR */ +#define SCFCR_RFRST 0x0002 +#define SCFCR_TFRST 0x0004 +#define SCFCR_TCRST 0x4000 +#define SCFCR_MCE   0x0008 + +#define SCI_MAJOR		204 +#define SCI_MINOR_START		8 + +/* Generic serial flags */ +#define SCI_RX_THROTTLE		0x0000001 + +#define SCI_MAGIC 0xbabeface + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define SCI_EVENT_WRITE_WAKEUP	0 + +#define SCI_IN(size, offset)\ +	if ((size) == 8) {\ +		return readb(port->membase + (offset));\ +	} else {\ +		return readw(port->membase + (offset));\ +	} +#define SCI_OUT(size, offset, value)\ +	if ((size) == 8) {\ +		writeb(value, port->membase + (offset));\ +	} else if ((size) == 16) {\ +		writew(value, port->membase + (offset));\ +	} + +#define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ +	static inline unsigned int sci_##name##_in(struct uart_port *port) {\ +		if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\ +			SCI_IN(scif_size, scif_offset)\ +		} else { /* PORT_SCI or PORT_SCIFA */\ +			SCI_IN(sci_size, sci_offset);\ +		}\ +	}\ +static inline void sci_##name##_out(struct uart_port *port,\ +				unsigned int value) {\ +	if (port->type == PORT_SCIF || port->type == PORT_SCIFB) {\ +		SCI_OUT(scif_size, scif_offset, value)\ +	} else {	/* PORT_SCI or PORT_SCIFA */\ +		SCI_OUT(sci_size, sci_offset, value);\ +	}\ +} + +#ifdef CONFIG_H8300 +/* h8300 don't have SCIF */ +#define CPU_SCIF_FNS(name)						\ +	static inline unsigned int sci_##name##_in(struct uart_port *port) {\ +		return 0;\ +	}\ +	static inline void sci_##name##_out(struct uart_port *port,\ +					unsigned int value) {\ +	} +#else +#define CPU_SCIF_FNS(name, scif_offset, scif_size)			\ +	static inline unsigned int sci_##name##_in(struct uart_port *port) {\ +		SCI_IN(scif_size, scif_offset);\ +	}\ +	static inline void sci_##name##_out(struct uart_port *port,\ +					unsigned int value) {\ +		SCI_OUT(scif_size, scif_offset, value);\ +	} +#endif + +#define CPU_SCI_FNS(name, sci_offset, sci_size)\ +	static inline unsigned int sci_##name##_in(struct uart_port *port) {\ +		SCI_IN(sci_size, sci_offset);\ +	}\ +	static inline void sci_##name##_out(struct uart_port *port,\ +					unsigned int value) {\ +		SCI_OUT(sci_size, sci_offset, value);\ +	} + +#if defined(CONFIG_SH3) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_SH73A0) || \ +	defined(CONFIG_R8A7740) +#if defined(CONFIG_CPU_SH7710) || defined(CONFIG_CPU_SH7712) +#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ +				sh4_sci_offset, sh4_sci_size, \ +				sh3_scif_offset, sh3_scif_size, \ +				sh4_scif_offset, sh4_scif_size, \ +				h8_sci_offset, h8_sci_size) \ +	CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size,\ +				sh4_scif_offset, sh4_scif_size) +#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size,\ +				sh4_scif_offset, sh4_scif_size) \ +	CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) +#elif defined(CONFIG_CPU_SH7705) || \ +	defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_SH73A0) +#define SCIF_FNS(name, scif_offset, scif_size) \ +	CPU_SCIF_FNS(name, scif_offset, scif_size) +#elif defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_R8A7740) +#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\ +				sh4_scifb_offset, sh4_scifb_size) \ +	CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\ +				sh4_scifb_offset, sh4_scifb_size) +#define SCIF_FNS(name, scif_offset, scif_size) \ +	CPU_SCIF_FNS(name, scif_offset, scif_size) +#else +#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ +				sh4_sci_offset, sh4_sci_size, \ +				sh3_scif_offset, sh3_scif_size,\ +				sh4_scif_offset, sh4_scif_size, \ +				h8_sci_offset, h8_sci_size) \ +	CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ +				sh3_scif_offset, sh3_scif_size) +#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size,\ +				sh4_scif_offset, sh4_scif_size) \ +	CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size) +#endif +#elif defined(__H8300H__) || defined(__H8300S__) +#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ +				sh4_sci_offset, sh4_sci_size, \ +				sh3_scif_offset, sh3_scif_size,\ +				sh4_scif_offset, sh4_scif_size, \ +				h8_sci_offset, h8_sci_size) \ +	CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) +#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size,\ +					sh4_scif_offset, sh4_scif_size) \ +	CPU_SCIF_FNS(name) +#elif defined(CONFIG_CPU_SH7723) || defined(CONFIG_CPU_SH7724) +		#define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\ +					sh4_scif_offset, sh4_scif_size) \ +			CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size,\ +					sh4_scif_offset, sh4_scif_size) +		#define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ +			CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) +#else +#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ +				sh4_sci_offset, sh4_sci_size, \ +				sh3_scif_offset, sh3_scif_size,\ +				sh4_scif_offset, sh4_scif_size, \ +				h8_sci_offset, h8_sci_size) \ +	CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size,\ +					sh4_scif_offset, sh4_scif_size) +#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, \ +				sh4_scif_offset, sh4_scif_size) \ +	CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) +#endif + +#if defined(CONFIG_CPU_SH7705) || \ +	defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_SH73A0) + +SCIF_FNS(SCSMR,  0x00, 16) +SCIF_FNS(SCBRR,  0x04,  8) +SCIF_FNS(SCSCR,  0x08, 16) +SCIF_FNS(SCTDSR, 0x0c,  8) +SCIF_FNS(SCFER,  0x10, 16) +SCIF_FNS(SCxSR,  0x14, 16) +SCIF_FNS(SCFCR,  0x18, 16) +SCIF_FNS(SCFDR,  0x1c, 16) +SCIF_FNS(SCxTDR, 0x20,  8) +SCIF_FNS(SCxRDR, 0x24,  8) +SCIF_FNS(SCLSR,  0x00,  0) +#elif defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_R8A7740) +SCIF_FNS(SCSMR,  0x00, 16) +SCIF_FNS(SCBRR,  0x04,  8) +SCIF_FNS(SCSCR,  0x08, 16) +SCIF_FNS(SCTDSR, 0x0c, 16) +SCIF_FNS(SCFER,  0x10, 16) +SCIF_FNS(SCxSR,  0x14, 16) +SCIF_FNS(SCFCR,  0x18, 16) +SCIF_FNS(SCFDR,  0x1c, 16) +SCIF_FNS(SCTFDR, 0x38, 16) +SCIF_FNS(SCRFDR, 0x3c, 16) +SCIx_FNS(SCxTDR, 0x20,  8, 0x40,  8) +SCIx_FNS(SCxRDR, 0x24,  8, 0x60,  8) +SCIF_FNS(SCLSR,  0x00,  0) +#elif defined(CONFIG_CPU_SH7723) ||\ +	defined(CONFIG_CPU_SH7724) +SCIx_FNS(SCSMR,  0x00, 16, 0x00, 16) +SCIx_FNS(SCBRR,  0x04,  8, 0x04,  8) +SCIx_FNS(SCSCR,  0x08, 16, 0x08, 16) +SCIx_FNS(SCxTDR, 0x20,  8, 0x0c,  8) +SCIx_FNS(SCxSR,  0x14, 16, 0x10, 16) +SCIx_FNS(SCxRDR, 0x24,  8, 0x14,  8) +SCIx_FNS(SCSPTR, 0,     0,    0,  0) +SCIF_FNS(SCTDSR, 0x0c,  8) +SCIF_FNS(SCFER,  0x10, 16) +SCIF_FNS(SCFCR,  0x18, 16) +SCIF_FNS(SCFDR,  0x1c, 16) +SCIF_FNS(SCLSR,  0x24, 16) +#else +/*      reg      SCI/SH3   SCI/SH4  SCIF/SH3   SCIF/SH4  SCI/H8*/ +/*      name     off  sz   off  sz   off  sz   off  sz   off  sz*/ +SCIx_FNS(SCSMR,  0x00,  8, 0x00,  8, 0x00,  8, 0x00, 16, 0x00,  8) +SCIx_FNS(SCBRR,  0x02,  8, 0x04,  8, 0x02,  8, 0x04,  8, 0x01,  8) +SCIx_FNS(SCSCR,  0x04,  8, 0x08,  8, 0x04,  8, 0x08, 16, 0x02,  8) +SCIx_FNS(SCxTDR, 0x06,  8, 0x0c,  8, 0x06,  8, 0x0C,  8, 0x03,  8) +SCIx_FNS(SCxSR,  0x08,  8, 0x10,  8, 0x08, 16, 0x10, 16, 0x04,  8) +SCIx_FNS(SCxRDR, 0x0a,  8, 0x14,  8, 0x0A,  8, 0x14,  8, 0x05,  8) +SCIF_FNS(SCFCR,                      0x0c,  8, 0x18, 16) +#if defined(CONFIG_CPU_SH7760) || \ +	defined(CONFIG_CPU_SH7780) || \ +	defined(CONFIG_CPU_SH7785) || \ +	defined(CONFIG_CPU_SH7786) +SCIF_FNS(SCFDR,			     0x0e, 16, 0x1C, 16) +SCIF_FNS(SCTFDR,		     0x0e, 16, 0x1C, 16) +SCIF_FNS(SCRFDR,		     0x0e, 16, 0x20, 16) +SCIF_FNS(SCSPTR,			0,  0, 0x24, 16) +SCIF_FNS(SCLSR,				0,  0, 0x28, 16) +#elif defined(CONFIG_CPU_SH7763) +SCIF_FNS(SCFDR,				0,  0, 0x1C, 16) +SCIF_FNS(SCSPTR2,			0,  0, 0x20, 16) +SCIF_FNS(SCLSR2,			0,  0, 0x24, 16) +SCIF_FNS(SCTFDR,		     0x0e, 16, 0x1C, 16) +SCIF_FNS(SCRFDR,		     0x0e, 16, 0x20, 16) +SCIF_FNS(SCSPTR,			0,  0, 0x24, 16) +SCIF_FNS(SCLSR,				0,  0, 0x28, 16) +#else +SCIF_FNS(SCFDR,                      0x0e, 16, 0x1C, 16) +#if defined(CONFIG_CPU_SH7722) +SCIF_FNS(SCSPTR,                        0,  0, 0, 0) +#else +SCIF_FNS(SCSPTR,                        0,  0, 0x20, 16) +#endif +#if defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +SCIF_FNS(DL,				0,  0, 0x30, 16) +SCIF_FNS(CKS,				0,  0, 0x34, 16) +#endif +SCIF_FNS(SCLSR,                         0,  0, 0x24, 16) +#endif +#endif +#define sci_in(port, reg) sci_##reg##_in(port) +#define sci_out(port, reg, value) sci_##reg##_out(port, value) + +/* H8/300 series SCI pins assignment */ +#if defined(__H8300H__) || defined(__H8300S__) +static const struct __attribute__((packed)) { +	int port;             /* GPIO port no */ +	unsigned short rx, tx; /* GPIO bit no */ +} h8300_sci_pins[] = { +#if defined(CONFIG_H83007) || defined(CONFIG_H83068) +	{    /* SCI0 */ +		.port = H8300_GPIO_P9, +		.rx   = H8300_GPIO_B2, +		.tx   = H8300_GPIO_B0, +	}, +	{    /* SCI1 */ +		.port = H8300_GPIO_P9, +		.rx   = H8300_GPIO_B3, +		.tx   = H8300_GPIO_B1, +	}, +	{    /* SCI2 */ +		.port = H8300_GPIO_PB, +		.rx   = H8300_GPIO_B7, +		.tx   = H8300_GPIO_B6, +	} +#elif defined(CONFIG_H8S2678) +	{    /* SCI0 */ +		.port = H8300_GPIO_P3, +		.rx   = H8300_GPIO_B2, +		.tx   = H8300_GPIO_B0, +	}, +	{    /* SCI1 */ +		.port = H8300_GPIO_P3, +		.rx   = H8300_GPIO_B3, +		.tx   = H8300_GPIO_B1, +	}, +	{    /* SCI2 */ +		.port = H8300_GPIO_P5, +		.rx   = H8300_GPIO_B1, +		.tx   = H8300_GPIO_B0, +	} +#endif +}; +#endif + +#if defined(CONFIG_CPU_SH7706) || \ +	defined(CONFIG_CPU_SH7707) || \ +	defined(CONFIG_CPU_SH7708) || \ +	defined(CONFIG_CPU_SH7709) +static inline int sci_rxd_in(struct uart_port *port) +{ +	if (port->mapbase == 0xfffffe80) +		return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */ +	return 1; +} +#elif defined(CONFIG_CPU_SH7750)  || \ +	defined(CONFIG_CPU_SH7751)  || \ +	defined(CONFIG_CPU_SH7751R) || \ +	defined(CONFIG_CPU_SH7750R) || \ +	defined(CONFIG_CPU_SH7750S) || \ +	defined(CONFIG_CPU_SH7091) +static inline int sci_rxd_in(struct uart_port *port) +{ +	if (port->mapbase == 0xffe00000) +		return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ +	return 1; +} +#elif defined(__H8300H__) || defined(__H8300S__) +static inline int sci_rxd_in(struct uart_port *port) +{ +	int ch = (port->mapbase - SMR0) >> 3; +	return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0; +} +#else /* default case for non-SCI processors */ +static inline int sci_rxd_in(struct uart_port *port) +{ +	return 1; +} +#endif + +/* + * Values for the BitRate Register (SCBRR) + * + * The values are actually divisors for a frequency which can + * be internal to the SH3 (14.7456MHz) or derived from an external + * clock source.  This driver assumes the internal clock is used; + * to support using an external clock source, config options or + * possibly command-line options would need to be added. + * + * Also, to support speeds below 2400 (why?) the lower 2 bits of + * the SCSMR register would also need to be set to non-zero values. + * + * -- Greg Banks 27Feb2000 + * + * Answer: The SCBRR register is only eight bits, and the value in + * it gets larger with lower baud rates. At around 2400 (depending on + * the peripherial module clock) you run out of bits. However the + * lower two bits of SCSMR allow the module clock to be divided down, + * scaling the value which is needed in SCBRR. + * + * -- Stuart Menefy - 23 May 2000 + * + * I meant, why would anyone bother with bitrates below 2400. + * + * -- Greg Banks - 7Jul2000 + * + * You "speedist"!  How will I use my 110bps ASR-33 teletype with paper + * tape reader as a console! + * + * -- Mitch Davis - 15 Jul 2000 + */ + +#if (defined(CONFIG_CPU_SH7780)  || \ +	defined(CONFIG_CPU_SH7785)  || \ +	defined(CONFIG_CPU_SH7786)) && \ +	!defined(CONFIG_SH_SH2007) +#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) +#elif defined(CONFIG_CPU_SH7705) || \ +	defined(CONFIG_CPU_SH7720) || \ +	defined(CONFIG_CPU_SH7721) || \ +	defined(CONFIG_ARCH_SH7367) || \ +	defined(CONFIG_ARCH_SH7377) || \ +	defined(CONFIG_ARCH_SH7372) || \ +	defined(CONFIG_SH73A0) || \ +	defined(CONFIG_R8A7740) +#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) +#elif defined(CONFIG_CPU_SH7723) ||\ +	defined(CONFIG_CPU_SH7724) +static inline int scbrr_calc(struct uart_port port, int bps, int clk) +{ +	if (port.type == PORT_SCIF) +		return (clk+16*bps)/(32*bps)-1; +	else +		return ((clk*2)+16*bps)/(16*bps)-1; +} +#define SCBRR_VALUE(bps, clk) scbrr_calc(sh_sci, bps, clk) +#elif defined(__H8300H__) || defined(__H8300S__) +#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1) +#elif defined(CONFIG_R8A7790) || defined(CONFIG_R8A7791) +#define SCBRR DL +#define SCBRR_VALUE(bps, clk) (clk / bps / 16) +#else /* Generic SH */ +#define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) +#endif diff --git a/roms/u-boot/drivers/serial/serial_xuartlite.c b/roms/u-boot/drivers/serial/serial_xuartlite.c new file mode 100644 index 00000000..988438e7 --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_xuartlite.c @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2008-2011 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> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> +#include <linux/compiler.h> +#include <serial.h> + +#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 ULITE_CONTROL_RST_TX	0x01 +#define ULITE_CONTROL_RST_RX	0x02 + +struct uartlite { +	unsigned int rx_fifo; +	unsigned int tx_fifo; +	unsigned int status; +	unsigned int control; +}; + +static struct uartlite *userial_ports[4] = { +#ifdef XILINX_UARTLITE_BASEADDR +	[0] = (struct uartlite *)XILINX_UARTLITE_BASEADDR, +#endif +#ifdef XILINX_UARTLITE_BASEADDR1 +	[1] = (struct uartlite *)XILINX_UARTLITE_BASEADDR1, +#endif +#ifdef XILINX_UARTLITE_BASEADDR2 +	[2] = (struct uartlite *)XILINX_UARTLITE_BASEADDR2, +#endif +#ifdef XILINX_UARTLITE_BASEADDR3 +	[3] = (struct uartlite *)XILINX_UARTLITE_BASEADDR3 +#endif +}; + +static void uartlite_serial_putc(const char c, const int port) +{ +	struct uartlite *regs = userial_ports[port]; + +	if (c == '\n') +		uartlite_serial_putc('\r', port); + +	while (in_be32(®s->status) & SR_TX_FIFO_FULL) +		; +	out_be32(®s->tx_fifo, c & 0xff); +} + +static void uartlite_serial_puts(const char *s, const int port) +{ +	while (*s) +		uartlite_serial_putc(*s++, port); +} + +static int uartlite_serial_getc(const int port) +{ +	struct uartlite *regs = userial_ports[port]; + +	while (!(in_be32(®s->status) & SR_RX_FIFO_VALID_DATA)) +		; +	return in_be32(®s->rx_fifo) & 0xff; +} + +static int uartlite_serial_tstc(const int port) +{ +	struct uartlite *regs = userial_ports[port]; + +	return in_be32(®s->status) & SR_RX_FIFO_VALID_DATA; +} + +static int uartlite_serial_init(const int port) +{ +	struct uartlite *regs = userial_ports[port]; + +	if (regs) { +		out_be32(®s->control, 0); +		out_be32(®s->control, +			 ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); +		in_be32(®s->control); +		return 0; +	} + +	return -1; +} + +/* Multi serial device functions */ +#define DECLARE_ESERIAL_FUNCTIONS(port) \ +	static int userial##port##_init(void) \ +				{ return uartlite_serial_init(port); } \ +	static void userial##port##_setbrg(void) {} \ +	static int userial##port##_getc(void) \ +				{ return uartlite_serial_getc(port); } \ +	static int userial##port##_tstc(void) \ +				{ return uartlite_serial_tstc(port); } \ +	static void userial##port##_putc(const char c) \ +				{ uartlite_serial_putc(c, port); } \ +	static void userial##port##_puts(const char *s) \ +				{ uartlite_serial_puts(s, port); } + +/* Serial device descriptor */ +#define INIT_ESERIAL_STRUCTURE(port, __name) {	\ +	.name	= __name,			\ +	.start	= userial##port##_init,		\ +	.stop	= NULL,				\ +	.setbrg	= userial##port##_setbrg,	\ +	.getc	= userial##port##_getc,		\ +	.tstc	= userial##port##_tstc,		\ +	.putc	= userial##port##_putc,		\ +	.puts	= userial##port##_puts,		\ +} + +DECLARE_ESERIAL_FUNCTIONS(0); +struct serial_device uartlite_serial0_device = +	INIT_ESERIAL_STRUCTURE(0, "ttyUL0"); +DECLARE_ESERIAL_FUNCTIONS(1); +struct serial_device uartlite_serial1_device = +	INIT_ESERIAL_STRUCTURE(1, "ttyUL1"); +DECLARE_ESERIAL_FUNCTIONS(2); +struct serial_device uartlite_serial2_device = +	INIT_ESERIAL_STRUCTURE(2, "ttyUL2"); +DECLARE_ESERIAL_FUNCTIONS(3); +struct serial_device uartlite_serial3_device = +	INIT_ESERIAL_STRUCTURE(3, "ttyUL3"); + +__weak struct serial_device *default_serial_console(void) +{ +	if (userial_ports[0]) +		return &uartlite_serial0_device; +	if (userial_ports[1]) +		return &uartlite_serial1_device; +	if (userial_ports[2]) +		return &uartlite_serial2_device; +	if (userial_ports[3]) +		return &uartlite_serial3_device; + +	return NULL; +} + +void uartlite_serial_initialize(void) +{ +#ifdef XILINX_UARTLITE_BASEADDR +	serial_register(&uartlite_serial0_device); +#endif /* XILINX_UARTLITE_BASEADDR */ +#ifdef XILINX_UARTLITE_BASEADDR1 +	serial_register(&uartlite_serial1_device); +#endif /* XILINX_UARTLITE_BASEADDR1 */ +#ifdef XILINX_UARTLITE_BASEADDR2 +	serial_register(&uartlite_serial2_device); +#endif /* XILINX_UARTLITE_BASEADDR2 */ +#ifdef XILINX_UARTLITE_BASEADDR3 +	serial_register(&uartlite_serial3_device); +#endif /* XILINX_UARTLITE_BASEADDR3 */ +} diff --git a/roms/u-boot/drivers/serial/serial_zynq.c b/roms/u-boot/drivers/serial/serial_zynq.c new file mode 100644 index 00000000..1ff27d5f --- /dev/null +++ b/roms/u-boot/drivers/serial/serial_zynq.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2012 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2011-2012 Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <watchdog.h> +#include <asm/io.h> +#include <linux/compiler.h> +#include <serial.h> +#include <asm/arch/clk.h> +#include <asm/arch/hardware.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ZYNQ_UART_SR_TXFULL	0x00000010 /* TX FIFO full */ +#define ZYNQ_UART_SR_RXEMPTY	0x00000002 /* RX FIFO empty */ + +#define ZYNQ_UART_CR_TX_EN	0x00000010 /* TX enabled */ +#define ZYNQ_UART_CR_RX_EN	0x00000004 /* RX enabled */ +#define ZYNQ_UART_CR_TXRST	0x00000002 /* TX logic reset */ +#define ZYNQ_UART_CR_RXRST	0x00000001 /* RX logic reset */ + +#define ZYNQ_UART_MR_PARITY_NONE	0x00000020  /* No parity mode */ + +struct uart_zynq { +	u32 control; /* Control Register [8:0] */ +	u32 mode; /* Mode Register [10:0] */ +	u32 reserved1[4]; +	u32 baud_rate_gen; /* Baud Rate Generator [15:0] */ +	u32 reserved2[4]; +	u32 channel_sts; /* Channel Status [11:0] */ +	u32 tx_rx_fifo; /* FIFO [15:0] or [7:0] */ +	u32 baud_rate_divider; /* Baud Rate Divider [7:0] */ +}; + +static struct uart_zynq *uart_zynq_ports[2] = { +	[0] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR0, +	[1] = (struct uart_zynq *)ZYNQ_SERIAL_BASEADDR1, +}; + +#if !defined(CONFIG_ZYNQ_SERIAL_BAUDRATE0) +# define CONFIG_ZYNQ_SERIAL_BAUDRATE0	CONFIG_BAUDRATE +#endif +#if !defined(CONFIG_ZYNQ_SERIAL_BAUDRATE1) +# define CONFIG_ZYNQ_SERIAL_BAUDRATE1	CONFIG_BAUDRATE +#endif + +struct uart_zynq_params { +	u32 baudrate; +}; + +static struct uart_zynq_params uart_zynq_ports_param[2] = { +	[0].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE0, +	[1].baudrate = CONFIG_ZYNQ_SERIAL_BAUDRATE1, +}; + +/* Set up the baud rate in gd struct */ +static void uart_zynq_serial_setbrg(const int port) +{ +	/* Calculation results. */ +	unsigned int calc_bauderror, bdiv, bgen; +	unsigned long calc_baud = 0; +	unsigned long baud = uart_zynq_ports_param[port].baudrate; +	unsigned long clock = get_uart_clk(port); +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	/*                master clock +	 * Baud rate = ------------------ +	 *              bgen * (bdiv + 1) +	 * +	 * Find acceptable values for baud generation. +	 */ +	for (bdiv = 4; bdiv < 255; bdiv++) { +		bgen = clock / (baud * (bdiv + 1)); +		if (bgen < 2 || bgen > 65535) +			continue; + +		calc_baud = clock / (bgen * (bdiv + 1)); + +		/* +		 * Use first calculated baudrate with +		 * an acceptable (<3%) error +		 */ +		if (baud > calc_baud) +			calc_bauderror = baud - calc_baud; +		else +			calc_bauderror = calc_baud - baud; +		if (((calc_bauderror * 100) / baud) < 3) +			break; +	} + +	writel(bdiv, ®s->baud_rate_divider); +	writel(bgen, ®s->baud_rate_gen); +} + +/* Initialize the UART, with...some settings. */ +static int uart_zynq_serial_init(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	if (!regs) +		return -1; + +	/* RX/TX enabled & reset */ +	writel(ZYNQ_UART_CR_TX_EN | ZYNQ_UART_CR_RX_EN | ZYNQ_UART_CR_TXRST | \ +					ZYNQ_UART_CR_RXRST, ®s->control); +	writel(ZYNQ_UART_MR_PARITY_NONE, ®s->mode); /* 8 bit, no parity */ +	uart_zynq_serial_setbrg(port); + +	return 0; +} + +static void uart_zynq_serial_putc(const char c, const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) +		WATCHDOG_RESET(); + +	if (c == '\n') { +		writel('\r', ®s->tx_rx_fifo); +		while ((readl(®s->channel_sts) & ZYNQ_UART_SR_TXFULL) != 0) +			WATCHDOG_RESET(); +	} +	writel(c, ®s->tx_rx_fifo); +} + +static void uart_zynq_serial_puts(const char *s, const int port) +{ +	while (*s) +		uart_zynq_serial_putc(*s++, port); +} + +static int uart_zynq_serial_tstc(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	return (readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY) == 0; +} + +static int uart_zynq_serial_getc(const int port) +{ +	struct uart_zynq *regs = uart_zynq_ports[port]; + +	while (!uart_zynq_serial_tstc(port)) +		WATCHDOG_RESET(); +	return readl(®s->tx_rx_fifo); +} + +/* Multi serial device functions */ +#define DECLARE_PSSERIAL_FUNCTIONS(port) \ +	static int uart_zynq##port##_init(void) \ +				{ return uart_zynq_serial_init(port); } \ +	static void uart_zynq##port##_setbrg(void) \ +				{ return uart_zynq_serial_setbrg(port); } \ +	static int uart_zynq##port##_getc(void) \ +				{ return uart_zynq_serial_getc(port); } \ +	static int uart_zynq##port##_tstc(void) \ +				{ return uart_zynq_serial_tstc(port); } \ +	static void uart_zynq##port##_putc(const char c) \ +				{ uart_zynq_serial_putc(c, port); } \ +	static void uart_zynq##port##_puts(const char *s) \ +				{ uart_zynq_serial_puts(s, port); } + +/* Serial device descriptor */ +#define INIT_PSSERIAL_STRUCTURE(port, __name) {	\ +	  .name   = __name,			\ +	  .start  = uart_zynq##port##_init,	\ +	  .stop   = NULL,			\ +	  .setbrg = uart_zynq##port##_setbrg,	\ +	  .getc   = uart_zynq##port##_getc,	\ +	  .tstc   = uart_zynq##port##_tstc,	\ +	  .putc   = uart_zynq##port##_putc,	\ +	  .puts   = uart_zynq##port##_puts,	\ +} + +DECLARE_PSSERIAL_FUNCTIONS(0); +static struct serial_device uart_zynq_serial0_device = +	INIT_PSSERIAL_STRUCTURE(0, "ttyPS0"); +DECLARE_PSSERIAL_FUNCTIONS(1); +static struct serial_device uart_zynq_serial1_device = +	INIT_PSSERIAL_STRUCTURE(1, "ttyPS1"); + +#ifdef CONFIG_OF_CONTROL +__weak struct serial_device *default_serial_console(void) +{ +	const void *blob = gd->fdt_blob; +	int node; +	unsigned int base_addr; + +	node = fdt_path_offset(blob, "serial0"); +	if (node < 0) +		return NULL; + +	base_addr = fdtdec_get_addr(blob, node, "reg"); +	if (base_addr == FDT_ADDR_T_NONE) +		return NULL; + +	if (base_addr == ZYNQ_SERIAL_BASEADDR0) +		return &uart_zynq_serial0_device; + +	if (base_addr == ZYNQ_SERIAL_BASEADDR1) +		return &uart_zynq_serial1_device; + +	return NULL; +} +#else +__weak struct serial_device *default_serial_console(void) +{ +#if defined(CONFIG_ZYNQ_SERIAL_UART0) +	if (uart_zynq_ports[0]) +		return &uart_zynq_serial0_device; +#endif +#if defined(CONFIG_ZYNQ_SERIAL_UART1) +	if (uart_zynq_ports[1]) +		return &uart_zynq_serial1_device; +#endif +	return NULL; +} +#endif + +void zynq_serial_initialize(void) +{ +	serial_register(&uart_zynq_serial0_device); +	serial_register(&uart_zynq_serial1_device); +} diff --git a/roms/u-boot/drivers/serial/usbtty.c b/roms/u-boot/drivers/serial/usbtty.c new file mode 100644 index 00000000..6b912efa --- /dev/null +++ b/roms/u-boot/drivers/serial/usbtty.c @@ -0,0 +1,1046 @@ +/* + * (C) Copyright 2003 + * Gerry Hamel, geh@ti.com, Texas Instruments + * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <config.h> +#include <circbuf.h> +#include <stdio_dev.h> +#include <asm/unaligned.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 2048 +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 +}; + + +#if defined(CONFIG_USBD_HS) +static struct usb_qualifier_descriptor qualifier_descriptor = { +	.bLength = sizeof(struct usb_qualifier_descriptor), +	.bDescriptorType =	USB_DT_QUAL, +	.bcdUSB =		cpu_to_le16(USB_BCD_VERSION), +	.bDeviceClass =		COMMUNICATIONS_DEVICE_CLASS, +	.bDeviceSubClass =	0x00, +	.bDeviceProtocol =	0x00, +	.bMaxPacketSize0 =	EP0_MAX_PACKET_SIZE, +	.bNumConfigurations =	NUM_CONFIGS +}; +#endif + +/* + * 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 (); + +	usbtty_init_endpoints (); + +	udc_startup_events (device_instance);/* Enable dev, init udc pointers */ +	udc_connect ();		/* Enable pullup for host detection */ + +	/* 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; +} + +#define init_wMaxPacketSize(x)	le16_to_cpu(get_unaligned(\ +			&ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize)); + +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; +#if defined(CONFIG_USBD_HS) +	device_instance->qualifier_descriptor = &qualifier_descriptor; +#endif +	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 = init_wMaxPacketSize(i); + +		endpoint_instance[i].tx_attributes = +			ep_descriptor_ptrs[i - 1]->bmAttributes; + +		endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i); + +		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); + +#if defined(CONFIG_USBD_HS) +			qualifier_descriptor.bDeviceClass = +				COMMUNICATIONS_DEVICE_CLASS; +#endif +			/* 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); +#if defined(CONFIG_USBD_HS) +			qualifier_descriptor.bDeviceClass = 0xFF; +#endif +			/* 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) +{ +#if defined(CONFIG_USBD_HS) +	int i; +#endif +	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: +#if defined(CONFIG_USBD_HS) +		/* +		 * is_usbd_high_speed routine needs to be defined by +		 * specific gadget driver +		 * It returns true if device enumerates at High speed +		 * Retuns false otherwise +		 */ +		for (i = 0; i < NUM_ENDPOINTS; i++) { +			if (((ep_descriptor_ptrs[i]->bmAttributes & +			      USB_ENDPOINT_XFERTYPE_MASK) == +			      USB_ENDPOINT_XFER_BULK) +			    && is_usbd_high_speed()) { + +				ep_descriptor_ptrs[i]->wMaxPacketSize = +					CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE; +			} + +			endpoint_instance[i + 1].tx_packetSize = +				ep_descriptor_ptrs[i]->wMaxPacketSize; +			endpoint_instance[i + 1].rcv_packetSize = +				ep_descriptor_ptrs[i]->wMaxPacketSize; +		} +#endif +		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/drivers/serial/usbtty.h b/roms/u-boot/drivers/serial/usbtty.h new file mode 100644 index 00000000..21a3ef4d --- /dev/null +++ b/roms/u-boot/drivers/serial/usbtty.h @@ -0,0 +1,79 @@ +/* + * (C) Copyright 2003 + * Gerry Hamel, geh@ti.com, Texas Instruments + * + * (C) Copyright 2006 + * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#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_CPU_PXA27X) +#include <usb/pxa27x_udc.h> +#elif defined(CONFIG_DW_UDC) +#include <usb/designware_udc.h> +#elif defined(CONFIG_CI_UDC) +#include <usb/ci_udc.h> +#endif + +#include <usb/udc.h> +#include <version.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 + +#if defined(CONFIG_USBD_HS) +#define CONFIG_USBD_SERIAL_BULK_HS_PKTSIZE	UDC_BULK_HS_PACKET_SIZE +#endif + +#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  | 
