147d19da4SIlya Yanok /*
247d19da4SIlya Yanok * (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>
347d19da4SIlya Yanok *
41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
547d19da4SIlya Yanok */
647d19da4SIlya Yanok
747d19da4SIlya Yanok #include <common.h>
8a8ba569cSSimon Glass #include <dm.h>
9a8ba569cSSimon Glass #include <errno.h>
104ec3d2a7SStefano Babic #include <watchdog.h>
1147d19da4SIlya Yanok #include <asm/arch/imx-regs.h>
1247d19da4SIlya Yanok #include <asm/arch/clock.h>
1386256b79SMasahiro Yamada #include <dm/platform_data/serial_mxc.h>
14a943472cSMarek Vasut #include <serial.h>
15a943472cSMarek Vasut #include <linux/compiler.h>
1647d19da4SIlya Yanok
1747d19da4SIlya Yanok /* UART Control Register Bit Fields.*/
1847d19da4SIlya Yanok #define URXD_CHARRDY (1<<15)
1947d19da4SIlya Yanok #define URXD_ERR (1<<14)
2047d19da4SIlya Yanok #define URXD_OVRRUN (1<<13)
2147d19da4SIlya Yanok #define URXD_FRMERR (1<<12)
2247d19da4SIlya Yanok #define URXD_BRK (1<<11)
2347d19da4SIlya Yanok #define URXD_PRERR (1<<10)
2447d19da4SIlya Yanok #define URXD_RX_DATA (0xFF)
2547d19da4SIlya Yanok #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
2647d19da4SIlya Yanok #define UCR1_ADBR (1<<14) /* Auto detect baud rate */
2747d19da4SIlya Yanok #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
2847d19da4SIlya Yanok #define UCR1_IDEN (1<<12) /* Idle condition interrupt */
2947d19da4SIlya Yanok #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
3047d19da4SIlya Yanok #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
3147d19da4SIlya Yanok #define UCR1_IREN (1<<7) /* Infrared interface enable */
3247d19da4SIlya Yanok #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
3347d19da4SIlya Yanok #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
3447d19da4SIlya Yanok #define UCR1_SNDBRK (1<<4) /* Send break */
3547d19da4SIlya Yanok #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
3647d19da4SIlya Yanok #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
3747d19da4SIlya Yanok #define UCR1_DOZE (1<<1) /* Doze */
3847d19da4SIlya Yanok #define UCR1_UARTEN (1<<0) /* UART enabled */
3947d19da4SIlya Yanok #define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
4047d19da4SIlya Yanok #define UCR2_IRTS (1<<14) /* Ignore RTS pin */
4147d19da4SIlya Yanok #define UCR2_CTSC (1<<13) /* CTS pin control */
4247d19da4SIlya Yanok #define UCR2_CTS (1<<12) /* Clear to send */
4347d19da4SIlya Yanok #define UCR2_ESCEN (1<<11) /* Escape enable */
4447d19da4SIlya Yanok #define UCR2_PREN (1<<8) /* Parity enable */
4547d19da4SIlya Yanok #define UCR2_PROE (1<<7) /* Parity odd/even */
4647d19da4SIlya Yanok #define UCR2_STPB (1<<6) /* Stop */
4747d19da4SIlya Yanok #define UCR2_WS (1<<5) /* Word size */
4847d19da4SIlya Yanok #define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
4947d19da4SIlya Yanok #define UCR2_TXEN (1<<2) /* Transmitter enabled */
5047d19da4SIlya Yanok #define UCR2_RXEN (1<<1) /* Receiver enabled */
5147d19da4SIlya Yanok #define UCR2_SRST (1<<0) /* SW reset */
5247d19da4SIlya Yanok #define UCR3_DTREN (1<<13) /* DTR interrupt enable */
5347d19da4SIlya Yanok #define UCR3_PARERREN (1<<12) /* Parity enable */
5447d19da4SIlya Yanok #define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
5547d19da4SIlya Yanok #define UCR3_DSR (1<<10) /* Data set ready */
5647d19da4SIlya Yanok #define UCR3_DCD (1<<9) /* Data carrier detect */
5747d19da4SIlya Yanok #define UCR3_RI (1<<8) /* Ring indicator */
583a564825SEric Nelson #define UCR3_ADNIMP (1<<7) /* Autobaud Detection Not Improved */
5947d19da4SIlya Yanok #define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
6047d19da4SIlya Yanok #define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
6147d19da4SIlya Yanok #define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
6247d19da4SIlya Yanok #define UCR3_REF25 (1<<3) /* Ref freq 25 MHz */
6347d19da4SIlya Yanok #define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz */
6447d19da4SIlya Yanok #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
6547d19da4SIlya Yanok #define UCR3_BPEN (1<<0) /* Preset registers enable */
6647d19da4SIlya Yanok #define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
6747d19da4SIlya Yanok #define UCR4_INVR (1<<9) /* Inverted infrared reception */
6847d19da4SIlya Yanok #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
6947d19da4SIlya Yanok #define UCR4_WKEN (1<<7) /* Wake interrupt enable */
7047d19da4SIlya Yanok #define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
7147d19da4SIlya Yanok #define UCR4_IRSC (1<<5) /* IR special case */
7247d19da4SIlya Yanok #define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
7347d19da4SIlya Yanok #define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
7447d19da4SIlya Yanok #define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
7547d19da4SIlya Yanok #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
7647d19da4SIlya Yanok #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
7747d19da4SIlya Yanok #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
78434afa80SMaximilian Schwerin #define UFCR_RFDIV_SHF 7 /* Reference freq divider shift */
7962af03eeSJagan Teki #define RFDIV 4 /* divide input clock by 2 */
8083fd908fSStefan Agner #define UFCR_DCEDTE (1<<6) /* DTE mode select */
8147d19da4SIlya Yanok #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
8247d19da4SIlya Yanok #define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
8347d19da4SIlya Yanok #define USR1_RTSS (1<<14) /* RTS pin status */
8447d19da4SIlya Yanok #define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
8547d19da4SIlya Yanok #define USR1_RTSD (1<<12) /* RTS delta */
8647d19da4SIlya Yanok #define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
8747d19da4SIlya Yanok #define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
8847d19da4SIlya Yanok #define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
8947d19da4SIlya Yanok #define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
9047d19da4SIlya Yanok #define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
9147d19da4SIlya Yanok #define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
9247d19da4SIlya Yanok #define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
9347d19da4SIlya Yanok #define USR2_ADET (1<<15) /* Auto baud rate detect complete */
9447d19da4SIlya Yanok #define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
9547d19da4SIlya Yanok #define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
9647d19da4SIlya Yanok #define USR2_IDLE (1<<12) /* Idle condition */
9747d19da4SIlya Yanok #define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
9847d19da4SIlya Yanok #define USR2_WAKE (1<<7) /* Wake */
9947d19da4SIlya Yanok #define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
10047d19da4SIlya Yanok #define USR2_TXDC (1<<3) /* Transmitter complete */
10147d19da4SIlya Yanok #define USR2_BRCD (1<<2) /* Break condition */
10247d19da4SIlya Yanok #define USR2_ORE (1<<1) /* Overrun error */
10347d19da4SIlya Yanok #define USR2_RDR (1<<0) /* Recv data ready */
10447d19da4SIlya Yanok #define UTS_FRCPERR (1<<13) /* Force parity error */
10547d19da4SIlya Yanok #define UTS_LOOP (1<<12) /* Loop tx and rx */
10647d19da4SIlya Yanok #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
10747d19da4SIlya Yanok #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
10847d19da4SIlya Yanok #define UTS_TXFULL (1<<4) /* TxFIFO full */
10947d19da4SIlya Yanok #define UTS_RXFULL (1<<3) /* RxFIFO full */
11062af03eeSJagan Teki #define UTS_SOFTRS (1<<0) /* Software reset */
11145d97511SJagan Teki #define TXTL 2 /* reset default */
11245d97511SJagan Teki #define RXTL 1 /* reset default */
11347d19da4SIlya Yanok
114a99546abSStefan Agner DECLARE_GLOBAL_DATA_PTR;
115a99546abSStefan Agner
116ffa8bcd7SJagan Teki struct mxc_uart {
117ffa8bcd7SJagan Teki u32 rxd;
118ffa8bcd7SJagan Teki u32 spare0[15];
119ffa8bcd7SJagan Teki
120ffa8bcd7SJagan Teki u32 txd;
121ffa8bcd7SJagan Teki u32 spare1[15];
122ffa8bcd7SJagan Teki
123ffa8bcd7SJagan Teki u32 cr1;
124ffa8bcd7SJagan Teki u32 cr2;
125ffa8bcd7SJagan Teki u32 cr3;
126ffa8bcd7SJagan Teki u32 cr4;
127ffa8bcd7SJagan Teki
128ffa8bcd7SJagan Teki u32 fcr;
129ffa8bcd7SJagan Teki u32 sr1;
130ffa8bcd7SJagan Teki u32 sr2;
131ffa8bcd7SJagan Teki u32 esc;
132ffa8bcd7SJagan Teki
133ffa8bcd7SJagan Teki u32 tim;
134ffa8bcd7SJagan Teki u32 bir;
135ffa8bcd7SJagan Teki u32 bmr;
136ffa8bcd7SJagan Teki u32 brc;
137ffa8bcd7SJagan Teki
138ffa8bcd7SJagan Teki u32 onems;
139ffa8bcd7SJagan Teki u32 ts;
140ffa8bcd7SJagan Teki };
141ffa8bcd7SJagan Teki
_mxc_serial_init(struct mxc_uart * base)14297548d59SJagan Teki static void _mxc_serial_init(struct mxc_uart *base)
14397548d59SJagan Teki {
14497548d59SJagan Teki writel(0, &base->cr1);
14597548d59SJagan Teki writel(0, &base->cr2);
14697548d59SJagan Teki
14797548d59SJagan Teki while (!(readl(&base->cr2) & UCR2_SRST));
14897548d59SJagan Teki
14997548d59SJagan Teki writel(0x704 | UCR3_ADNIMP, &base->cr3);
15097548d59SJagan Teki writel(0x8000, &base->cr4);
15197548d59SJagan Teki writel(0x2b, &base->esc);
15297548d59SJagan Teki writel(0, &base->tim);
15397548d59SJagan Teki
15497548d59SJagan Teki writel(0, &base->ts);
15597548d59SJagan Teki }
15697548d59SJagan Teki
_mxc_serial_setbrg(struct mxc_uart * base,unsigned long clk,unsigned long baudrate,bool use_dte)15745d97511SJagan Teki static void _mxc_serial_setbrg(struct mxc_uart *base, unsigned long clk,
15845d97511SJagan Teki unsigned long baudrate, bool use_dte)
15945d97511SJagan Teki {
16045d97511SJagan Teki u32 tmp;
16145d97511SJagan Teki
16245d97511SJagan Teki tmp = RFDIV << UFCR_RFDIV_SHF;
16345d97511SJagan Teki if (use_dte)
16445d97511SJagan Teki tmp |= UFCR_DCEDTE;
16545d97511SJagan Teki else
16645d97511SJagan Teki tmp |= (TXTL << UFCR_TXTL_SHF) | (RXTL << UFCR_RXTL_SHF);
16745d97511SJagan Teki writel(tmp, &base->fcr);
16845d97511SJagan Teki
16945d97511SJagan Teki writel(0xf, &base->bir);
17045d97511SJagan Teki writel(clk / (2 * baudrate), &base->bmr);
17145d97511SJagan Teki
17245d97511SJagan Teki writel(UCR2_WS | UCR2_IRTS | UCR2_RXEN | UCR2_TXEN | UCR2_SRST,
17345d97511SJagan Teki &base->cr2);
17445d97511SJagan Teki writel(UCR1_UARTEN, &base->cr1);
17545d97511SJagan Teki }
17645d97511SJagan Teki
177a8ba569cSSimon Glass #ifndef CONFIG_DM_SERIAL
178a8ba569cSSimon Glass
179a8ba569cSSimon Glass #ifndef CONFIG_MXC_UART_BASE
180a8ba569cSSimon Glass #error "define CONFIG_MXC_UART_BASE to use the MXC UART driver"
181a8ba569cSSimon Glass #endif
182a8ba569cSSimon Glass
183ffa8bcd7SJagan Teki #define mxc_base ((struct mxc_uart *)CONFIG_MXC_UART_BASE)
184a8ba569cSSimon Glass
mxc_serial_setbrg(void)185a943472cSMarek Vasut static void mxc_serial_setbrg(void)
18647d19da4SIlya Yanok {
18771d64c0eSStefano Babic u32 clk = imx_get_uartclk();
18847d19da4SIlya Yanok
18947d19da4SIlya Yanok if (!gd->baudrate)
19047d19da4SIlya Yanok gd->baudrate = CONFIG_BAUDRATE;
19147d19da4SIlya Yanok
19245d97511SJagan Teki _mxc_serial_setbrg(mxc_base, clk, gd->baudrate, false);
19347d19da4SIlya Yanok }
19447d19da4SIlya Yanok
mxc_serial_getc(void)195a943472cSMarek Vasut static int mxc_serial_getc(void)
19647d19da4SIlya Yanok {
197ffa8bcd7SJagan Teki while (readl(&mxc_base->ts) & UTS_RXEMPTY)
1984ec3d2a7SStefano Babic WATCHDOG_RESET();
199ffa8bcd7SJagan Teki return (readl(&mxc_base->rxd) & URXD_RX_DATA); /* mask out status from upper word */
20047d19da4SIlya Yanok }
20147d19da4SIlya Yanok
mxc_serial_putc(const char c)202a943472cSMarek Vasut static void mxc_serial_putc(const char c)
20347d19da4SIlya Yanok {
204055457efSAlison Wang /* If \n, also do \r */
205055457efSAlison Wang if (c == '\n')
206055457efSAlison Wang serial_putc('\r');
207055457efSAlison Wang
208ffa8bcd7SJagan Teki writel(c, &mxc_base->txd);
20947d19da4SIlya Yanok
21047d19da4SIlya Yanok /* wait for transmitter to be ready */
211ffa8bcd7SJagan Teki while (!(readl(&mxc_base->ts) & UTS_TXEMPTY))
2124ec3d2a7SStefano Babic WATCHDOG_RESET();
21347d19da4SIlya Yanok }
21447d19da4SIlya Yanok
21552c14cabSJagan Teki /* Test whether a character is in the RX buffer */
mxc_serial_tstc(void)216a943472cSMarek Vasut static int mxc_serial_tstc(void)
21747d19da4SIlya Yanok {
21847d19da4SIlya Yanok /* If receive fifo is empty, return false */
219ffa8bcd7SJagan Teki if (readl(&mxc_base->ts) & UTS_RXEMPTY)
22047d19da4SIlya Yanok return 0;
22147d19da4SIlya Yanok return 1;
22247d19da4SIlya Yanok }
22347d19da4SIlya Yanok
22447d19da4SIlya Yanok /*
22547d19da4SIlya Yanok * Initialise the serial port with the given baudrate. The settings
22647d19da4SIlya Yanok * are always 8 data bits, no parity, 1 stop bit, no start bits.
22747d19da4SIlya Yanok */
mxc_serial_init(void)228a943472cSMarek Vasut static int mxc_serial_init(void)
22947d19da4SIlya Yanok {
23097548d59SJagan Teki _mxc_serial_init(mxc_base);
23147d19da4SIlya Yanok
23247d19da4SIlya Yanok serial_setbrg();
23347d19da4SIlya Yanok
23447d19da4SIlya Yanok return 0;
23547d19da4SIlya Yanok }
236a943472cSMarek Vasut
237a943472cSMarek Vasut static struct serial_device mxc_serial_drv = {
238a943472cSMarek Vasut .name = "mxc_serial",
239a943472cSMarek Vasut .start = mxc_serial_init,
240a943472cSMarek Vasut .stop = NULL,
241a943472cSMarek Vasut .setbrg = mxc_serial_setbrg,
242a943472cSMarek Vasut .putc = mxc_serial_putc,
243ec3fd689SMarek Vasut .puts = default_serial_puts,
244a943472cSMarek Vasut .getc = mxc_serial_getc,
245a943472cSMarek Vasut .tstc = mxc_serial_tstc,
246a943472cSMarek Vasut };
247a943472cSMarek Vasut
mxc_serial_initialize(void)248a943472cSMarek Vasut void mxc_serial_initialize(void)
249a943472cSMarek Vasut {
250a943472cSMarek Vasut serial_register(&mxc_serial_drv);
251a943472cSMarek Vasut }
252a943472cSMarek Vasut
default_serial_console(void)253a943472cSMarek Vasut __weak struct serial_device *default_serial_console(void)
254a943472cSMarek Vasut {
255a943472cSMarek Vasut return &mxc_serial_drv;
256a943472cSMarek Vasut }
257a8ba569cSSimon Glass #endif
258a8ba569cSSimon Glass
259a8ba569cSSimon Glass #ifdef CONFIG_DM_SERIAL
260a8ba569cSSimon Glass
mxc_serial_setbrg(struct udevice * dev,int baudrate)261a8ba569cSSimon Glass int mxc_serial_setbrg(struct udevice *dev, int baudrate)
262a8ba569cSSimon Glass {
263a8ba569cSSimon Glass struct mxc_serial_platdata *plat = dev->platdata;
264a8ba569cSSimon Glass u32 clk = imx_get_uartclk();
265a8ba569cSSimon Glass
26645d97511SJagan Teki _mxc_serial_setbrg(plat->reg, clk, baudrate, plat->use_dte);
267a8ba569cSSimon Glass
268a8ba569cSSimon Glass return 0;
269a8ba569cSSimon Glass }
270a8ba569cSSimon Glass
mxc_serial_probe(struct udevice * dev)271a8ba569cSSimon Glass static int mxc_serial_probe(struct udevice *dev)
272a8ba569cSSimon Glass {
273a8ba569cSSimon Glass struct mxc_serial_platdata *plat = dev->platdata;
274a8ba569cSSimon Glass
27597548d59SJagan Teki _mxc_serial_init(plat->reg);
276a8ba569cSSimon Glass
277a8ba569cSSimon Glass return 0;
278a8ba569cSSimon Glass }
279a8ba569cSSimon Glass
mxc_serial_getc(struct udevice * dev)280a8ba569cSSimon Glass static int mxc_serial_getc(struct udevice *dev)
281a8ba569cSSimon Glass {
282a8ba569cSSimon Glass struct mxc_serial_platdata *plat = dev->platdata;
283a8ba569cSSimon Glass struct mxc_uart *const uart = plat->reg;
284a8ba569cSSimon Glass
285a8ba569cSSimon Glass if (readl(&uart->ts) & UTS_RXEMPTY)
286a8ba569cSSimon Glass return -EAGAIN;
287a8ba569cSSimon Glass
288a8ba569cSSimon Glass return readl(&uart->rxd) & URXD_RX_DATA;
289a8ba569cSSimon Glass }
290a8ba569cSSimon Glass
mxc_serial_putc(struct udevice * dev,const char ch)291a8ba569cSSimon Glass static int mxc_serial_putc(struct udevice *dev, const char ch)
292a8ba569cSSimon Glass {
293a8ba569cSSimon Glass struct mxc_serial_platdata *plat = dev->platdata;
294a8ba569cSSimon Glass struct mxc_uart *const uart = plat->reg;
295a8ba569cSSimon Glass
296a8ba569cSSimon Glass if (!(readl(&uart->ts) & UTS_TXEMPTY))
297a8ba569cSSimon Glass return -EAGAIN;
298a8ba569cSSimon Glass
299a8ba569cSSimon Glass writel(ch, &uart->txd);
300a8ba569cSSimon Glass
301a8ba569cSSimon Glass return 0;
302a8ba569cSSimon Glass }
303a8ba569cSSimon Glass
mxc_serial_pending(struct udevice * dev,bool input)304a8ba569cSSimon Glass static int mxc_serial_pending(struct udevice *dev, bool input)
305a8ba569cSSimon Glass {
306a8ba569cSSimon Glass struct mxc_serial_platdata *plat = dev->platdata;
307a8ba569cSSimon Glass struct mxc_uart *const uart = plat->reg;
308a8ba569cSSimon Glass uint32_t sr2 = readl(&uart->sr2);
309a8ba569cSSimon Glass
310a8ba569cSSimon Glass if (input)
311a8ba569cSSimon Glass return sr2 & USR2_RDR ? 1 : 0;
312a8ba569cSSimon Glass else
313a8ba569cSSimon Glass return sr2 & USR2_TXDC ? 0 : 1;
314a8ba569cSSimon Glass }
315a8ba569cSSimon Glass
316a8ba569cSSimon Glass static const struct dm_serial_ops mxc_serial_ops = {
317a8ba569cSSimon Glass .putc = mxc_serial_putc,
318a8ba569cSSimon Glass .pending = mxc_serial_pending,
319a8ba569cSSimon Glass .getc = mxc_serial_getc,
320a8ba569cSSimon Glass .setbrg = mxc_serial_setbrg,
321a8ba569cSSimon Glass };
322a8ba569cSSimon Glass
323a99546abSStefan Agner #if CONFIG_IS_ENABLED(OF_CONTROL)
mxc_serial_ofdata_to_platdata(struct udevice * dev)324a99546abSStefan Agner static int mxc_serial_ofdata_to_platdata(struct udevice *dev)
325a99546abSStefan Agner {
326a99546abSStefan Agner struct mxc_serial_platdata *plat = dev->platdata;
327a99546abSStefan Agner fdt_addr_t addr;
328a99546abSStefan Agner
329a821c4afSSimon Glass addr = devfdt_get_addr(dev);
330a99546abSStefan Agner if (addr == FDT_ADDR_T_NONE)
331a99546abSStefan Agner return -EINVAL;
332a99546abSStefan Agner
333a99546abSStefan Agner plat->reg = (struct mxc_uart *)addr;
334a99546abSStefan Agner
335e160f7d4SSimon Glass plat->use_dte = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev),
336a99546abSStefan Agner "fsl,dte-mode");
337a99546abSStefan Agner return 0;
338a99546abSStefan Agner }
339a99546abSStefan Agner
340a99546abSStefan Agner static const struct udevice_id mxc_serial_ids[] = {
3413a5d6363SSébastien Szymanski { .compatible = "fsl,imx6ul-uart" },
342a99546abSStefan Agner { .compatible = "fsl,imx7d-uart" },
343a99546abSStefan Agner { }
344a99546abSStefan Agner };
345a99546abSStefan Agner #endif
346a99546abSStefan Agner
347a8ba569cSSimon Glass U_BOOT_DRIVER(serial_mxc) = {
348a8ba569cSSimon Glass .name = "serial_mxc",
349a8ba569cSSimon Glass .id = UCLASS_SERIAL,
350a99546abSStefan Agner #if CONFIG_IS_ENABLED(OF_CONTROL)
351a99546abSStefan Agner .of_match = mxc_serial_ids,
352a99546abSStefan Agner .ofdata_to_platdata = mxc_serial_ofdata_to_platdata,
353a99546abSStefan Agner .platdata_auto_alloc_size = sizeof(struct mxc_serial_platdata),
354a99546abSStefan Agner #endif
355a8ba569cSSimon Glass .probe = mxc_serial_probe,
356a8ba569cSSimon Glass .ops = &mxc_serial_ops,
357a8ba569cSSimon Glass .flags = DM_FLAG_PRE_RELOC,
358a8ba569cSSimon Glass };
359a8ba569cSSimon Glass #endif
360*61366b71SJagan Teki
361*61366b71SJagan Teki #ifdef CONFIG_DEBUG_UART_MXC
362*61366b71SJagan Teki #include <debug_uart.h>
363*61366b71SJagan Teki
_debug_uart_init(void)364*61366b71SJagan Teki static inline void _debug_uart_init(void)
365*61366b71SJagan Teki {
366*61366b71SJagan Teki struct mxc_uart *base = (struct mxc_uart *)CONFIG_DEBUG_UART_BASE;
367*61366b71SJagan Teki
368*61366b71SJagan Teki _mxc_serial_init(base);
369*61366b71SJagan Teki _mxc_serial_setbrg(base, CONFIG_DEBUG_UART_CLOCK,
370*61366b71SJagan Teki CONFIG_BAUDRATE, false);
371*61366b71SJagan Teki }
372*61366b71SJagan Teki
_debug_uart_putc(int ch)373*61366b71SJagan Teki static inline void _debug_uart_putc(int ch)
374*61366b71SJagan Teki {
375*61366b71SJagan Teki struct mxc_uart *base = (struct mxc_uart *)CONFIG_DEBUG_UART_BASE;
376*61366b71SJagan Teki
377*61366b71SJagan Teki while (!(readl(&base->ts) & UTS_TXEMPTY))
378*61366b71SJagan Teki WATCHDOG_RESET();
379*61366b71SJagan Teki
380*61366b71SJagan Teki writel(ch, &base->txd);
381*61366b71SJagan Teki }
382*61366b71SJagan Teki
383*61366b71SJagan Teki DEBUG_UART_FUNCS
384*61366b71SJagan Teki
385*61366b71SJagan Teki #endif
386