2 * Freescale i.MX23/i.MX28 AUART driver
4 * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com>
6 * Based on the MXC serial driver:
8 * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
10 * Further based on the Linux mxs-auart.c driver:
12 * Freescale STMP37XX/STMP38X Application UART drkiver
13 * Copyright 2008-2010 Freescale Semiconductor, Inc.
15 * SPDX-License-Identifier: GPL-2.0+
20 #include <linux/compiler.h>
21 #include <asm/arch/regs-base.h>
22 #include <asm/arch/regs-uartapp.h>
23 #include <asm/arch/sys_proto.h>
25 DECLARE_GLOBAL_DATA_PTR;
27 #ifndef CONFIG_MXS_AUART_BASE
28 #error "CONFIG_MXS_AUART_BASE must be set to the base UART to use"
31 /* AUART clock always supplied by XTAL and always 24MHz */
32 #define MXS_AUART_CLK 24000000
34 static struct mxs_uartapp_regs *get_uartapp_registers(void)
36 return (struct mxs_uartapp_regs *)CONFIG_MXS_AUART_BASE;
40 * Sets the baud rate and settings.
41 * The settings are: 8 data bits, no parit and 1 stop bit.
43 static void mxs_auart_setbrg(void)
47 struct mxs_uartapp_regs *regs = get_uartapp_registers();
50 gd->baudrate = CONFIG_BAUDRATE;
53 * From i.MX28 datasheet:
54 * div is calculated by calculating UARTCLK*32/baudrate, rounded to int
55 * div must be between 0xEC and 0x003FFFC0 inclusive
56 * Lowest 6 bits of div goes in BAUD_DIVFRAC part of LINECTRL register
57 * Next 16 bits goes in BAUD_DIVINT part of LINECTRL register
59 div = (MXS_AUART_CLK * 32) / gd->baudrate;
60 if (div < 0xEC || div > 0x003FFFC0)
63 linectrl |= ((div & UARTAPP_LINECTRL_EXTRACT_BAUD_DIVFRAC_MASK) <<
64 UARTAPP_LINECTRL_BAUD_DIVFRAC_OFFSET) &
65 UARTAPP_LINECTRL_BAUD_DIVFRAC_MASK;
66 linectrl |= ((div >> UARTAPP_LINECTRL_EXTRACT_BAUD_DIVINT_OFFSET) <<
67 UARTAPP_LINECTRL_BAUD_DIVINT_OFFSET) &
68 UARTAPP_LINECTRL_BAUD_DIVINT_MASK;
70 /* Word length: 8 bits */
71 linectrl |= UARTAPP_LINECTRL_WLEN_8BITS;
74 linectrl |= UARTAPP_LINECTRL_FEN_MASK;
76 /* Write above settings, no parity, 1 stop bit */
77 writel(linectrl, ®s->hw_uartapp_linectrl);
80 static int mxs_auart_init(void)
82 struct mxs_uartapp_regs *regs = get_uartapp_registers();
83 /* Reset everything */
84 mxs_reset_block(®s->hw_uartapp_ctrl0_reg);
85 /* Disable interrupts */
86 writel(0, ®s->hw_uartapp_intr);
87 /* Set baud rate and settings */
89 /* Disable RTS and CTS, ignore LINECTRL2 register */
90 writel(UARTAPP_CTRL2_RTSEN_MASK |
91 UARTAPP_CTRL2_CTSEN_MASK |
92 UARTAPP_CTRL2_USE_LCR2_MASK,
93 ®s->hw_uartapp_ctrl2_clr);
94 /* Enable receiver, transmitter and UART */
95 writel(UARTAPP_CTRL2_RXE_MASK |
96 UARTAPP_CTRL2_TXE_MASK |
97 UARTAPP_CTRL2_UARTEN_MASK,
98 ®s->hw_uartapp_ctrl2_set);
102 static void mxs_auart_putc(const char c)
104 struct mxs_uartapp_regs *regs = get_uartapp_registers();
105 /* Wait in loop while the transmit FIFO is full */
106 while (readl(®s->hw_uartapp_stat) & UARTAPP_STAT_TXFF_MASK)
109 writel(c, ®s->hw_uartapp_data);
112 mxs_auart_putc('\r');
115 static int mxs_auart_tstc(void)
117 struct mxs_uartapp_regs *regs = get_uartapp_registers();
118 /* Checks if receive FIFO is empty */
119 return !(readl(®s->hw_uartapp_stat) & UARTAPP_STAT_RXFE_MASK);
122 static int mxs_auart_getc(void)
124 struct mxs_uartapp_regs *regs = get_uartapp_registers();
125 /* Wait until a character is available to read */
126 while (!mxs_auart_tstc())
128 /* Read the character from the data register */
129 return readl(®s->hw_uartapp_data) & 0xFF;
132 static struct serial_device mxs_auart_drv = {
133 .name = "mxs_auart_serial",
134 .start = mxs_auart_init,
136 .setbrg = mxs_auart_setbrg,
137 .putc = mxs_auart_putc,
138 .puts = default_serial_puts,
139 .getc = mxs_auart_getc,
140 .tstc = mxs_auart_tstc,
143 void mxs_auart_initialize(void)
145 serial_register(&mxs_auart_drv);
148 __weak struct serial_device *default_serial_console(void)
150 return &mxs_auart_drv;