xref: /optee_os/core/drivers/lpc_uart.c (revision de7a768c7fc1489b1135b82576339001e0f769c8)
1*de7a768cSXiaoxu Zeng // SPDX-License-Identifier: BSD-2-Clause
2*de7a768cSXiaoxu Zeng /*
3*de7a768cSXiaoxu Zeng  * Copyright (c) 2022, HiSilicon Limited
4*de7a768cSXiaoxu Zeng  */
5*de7a768cSXiaoxu Zeng 
6*de7a768cSXiaoxu Zeng #include <assert.h>
7*de7a768cSXiaoxu Zeng #include <drivers/lpc_uart.h>
8*de7a768cSXiaoxu Zeng #include <io.h>
9*de7a768cSXiaoxu Zeng #include <keep.h>
10*de7a768cSXiaoxu Zeng #include <mm/core_mmu.h>
11*de7a768cSXiaoxu Zeng #include <util.h>
12*de7a768cSXiaoxu Zeng 
chip_to_base(struct serial_chip * chip)13*de7a768cSXiaoxu Zeng static paddr_t chip_to_base(struct serial_chip *chip)
14*de7a768cSXiaoxu Zeng {
15*de7a768cSXiaoxu Zeng 	struct lpc_uart_data *pd =
16*de7a768cSXiaoxu Zeng 		container_of(chip, struct lpc_uart_data, chip);
17*de7a768cSXiaoxu Zeng 
18*de7a768cSXiaoxu Zeng 	return io_pa_or_va(&pd->base, LPC_SIZE);
19*de7a768cSXiaoxu Zeng }
20*de7a768cSXiaoxu Zeng 
lpc_byte_read(paddr_t addr,uint8_t * data)21*de7a768cSXiaoxu Zeng static void lpc_byte_read(paddr_t addr, uint8_t *data)
22*de7a768cSXiaoxu Zeng {
23*de7a768cSXiaoxu Zeng 	uint32_t status = 0;
24*de7a768cSXiaoxu Zeng 	uint32_t cnt = 0;
25*de7a768cSXiaoxu Zeng 
26*de7a768cSXiaoxu Zeng 	io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_READ);
27*de7a768cSXiaoxu Zeng 
28*de7a768cSXiaoxu Zeng 	io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1);
29*de7a768cSXiaoxu Zeng 	io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_LSR);
30*de7a768cSXiaoxu Zeng 
31*de7a768cSXiaoxu Zeng 	io_write32(LPC_START_REG_OFFSET + addr, 1);
32*de7a768cSXiaoxu Zeng 
33*de7a768cSXiaoxu Zeng 	status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr);
34*de7a768cSXiaoxu Zeng 	while (!(status & LPC_IRQ_ST_ON)) {
35*de7a768cSXiaoxu Zeng 		if (cnt > UART_SEND_LOOP_MAX)
36*de7a768cSXiaoxu Zeng 			return;
37*de7a768cSXiaoxu Zeng 		cnt++;
38*de7a768cSXiaoxu Zeng 		status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr);
39*de7a768cSXiaoxu Zeng 	}
40*de7a768cSXiaoxu Zeng 
41*de7a768cSXiaoxu Zeng 	io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON);
42*de7a768cSXiaoxu Zeng 
43*de7a768cSXiaoxu Zeng 	if (io_read32(LPC_OP_STATUS_REG_OFFSET + addr) & LPC_IRQ_ST_ON)
44*de7a768cSXiaoxu Zeng 		*data = io_read32(LPC_RDATA_REG_OFFSET + addr);
45*de7a768cSXiaoxu Zeng }
46*de7a768cSXiaoxu Zeng 
lpc_byte_write(paddr_t addr,uint8_t data)47*de7a768cSXiaoxu Zeng static void lpc_byte_write(paddr_t addr, uint8_t data)
48*de7a768cSXiaoxu Zeng {
49*de7a768cSXiaoxu Zeng 	uint32_t status = 0;
50*de7a768cSXiaoxu Zeng 	uint32_t cnt = 0;
51*de7a768cSXiaoxu Zeng 
52*de7a768cSXiaoxu Zeng 	io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_WRITE);
53*de7a768cSXiaoxu Zeng 	io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1);
54*de7a768cSXiaoxu Zeng 	io_write32(LPC_WDATA_REG_OFFSET + addr, data);
55*de7a768cSXiaoxu Zeng 
56*de7a768cSXiaoxu Zeng 	io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_THR);
57*de7a768cSXiaoxu Zeng 	io_write32(LPC_START_REG_OFFSET + addr, 1);
58*de7a768cSXiaoxu Zeng 
59*de7a768cSXiaoxu Zeng 	status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr);
60*de7a768cSXiaoxu Zeng 	while (!(status & LPC_IRQ_ST_ON)) {
61*de7a768cSXiaoxu Zeng 		if (cnt > UART_SEND_LOOP_MAX)
62*de7a768cSXiaoxu Zeng 			return;
63*de7a768cSXiaoxu Zeng 		cnt++;
64*de7a768cSXiaoxu Zeng 		status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr);
65*de7a768cSXiaoxu Zeng 	}
66*de7a768cSXiaoxu Zeng 
67*de7a768cSXiaoxu Zeng 	io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON);
68*de7a768cSXiaoxu Zeng }
69*de7a768cSXiaoxu Zeng 
lpc_uart_core_putc(paddr_t base,int ch)70*de7a768cSXiaoxu Zeng static void lpc_uart_core_putc(paddr_t base, int ch)
71*de7a768cSXiaoxu Zeng {
72*de7a768cSXiaoxu Zeng 	uint8_t var = '\0';
73*de7a768cSXiaoxu Zeng 	uint32_t i = 0;
74*de7a768cSXiaoxu Zeng 
75*de7a768cSXiaoxu Zeng 	for (i = 0; i < UART_SEND_LOOP_MAX; i++) {
76*de7a768cSXiaoxu Zeng 		lpc_byte_read(base, &var);
77*de7a768cSXiaoxu Zeng 		if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN)
78*de7a768cSXiaoxu Zeng 			break;
79*de7a768cSXiaoxu Zeng 	}
80*de7a768cSXiaoxu Zeng 
81*de7a768cSXiaoxu Zeng 	lpc_byte_write(base, ch);
82*de7a768cSXiaoxu Zeng 
83*de7a768cSXiaoxu Zeng 	for (i = 0; i < UART_SEND_LOOP_MAX; i++) {
84*de7a768cSXiaoxu Zeng 		lpc_byte_read(base, &var);
85*de7a768cSXiaoxu Zeng 		if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN)
86*de7a768cSXiaoxu Zeng 			break;
87*de7a768cSXiaoxu Zeng 	}
88*de7a768cSXiaoxu Zeng }
89*de7a768cSXiaoxu Zeng 
lpc_uart_putc(struct serial_chip * chip,int ch)90*de7a768cSXiaoxu Zeng static void lpc_uart_putc(struct serial_chip *chip, int ch)
91*de7a768cSXiaoxu Zeng {
92*de7a768cSXiaoxu Zeng 	paddr_t base = chip_to_base(chip);
93*de7a768cSXiaoxu Zeng 
94*de7a768cSXiaoxu Zeng 	lpc_uart_core_putc(base, ch);
95*de7a768cSXiaoxu Zeng }
96*de7a768cSXiaoxu Zeng 
97*de7a768cSXiaoxu Zeng static const struct serial_ops lpc_uart_ops = {
98*de7a768cSXiaoxu Zeng 	.putc = lpc_uart_putc,
99*de7a768cSXiaoxu Zeng };
100*de7a768cSXiaoxu Zeng DECLARE_KEEP_PAGER(lpc_uart_ops);
101*de7a768cSXiaoxu Zeng 
lpc_uart_init(struct lpc_uart_data * pd,paddr_t base,uint32_t uart_clk __unused,uint32_t baud_rate __unused)102*de7a768cSXiaoxu Zeng void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base,
103*de7a768cSXiaoxu Zeng 		   uint32_t uart_clk __unused, uint32_t baud_rate __unused)
104*de7a768cSXiaoxu Zeng {
105*de7a768cSXiaoxu Zeng 	pd->base.pa = base;
106*de7a768cSXiaoxu Zeng 	pd->chip.ops = &lpc_uart_ops;
107*de7a768cSXiaoxu Zeng }
108*de7a768cSXiaoxu Zeng 
109