]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/serial/mxs_auart.c
usb: dfu: make nand upload working
[karo-tx-uboot.git] / drivers / serial / mxs_auart.c
1 /*
2  * Freescale i.MX23/i.MX28 AUART driver
3  *
4  * Copyright (C) 2013 Andreas Wass <andreas.wass@dalelven.com>
5  *
6  * Based on the MXC serial driver:
7  *
8  * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
9  *
10  * Further based on the Linux mxs-auart.c driver:
11  *
12  * Freescale STMP37XX/STMP38X Application UART drkiver
13  * Copyright 2008-2010 Freescale Semiconductor, Inc.
14  *
15  * SPDX-License-Identifier:     GPL-2.0+
16  */
17 #include <common.h>
18 #include <asm/io.h>
19 #include <serial.h>
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>
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 #ifndef CONFIG_MXS_AUART_BASE
28 #error "CONFIG_MXS_AUART_BASE must be set to the base UART to use"
29 #endif
30
31 /* AUART clock always supplied by XTAL and always 24MHz */
32 #define MXS_AUART_CLK 24000000
33
34 static struct mxs_uartapp_regs *get_uartapp_registers(void)
35 {
36         return (struct mxs_uartapp_regs *)CONFIG_MXS_AUART_BASE;
37 }
38
39 /**
40  * Sets the baud rate and settings.
41  * The settings are: 8 data bits, no parit and 1 stop bit.
42  */
43 void mxs_auart_setbrg(void)
44 {
45         u32 div;
46         u32 linectrl = 0;
47         struct mxs_uartapp_regs *regs = get_uartapp_registers();
48
49         if (!gd->baudrate)
50                 gd->baudrate = CONFIG_BAUDRATE;
51
52         /*
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
58          */
59         div = (MXS_AUART_CLK * 32) / gd->baudrate;
60         if (div < 0xEC || div > 0x003FFFC0)
61                 return;
62
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;
69
70         /* Word length: 8 bits */
71         linectrl |= UARTAPP_LINECTRL_WLEN_8BITS;
72
73         /* Enable FIFOs. */
74         linectrl |= UARTAPP_LINECTRL_FEN_MASK;
75
76         /* Write above settings, no parity, 1 stop bit */
77         writel(linectrl, &regs->hw_uartapp_linectrl);
78 }
79
80 int mxs_auart_init(void)
81 {
82         struct mxs_uartapp_regs *regs = get_uartapp_registers();
83         /* Reset everything */
84         mxs_reset_block(&regs->hw_uartapp_ctrl0_reg);
85         /* Disable interrupts */
86         writel(0, &regs->hw_uartapp_intr);
87         /* Set baud rate and settings */
88         serial_setbrg();
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                         &regs->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                         &regs->hw_uartapp_ctrl2_set);
99         return 0;
100 }
101
102 void mxs_auart_putc(const char c)
103 {
104         struct mxs_uartapp_regs *regs = get_uartapp_registers();
105         /* Wait in loop while the transmit FIFO is full */
106         while (readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_TXFF_MASK)
107                 ;
108
109         writel(c, &regs->hw_uartapp_data);
110
111         if (c == '\n')
112                 mxs_auart_putc('\r');
113 }
114
115 int mxs_auart_tstc(void)
116 {
117         struct mxs_uartapp_regs *regs = get_uartapp_registers();
118         /* Checks if receive FIFO is empty */
119         return !(readl(&regs->hw_uartapp_stat) & UARTAPP_STAT_RXFE_MASK);
120 }
121
122 int mxs_auart_getc(void)
123 {
124         struct mxs_uartapp_regs *regs = get_uartapp_registers();
125         /* Wait until a character is available to read */
126         while (!mxs_auart_tstc())
127                 ;
128         /* Read the character from the data register */
129         return readl(&regs->hw_uartapp_data) & 0xFF;
130 }
131
132 static struct serial_device mxs_auart_drv = {
133         .name = "mxs_auart_serial",
134         .start = mxs_auart_init,
135         .stop = NULL,
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,
141 };
142
143 void mxs_auart_initialize(void)
144 {
145         serial_register(&mxs_auart_drv);
146 }
147
148 __weak struct serial_device *default_serial_console(void)
149 {
150         return &mxs_auart_drv;
151 }