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