blob: 9c506111faffe573d3939f7131a1754d799f7208 [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 */
Varadarajan Narayanana6935c22016-03-02 16:57:10 +05303
Kyösti Mälkki13f66502019-03-03 08:01:05 +02004#include <device/mmio.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +05305#include <boot/coreboot_tables.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +05306#include <console/uart.h>
7#include <delay.h>
8#include <gpio.h>
9#include <soc/clock.h>
Varadarajan Narayanan25967642016-03-08 15:02:56 +053010#include <soc/blsp.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053011#include <soc/ipq_uart.h>
12#include <stdint.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053013
14#define FIFO_DATA_SIZE 4
15
16typedef struct {
17 void *uart_dm_base;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053018 uart_clk_mnd_t mnd_value;
Martin Roth57e89092019-10-23 21:45:23 -060019 unsigned int blsp_uart;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053020 gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS];
21} uart_params_t;
22
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053023static const uart_params_t uart_board_param = {
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053024 .uart_dm_base = UART1_DM_BASE,
25 .mnd_value = { 24, 625, 313 },
26 .blsp_uart = BLSP1_UART1,
27 .dbg_uart_gpio = {
28 {
Julius Wernercd49cce2019-03-05 16:53:33 -080029#if CONFIG(IPQ_QFN_PART)
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053030 .gpio = 60,
31 .func = 2,
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053032#else /* bga */
33 .gpio = 16,
34 .func = 1,
35#endif
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053036 .dir = GPIO_INPUT,
37 .pull = GPIO_NO_PULL,
38 .enable = GPIO_ENABLE
39 },
40 {
Julius Wernercd49cce2019-03-05 16:53:33 -080041#if CONFIG(IPQ_QFN_PART)
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053042 .gpio = 61,
43 .func = 2,
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053044#else /* bga */
45 .gpio = 17,
46 .func = 1,
47#endif
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053048 .dir = GPIO_OUTPUT,
49 .pull = GPIO_NO_PULL,
50 .enable = GPIO_ENABLE
51 },
52 },
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053053};
54
55/**
Martin Roth49348182016-07-06 10:17:19 -060056 * @brief msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
57 * @param uart_dm_base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053058 */
59static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base)
60{
61 /* Reset receiver */
62 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
63 MSM_BOOT_UART_DM_CMD_RESET_RX);
64
65 /* Enable receiver */
66 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
67 MSM_BOOT_UART_DM_CR_RX_ENABLE);
68 write32(MSM_BOOT_UART_DM_DMRX(uart_dm_base),
69 MSM_BOOT_UART_DM_DMRX_DEF_VALUE);
70
71 /* Clear stale event */
72 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
73 MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
74
75 /* Enable stale event */
76 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
77 MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT);
78
79 return MSM_BOOT_UART_DM_E_SUCCESS;
80}
81
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053082static unsigned int msm_boot_uart_dm_init(void *uart_dm_base);
83
84/* Received data is valid or not */
85static int valid_data = 0;
86
87/* Received data */
88static unsigned int word = 0;
89
Felix Helde3a12472020-09-11 15:47:09 +020090void uart_tx_byte(unsigned int idx, unsigned char data)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053091{
92 int num_of_chars = 1;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053093 void *base = uart_board_param.uart_dm_base;
94
95 /* Wait until transmit FIFO is empty. */
96 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
97 MSM_BOOT_UART_DM_SR_TXEMT))
98 udelay(1);
99 /*
100 * TX FIFO is ready to accept new character(s). First write number of
101 * characters to be transmitted.
102 */
103 write32(MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base), num_of_chars);
104
105 /* And now write the character(s) */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530106 write32(MSM_BOOT_UART_DM_TF(base, 0), data);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530107}
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530108
Martin Roth49348182016-07-06 10:17:19 -0600109/**
110 * @brief msm_boot_uart_dm_reset - resets UART controller
111 * @param base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530112 */
113static unsigned int msm_boot_uart_dm_reset(void *base)
114{
115 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_RX);
116 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_TX);
117 write32(MSM_BOOT_UART_DM_CR(base),
118 MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT);
119 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_TX_ERR);
120 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
121
122 return MSM_BOOT_UART_DM_E_SUCCESS;
123}
124
Martin Roth49348182016-07-06 10:17:19 -0600125/**
126 * @brief msm_boot_uart_dm_init - initilaizes UART controller
127 * @param uart_dm_base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530128 */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530129unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530130{
131 /* Configure UART mode registers MR1 and MR2 */
132 /* Hardware flow control isn't supported */
133 write32(MSM_BOOT_UART_DM_MR1(uart_dm_base), 0x0);
134
135 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
136 write32(MSM_BOOT_UART_DM_MR2(uart_dm_base),
137 MSM_BOOT_UART_DM_8_N_1_MODE);
138
139 /* Configure Interrupt Mask register IMR */
140 write32(MSM_BOOT_UART_DM_IMR(uart_dm_base),
141 MSM_BOOT_UART_DM_IMR_ENABLED);
142
143 /*
144 * Configure Tx and Rx watermarks configuration registers
145 * TX watermark value is set to 0 - interrupt is generated when
146 * FIFO level is less than or equal to 0
147 */
148 write32(MSM_BOOT_UART_DM_TFWR(uart_dm_base),
149 MSM_BOOT_UART_DM_TFW_VALUE);
150
151 /* RX watermark value */
152 write32(MSM_BOOT_UART_DM_RFWR(uart_dm_base),
153 MSM_BOOT_UART_DM_RFW_VALUE);
154
155 /* Configure Interrupt Programming Register */
156 /* Set initial Stale timeout value */
157 write32(MSM_BOOT_UART_DM_IPR(uart_dm_base),
158 MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB);
159
160 /* Configure IRDA if required */
161 /* Disabling IRDA mode */
162 write32(MSM_BOOT_UART_DM_IRDA(uart_dm_base), 0x0);
163
164 /* Configure hunt character value in HCR register */
165 /* Keep it in reset state */
166 write32(MSM_BOOT_UART_DM_HCR(uart_dm_base), 0x0);
167
168 /*
169 * Configure Rx FIFO base address
170 * Both TX/RX shares same SRAM and default is half-n-half.
171 * Sticking with default value now.
172 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
173 * We have found RAM_ADDR_WIDTH = 0x7f
174 */
175
176 /* Issue soft reset command */
177 msm_boot_uart_dm_reset(uart_dm_base);
178
179 /* Enable/Disable Rx/Tx DM interfaces */
180 /* Data Mover not currently utilized. */
181 write32(MSM_BOOT_UART_DM_DMEN(uart_dm_base), 0x0);
182
183 /* Enable transmitter */
184 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
185 MSM_BOOT_UART_DM_CR_TX_ENABLE);
186
187 /* Initialize Receive Path */
188 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
189
190 return 0;
191}
192
193/**
Martin Roth49348182016-07-06 10:17:19 -0600194 * @brief ipq40xx_uart_init - initializes UART
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530195 *
196 * Initializes clocks, GPIO and UART controller.
197 */
Felix Helde3a12472020-09-11 15:47:09 +0200198void uart_init(unsigned int idx)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530199{
200 /* Note int idx isn't used in this driver. */
201 void *dm_base;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530202
203 dm_base = uart_board_param.uart_dm_base;
204
205 if (read32(MSM_BOOT_UART_DM_CSR(dm_base)) == UART_DM_CLK_RX_TX_BIT_RATE)
206 return; /* UART must have been already initialized. */
207
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530208 ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
209 NO_OF_DBG_UART_GPIOS);
210
211 /* Configure the uart clock */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530212 uart_clock_config(uart_board_param.blsp_uart,
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530213 uart_board_param.mnd_value.m_value,
214 uart_board_param.mnd_value.n_value,
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530215 uart_board_param.mnd_value.d_value);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530216
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530217 write32(MSM_BOOT_UART_DM_CSR(dm_base), UART_DM_CLK_RX_TX_BIT_RATE);
218
219 /* Initialize UART_DM */
220 msm_boot_uart_dm_init(dm_base);
221}
222
223/* for the benefit of non-console uart init */
224void ipq40xx_uart_init(void)
225{
226 uart_init(0);
227}
228
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530229/**
Martin Roth49348182016-07-06 10:17:19 -0600230 * @brief uart_tx_flush - transmits a string of data
231 * @param idx: string to transmit
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530232 */
Felix Helde3a12472020-09-11 15:47:09 +0200233void uart_tx_flush(unsigned int idx)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530234{
235 void *base = uart_board_param.uart_dm_base;
236
237 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
238 MSM_BOOT_UART_DM_SR_TXEMT))
239 ;
240}
241
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530242/**
243 * ipq40xx_serial_getc - reads a character
244 *
245 * Returns the character read from serial port.
246 */
Felix Helde3a12472020-09-11 15:47:09 +0200247uint8_t uart_rx_byte(unsigned int idx)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530248{
249 uint8_t byte;
250
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530251 byte = (uint8_t)(word & 0xff);
252 word = word >> 8;
253 valid_data--;
254
255 return byte;
256}
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530257
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530258/* TODO: Implement function */
259void uart_fill_lb(void *data)
260{
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530261 struct lb_serial serial;
262
263 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
264 serial.baseaddr = (uint32_t)UART1_DM_BASE;
Julien Viard de Galbert235daa42018-02-20 11:45:48 +0100265 serial.baud = get_uart_baudrate();
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530266 serial.regwidth = 1;
Jacob Garber78398272019-07-24 11:12:09 -0600267 serial.input_hertz = uart_platform_refclk();
268 serial.uart_pci_addr = CONFIG_UART_PCI_ADDR;
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530269 lb_add_serial(&serial, data);
Jacob Garber78398272019-07-24 11:12:09 -0600270
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530271 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530272}