blob: d3f2a05ea2de68cdf525fde6b9bc1f3478f335dd [file] [log] [blame]
Ajay Dudanib01e5062011-12-03 23:23:42 -08001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <string.h>
30#include <stdlib.h>
31#include <debug.h>
32#include <reg.h>
33#include <sys/types.h>
34#include <platform/iomap.h>
35#include <platform/irqs.h>
36#include <platform/interrupts.h>
37#include <platform/clock.h>
38#include <platform/gpio.h>
39#include <uart_dm.h>
40#include <gsbi.h>
41
42#ifndef NULL
43#define NULL 0
44#endif
45
46extern void dsb(void);
47
48static int uart_init_flag = 0;
49
50/* Note:
51 * This is a basic implementation of UART_DM protocol. More focus has been
52 * given on simplicity than efficiency. Few of the things to be noted are:
53 * - RX path may not be suitable for multi-threaded scenaraio because of the
54 * use of static variables. TX path shouldn't have any problem though. If
55 * multi-threaded support is required, a simple data-structure can
56 * be maintained for each thread.
57 * - Right now we are using polling method than interrupt based.
58 * - We are using legacy UART protocol without Data Mover.
59 * - Not all interrupts and error events are handled.
60 * - While waiting Watchdog hasn't been taken into consideration.
61 */
62
63#define PACK_CHARS_INTO_WORDS(a, cnt, word) { \
64 word = 0; \
65 for(int j=0; j < (int)cnt; j++) \
66 { \
67 word |= (a[j] & 0xff) \
68 << (j * 8); \
69 } \
70 }
71
72/* Static Function Prototype Declarations */
Ajay Dudanib01e5062011-12-03 23:23:42 -080073static unsigned int msm_boot_uart_replace_lr_with_cr(char *data_in,
74 int num_of_chars,
75 char *data_out,
76 int *num_of_chars_out);
Amol Jadia63aaff2012-02-01 15:51:50 -080077static unsigned int msm_boot_uart_dm_init(uint32_t base);
78static unsigned int msm_boot_uart_dm_read(uint32_t base, unsigned int *data,
79 int wait);
80static unsigned int msm_boot_uart_dm_write(uint32_t base, char *data,
81 unsigned int num_of_chars);
82static unsigned int msm_boot_uart_dm_init_rx_transfer(uint32_t base);
83static unsigned int msm_boot_uart_dm_reset(uint32_t base);
Ajay Dudanib01e5062011-12-03 23:23:42 -080084
85/* Keep track of gsbi vs port mapping.
86 */
Amol Jadia63aaff2012-02-01 15:51:50 -080087static uint32_t gsbi_lookup[4];
Ajay Dudanib01e5062011-12-03 23:23:42 -080088
89/* Extern functions */
90void udelay(unsigned usecs);
91
92/*
93 * Helper function to replace Line Feed char "\n" with
94 * Carriage Return "\r\n".
95 * Currently keeping it simple than efficient
96 */
97static unsigned int
98msm_boot_uart_replace_lr_with_cr(char *data_in,
99 int num_of_chars,
100 char *data_out, int *num_of_chars_out)
101{
102 int i = 0, j = 0;
103
104 if ((data_in == NULL) || (data_out == NULL) || (num_of_chars < 0)) {
105 return MSM_BOOT_UART_DM_E_INVAL;
106 }
107
108 for (i = 0, j = 0; i < num_of_chars; i++, j++) {
109 if (data_in[i] == '\n') {
110 data_out[j++] = '\r';
111 }
112
113 data_out[j] = data_in[i];
114 }
115
116 *num_of_chars_out = j;
117
118 return MSM_BOOT_UART_DM_E_SUCCESS;
119}
120
121/*
Ajay Dudanib01e5062011-12-03 23:23:42 -0800122 * Reset the UART
123 */
Amol Jadia63aaff2012-02-01 15:51:50 -0800124static unsigned int msm_boot_uart_dm_reset(uint32_t base)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800125{
Amol Jadia63aaff2012-02-01 15:51:50 -0800126 writel(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(base));
127 writel(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(base));
128 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(base));
129 writel(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(base));
130 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800131
132 return MSM_BOOT_UART_DM_E_SUCCESS;
133}
134
135/*
136 * Initialize UART_DM - configure clock and required registers.
137 */
Amol Jadia63aaff2012-02-01 15:51:50 -0800138static unsigned int msm_boot_uart_dm_init(uint32_t uart_dm_base)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800139{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800140 /* Configure UART mode registers MR1 and MR2 */
141 /* Hardware flow control isn't supported */
Amol Jadia63aaff2012-02-01 15:51:50 -0800142 writel(0x0, MSM_BOOT_UART_DM_MR1(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800143
144 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
Amol Jadia63aaff2012-02-01 15:51:50 -0800145 writel(MSM_BOOT_UART_DM_8_N_1_MODE, MSM_BOOT_UART_DM_MR2(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800146
147 /* Configure Interrupt Mask register IMR */
Amol Jadia63aaff2012-02-01 15:51:50 -0800148 writel(MSM_BOOT_UART_DM_IMR_ENABLED, MSM_BOOT_UART_DM_IMR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800149
150 /* Configure Tx and Rx watermarks configuration registers */
151 /* TX watermark value is set to 0 - interrupt is generated when
152 * FIFO level is less than or equal to 0 */
Amol Jadia63aaff2012-02-01 15:51:50 -0800153 writel(MSM_BOOT_UART_DM_TFW_VALUE, MSM_BOOT_UART_DM_TFWR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800154
155 /* RX watermark value */
Amol Jadia63aaff2012-02-01 15:51:50 -0800156 writel(MSM_BOOT_UART_DM_RFW_VALUE, MSM_BOOT_UART_DM_RFWR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800157
158 /* Configure Interrupt Programming Register */
159 /* Set initial Stale timeout value */
Amol Jadia63aaff2012-02-01 15:51:50 -0800160 writel(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB, MSM_BOOT_UART_DM_IPR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800161
162 /* Configure IRDA if required */
163 /* Disabling IRDA mode */
Amol Jadia63aaff2012-02-01 15:51:50 -0800164 writel(0x0, MSM_BOOT_UART_DM_IRDA(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800165
166 /* Configure and enable sim interface if required */
167
168 /* Configure hunt character value in HCR register */
169 /* Keep it in reset state */
Amol Jadia63aaff2012-02-01 15:51:50 -0800170 writel(0x0, MSM_BOOT_UART_DM_HCR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800171
172 /* Configure Rx FIFO base address */
173 /* Both TX/RX shares same SRAM and default is half-n-half.
174 * Sticking with default value now.
175 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
176 * We have found RAM_ADDR_WIDTH = 0x7f */
177
178 /* Issue soft reset command */
Amol Jadia63aaff2012-02-01 15:51:50 -0800179 msm_boot_uart_dm_reset(uart_dm_base);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800180
181 /* Enable/Disable Rx/Tx DM interfaces */
182 /* Data Mover not currently utilized. */
Amol Jadia63aaff2012-02-01 15:51:50 -0800183 writel(0x0, MSM_BOOT_UART_DM_DMEN(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800184
185 /* Enable transmitter and receiver */
Amol Jadia63aaff2012-02-01 15:51:50 -0800186 writel(MSM_BOOT_UART_DM_CR_RX_ENABLE, MSM_BOOT_UART_DM_CR(uart_dm_base));
187 writel(MSM_BOOT_UART_DM_CR_TX_ENABLE, MSM_BOOT_UART_DM_CR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800188
189 /* Initialize Receive Path */
Amol Jadia63aaff2012-02-01 15:51:50 -0800190 msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800191
192 return MSM_BOOT_UART_DM_E_SUCCESS;
193}
194
195/*
196 * Initialize Receive Path
197 */
Amol Jadia63aaff2012-02-01 15:51:50 -0800198static unsigned int msm_boot_uart_dm_init_rx_transfer(uint32_t uart_dm_base)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800199{
Amol Jadia63aaff2012-02-01 15:51:50 -0800200 writel(MSM_BOOT_UART_DM_GCMD_DIS_STALE_EVT, MSM_BOOT_UART_DM_CR(uart_dm_base));
201 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(uart_dm_base));
202 writel(MSM_BOOT_UART_DM_DMRX_DEF_VALUE, MSM_BOOT_UART_DM_DMRX(uart_dm_base));
203 writel(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT, MSM_BOOT_UART_DM_CR(uart_dm_base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800204
205 return MSM_BOOT_UART_DM_E_SUCCESS;
206}
207
208/*
209 * UART Receive operation
210 * Reads a word from the RX FIFO.
211 */
212static unsigned int
Amol Jadia63aaff2012-02-01 15:51:50 -0800213msm_boot_uart_dm_read(uint32_t base, unsigned int *data, int wait)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800214{
215 static int rx_last_snap_count = 0;
216 static int rx_chars_read_since_last_xfer = 0;
217
218 if (data == NULL) {
219 return MSM_BOOT_UART_DM_E_INVAL;
220 }
221
222 /* We will be polling RXRDY status bit */
Amol Jadia63aaff2012-02-01 15:51:50 -0800223 while (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_RXRDY)) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800224 /* if this is not a blocking call, we'll just return */
225 if (!wait) {
226 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
227 }
228 }
229
230 /* Check for Overrun error. We'll just reset Error Status */
Amol Jadia63aaff2012-02-01 15:51:50 -0800231 if (readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_UART_OVERRUN) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800232 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
Amol Jadia63aaff2012-02-01 15:51:50 -0800233 MSM_BOOT_UART_DM_CR(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800234 }
235
236 /* RX FIFO is ready; read a word. */
Amol Jadia63aaff2012-02-01 15:51:50 -0800237 *data = readl(MSM_BOOT_UART_DM_RF(base, 0));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800238
239 /* increment the total count of chars we've read so far */
240 rx_chars_read_since_last_xfer += 4;
241
242 /* Rx transfer ends when one of the conditions is met:
243 * - The number of characters received since the end of the previous xfer
244 * equals the value written to DMRX at Transfer Initialization
245 * - A stale event occurred
246 */
247
248 /* If RX transfer has not ended yet */
249 if (rx_last_snap_count == 0) {
250 /* Check if we've received stale event */
Amol Jadia63aaff2012-02-01 15:51:50 -0800251 if (readl(MSM_BOOT_UART_DM_MISR(base)) & MSM_BOOT_UART_DM_RXSTALE) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800252 /* Send command to reset stale interrupt */
253 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT,
Amol Jadia63aaff2012-02-01 15:51:50 -0800254 MSM_BOOT_UART_DM_CR(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800255 }
256
257 /* Check if we haven't read more than DMRX value */
258 else if ((unsigned int)rx_chars_read_since_last_xfer <
Amol Jadia63aaff2012-02-01 15:51:50 -0800259 readl(MSM_BOOT_UART_DM_DMRX(base))) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800260 /* We can still continue reading before initializing RX transfer */
261 return MSM_BOOT_UART_DM_E_SUCCESS;
262 }
263
264 /* If we've reached here it means RX xfer end conditions been met */
265
266 /* Read UART_DM_RX_TOTAL_SNAP register to know how many valid chars
267 * we've read so far since last transfer */
Amol Jadia63aaff2012-02-01 15:51:50 -0800268 rx_last_snap_count = readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800269
270 }
271
272 /* If there are still data left in FIFO we'll read them before
273 * initializing RX Transfer again */
274 if ((rx_last_snap_count - rx_chars_read_since_last_xfer) >= 0) {
275 return MSM_BOOT_UART_DM_E_SUCCESS;
276 }
277
Amol Jadia63aaff2012-02-01 15:51:50 -0800278 msm_boot_uart_dm_init_rx_transfer(base);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800279 rx_last_snap_count = 0;
280 rx_chars_read_since_last_xfer = 0;
281
282 return MSM_BOOT_UART_DM_E_SUCCESS;
283}
284
285/*
286 * UART transmit operation
287 */
288static unsigned int
Amol Jadia63aaff2012-02-01 15:51:50 -0800289msm_boot_uart_dm_write(uint32_t base, char *data, unsigned int num_of_chars)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800290{
291 unsigned int tx_word_count = 0;
292 unsigned int tx_char_left = 0, tx_char = 0;
293 unsigned int tx_word = 0;
294 int i = 0;
295 char *tx_data = NULL;
296 char new_data[1024];
297
298 if ((data == NULL) || (num_of_chars <= 0)) {
299 return MSM_BOOT_UART_DM_E_INVAL;
300 }
301
302 /* Replace line-feed (/n) with carriage-return + line-feed (/r/n) */
303
304 msm_boot_uart_replace_lr_with_cr(data, num_of_chars, new_data, &i);
305
306 tx_data = new_data;
307 num_of_chars = i;
308
309 /* Write to NO_CHARS_FOR_TX register number of characters
310 * to be transmitted. However, before writing TX_FIFO must
311 * be empty as indicated by TX_READY interrupt in IMR register
312 */
313
314 /* Check if transmit FIFO is empty.
315 * If not we'll wait for TX_READY interrupt. */
Amol Jadia63aaff2012-02-01 15:51:50 -0800316 if (!(readl(MSM_BOOT_UART_DM_SR(base)) & MSM_BOOT_UART_DM_SR_TXEMT)) {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800317 while (!
Amol Jadia63aaff2012-02-01 15:51:50 -0800318 (readl(MSM_BOOT_UART_DM_ISR(base)) &
Ajay Dudanib01e5062011-12-03 23:23:42 -0800319 MSM_BOOT_UART_DM_TX_READY)) {
320 udelay(1);
321 /* Kick watchdog? */
322 }
323 }
324
325 /* We are here. FIFO is ready to be written. */
326 /* Write number of characters to be written */
Amol Jadia63aaff2012-02-01 15:51:50 -0800327 writel(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800328
329 /* Clear TX_READY interrupt */
Amol Jadia63aaff2012-02-01 15:51:50 -0800330 writel(MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT, MSM_BOOT_UART_DM_CR(base));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800331
332 /* We use four-character word FIFO. So we need to divide data into
333 * four characters and write in UART_DM_TF register */
334 tx_word_count = (num_of_chars % 4) ? ((num_of_chars / 4) + 1) :
335 (num_of_chars / 4);
336 tx_char_left = num_of_chars;
337
338 for (i = 0; i < (int)tx_word_count; i++) {
339 tx_char = (tx_char_left < 4) ? tx_char_left : 4;
340 PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word);
341
342 /* Wait till TX FIFO has space */
343 while (!
Amol Jadia63aaff2012-02-01 15:51:50 -0800344 (readl(MSM_BOOT_UART_DM_SR(base)) &
Ajay Dudanib01e5062011-12-03 23:23:42 -0800345 MSM_BOOT_UART_DM_SR_TXRDY)) {
346 udelay(1);
347 }
348
349 /* TX FIFO has space. Write the chars */
Amol Jadia63aaff2012-02-01 15:51:50 -0800350 writel(tx_word, MSM_BOOT_UART_DM_TF(base, 0));
Ajay Dudanib01e5062011-12-03 23:23:42 -0800351 tx_char_left = num_of_chars - (i + 1) * 4;
352 tx_data = tx_data + 4;
353 }
354
355 return MSM_BOOT_UART_DM_E_SUCCESS;
356}
357
358/* Defining functions that's exposed to outside world and in coformance to
359 * existing uart implemention. These functions are being called to initialize
360 * UART and print debug messages in bootloader.
361 */
Amol Jadia63aaff2012-02-01 15:51:50 -0800362void uart_dm_init(uint8_t id, uint32_t gsbi_base, uint32_t uart_dm_base)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800363{
364 static uint8_t port = 0;
365 char *data = "Android Bootloader - UART_DM Initialized!!!\n";
366
Amol Jadia63aaff2012-02-01 15:51:50 -0800367 /* Configure the uart clock */
368 clock_config_uart_dm(id);
369 dsb();
370
371 /* Configure GPIO to provide connectivity between GSBI
372 product ports and chip pads */
373 gpio_config_uart_dm(id);
374 dsb();
375
376 /* Configure GSBI for UART_DM protocol.
377 * I2C on 2 ports, UART (without HS flow control) on the other 2. */
378 writel(GSBI_PROTOCOL_CODE_I2C_UART << GSBI_CTRL_REG_PROTOCOL_CODE_S,
379 GSBI_CTRL_REG(gsbi_base));
380 dsb();
381
382 /* Configure clock selection register for tx and rx rates.
383 * Selecting 115.2k for both RX and TX.
384 */
385 writel(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(uart_dm_base));
386 dsb();
387
388 /* Intialize UART_DM */
389 msm_boot_uart_dm_init(uart_dm_base);
390
391 msm_boot_uart_dm_write(uart_dm_base, data, 44);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800392
393 ASSERT(port < ARRAY_SIZE(gsbi_lookup));
Amol Jadia63aaff2012-02-01 15:51:50 -0800394 gsbi_lookup[port++] = uart_dm_base;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800395
396 /* Set UART init flag */
397 uart_init_flag = 1;
398}
399
400/* UART_DM uses four character word FIFO where as UART core
401 * uses a character FIFO. so it's really inefficient to try
402 * to write single character. But that's how dprintf has been
403 * implemented.
404 */
405int uart_putc(int port, char c)
406{
Amol Jadia63aaff2012-02-01 15:51:50 -0800407 uint32_t gsbi_base = gsbi_lookup[port];
Ajay Dudanib01e5062011-12-03 23:23:42 -0800408
409 /* Don't do anything if UART is not initialized */
410 if (!uart_init_flag)
Amol Jadia63aaff2012-02-01 15:51:50 -0800411 return -1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800412
Amol Jadia63aaff2012-02-01 15:51:50 -0800413 msm_boot_uart_dm_write(gsbi_base, &c, 1);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800414
415 return 0;
416}
417
418/* UART_DM uses four character word FIFO whereas uart_getc
419 * is supposed to read only one character. So we need to
420 * read a word and keep track of each character in the word.
421 */
422int uart_getc(int port, bool wait)
423{
424 int byte;
425 static unsigned int word = 0;
Amol Jadia63aaff2012-02-01 15:51:50 -0800426 uint32_t gsbi_base = gsbi_lookup[port];
Ajay Dudanib01e5062011-12-03 23:23:42 -0800427
428 /* Don't do anything if UART is not initialized */
429 if (!uart_init_flag)
Amol Jadia63aaff2012-02-01 15:51:50 -0800430 return -1;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800431
432 if (!word) {
433 /* Read from FIFO only if it's a first read or all the four
434 * characters out of a word have been read */
Amol Jadia63aaff2012-02-01 15:51:50 -0800435 if (msm_boot_uart_dm_read(gsbi_base, &word, wait) !=
Ajay Dudanib01e5062011-12-03 23:23:42 -0800436 MSM_BOOT_UART_DM_E_SUCCESS) {
437 return -1;
438 }
439
440 }
441
442 byte = (int)word & 0xff;
443 word = word >> 8;
444
445 return byte;
446}