1 /* Source : APQ8064 LK boot */
2 /* SPDX-License-Identifier: BSD-3-Clause */
4 #include <device/mmio.h>
5 #include <boot/coreboot_tables.h>
6 #include <console/uart.h>
14 #include <soc/iomap.h>
16 #define FIFO_DATA_SIZE 4
20 unsigned int blsp_uart
;
21 gpio_func_data_t dbg_uart_gpio
[NO_OF_DBG_UART_GPIOS
];
24 void ipq_configure_gpio(const gpio_func_data_t
*gpio
, unsigned int count
)
28 for (i
= 0; i
< count
; i
++) {
29 gpio_configure(gpio
->gpio
, gpio
->func
,
30 gpio
->pull
, gpio
->drvstr
, gpio
->enable
);
35 static const uart_params_t uart_board_param
= {
36 .uart_dm_base
= UART2_DM_BASE
,
37 .blsp_uart
= BLSP1_UART2
,
57 * @brief msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
58 * @param uart_dm_base: UART controller base address
60 static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base
)
63 write32(MSM_BOOT_UART_DM_CR(uart_dm_base
),
64 MSM_BOOT_UART_DM_CMD_RESET_RX
);
67 write32(MSM_BOOT_UART_DM_CR(uart_dm_base
),
68 MSM_BOOT_UART_DM_CR_RX_ENABLE
);
69 write32(MSM_BOOT_UART_DM_DMRX(uart_dm_base
),
70 MSM_BOOT_UART_DM_DMRX_DEF_VALUE
);
72 /* Clear stale event */
73 write32(MSM_BOOT_UART_DM_CR(uart_dm_base
),
74 MSM_BOOT_UART_DM_CMD_RES_STALE_INT
);
76 /* Enable stale event */
77 write32(MSM_BOOT_UART_DM_CR(uart_dm_base
),
78 MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT
);
80 return MSM_BOOT_UART_DM_E_SUCCESS
;
83 #if CONFIG(DRIVERS_UART)
84 static unsigned int msm_boot_uart_dm_init(void *uart_dm_base
);
86 /* Received data is valid or not */
87 static int valid_data
= 0;
90 static unsigned int word
= 0;
92 void uart_tx_byte(unsigned int idx
, unsigned char data
)
95 void *base
= uart_board_param
.uart_dm_base
;
97 /* Wait until transmit FIFO is empty. */
98 while (!(read32(MSM_BOOT_UART_DM_SR(base
)) &
99 MSM_BOOT_UART_DM_SR_TXEMT
))
102 * TX FIFO is ready to accept new character(s). First write number of
103 * characters to be transmitted.
105 write32(MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base
), num_of_chars
);
107 /* And now write the character(s) */
108 write32(MSM_BOOT_UART_DM_TF(base
, 0), data
);
110 #endif /* CONFIG_SERIAL_UART */
113 * @brief msm_boot_uart_dm_reset - resets UART controller
114 * @param base: UART controller base address
116 static unsigned int msm_boot_uart_dm_reset(void *base
)
118 write32(MSM_BOOT_UART_DM_CR(base
), MSM_BOOT_UART_DM_CMD_RESET_RX
);
119 write32(MSM_BOOT_UART_DM_CR(base
), MSM_BOOT_UART_DM_CMD_RESET_TX
);
120 write32(MSM_BOOT_UART_DM_CR(base
),
121 MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT
);
122 write32(MSM_BOOT_UART_DM_CR(base
), MSM_BOOT_UART_DM_CMD_RES_TX_ERR
);
123 write32(MSM_BOOT_UART_DM_CR(base
), MSM_BOOT_UART_DM_CMD_RES_STALE_INT
);
125 return MSM_BOOT_UART_DM_E_SUCCESS
;
129 * @brief msm_boot_uart_dm_init - initilaizes UART controller
130 * @param uart_dm_base: UART controller base address
132 unsigned int msm_boot_uart_dm_init(void *uart_dm_base
)
134 /* Configure UART mode registers MR1 and MR2 */
135 /* Hardware flow control isn't supported */
136 write32(MSM_BOOT_UART_DM_MR1(uart_dm_base
), 0x0);
138 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
139 write32(MSM_BOOT_UART_DM_MR2(uart_dm_base
),
140 MSM_BOOT_UART_DM_8_N_1_MODE
);
142 /* Configure Interrupt Mask register IMR */
143 write32(MSM_BOOT_UART_DM_IMR(uart_dm_base
),
144 MSM_BOOT_UART_DM_IMR_ENABLED
);
147 * Configure Tx and Rx watermarks configuration registers
148 * TX watermark value is set to 0 - interrupt is generated when
149 * FIFO level is less than or equal to 0
151 write32(MSM_BOOT_UART_DM_TFWR(uart_dm_base
),
152 MSM_BOOT_UART_DM_TFW_VALUE
);
154 /* RX watermark value */
155 write32(MSM_BOOT_UART_DM_RFWR(uart_dm_base
),
156 MSM_BOOT_UART_DM_RFW_VALUE
);
158 /* Configure Interrupt Programming Register */
159 /* Set initial Stale timeout value */
160 write32(MSM_BOOT_UART_DM_IPR(uart_dm_base
),
161 MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB
);
163 /* Configure IRDA if required */
164 /* Disabling IRDA mode */
165 write32(MSM_BOOT_UART_DM_IRDA(uart_dm_base
), 0x0);
167 /* Configure hunt character value in HCR register */
168 /* Keep it in reset state */
169 write32(MSM_BOOT_UART_DM_HCR(uart_dm_base
), 0x0);
172 * Configure Rx FIFO base address
173 * Both TX/RX shares same SRAM and default is half-n-half.
174 * Sticking with default value now.
175 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
176 * We have found RAM_ADDR_WIDTH = 0x7f
179 /* Issue soft reset command */
180 msm_boot_uart_dm_reset(uart_dm_base
);
182 /* Enable/Disable Rx/Tx DM interfaces */
183 /* Data Mover not currently utilized. */
184 write32(MSM_BOOT_UART_DM_DMEN(uart_dm_base
), 0x0);
186 /* Enable transmitter */
187 write32(MSM_BOOT_UART_DM_CR(uart_dm_base
),
188 MSM_BOOT_UART_DM_CR_TX_ENABLE
);
190 /* Initialize Receive Path */
191 msm_boot_uart_dm_init_rx_transfer(uart_dm_base
);
197 * @brief qcs405_uart_init - initializes UART
199 * Initializes clocks, GPIO and UART controller.
201 void uart_init(unsigned int idx
)
203 /* Note int idx isn't used in this driver. */
206 dm_base
= uart_board_param
.uart_dm_base
;
208 if (read32(MSM_BOOT_UART_DM_CSR(dm_base
)) == 0xFF)
209 return; /* UART must have been already initialized. */
211 clock_configure_uart(1843200);
214 ipq_configure_gpio(uart_board_param
.dbg_uart_gpio
,
215 NO_OF_DBG_UART_GPIOS
);
217 write32(MSM_BOOT_UART_DM_CSR(dm_base
), 0xFF);
219 /* Initialize UART_DM */
220 msm_boot_uart_dm_init(dm_base
);
223 /* for the benefit of non-console uart init */
224 void qcs405_uart_init(void)
230 * @brief uart_tx_flush - transmits a string of data
231 * @param idx: string to transmit
233 void uart_tx_flush(unsigned int idx
)
235 void *base
= uart_board_param
.uart_dm_base
;
237 while (!(read32(MSM_BOOT_UART_DM_SR(base
)) &
238 MSM_BOOT_UART_DM_SR_TXEMT
))
242 #if CONFIG(DRIVERS_UART)
244 * qcs405_serial_getc - reads a character
246 * Returns the character read from serial port.
248 uint8_t uart_rx_byte(unsigned int idx
)
252 byte
= (uint8_t)(word
& 0xff);
260 enum cb_err
fill_lb_serial(struct lb_serial
*serial
)
262 serial
->type
= LB_SERIAL_TYPE_MEMORY_MAPPED
;
263 serial
->baseaddr
= (uint64_t)UART2_DM_BASE
;
264 serial
->baud
= get_uart_baudrate();
265 serial
->regwidth
= 1;
266 serial
->input_hertz
= uart_platform_refclk();