diff options
Diffstat (limited to 'drivers/serial')
| -rw-r--r-- | drivers/serial/Makefile | 1 | ||||
| -rw-r--r-- | drivers/serial/mxs_auart.c | 151 | ||||
| -rw-r--r-- | drivers/serial/serial.c | 2 | 
3 files changed, 154 insertions, 0 deletions
| diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 697f2bb4e..4c45bfa36 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -38,6 +38,7 @@ COBJS-$(CONFIG_SCIF_CONSOLE) += serial_sh.o  COBJS-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o  COBJS-$(CONFIG_BFIN_SERIAL) += serial_bfin.o  COBJS-$(CONFIG_FSL_LPUART) += serial_lpuart.o +COBJS-$(CONFIG_MXS_AUART) += mxs_auart.o  ifndef CONFIG_SPL_BUILD  COBJS-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/mxs_auart.c b/drivers/serial/mxs_auart.c new file mode 100644 index 000000000..7cfe5bccf --- /dev/null +++ b/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. + */ +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); +} + +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; +} + +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'); +} + +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); +} + +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/drivers/serial/serial.c b/drivers/serial/serial.c index 118fbc305..35dc61e02 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -160,6 +160,7 @@ serial_initfunc(s3c44b0_serial_initialize);  serial_initfunc(sa1100_serial_initialize);  serial_initfunc(sh_serial_initialize);  serial_initfunc(arm_dcc_initialize); +serial_initfunc(mxs_auart_initialize);  /**   * serial_register() - Register serial driver with serial driver core @@ -253,6 +254,7 @@ void serial_initialize(void)  	sa1100_serial_initialize();  	sh_serial_initialize();  	arm_dcc_initialize(); +	mxs_auart_initialize();  	serial_assign(default_serial_console()->name);  } |