blob: c65f876821717d22067800e7a5e57e081db22e2f [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
34
35#include <common.h>
36#include <asm/arch-ipq806x/gsbi.h>
37#include <asm/arch-ipq806x/clock.h>
38#include <asm/arch-ipq806x/uart.h>
39#include <serial.h>
40
41#define FIFO_DATA_SIZE 4
42
43extern board_ipq806x_params_t *gboard_param;
44
45static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base);
46
47/* Received data is valid or not */
48static int valid_data = 0;
49
50/* Received data */
51static unsigned int word = 0;
52
53/**
54 * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
55 * @uart_dm_base: UART controller base address
56 */
57static unsigned int msm_boot_uart_dm_init_rx_transfer(unsigned int uart_dm_base)
58{
59 /* Reset receiver */
60 writel(MSM_BOOT_UART_DM_CMD_RESET_RX,
61 MSM_BOOT_UART_DM_CR(uart_dm_base));
62
63 /* Enable receiver */
64 writel(MSM_BOOT_UART_DM_CR_RX_ENABLE,
65 MSM_BOOT_UART_DM_CR(uart_dm_base));
66 writel(MSM_BOOT_UART_DM_DMRX_DEF_VALUE,
67 MSM_BOOT_UART_DM_DMRX(uart_dm_base));
68
69 /* Clear stale event */
70 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT,
71 MSM_BOOT_UART_DM_CR(uart_dm_base));
72
73 /* Enable stale event */
74 writel(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT,
75 MSM_BOOT_UART_DM_CR(uart_dm_base));
76
77 return MSM_BOOT_UART_DM_E_SUCCESS;
78}
79
80/**
81 * msm_boot_uart_dm_read - reads a word from the RX FIFO.
82 * @data: location where the read data is stored
83 * @count: no of valid data in the FIFO
84 * @wait: indicates blocking call or not blocking call
85 *
86 * Reads a word from the RX FIFO. If no data is available blocks if
87 * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY.
88 */
89static unsigned int
90msm_boot_uart_dm_read(unsigned int *data, int *count, int wait)
91{
92 static int total_rx_data = 0;
93 static int rx_data_read = 0;
94 unsigned int base = 0;
95 uint32_t status_reg;
96
97 base = gboard_param->uart_dm_base;
98
99 if (data == NULL)
100 return MSM_BOOT_UART_DM_E_INVAL;
101
102 status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
103
104 /* Check for DM_RXSTALE for RX transfer to finish */
105 while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) {
106 status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
107 if (!wait)
108 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
109 }
110
111 /* Check for Overrun error. We'll just reset Error Status */
112 if (readl(MSM_BOOT_UART_DM_SR(base)) &
113 MSM_BOOT_UART_DM_SR_UART_OVERRUN) {
114 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
115 MSM_BOOT_UART_DM_CR(base));
116 total_rx_data = rx_data_read = 0;
117 msm_boot_uart_dm_init(base);
118 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
119 }
120
121 /* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */
122 if (total_rx_data == 0)
123 total_rx_data = readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base));
124
125 /* Data available in FIFO; read a word. */
126 *data = readl(MSM_BOOT_UART_DM_RF(base, 0));
127
128 /* WAR for http://prism/CR/548280 */
129 if (*data == 0) {
130 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
131 }
132
133 /* increment the total count of chars we've read so far */
134 rx_data_read += FIFO_DATA_SIZE;
135
136 /* actual count of valid data in word */
137 *count = ((total_rx_data < rx_data_read) ?
138 (FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) :
139 FIFO_DATA_SIZE);
140
141 /* If there are still data left in FIFO we'll read them before
142 * initializing RX Transfer again
143 */
144 if (rx_data_read < total_rx_data)
145 return MSM_BOOT_UART_DM_E_SUCCESS;
146
147 msm_boot_uart_dm_init_rx_transfer(base);
148 total_rx_data = rx_data_read = 0;
149
150 return MSM_BOOT_UART_DM_E_SUCCESS;
151}
152
153/**
154 * msm_boot_uart_replace_lr_with_cr - replaces "\n" with "\r\n"
155 * @data_in: characters to be converted
156 * @num_of_chars: no. of characters
157 * @data_out: location where converted chars are stored
158 *
159 * Replace linefeed char "\n" with carriage return + linefeed
160 * "\r\n". Currently keeping it simple than efficient.
161 */
162static unsigned int
163msm_boot_uart_replace_lr_with_cr(char *data_in,
164 int num_of_chars,
165 char *data_out, int *num_of_chars_out)
166{
167 int i = 0, j = 0;
168
169 if ((data_in == NULL) || (data_out == NULL) || (num_of_chars < 0))
170 return MSM_BOOT_UART_DM_E_INVAL;
171
172 for (i = 0, j = 0; i < num_of_chars; i++, j++) {
173 if (data_in[i] == '\n')
174 data_out[j++] = '\r';
175
176 data_out[j] = data_in[i];
177 }
178
179 *num_of_chars_out = j;
180
181 return MSM_BOOT_UART_DM_E_SUCCESS;
182}
183
184/**
185 * msm_boot_uart_dm_write - transmit data
186 * @data: data to transmit
187 * @num_of_chars: no. of bytes to transmit
188 *
189 * Writes the data to the TX FIFO. If no space is available blocks
190 * till space becomes available.
191 */
192static unsigned int
193msm_boot_uart_dm_write(char *data, unsigned int num_of_chars)
194{
195 unsigned int tx_word_count = 0;
196 unsigned int tx_char_left = 0, tx_char = 0;
197 unsigned int tx_word = 0;
198 int i = 0;
199 char *tx_data = NULL;
200 char new_data[1024];
201 unsigned int base = gboard_param->uart_dm_base;
202
203 if ((data == NULL) || (num_of_chars <= 0))
204 return MSM_BOOT_UART_DM_E_INVAL;
205
206 /* Replace line-feed (/n) with carriage-return + line-feed (/r/n) */
207 msm_boot_uart_replace_lr_with_cr(data, num_of_chars, new_data, &i);
208
209 tx_data = new_data;
210 num_of_chars = i;
211
212 /* Write to NO_CHARS_FOR_TX register number of characters
213 * to be transmitted. However, before writing TX_FIFO must
214 * be empty as indicated by TX_READY interrupt in IMR register
215 */
216 /* Check if transmit FIFO is empty.
217 * If not we'll wait for TX_READY interrupt. */
218
219 if (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXEMT)) {
220 while (!(readl(MSM_BOOT_UART_DM_ISR(base)) & MSM_BOOT_UART_DM_TX_READY))
221 __udelay(1);
222 }
223
224 /* We are here. FIFO is ready to be written. */
225 /* Write number of characters to be written */
226 writel(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base));
227
228 /* Clear TX_READY interrupt */
229 writel(MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT, MSM_BOOT_UART_DM_CR(base));
230
231 /* We use four-character word FIFO. So we need to divide data into
232 * four characters and write in UART_DM_TF register */
233 tx_word_count = (num_of_chars % 4) ? ((num_of_chars / 4) + 1) :
234 (num_of_chars / 4);
235 tx_char_left = num_of_chars;
236
237 for (i = 0; i < (int)tx_word_count; i++) {
238 tx_char = (tx_char_left < 4) ? tx_char_left : 4;
239 PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word);
240
241 /* Wait till TX FIFO has space */
242 while (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXRDY))
243 __udelay(1);
244
245 /* TX FIFO has space. Write the chars */
246 writel(tx_word, MSM_BOOT_UART_DM_TF(base, 0));
247 tx_char_left = num_of_chars - (i + 1) * 4;
248 tx_data = tx_data + 4;
249 }
250
251 return MSM_BOOT_UART_DM_E_SUCCESS;
252}
253
254/*
255 * msm_boot_uart_dm_reset - resets UART controller
256 * @base: UART controller base address
257 */
258static unsigned int msm_boot_uart_dm_reset(unsigned int base)
259{
260 writel(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base));
261 writel(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base));
262 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(base));
263 writel(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base));
264 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base));
265
266 return MSM_BOOT_UART_DM_E_SUCCESS;
267}
268
269/*
270 * msm_boot_uart_dm_init - initilaizes UART controller
271 * @uart_dm_base: UART controller base address
272 */
273static unsigned int msm_boot_uart_dm_init(unsigned int uart_dm_base)
274{
275 /* Configure UART mode registers MR1 and MR2 */
276 /* Hardware flow control isn't supported */
277 writel(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base));
278
279 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
280 writel(MSM_BOOT_UART_DM_8_N_1_MODE, MSM_BOOT_UART_DM_MR2(uart_dm_base));
281
282 /* Configure Interrupt Mask register IMR */
283 writel(MSM_BOOT_UART_DM_IMR_ENABLED, MSM_BOOT_UART_DM_IMR(uart_dm_base));
284
285 /*
286 * Configure Tx and Rx watermarks configuration registers
287 * TX watermark value is set to 0 - interrupt is generated when
288 * FIFO level is less than or equal to 0
289 */
290 writel(MSM_BOOT_UART_DM_TFW_VALUE, MSM_BOOT_UART_DM_TFWR(uart_dm_base));
291
292 /* RX watermark value */
293 writel(MSM_BOOT_UART_DM_RFW_VALUE, MSM_BOOT_UART_DM_RFWR(uart_dm_base));
294
295 /* Configure Interrupt Programming Register */
296 /* Set initial Stale timeout value */
297 writel(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB,
298 MSM_BOOT_UART_DM_IPR(uart_dm_base));
299
300 /* Configure IRDA if required */
301 /* Disabling IRDA mode */
302 writel(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base));
303
304 /* Configure hunt character value in HCR register */
305 /* Keep it in reset state */
306 writel(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base));
307
308 /*
309 * Configure Rx FIFO base address
310 * Both TX/RX shares same SRAM and default is half-n-half.
311 * Sticking with default value now.
312 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
313 * We have found RAM_ADDR_WIDTH = 0x7f
314 */
315
316 /* Issue soft reset command */
317 msm_boot_uart_dm_reset(uart_dm_base);
318
319 /* Enable/Disable Rx/Tx DM interfaces */
320 /* Data Mover not currently utilized. */
321 writel(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base));
322
323 /* Enable transmitter */
324 writel(MSM_BOOT_UART_DM_CR_TX_ENABLE,
325 MSM_BOOT_UART_DM_CR(uart_dm_base));
326
327 /* Initialize Receive Path */
328 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
329
330 return 0;
331}
332
333/**
334 * uart_dm_init - initializes UART
335 *
336 * Initializes clocks, GPIO and UART controller.
337 */
338static int uart_dm_init(void)
339{
340 unsigned int dm_base, gsbi_base;
341
342 dm_base = gboard_param->uart_dm_base;
343 gsbi_base = gboard_param->uart_gsbi_base;
344 ipq_configure_gpio(gboard_param->dbg_uart_gpio, NO_OF_DBG_UART_GPIOS);
345
346 /* Configure the uart clock */
347 uart_clock_config(gboard_param->uart_gsbi,
348 gboard_param->mnd_value.m_value,
349 gboard_param->mnd_value.n_value,
350 gboard_param->mnd_value.d_value,
351 gboard_param->clk_dummy);
352
353 writel(GSBI_PROTOCOL_CODE_I2C_UART <<
354 GSBI_CTRL_REG_PROTOCOL_CODE_S,
355 GSBI_CTRL_REG(gsbi_base));
356 writel(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(dm_base));
357 /* Intialize UART_DM */
358 msm_boot_uart_dm_init(dm_base);
359
360 return 0;
361}
362
363/**
364 * ipq806x_serial_putc - transmits a character
365 * @c: character to transmit
366 */
367static void ipq806x_serial_putc(char c)
368{
369 msm_boot_uart_dm_write(&c, 1);
370}
371
372/**
373 * ipq806x_serial_puts - transmits a string of data
374 * @s: string to transmit
375 */
376static void ipq806x_serial_puts(const char *s)
377{
378 while (*s != '\0')
379 serial_putc(*s++);
380}
381
382/**
383 * ipq806x_serial_tstc - checks if data available for reading
384 *
385 * Returns 1 if data available, 0 otherwise
386 */
387static int ipq806x_serial_tstc(void)
388{
389 /* Return if data is already read */
390 if (valid_data)
391 return 1;
392
393 /* Read data from the FIFO */
394 if (msm_boot_uart_dm_read(&word, &valid_data, 0) != MSM_BOOT_UART_DM_E_SUCCESS)
395 return 0;
396
397 return 1;
398}
399
400/**
401 * ipq806x_serial_getc - reads a character
402 *
403 * Returns the character read from serial port.
404 */
405static int ipq806x_serial_getc(void)
406{
407 int byte;
408
409 while (!serial_tstc()) {
410 /* wait for incoming data */
411 }
412
413 byte = (int)word & 0xff;
414 word = word >> 8;
415 valid_data--;
416
417 return byte;
418}
419
420static struct serial_device ipq_serial_device = {
421 .name = "ipq_serial",
422 .start = uart_dm_init,
423 .getc = ipq806x_serial_getc,
424 .tstc = ipq806x_serial_tstc,
425 .putc = ipq806x_serial_putc,
426 .puts = ipq806x_serial_puts,
427};
428
429__weak struct serial_device *default_serial_console(void)
430{
431 return &ipq_serial_device;
432}
433
434/**
435 * ipq806x_serial_init - initializes serial controller
436 */
437void ipq806x_serial_initialize(void)
438{
439 serial_register(&ipq_serial_device);
440}