blob: 3a3a8bf27b76b92f1b391dd8a61c477b777611b9 [file] [log] [blame]
Patrick Georgi16849bb2020-05-10 17:52:40 +02001/* Source : APQ8064 LK boot */
Patrick Georgi70517072020-05-10 18:47:05 +02002/* SPDX-License-Identifier: BSD-3-Clause */
Vadim Bendebury476f7312014-04-08 18:45:46 -07003
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Vadim Bendeburyf17680b2014-04-23 14:00:59 -07005#include <boot/coreboot_tables.h>
Vadim Bendeburyf17680b2014-04-23 14:00:59 -07006#include <console/uart.h>
Julius Werner73d1ed62014-10-20 13:20:49 -07007#include <delay.h>
Julius Wernereaa9c452014-09-24 15:40:49 -07008#include <gpio.h>
Julius Werner73d1ed62014-10-20 13:20:49 -07009#include <soc/clock.h>
Julius Werner73d1ed62014-10-20 13:20:49 -070010#include <soc/gsbi.h>
11#include <soc/ipq_uart.h>
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070012#include <stdint.h>
Vadim Bendebury476f7312014-04-08 18:45:46 -070013
14#define FIFO_DATA_SIZE 4
15
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070016typedef struct {
Vadim Bendeburyb67b7152015-01-13 12:46:57 -080017 void *uart_dm_base;
18 void *uart_gsbi_base;
Martin Roth57e89092019-10-23 21:45:23 -060019 unsigned int uart_gsbi;
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070020 uart_clk_mnd_t mnd_value;
21 gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS];
22} uart_params_t;
23
24/*
25 * All constants lifted from u-boot's
26 * board/qcom/ipq806x_cdp/ipq806x_board_param.h
27 */
28static const uart_params_t uart_board_param = {
Vadim Bendeburyb67b7152015-01-13 12:46:57 -080029 .uart_dm_base = (void *)UART4_DM_BASE,
30 .uart_gsbi_base = (void *)UART_GSBI4_BASE,
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070031 .uart_gsbi = GSBI_4,
32 .mnd_value = { 12, 625, 313 },
Vadim Bendeburyb67b7152015-01-13 12:46:57 -080033 .dbg_uart_gpio = {
34 {
35 .gpio = 10,
36 .func = 1,
37 .dir = GPIO_OUTPUT,
38 .pull = GPIO_NO_PULL,
39 .drvstr = GPIO_12MA,
40 .enable = GPIO_DISABLE
41 },
42 {
43 .gpio = 11,
44 .func = 1,
45 .dir = GPIO_INPUT,
46 .pull = GPIO_NO_PULL,
47 .drvstr = GPIO_12MA,
48 .enable = GPIO_DISABLE
49 },
50 }
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070051};
Vadim Bendebury476f7312014-04-08 18:45:46 -070052
Vadim Bendebury476f7312014-04-08 18:45:46 -070053/**
54 * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
Martin Roth49348182016-07-06 10:17:19 -060055 * @param uart_dm_base: UART controller base address
Vadim Bendebury476f7312014-04-08 18:45:46 -070056 */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -080057static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base)
Vadim Bendebury476f7312014-04-08 18:45:46 -070058{
59 /* Reset receiver */
Julius Werner2f37bd62015-02-19 14:51:15 -080060 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
61 MSM_BOOT_UART_DM_CMD_RESET_RX);
Vadim Bendebury476f7312014-04-08 18:45:46 -070062
63 /* Enable receiver */
Julius Werner2f37bd62015-02-19 14:51:15 -080064 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
65 MSM_BOOT_UART_DM_CR_RX_ENABLE);
66 write32(MSM_BOOT_UART_DM_DMRX(uart_dm_base),
67 MSM_BOOT_UART_DM_DMRX_DEF_VALUE);
Vadim Bendebury476f7312014-04-08 18:45:46 -070068
69 /* Clear stale event */
Julius Werner2f37bd62015-02-19 14:51:15 -080070 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
71 MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
Vadim Bendebury476f7312014-04-08 18:45:46 -070072
73 /* Enable stale event */
Julius Werner2f37bd62015-02-19 14:51:15 -080074 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
75 MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT);
Vadim Bendebury476f7312014-04-08 18:45:46 -070076
77 return MSM_BOOT_UART_DM_E_SUCCESS;
78}
79
Vadim Bendebury7c256402015-01-13 13:07:48 -080080static unsigned int msm_boot_uart_dm_init(void *uart_dm_base);
81
82/* Received data is valid or not */
83static int valid_data = 0;
84
85/* Received data */
86static unsigned int word = 0;
87
Vadim Bendebury476f7312014-04-08 18:45:46 -070088/**
89 * msm_boot_uart_dm_read - reads a word from the RX FIFO.
90 * @data: location where the read data is stored
91 * @count: no of valid data in the FIFO
92 * @wait: indicates blocking call or not blocking call
93 *
94 * Reads a word from the RX FIFO. If no data is available blocks if
95 * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY.
96 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070097 #if 0 /* Not used yet */
Vadim Bendebury476f7312014-04-08 18:45:46 -070098static unsigned int
99msm_boot_uart_dm_read(unsigned int *data, int *count, int wait)
100{
101 static int total_rx_data = 0;
102 static int rx_data_read = 0;
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800103 void *base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700104 uint32_t status_reg;
105
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700106 base = uart_board_param.uart_dm_base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700107
108 if (data == NULL)
109 return MSM_BOOT_UART_DM_E_INVAL;
110
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800111 status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700112
113 /* Check for DM_RXSTALE for RX transfer to finish */
114 while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) {
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800115 status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700116 if (!wait)
117 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
118 }
119
120 /* Check for Overrun error. We'll just reset Error Status */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800121 if (readl(MSM_BOOT_UART_DM_SR(base)) &
Vadim Bendebury476f7312014-04-08 18:45:46 -0700122 MSM_BOOT_UART_DM_SR_UART_OVERRUN) {
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800123 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700124 MSM_BOOT_UART_DM_CR(base));
125 total_rx_data = rx_data_read = 0;
126 msm_boot_uart_dm_init(base);
127 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
128 }
129
130 /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */
131 if (total_rx_data == 0)
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800132 total_rx_data = readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700133
134 /* Data available in FIFO; read a word. */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800135 *data = readl(MSM_BOOT_UART_DM_RF(base, 0));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700136
137 /* WAR for http://prism/CR/548280 */
138 if (*data == 0) {
139 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
140 }
141
142 /* increment the total count of chars we've read so far */
143 rx_data_read += FIFO_DATA_SIZE;
144
145 /* actual count of valid data in word */
146 *count = ((total_rx_data < rx_data_read) ?
147 (FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) :
148 FIFO_DATA_SIZE);
149
150 /* If there are still data left in FIFO we'll read them before
151 * initializing RX Transfer again
152 */
153 if (rx_data_read < total_rx_data)
154 return MSM_BOOT_UART_DM_E_SUCCESS;
155
156 msm_boot_uart_dm_init_rx_transfer(base);
157 total_rx_data = rx_data_read = 0;
158
159 return MSM_BOOT_UART_DM_E_SUCCESS;
160}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700161#endif
Vadim Bendebury476f7312014-04-08 18:45:46 -0700162
Felix Helde3a12472020-09-11 15:47:09 +0200163void uart_tx_byte(unsigned int idx, unsigned char data)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700164{
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800165 int num_of_chars = 1;
Martin Roth57e89092019-10-23 21:45:23 -0600166 unsigned int tx_data = 0;
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800167 void *base = uart_board_param.uart_dm_base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700168
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700169 /* Wait until transmit FIFO is empty. */
Julius Werner2f37bd62015-02-19 14:51:15 -0800170 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800171 MSM_BOOT_UART_DM_SR_TXEMT))
172 udelay(1);
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700173 /*
174 * TX FIFO is ready to accept new character(s). First write number of
175 * characters to be transmitted.
176 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800177 write32(MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base), num_of_chars);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700178
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700179 /* And now write the character(s) */
Julius Werner2f37bd62015-02-19 14:51:15 -0800180 write32(MSM_BOOT_UART_DM_TF(base, 0), tx_data);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700181}
182
183/*
184 * msm_boot_uart_dm_reset - resets UART controller
185 * @base: UART controller base address
186 */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800187static unsigned int msm_boot_uart_dm_reset(void *base)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700188{
Julius Werner2f37bd62015-02-19 14:51:15 -0800189 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_RX);
190 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_TX);
191 write32(MSM_BOOT_UART_DM_CR(base),
192 MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT);
193 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_TX_ERR);
194 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700195
196 return MSM_BOOT_UART_DM_E_SUCCESS;
197}
198
199/*
200 * msm_boot_uart_dm_init - initilaizes UART controller
201 * @uart_dm_base: UART controller base address
202 */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800203static unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700204{
205 /* Configure UART mode registers MR1 and MR2 */
206 /* Hardware flow control isn't supported */
Julius Werner2f37bd62015-02-19 14:51:15 -0800207 write32(MSM_BOOT_UART_DM_MR1(uart_dm_base), 0x0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700208
209 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
Julius Werner2f37bd62015-02-19 14:51:15 -0800210 write32(MSM_BOOT_UART_DM_MR2(uart_dm_base),
211 MSM_BOOT_UART_DM_8_N_1_MODE);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700212
213 /* Configure Interrupt Mask register IMR */
Julius Werner2f37bd62015-02-19 14:51:15 -0800214 write32(MSM_BOOT_UART_DM_IMR(uart_dm_base),
215 MSM_BOOT_UART_DM_IMR_ENABLED);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700216
217 /*
218 * Configure Tx and Rx watermarks configuration registers
219 * TX watermark value is set to 0 - interrupt is generated when
220 * FIFO level is less than or equal to 0
221 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800222 write32(MSM_BOOT_UART_DM_TFWR(uart_dm_base),
223 MSM_BOOT_UART_DM_TFW_VALUE);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700224
225 /* RX watermark value */
Julius Werner2f37bd62015-02-19 14:51:15 -0800226 write32(MSM_BOOT_UART_DM_RFWR(uart_dm_base),
227 MSM_BOOT_UART_DM_RFW_VALUE);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700228
229 /* Configure Interrupt Programming Register */
230 /* Set initial Stale timeout value */
Julius Werner2f37bd62015-02-19 14:51:15 -0800231 write32(MSM_BOOT_UART_DM_IPR(uart_dm_base),
232 MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700233
234 /* Configure IRDA if required */
235 /* Disabling IRDA mode */
Julius Werner2f37bd62015-02-19 14:51:15 -0800236 write32(MSM_BOOT_UART_DM_IRDA(uart_dm_base), 0x0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700237
238 /* Configure hunt character value in HCR register */
239 /* Keep it in reset state */
Julius Werner2f37bd62015-02-19 14:51:15 -0800240 write32(MSM_BOOT_UART_DM_HCR(uart_dm_base), 0x0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700241
242 /*
243 * Configure Rx FIFO base address
244 * Both TX/RX shares same SRAM and default is half-n-half.
245 * Sticking with default value now.
246 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
247 * We have found RAM_ADDR_WIDTH = 0x7f
248 */
249
250 /* Issue soft reset command */
251 msm_boot_uart_dm_reset(uart_dm_base);
252
253 /* Enable/Disable Rx/Tx DM interfaces */
254 /* Data Mover not currently utilized. */
Julius Werner2f37bd62015-02-19 14:51:15 -0800255 write32(MSM_BOOT_UART_DM_DMEN(uart_dm_base), 0x0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700256
257 /* Enable transmitter */
Julius Werner2f37bd62015-02-19 14:51:15 -0800258 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
259 MSM_BOOT_UART_DM_CR_TX_ENABLE);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700260
261 /* Initialize Receive Path */
262 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
263
264 return 0;
265}
266
267/**
Vadim Bendebury7c256402015-01-13 13:07:48 -0800268 * ipq806x_uart_init - initializes UART
Vadim Bendebury476f7312014-04-08 18:45:46 -0700269 *
270 * Initializes clocks, GPIO and UART controller.
271 */
Felix Helde3a12472020-09-11 15:47:09 +0200272void uart_init(unsigned int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700273{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700274 /* Note int idx isn't used in this driver. */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800275 void *dm_base;
276 void *gsbi_base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700277
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700278 dm_base = uart_board_param.uart_dm_base;
Vadim Bendebury7c256402015-01-13 13:07:48 -0800279
Julius Werner2f37bd62015-02-19 14:51:15 -0800280 if (read32(MSM_BOOT_UART_DM_CSR(dm_base)) == UART_DM_CLK_RX_TX_BIT_RATE)
Vadim Bendebury7c256402015-01-13 13:07:48 -0800281 return; /* UART must have been already initialized. */
282
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700283 gsbi_base = uart_board_param.uart_gsbi_base;
284 ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
285 NO_OF_DBG_UART_GPIOS);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700286
287 /* Configure the uart clock */
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800288 uart_clock_config(uart_board_param.uart_gsbi,
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700289 uart_board_param.mnd_value.m_value,
290 uart_board_param.mnd_value.n_value,
291 uart_board_param.mnd_value.d_value,
292 0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700293
Julius Werner2f37bd62015-02-19 14:51:15 -0800294 write32(GSBI_CTRL_REG(gsbi_base),
295 GSBI_PROTOCOL_CODE_I2C_UART << GSBI_CTRL_REG_PROTOCOL_CODE_S);
296 write32(MSM_BOOT_UART_DM_CSR(dm_base), UART_DM_CLK_RX_TX_BIT_RATE);
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700297
Elyes HAOUAS809aeee2018-08-07 12:14:33 +0200298 /* Initialize UART_DM */
Vadim Bendebury476f7312014-04-08 18:45:46 -0700299 msm_boot_uart_dm_init(dm_base);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700300}
301
Vadim Bendebury7c256402015-01-13 13:07:48 -0800302/* for the benefit of non-console uart init */
303void ipq806x_uart_init(void)
304{
305 uart_init(0);
306}
307
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700308#if 0 /* Not used yet */
309uint32_t uartmem_getbaseaddr(void)
310{
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800311 return (uint32_t)uart_board_param.uart_dm_base;
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700312}
313#endif
314
Vadim Bendebury476f7312014-04-08 18:45:46 -0700315/**
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700316 * uart_tx_flush - transmits a string of data
Vadim Bendebury476f7312014-04-08 18:45:46 -0700317 * @s: string to transmit
318 */
Felix Helde3a12472020-09-11 15:47:09 +0200319void uart_tx_flush(unsigned int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700320{
Vadim Bendeburyb67b7152015-01-13 12:46:57 -0800321 void *base = uart_board_param.uart_dm_base;
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700322
Julius Werner2f37bd62015-02-19 14:51:15 -0800323 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700324 MSM_BOOT_UART_DM_SR_TXEMT))
325 ;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700326}
327
328/**
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700329 * uart_can_rx_byte - checks if data available for reading
Vadim Bendebury476f7312014-04-08 18:45:46 -0700330 *
331 * Returns 1 if data available, 0 otherwise
332 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700333 #if 0 /* Not used yet */
334int uart_can_rx_byte(void)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700335{
336 /* Return if data is already read */
337 if (valid_data)
338 return 1;
339
340 /* Read data from the FIFO */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700341 if (msm_boot_uart_dm_read(&word, &valid_data, 0) !=
342 MSM_BOOT_UART_DM_E_SUCCESS)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700343 return 0;
344
345 return 1;
346}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700347#endif
Vadim Bendebury476f7312014-04-08 18:45:46 -0700348
349/**
350 * ipq806x_serial_getc - reads a character
351 *
352 * Returns the character read from serial port.
353 */
Felix Helde3a12472020-09-11 15:47:09 +0200354uint8_t uart_rx_byte(unsigned int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700355{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700356 uint8_t byte;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700357
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700358#if 0 /* Not used yet */
359 while (!uart_can_rx_byte()) {
Vadim Bendebury476f7312014-04-08 18:45:46 -0700360 /* wait for incoming data */
361 }
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700362#endif
363 byte = (uint8_t)(word & 0xff);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700364 word = word >> 8;
365 valid_data--;
366
367 return byte;
368}
Vadim Bendebury7c256402015-01-13 13:07:48 -0800369
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700370/* TODO: Implement fuction */
371void uart_fill_lb(void *data)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700372{
Vadim Bendebury476f7312014-04-08 18:45:46 -0700373}