blob: 4989247f33f5b12f9638e07e1efc95f597b5cfac [file] [log] [blame]
Vadim Bendebury476f7312014-04-08 18:45:46 -07001/*
2 * Copyright (c) 2012 The Linux Foundation. All rights reserved.
3 * Source : APQ8064 LK boot
4 *
5 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070034#include <arch/io.h>
35#include <boot/coreboot_tables.h>
36#include <console/console.h>
37#include <delay.h>
38#include <clock.h>
39#include <gpio.h>
40#include <gsbi.h>
41#include <console/uart.h>
42#include <ipq_uart.h>
43#include <stdint.h>
44#include <stdlib.h>
Vadim Bendebury476f7312014-04-08 18:45:46 -070045
46#define FIFO_DATA_SIZE 4
47
Vadim Bendeburyf17680b2014-04-23 14:00:59 -070048typedef struct {
49 unsigned uart_dm_base;
50 unsigned uart_gsbi_base;
51 unsigned uart_gsbi;
52 uart_clk_mnd_t mnd_value;
53 gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS];
54} uart_params_t;
55
56/*
57 * All constants lifted from u-boot's
58 * board/qcom/ipq806x_cdp/ipq806x_board_param.h
59 */
60static const uart_params_t uart_board_param = {
61 .uart_dm_base = UART4_DM_BASE,
62 .uart_gsbi_base = UART_GSBI4_BASE,
63 .uart_gsbi = GSBI_4,
64 .mnd_value = { 12, 625, 313 },
65 .dbg_uart_gpio = {
66 {
67 .gpio = 10,
68 .func = 1,
69 .dir = GPIO_OUTPUT,
70 .pull = GPIO_NO_PULL,
71 .drvstr = GPIO_12MA,
72 .enable = GPIO_DISABLE
73 },
74 {
75 .gpio = 11,
76 .func = 1,
77 .dir = GPIO_INPUT,
78 .pull = GPIO_NO_PULL,
79 .drvstr = GPIO_12MA,
80 .enable = GPIO_DISABLE
81 },
82 }
83};
Vadim Bendebury476f7312014-04-08 18:45:46 -070084
85static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base);
86
87/* Received data is valid or not */
88static int valid_data = 0;
89
90/* Received data */
91static unsigned int word = 0;
92
93/**
94 * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
95 * @uart_dm_base: UART controller base address
96 */
97static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base)
98{
99 /* Reset receiver */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700100 writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700101 MSM_BOOT_UART_DM_CR(uart_dm_base));
102
103 /* Enable receiver */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700104 writel_i(MSM_BOOT_UART_DM_CR_RX_ENABLE,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700105 MSM_BOOT_UART_DM_CR(uart_dm_base));
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700106 writel_i(MSM_BOOT_UART_DM_DMRX_DEF_VALUE,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700107 MSM_BOOT_UART_DM_DMRX(uart_dm_base));
108
109 /* Clear stale event */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700110 writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700111 MSM_BOOT_UART_DM_CR(uart_dm_base));
112
113 /* Enable stale event */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700114 writel_i(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700115 MSM_BOOT_UART_DM_CR(uart_dm_base));
116
117 return MSM_BOOT_UART_DM_E_SUCCESS;
118}
119
120/**
121 * msm_boot_uart_dm_read - reads a word from the RX FIFO.
122 * @data: location where the read data is stored
123 * @count: no of valid data in the FIFO
124 * @wait: indicates blocking call or not blocking call
125 *
126 * Reads a word from the RX FIFO. If no data is available blocks if
127 * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY.
128 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700129 #if 0 /* Not used yet */
Vadim Bendebury476f7312014-04-08 18:45:46 -0700130static unsigned int
131msm_boot_uart_dm_read(unsigned int *data, int *count, int wait)
132{
133 static int total_rx_data = 0;
134 static int rx_data_read = 0;
135 unsigned int base = 0;
136 uint32_t status_reg;
137
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700138 base = uart_board_param.uart_dm_base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700139
140 if (data == NULL)
141 return MSM_BOOT_UART_DM_E_INVAL;
142
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700143 status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700144
145 /* Check for DM_RXSTALE for RX transfer to finish */
146 while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) {
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700147 status_reg = readl_i(MSM_BOOT_UART_DM_MISR(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700148 if (!wait)
149 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
150 }
151
152 /* Check for Overrun error. We'll just reset Error Status */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700153 if (readl_i(MSM_BOOT_UART_DM_SR(base)) &
Vadim Bendebury476f7312014-04-08 18:45:46 -0700154 MSM_BOOT_UART_DM_SR_UART_OVERRUN) {
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700155 writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700156 MSM_BOOT_UART_DM_CR(base));
157 total_rx_data = rx_data_read = 0;
158 msm_boot_uart_dm_init(base);
159 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
160 }
161
162 /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */
163 if (total_rx_data == 0)
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700164 total_rx_data = readl_i(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700165
166 /* Data available in FIFO; read a word. */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700167 *data = readl_i(MSM_BOOT_UART_DM_RF(base, 0));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700168
169 /* WAR for http://prism/CR/548280 */
170 if (*data == 0) {
171 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
172 }
173
174 /* increment the total count of chars we've read so far */
175 rx_data_read += FIFO_DATA_SIZE;
176
177 /* actual count of valid data in word */
178 *count = ((total_rx_data < rx_data_read) ?
179 (FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) :
180 FIFO_DATA_SIZE);
181
182 /* If there are still data left in FIFO we'll read them before
183 * initializing RX Transfer again
184 */
185 if (rx_data_read < total_rx_data)
186 return MSM_BOOT_UART_DM_E_SUCCESS;
187
188 msm_boot_uart_dm_init_rx_transfer(base);
189 total_rx_data = rx_data_read = 0;
190
191 return MSM_BOOT_UART_DM_E_SUCCESS;
192}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700193#endif
Vadim Bendebury476f7312014-04-08 18:45:46 -0700194
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700195void uart_tx_byte(int idx, unsigned char data)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700196{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700197 unsigned int base = uart_board_param.uart_dm_base;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700198
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700199 /* Wait until transmit FIFO is empty. */
200 while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) &
201 MSM_BOOT_UART_DM_SR_TXEMT))
202 udelay(1);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700203
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700204 /*
205 * TX FIFO is ready to accept new character(s). First write number of
206 * characters to be transmitted.
207 */
208 writel_i(1, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700209
Vadim Bendebury24a53dd2014-05-27 18:03:38 -0700210 /* And now write the character(s) */
211 writel_i(data, MSM_BOOT_UART_DM_TF(base, 0));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700212}
213
214/*
215 * msm_boot_uart_dm_reset - resets UART controller
216 * @base: UART controller base address
217 */
218static unsigned int msm_boot_uart_dm_reset(unsigned int base)
219{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700220 writel_i(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base));
221 writel_i(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base));
222 writel_i(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
223 MSM_BOOT_UART_DM_CR(base));
224 writel_i(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base));
225 writel_i(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700226
227 return MSM_BOOT_UART_DM_E_SUCCESS;
228}
229
230/*
231 * msm_boot_uart_dm_init - initilaizes UART controller
232 * @uart_dm_base: UART controller base address
233 */
234static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base)
235{
236 /* Configure UART mode registers MR1 and MR2 */
237 /* Hardware flow control isn't supported */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700238 writel_i(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700239
240 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700241 writel_i(MSM_BOOT_UART_DM_8_N_1_MODE,
242 MSM_BOOT_UART_DM_MR2(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700243
244 /* Configure Interrupt Mask register IMR */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700245 writel_i(MSM_BOOT_UART_DM_IMR_ENABLED,
246 MSM_BOOT_UART_DM_IMR(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700247
248 /*
249 * Configure Tx and Rx watermarks configuration registers
250 * TX watermark value is set to 0 - interrupt is generated when
251 * FIFO level is less than or equal to 0
252 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700253 writel_i(MSM_BOOT_UART_DM_TFW_VALUE,
254 MSM_BOOT_UART_DM_TFWR(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700255
256 /* RX watermark value */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700257 writel_i(MSM_BOOT_UART_DM_RFW_VALUE,
258 MSM_BOOT_UART_DM_RFWR(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700259
260 /* Configure Interrupt Programming Register */
261 /* Set initial Stale timeout value */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700262 writel_i(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700263 MSM_BOOT_UART_DM_IPR(uart_dm_base));
264
265 /* Configure IRDA if required */
266 /* Disabling IRDA mode */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700267 writel_i(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700268
269 /* Configure hunt character value in HCR register */
270 /* Keep it in reset state */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700271 writel_i(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700272
273 /*
274 * Configure Rx FIFO base address
275 * Both TX/RX shares same SRAM and default is half-n-half.
276 * Sticking with default value now.
277 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
278 * We have found RAM_ADDR_WIDTH = 0x7f
279 */
280
281 /* Issue soft reset command */
282 msm_boot_uart_dm_reset(uart_dm_base);
283
284 /* Enable/Disable Rx/Tx DM interfaces */
285 /* Data Mover not currently utilized. */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700286 writel_i(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base));
Vadim Bendebury476f7312014-04-08 18:45:46 -0700287
288 /* Enable transmitter */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700289 writel_i(MSM_BOOT_UART_DM_CR_TX_ENABLE,
Vadim Bendebury476f7312014-04-08 18:45:46 -0700290 MSM_BOOT_UART_DM_CR(uart_dm_base));
291
292 /* Initialize Receive Path */
293 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
294
295 return 0;
296}
297
298/**
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700299 * uart_init - initializes UART
Vadim Bendebury476f7312014-04-08 18:45:46 -0700300 *
301 * Initializes clocks, GPIO and UART controller.
302 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700303void uart_init(int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700304{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700305 /* Note int idx isn't used in this driver. */
Vadim Bendebury476f7312014-04-08 18:45:46 -0700306 unsigned int dm_base, gsbi_base;
307
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700308 dm_base = uart_board_param.uart_dm_base;
309 gsbi_base = uart_board_param.uart_gsbi_base;
310 ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
311 NO_OF_DBG_UART_GPIOS);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700312
313 /* Configure the uart clock */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700314 uart_clock_config(uart_board_param.uart_gsbi,
315 uart_board_param.mnd_value.m_value,
316 uart_board_param.mnd_value.n_value,
317 uart_board_param.mnd_value.d_value,
318 0);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700319
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700320 writel_i(GSBI_PROTOCOL_CODE_I2C_UART <<
Vadim Bendebury476f7312014-04-08 18:45:46 -0700321 GSBI_CTRL_REG_PROTOCOL_CODE_S,
322 GSBI_CTRL_REG(gsbi_base));
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700323 writel_i(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(dm_base));
324
Vadim Bendebury476f7312014-04-08 18:45:46 -0700325 /* Intialize UART_DM */
326 msm_boot_uart_dm_init(dm_base);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700327}
328
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700329#if 0 /* Not used yet */
330uint32_t uartmem_getbaseaddr(void)
331{
332 return uart_board_param.uart_dm_base;
333}
334#endif
335
Vadim Bendebury476f7312014-04-08 18:45:46 -0700336/**
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700337 * uart_tx_flush - transmits a string of data
Vadim Bendebury476f7312014-04-08 18:45:46 -0700338 * @s: string to transmit
339 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700340void uart_tx_flush(int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700341{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700342 unsigned int base = uart_board_param.uart_dm_base;
343
344 while (!(readl_i(MSM_BOOT_UART_DM_SR(base)) &
345 MSM_BOOT_UART_DM_SR_TXEMT))
346 ;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700347}
348
349/**
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700350 * uart_can_rx_byte - checks if data available for reading
Vadim Bendebury476f7312014-04-08 18:45:46 -0700351 *
352 * Returns 1 if data available, 0 otherwise
353 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700354 #if 0 /* Not used yet */
355int uart_can_rx_byte(void)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700356{
357 /* Return if data is already read */
358 if (valid_data)
359 return 1;
360
361 /* Read data from the FIFO */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700362 if (msm_boot_uart_dm_read(&word, &valid_data, 0) !=
363 MSM_BOOT_UART_DM_E_SUCCESS)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700364 return 0;
365
366 return 1;
367}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700368#endif
Vadim Bendebury476f7312014-04-08 18:45:46 -0700369
370/**
371 * ipq806x_serial_getc - reads a character
372 *
373 * Returns the character read from serial port.
374 */
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700375uint8_t uart_rx_byte(int idx)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700376{
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700377 uint8_t byte;
Vadim Bendebury476f7312014-04-08 18:45:46 -0700378
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700379#if 0 /* Not used yet */
380 while (!uart_can_rx_byte()) {
Vadim Bendebury476f7312014-04-08 18:45:46 -0700381 /* wait for incoming data */
382 }
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700383#endif
384 byte = (uint8_t)(word & 0xff);
Vadim Bendebury476f7312014-04-08 18:45:46 -0700385 word = word >> 8;
386 valid_data--;
387
388 return byte;
389}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700390#ifndef __PRE_RAM__
391/* TODO: Implement fuction */
392void uart_fill_lb(void *data)
Vadim Bendebury476f7312014-04-08 18:45:46 -0700393{
Vadim Bendebury476f7312014-04-08 18:45:46 -0700394}
Vadim Bendeburyf17680b2014-04-23 14:00:59 -0700395#endif