xref: /optee_os/core/drivers/imx_uart.c (revision 21145fe52f77fe9b58c365d9f760eeb16c1ae8b7)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
28c4a5a9aSPeng Fan /*
38c4a5a9aSPeng Fan  * Copyright (C) 2015 Freescale Semiconductor, Inc.
48c4a5a9aSPeng Fan  * All rights reserved.
58c4a5a9aSPeng Fan  *
68c4a5a9aSPeng Fan  * Redistribution and use in source and binary forms, with or without
78c4a5a9aSPeng Fan  * modification, are permitted provided that the following conditions are met:
88c4a5a9aSPeng Fan  *
98c4a5a9aSPeng Fan  * 1. Redistributions of source code must retain the above copyright notice,
108c4a5a9aSPeng Fan  * this list of conditions and the following disclaimer.
118c4a5a9aSPeng Fan  *
128c4a5a9aSPeng Fan  * 2. Redistributions in binary form must reproduce the above copyright notice,
138c4a5a9aSPeng Fan  * this list of conditions and the following disclaimer in the documentation
148c4a5a9aSPeng Fan  * and/or other materials provided with the distribution.
158c4a5a9aSPeng Fan  *
168c4a5a9aSPeng Fan  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
178c4a5a9aSPeng Fan  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188c4a5a9aSPeng Fan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198c4a5a9aSPeng Fan  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
208c4a5a9aSPeng Fan  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
218c4a5a9aSPeng Fan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
228c4a5a9aSPeng Fan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
238c4a5a9aSPeng Fan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
248c4a5a9aSPeng Fan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
258c4a5a9aSPeng Fan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
268c4a5a9aSPeng Fan  * POSSIBILITY OF SUCH DAMAGE.
278c4a5a9aSPeng Fan  */
288c4a5a9aSPeng Fan 
2926267e82SJerome Forissier #include <assert.h>
308c4a5a9aSPeng Fan #include <drivers/imx_uart.h>
318c4a5a9aSPeng Fan #include <io.h>
328d94060aSEtienne Carriere #include <keep.h>
3326267e82SJerome Forissier #include <util.h>
348c4a5a9aSPeng Fan 
358c4a5a9aSPeng Fan /* Register definitions */
368c4a5a9aSPeng Fan #define URXD  0x0  /* Receiver Register */
378c4a5a9aSPeng Fan #define UTXD  0x40 /* Transmitter Register */
388c4a5a9aSPeng Fan #define UCR1  0x80 /* Control Register 1 */
398c4a5a9aSPeng Fan #define UCR2  0x84 /* Control Register 2 */
408c4a5a9aSPeng Fan #define UCR3  0x88 /* Control Register 3 */
418c4a5a9aSPeng Fan #define UCR4  0x8c /* Control Register 4 */
428c4a5a9aSPeng Fan #define UFCR  0x90 /* FIFO Control Register */
438c4a5a9aSPeng Fan #define USR1  0x94 /* Status Register 1 */
448c4a5a9aSPeng Fan #define USR2  0x98 /* Status Register 2 */
458c4a5a9aSPeng Fan #define UESC  0x9c /* Escape Character Register */
468c4a5a9aSPeng Fan #define UTIM  0xa0 /* Escape Timer Register */
478c4a5a9aSPeng Fan #define UBIR  0xa4 /* BRM Incremental Register */
488c4a5a9aSPeng Fan #define UBMR  0xa8 /* BRM Modulator Register */
498c4a5a9aSPeng Fan #define UBRC  0xac /* Baud Rate Count Register */
508c4a5a9aSPeng Fan #define UTS   0xb4 /* UART Test Register (mx31) */
518c4a5a9aSPeng Fan 
528c4a5a9aSPeng Fan /* UART Control Register Bit Fields.*/
538c4a5a9aSPeng Fan #define  URXD_CHARRDY    (1<<15)
548c4a5a9aSPeng Fan #define  URXD_ERR        (1<<14)
558c4a5a9aSPeng Fan #define  URXD_OVRRUN     (1<<13)
568c4a5a9aSPeng Fan #define  URXD_FRMERR     (1<<12)
578c4a5a9aSPeng Fan #define  URXD_BRK        (1<<11)
588c4a5a9aSPeng Fan #define  URXD_PRERR      (1<<10)
598c4a5a9aSPeng Fan #define  URXD_RX_DATA    (0xFF)
608c4a5a9aSPeng Fan #define  UCR1_ADEN       (1<<15) /* Auto dectect interrupt */
618c4a5a9aSPeng Fan #define  UCR1_ADBR       (1<<14) /* Auto detect baud rate */
628c4a5a9aSPeng Fan #define  UCR1_TRDYEN     (1<<13) /* Transmitter ready interrupt enable */
638c4a5a9aSPeng Fan #define  UCR1_IDEN       (1<<12) /* Idle condition interrupt */
648c4a5a9aSPeng Fan #define  UCR1_RRDYEN     (1<<9)	 /* Recv ready interrupt enable */
658c4a5a9aSPeng Fan #define  UCR1_RDMAEN     (1<<8)	 /* Recv ready DMA enable */
668c4a5a9aSPeng Fan #define  UCR1_IREN       (1<<7)	 /* Infrared interface enable */
678c4a5a9aSPeng Fan #define  UCR1_TXMPTYEN   (1<<6)	 /* Transimitter empty interrupt enable */
688c4a5a9aSPeng Fan #define  UCR1_RTSDEN     (1<<5)	 /* RTS delta interrupt enable */
698c4a5a9aSPeng Fan #define  UCR1_SNDBRK     (1<<4)	 /* Send break */
708c4a5a9aSPeng Fan #define  UCR1_TDMAEN     (1<<3)	 /* Transmitter ready DMA enable */
718c4a5a9aSPeng Fan #define  UCR1_UARTCLKEN  (1<<2)	 /* UART clock enabled */
728c4a5a9aSPeng Fan #define  UCR1_DOZE       (1<<1)	 /* Doze */
738c4a5a9aSPeng Fan #define  UCR1_UARTEN     (1<<0)	 /* UART enabled */
748c4a5a9aSPeng Fan 
758c4a5a9aSPeng Fan #define  UTS_FRCPERR	 (1<<13) /* Force parity error */
768c4a5a9aSPeng Fan #define  UTS_LOOP        (1<<12) /* Loop tx and rx */
778c4a5a9aSPeng Fan #define  UTS_TXEMPTY	 (1<<6)	 /* TxFIFO empty */
788c4a5a9aSPeng Fan #define  UTS_RXEMPTY	 (1<<5)	 /* RxFIFO empty */
798c4a5a9aSPeng Fan #define  UTS_TXFULL	 (1<<4)	 /* TxFIFO full */
808c4a5a9aSPeng Fan #define  UTS_RXFULL	 (1<<3)	 /* RxFIFO full */
818c4a5a9aSPeng Fan #define  UTS_SOFTRST	 (1<<0)	 /* Software reset */
828c4a5a9aSPeng Fan 
8326267e82SJerome Forissier static vaddr_t chip_to_base(struct serial_chip *chip)
848c4a5a9aSPeng Fan {
8526267e82SJerome Forissier 	struct imx_uart_data *pd =
8626267e82SJerome Forissier 		container_of(chip, struct imx_uart_data, chip);
8726267e82SJerome Forissier 
8826267e82SJerome Forissier 	return io_pa_or_va(&pd->base);
898c4a5a9aSPeng Fan }
908c4a5a9aSPeng Fan 
9126267e82SJerome Forissier static void imx_uart_flush(struct serial_chip *chip)
928c4a5a9aSPeng Fan {
9326267e82SJerome Forissier 	vaddr_t base = chip_to_base(chip);
9426267e82SJerome Forissier 
95*21145fe5SJordan Rhee 
968c4a5a9aSPeng Fan 	while (!(read32(base + UTS) & UTS_TXEMPTY))
97*21145fe5SJordan Rhee 		if (!(read32(base + UCR1) & UCR1_UARTEN))
98*21145fe5SJordan Rhee 			return;
998c4a5a9aSPeng Fan }
1008c4a5a9aSPeng Fan 
10126267e82SJerome Forissier static int imx_uart_getchar(struct serial_chip *chip)
1028c4a5a9aSPeng Fan {
10326267e82SJerome Forissier 	vaddr_t base = chip_to_base(chip);
10426267e82SJerome Forissier 
1058c4a5a9aSPeng Fan 	while (read32(base + UTS) & UTS_RXEMPTY)
1068c4a5a9aSPeng Fan 		;
1078c4a5a9aSPeng Fan 
1088c4a5a9aSPeng Fan 	return (read32(base + URXD) & URXD_RX_DATA);
1098c4a5a9aSPeng Fan }
1108c4a5a9aSPeng Fan 
11126267e82SJerome Forissier static void imx_uart_putc(struct serial_chip *chip, int ch)
1128c4a5a9aSPeng Fan {
11326267e82SJerome Forissier 	vaddr_t base = chip_to_base(chip);
1148c4a5a9aSPeng Fan 
1154c85b2cfSJordan Rhee 	/* Wait until there's space in the TX FIFO */
1164c85b2cfSJordan Rhee 	while (read32(base + UTS) & UTS_TXFULL)
117*21145fe5SJordan Rhee 		if (!(read32(base + UCR1) & UCR1_UARTEN))
118*21145fe5SJordan Rhee 			return;
1194c85b2cfSJordan Rhee 
1204c85b2cfSJordan Rhee 	write32(ch, base + UTXD);
1218c4a5a9aSPeng Fan }
12226267e82SJerome Forissier 
12326267e82SJerome Forissier static const struct serial_ops imx_uart_ops = {
12426267e82SJerome Forissier 	.flush = imx_uart_flush,
12526267e82SJerome Forissier 	.getchar = imx_uart_getchar,
12626267e82SJerome Forissier 	.putc = imx_uart_putc,
12726267e82SJerome Forissier };
1288d94060aSEtienne Carriere KEEP_PAGER(imx_uart_ops);
12926267e82SJerome Forissier 
13026267e82SJerome Forissier void imx_uart_init(struct imx_uart_data *pd, paddr_t base)
13126267e82SJerome Forissier {
13226267e82SJerome Forissier 	pd->base.pa = base;
13326267e82SJerome Forissier 	pd->chip.ops = &imx_uart_ops;
13426267e82SJerome Forissier 
13526267e82SJerome Forissier 	/*
13626267e82SJerome Forissier 	 * Do nothing, debug uart(uart0) share with normal world,
13726267e82SJerome Forissier 	 * everything for uart0 initialization is done in bootloader.
13826267e82SJerome Forissier 	 */
13926267e82SJerome Forissier }
140