blob: 90edd11cfbfbdeb24487721e25c32995ddaff90c [file] [log] [blame]
Varadarajan Narayanana6935c22016-03-02 16:57:10 +05301/*
2 * Copyright (c) 2012 The Linux Foundation. All rights reserved.
3 * Source : APQ8064 LK boot
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * * Neither the name of The Linux Foundation nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Kyösti Mälkki13f66502019-03-03 08:01:05 +020031#include <device/mmio.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053032#include <boot/coreboot_tables.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053033#include <console/uart.h>
34#include <delay.h>
35#include <gpio.h>
36#include <soc/clock.h>
Varadarajan Narayanan25967642016-03-08 15:02:56 +053037#include <soc/blsp.h>
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053038#include <soc/ipq_uart.h>
39#include <stdint.h>
40#include <stdlib.h>
41
42#define FIFO_DATA_SIZE 4
43
44typedef struct {
45 void *uart_dm_base;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053046 uart_clk_mnd_t mnd_value;
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053047 unsigned blsp_uart;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053048 gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS];
49} uart_params_t;
50
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053051static const uart_params_t uart_board_param = {
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053052 .uart_dm_base = UART1_DM_BASE,
53 .mnd_value = { 24, 625, 313 },
54 .blsp_uart = BLSP1_UART1,
55 .dbg_uart_gpio = {
56 {
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053057#if IS_ENABLED(CONFIG_IPQ_QFN_PART)
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053058 .gpio = 60,
59 .func = 2,
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053060#else /* bga */
61 .gpio = 16,
62 .func = 1,
63#endif
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053064 .dir = GPIO_INPUT,
65 .pull = GPIO_NO_PULL,
66 .enable = GPIO_ENABLE
67 },
68 {
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053069#if IS_ENABLED(CONFIG_IPQ_QFN_PART)
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053070 .gpio = 61,
71 .func = 2,
Varadarajan Narayanan520d5fb2015-10-01 16:11:29 +053072#else /* bga */
73 .gpio = 17,
74 .func = 1,
75#endif
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +053076 .dir = GPIO_OUTPUT,
77 .pull = GPIO_NO_PULL,
78 .enable = GPIO_ENABLE
79 },
80 },
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053081};
82
83/**
Martin Roth49348182016-07-06 10:17:19 -060084 * @brief msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
85 * @param uart_dm_base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +053086 */
87static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base)
88{
89 /* Reset receiver */
90 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
91 MSM_BOOT_UART_DM_CMD_RESET_RX);
92
93 /* Enable receiver */
94 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
95 MSM_BOOT_UART_DM_CR_RX_ENABLE);
96 write32(MSM_BOOT_UART_DM_DMRX(uart_dm_base),
97 MSM_BOOT_UART_DM_DMRX_DEF_VALUE);
98
99 /* Clear stale event */
100 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
101 MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
102
103 /* Enable stale event */
104 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
105 MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT);
106
107 return MSM_BOOT_UART_DM_E_SUCCESS;
108}
109
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530110static unsigned int msm_boot_uart_dm_init(void *uart_dm_base);
111
112/* Received data is valid or not */
113static int valid_data = 0;
114
115/* Received data */
116static unsigned int word = 0;
117
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530118void uart_tx_byte(int idx, unsigned char data)
119{
120 int num_of_chars = 1;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530121 void *base = uart_board_param.uart_dm_base;
122
123 /* Wait until transmit FIFO is empty. */
124 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
125 MSM_BOOT_UART_DM_SR_TXEMT))
126 udelay(1);
127 /*
128 * TX FIFO is ready to accept new character(s). First write number of
129 * characters to be transmitted.
130 */
131 write32(MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base), num_of_chars);
132
133 /* And now write the character(s) */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530134 write32(MSM_BOOT_UART_DM_TF(base, 0), data);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530135}
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530136
Martin Roth49348182016-07-06 10:17:19 -0600137/**
138 * @brief msm_boot_uart_dm_reset - resets UART controller
139 * @param base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530140 */
141static unsigned int msm_boot_uart_dm_reset(void *base)
142{
143 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_RX);
144 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_TX);
145 write32(MSM_BOOT_UART_DM_CR(base),
146 MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT);
147 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_TX_ERR);
148 write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
149
150 return MSM_BOOT_UART_DM_E_SUCCESS;
151}
152
Martin Roth49348182016-07-06 10:17:19 -0600153/**
154 * @brief msm_boot_uart_dm_init - initilaizes UART controller
155 * @param uart_dm_base: UART controller base address
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530156 */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530157unsigned int msm_boot_uart_dm_init(void *uart_dm_base)
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530158{
159 /* Configure UART mode registers MR1 and MR2 */
160 /* Hardware flow control isn't supported */
161 write32(MSM_BOOT_UART_DM_MR1(uart_dm_base), 0x0);
162
163 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
164 write32(MSM_BOOT_UART_DM_MR2(uart_dm_base),
165 MSM_BOOT_UART_DM_8_N_1_MODE);
166
167 /* Configure Interrupt Mask register IMR */
168 write32(MSM_BOOT_UART_DM_IMR(uart_dm_base),
169 MSM_BOOT_UART_DM_IMR_ENABLED);
170
171 /*
172 * Configure Tx and Rx watermarks configuration registers
173 * TX watermark value is set to 0 - interrupt is generated when
174 * FIFO level is less than or equal to 0
175 */
176 write32(MSM_BOOT_UART_DM_TFWR(uart_dm_base),
177 MSM_BOOT_UART_DM_TFW_VALUE);
178
179 /* RX watermark value */
180 write32(MSM_BOOT_UART_DM_RFWR(uart_dm_base),
181 MSM_BOOT_UART_DM_RFW_VALUE);
182
183 /* Configure Interrupt Programming Register */
184 /* Set initial Stale timeout value */
185 write32(MSM_BOOT_UART_DM_IPR(uart_dm_base),
186 MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB);
187
188 /* Configure IRDA if required */
189 /* Disabling IRDA mode */
190 write32(MSM_BOOT_UART_DM_IRDA(uart_dm_base), 0x0);
191
192 /* Configure hunt character value in HCR register */
193 /* Keep it in reset state */
194 write32(MSM_BOOT_UART_DM_HCR(uart_dm_base), 0x0);
195
196 /*
197 * Configure Rx FIFO base address
198 * Both TX/RX shares same SRAM and default is half-n-half.
199 * Sticking with default value now.
200 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
201 * We have found RAM_ADDR_WIDTH = 0x7f
202 */
203
204 /* Issue soft reset command */
205 msm_boot_uart_dm_reset(uart_dm_base);
206
207 /* Enable/Disable Rx/Tx DM interfaces */
208 /* Data Mover not currently utilized. */
209 write32(MSM_BOOT_UART_DM_DMEN(uart_dm_base), 0x0);
210
211 /* Enable transmitter */
212 write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
213 MSM_BOOT_UART_DM_CR_TX_ENABLE);
214
215 /* Initialize Receive Path */
216 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
217
218 return 0;
219}
220
221/**
Martin Roth49348182016-07-06 10:17:19 -0600222 * @brief ipq40xx_uart_init - initializes UART
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530223 *
224 * Initializes clocks, GPIO and UART controller.
225 */
226void uart_init(int idx)
227{
228 /* Note int idx isn't used in this driver. */
229 void *dm_base;
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530230
231 dm_base = uart_board_param.uart_dm_base;
232
233 if (read32(MSM_BOOT_UART_DM_CSR(dm_base)) == UART_DM_CLK_RX_TX_BIT_RATE)
234 return; /* UART must have been already initialized. */
235
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530236 ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
237 NO_OF_DBG_UART_GPIOS);
238
239 /* Configure the uart clock */
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530240 uart_clock_config(uart_board_param.blsp_uart,
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530241 uart_board_param.mnd_value.m_value,
242 uart_board_param.mnd_value.n_value,
Varadarajan Narayanan9541ba82016-03-03 13:30:07 +0530243 uart_board_param.mnd_value.d_value);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530244
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530245 write32(MSM_BOOT_UART_DM_CSR(dm_base), UART_DM_CLK_RX_TX_BIT_RATE);
246
247 /* Initialize UART_DM */
248 msm_boot_uart_dm_init(dm_base);
249}
250
251/* for the benefit of non-console uart init */
252void ipq40xx_uart_init(void)
253{
254 uart_init(0);
255}
256
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530257/**
Martin Roth49348182016-07-06 10:17:19 -0600258 * @brief uart_tx_flush - transmits a string of data
259 * @param idx: string to transmit
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530260 */
261void uart_tx_flush(int idx)
262{
263 void *base = uart_board_param.uart_dm_base;
264
265 while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
266 MSM_BOOT_UART_DM_SR_TXEMT))
267 ;
268}
269
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530270/**
271 * ipq40xx_serial_getc - reads a character
272 *
273 * Returns the character read from serial port.
274 */
275uint8_t uart_rx_byte(int idx)
276{
277 uint8_t byte;
278
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530279 byte = (uint8_t)(word & 0xff);
280 word = word >> 8;
281 valid_data--;
282
283 return byte;
284}
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530285
286#ifndef __PRE_RAM__
287/* TODO: Implement function */
288void uart_fill_lb(void *data)
289{
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530290 struct lb_serial serial;
291
292 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
293 serial.baseaddr = (uint32_t)UART1_DM_BASE;
Julien Viard de Galbert235daa42018-02-20 11:45:48 +0100294 serial.baud = get_uart_baudrate();
Varadarajan Narayanana486af42015-10-01 16:12:23 +0530295 serial.regwidth = 1;
296
297 lb_add_serial(&serial, data);
298 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
Varadarajan Narayanana6935c22016-03-02 16:57:10 +0530299}
300#endif