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