1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Qualcomm GENI serial engine UART driver
4 *
5 * Copyright (c) 2025, Linaro Limited
6 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
7 */
8
9 #include <drivers/qcom_geni_uart.h>
10 #include <io.h>
11
12 #define GENI_STATUS_REG 0x40
13 #define GENI_STATUS_REG_CMD_ACTIVE BIT(0)
14 #define GENI_TX_FIFO_REG 0x700
15 #define GENI_TX_TRANS_LEN_REG 0x270
16 #define GENI_M_CMD0_REG 0x600
17
18 #define GENI_M_CMD_TX 0x8000000
19 #define GENI_TIMEOUT_US 1000000
20
qcom_geni_uart_putc(struct serial_chip * chip,int ch)21 static void qcom_geni_uart_putc(struct serial_chip *chip, int ch)
22 {
23 struct qcom_geni_uart_data *pd =
24 container_of(chip, struct qcom_geni_uart_data, chip);
25 vaddr_t base = io_pa_or_va(&pd->base, GENI_UART_REG_SIZE);
26 uint64_t timer = timeout_init_us(GENI_TIMEOUT_US);
27
28 while (io_read32(base + GENI_STATUS_REG) & GENI_STATUS_REG_CMD_ACTIVE)
29 if (timeout_elapsed(timer))
30 return;
31
32 io_write32(base + GENI_TX_TRANS_LEN_REG, 1);
33 io_write32(base + GENI_M_CMD0_REG, GENI_M_CMD_TX);
34 io_write32(base + GENI_TX_FIFO_REG, ch);
35 }
36
37 static const struct serial_ops qcom_geni_uart_ops = {
38 .putc = qcom_geni_uart_putc,
39 };
40 DECLARE_KEEP_PAGER(qcom_geni_uart_ops);
41
qcom_geni_uart_init(struct qcom_geni_uart_data * pd,paddr_t base)42 void qcom_geni_uart_init(struct qcom_geni_uart_data *pd, paddr_t base)
43 {
44 pd->base.pa = base;
45 pd->chip.ops = &qcom_geni_uart_ops;
46
47 /*
48 * Do nothing, debug uart is shared with normal world, everything
49 * for debug uart initialization is done in the bootloader.
50 */
51 }
52