blob: 0a7aedceab4c41fcbf2f32d945605dec4bee2937 [file] [log] [blame]
Bikas Gurungd1aa5902010-10-01 23:45:33 -07001/* 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>
Amol Jadic52c8a32011-07-12 11:27:04 -070033#include <sys/types.h>
Bikas Gurungd1aa5902010-10-01 23:45:33 -070034#include <platform/iomap.h>
35#include <platform/irqs.h>
36#include <platform/interrupts.h>
Amol Jadic52c8a32011-07-12 11:27:04 -070037#include <platform/clock.h>
38#include <platform/gpio.h>
39#include <uart_dm.h>
40#include <gsbi.h>
Bikas Gurungd1aa5902010-10-01 23:45:33 -070041
Greg Griscod2471ef2011-07-14 13:00:42 -070042
Bikas Gurungd1aa5902010-10-01 23:45:33 -070043#ifndef NULL
44#define NULL 0
45#endif
46
47/* Note:
48 * This is a basic implementation of UART_DM protocol. More focus has been
49 * given on simplicity than efficiency. Few of the things to be noted are:
50 * - RX path may not be suitable for multi-threaded scenaraio because of the
51 * use of static variables. TX path shouldn't have any problem though. If
52 * multi-threaded support is required, a simple data-structure can
53 * be maintained for each thread.
54 * - Right now we are using polling method than interrupt based.
55 * - We are using legacy UART protocol without Data Mover.
56 * - Not all interrupts and error events are handled.
57 * - While waiting Watchdog hasn't been taken into consideration.
58 */
59
60
61#define PACK_CHARS_INTO_WORDS(a, cnt, word) { \
62 word = 0; \
63 for(int j=0; j < (int)cnt; j++) \
64 { \
65 word |= (a[j] & 0xff) \
66 << (j * 8); \
67 } \
68 }
69
70
71/* Static Function Prototype Declarations */
Amol Jadic52c8a32011-07-12 11:27:04 -070072static unsigned int msm_boot_uart_dm_gsbi_init(uint8_t id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -070073static 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 Jadic52c8a32011-07-12 11:27:04 -070077static unsigned int msm_boot_uart_dm_init(uint8_t id);
78static unsigned int msm_boot_uart_dm_read(uint8_t id, unsigned int* data,
Bikas Gurungd1aa5902010-10-01 23:45:33 -070079 int wait);
Amol Jadic52c8a32011-07-12 11:27:04 -070080static unsigned int msm_boot_uart_dm_write(uint8_t id, char* data,
Bikas Gurungd1aa5902010-10-01 23:45:33 -070081 unsigned int num_of_chars);
Amol Jadic52c8a32011-07-12 11:27:04 -070082static unsigned int msm_boot_uart_dm_init_rx_transfer(uint8_t id);
83static unsigned int msm_boot_uart_dm_reset(uint8_t id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -070084
Amol Jadic52c8a32011-07-12 11:27:04 -070085/* Keep track of gsbi vs port mapping.
86 */
87static uint8_t gsbi_lookup[4];
Bikas Gurungd1aa5902010-10-01 23:45:33 -070088
89/* Extern functions */
Bikas Gurungd1aa5902010-10-01 23:45:33 -070090void udelay(unsigned usecs);
91
92
93/*
94 * Helper function to replace Line Feed char "\n" with
95 * Carriage Return "\r\n".
96 * Currently keeping it simple than efficient
97 */
98static unsigned int msm_boot_uart_replace_lr_with_cr(char* data_in,
99 int num_of_chars,
100 char *data_out,
101 int *num_of_chars_out )
102{
103 int i = 0, j = 0;
104
105 if ((data_in == NULL) || (data_out == NULL) || (num_of_chars < 0))
106 {
107 return MSM_BOOT_UART_DM_E_INVAL;
108 }
109
110 for (i=0, j=0; i < num_of_chars; i++, j++)
111 {
112 if ( data_in[i] == '\n' )
113 {
114 data_out[j++] = '\r';
115 }
116
117 data_out[j] = data_in[i];
118 }
119
120 *num_of_chars_out = j;
121
122 return MSM_BOOT_UART_DM_E_SUCCESS;
123}
124
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700125/*
126 * Initialize and configure GSBI for operation
127 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700128static unsigned int msm_boot_uart_dm_gsbi_init(uint8_t id)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700129{
Amol Jadic52c8a32011-07-12 11:27:04 -0700130 /* Configure the uart clock */
131 clock_config_uart_dm(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700132
Amol Jadic52c8a32011-07-12 11:27:04 -0700133 /* Configure GPIO to provide connectivity between GSBI
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700134 product ports and chip pads */
Amol Jadic52c8a32011-07-12 11:27:04 -0700135 gpio_config_uart_dm(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700136
137 /* Configure Data Mover for GSBI operation.
138 * Currently not supported. */
139
140 /* Configure GSBI for UART_DM protocol.
141 * I2C on 2 ports, UART (without HS flow control) on the other 2. */
Amol Jadic52c8a32011-07-12 11:27:04 -0700142 writel(GSBI_PROTOCOL_CODE_I2C_UART << GSBI_CTRL_REG_PROTOCOL_CODE_S,
143 GSBI_CTRL_REG(id));
144
145 /* Configure clock selection register for tx and rx rates.
146 * Selecting 115.2k for both RX and TX.
147 */
148 writel(UART_DM_CLK_RX_TX_BIT_RATE, MSM_BOOT_UART_DM_CSR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700149
150 return MSM_BOOT_UART_DM_E_SUCCESS;
151}
152
153/*
154 * Reset the UART
155 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700156static unsigned int msm_boot_uart_dm_reset(uint8_t id)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700157{
Amol Jadic52c8a32011-07-12 11:27:04 -0700158 writel(MSM_BOOT_UART_DM_CMD_RESET_RX, MSM_BOOT_UART_DM_CR(id));
159 writel(MSM_BOOT_UART_DM_CMD_RESET_TX, MSM_BOOT_UART_DM_CR(id));
160 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(id));
161 writel(MSM_BOOT_UART_DM_CMD_RES_TX_ERR, MSM_BOOT_UART_DM_CR(id));
162 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700163
164 return MSM_BOOT_UART_DM_E_SUCCESS;
165}
166
167
168/*
169 * Initialize UART_DM - configure clock and required registers.
170 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700171static unsigned int msm_boot_uart_dm_init(uint8_t id)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700172{
Amol Jadic52c8a32011-07-12 11:27:04 -0700173 /* Configure GSBI for uart dm */
174 msm_boot_uart_dm_gsbi_init(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700175
176 /* Configure UART mode registers MR1 and MR2 */
177 /* Hardware flow control isn't supported */
Amol Jadic52c8a32011-07-12 11:27:04 -0700178 writel(0x0, MSM_BOOT_UART_DM_MR1(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700179
180 /* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
Amol Jadic52c8a32011-07-12 11:27:04 -0700181 writel(MSM_BOOT_UART_DM_8_N_1_MODE, MSM_BOOT_UART_DM_MR2(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700182
183 /* Configure Interrupt Mask register IMR */
Amol Jadic52c8a32011-07-12 11:27:04 -0700184 writel(MSM_BOOT_UART_DM_IMR_ENABLED, MSM_BOOT_UART_DM_IMR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700185
186 /* Configure Tx and Rx watermarks configuration registers */
187 /* TX watermark value is set to 0 - interrupt is generated when
188 * FIFO level is less than or equal to 0 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700189 writel(MSM_BOOT_UART_DM_TFW_VALUE, MSM_BOOT_UART_DM_TFWR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700190
191 /* RX watermark value*/
Amol Jadic52c8a32011-07-12 11:27:04 -0700192 writel(MSM_BOOT_UART_DM_RFW_VALUE, MSM_BOOT_UART_DM_RFWR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700193
194 /* Configure Interrupt Programming Register*/
195 /* Set initial Stale timeout value*/
Amol Jadic52c8a32011-07-12 11:27:04 -0700196 writel(MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB, MSM_BOOT_UART_DM_IPR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700197
198 /* Configure IRDA if required */
199 /* Disabling IRDA mode */
Amol Jadic52c8a32011-07-12 11:27:04 -0700200 writel(0x0, MSM_BOOT_UART_DM_IRDA(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700201
202 /* Configure and enable sim interface if required */
203
204 /* Configure hunt character value in HCR register */
205 /* Keep it in reset state */
Amol Jadic52c8a32011-07-12 11:27:04 -0700206 writel(0x0, MSM_BOOT_UART_DM_HCR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700207
208 /* Configure Rx FIFO base address */
209 /* Both TX/RX shares same SRAM and default is half-n-half.
210 * Sticking with default value now.
211 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
212 * We have found RAM_ADDR_WIDTH = 0x7f */
213
214 /* Issue soft reset command */
Amol Jadic52c8a32011-07-12 11:27:04 -0700215 msm_boot_uart_dm_reset(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700216
217 /* Enable/Disable Rx/Tx DM interfaces */
218 /* Data Mover not currently utilized. */
Amol Jadic52c8a32011-07-12 11:27:04 -0700219 writel(0x0, MSM_BOOT_UART_DM_DMEN(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700220
221
222 /* Enable transmitter and receiver */
Amol Jadic52c8a32011-07-12 11:27:04 -0700223 writel(MSM_BOOT_UART_DM_CR_RX_ENABLE, MSM_BOOT_UART_DM_CR(id));
224 writel(MSM_BOOT_UART_DM_CR_TX_ENABLE, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700225
226 /* Initialize Receive Path */
Amol Jadic52c8a32011-07-12 11:27:04 -0700227 msm_boot_uart_dm_init_rx_transfer(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700228
229 return MSM_BOOT_UART_DM_E_SUCCESS;
230}
231
232
233/*
234 * Initialize Receive Path
235 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700236static unsigned int msm_boot_uart_dm_init_rx_transfer(uint8_t id)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700237{
Amol Jadic52c8a32011-07-12 11:27:04 -0700238 writel(MSM_BOOT_UART_DM_GCMD_DIS_STALE_EVT, MSM_BOOT_UART_DM_CR(id));
239 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(id));
240 writel(MSM_BOOT_UART_DM_DMRX_DEF_VALUE, MSM_BOOT_UART_DM_DMRX(id));
241 writel(MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700242
243 return MSM_BOOT_UART_DM_E_SUCCESS;
244}
245
246/*
247 * UART Receive operation
248 * Reads a word from the RX FIFO.
249 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700250static unsigned int msm_boot_uart_dm_read(uint8_t id, unsigned int* data, int wait)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700251{
252 static int rx_last_snap_count = 0;
253 static int rx_chars_read_since_last_xfer = 0;
254
255 if (data == NULL)
256 {
257 return MSM_BOOT_UART_DM_E_INVAL;
258 }
259
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700260 /* We will be polling RXRDY status bit */
Amol Jadic52c8a32011-07-12 11:27:04 -0700261 while (!(readl(MSM_BOOT_UART_DM_SR(id)) & MSM_BOOT_UART_DM_SR_RXRDY))
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700262 {
263 /* if this is not a blocking call, we'll just return */
264 if (!wait)
265 {
266 return MSM_BOOT_UART_DM_E_RX_NOT_READY;
267 }
268 }
269
270 /* Check for Overrun error. We'll just reset Error Status */
Amol Jadic52c8a32011-07-12 11:27:04 -0700271 if (readl(MSM_BOOT_UART_DM_SR(id)) & MSM_BOOT_UART_DM_SR_UART_OVERRUN)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700272 {
Amol Jadic52c8a32011-07-12 11:27:04 -0700273 writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700274 }
275
276 /* RX FIFO is ready; read a word. */
Amol Jadic52c8a32011-07-12 11:27:04 -0700277 *data = readl(MSM_BOOT_UART_DM_RF(id, 0));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700278
279 /* increment the total count of chars we've read so far */
280 rx_chars_read_since_last_xfer += 4;
Shashank Mittaled177732011-05-06 19:12:59 -0700281
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700282 /* Rx transfer ends when one of the conditions is met:
283 * - The number of characters received since the end of the previous xfer
284 * equals the value written to DMRX at Transfer Initialization
285 * - A stale event occurred
286 */
287
288 /* If RX transfer has not ended yet */
289 if (rx_last_snap_count == 0)
290 {
291 /* Check if we've received stale event */
Amol Jadic52c8a32011-07-12 11:27:04 -0700292 if (readl(MSM_BOOT_UART_DM_MISR(id)) & MSM_BOOT_UART_DM_RXSTALE)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700293 {
294 /* Send command to reset stale interrupt */
Amol Jadic52c8a32011-07-12 11:27:04 -0700295 writel(MSM_BOOT_UART_DM_CMD_RES_STALE_INT, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700296 }
297
298 /* Check if we haven't read more than DMRX value */
299 else if ((unsigned int)rx_chars_read_since_last_xfer <
Amol Jadic52c8a32011-07-12 11:27:04 -0700300 readl(MSM_BOOT_UART_DM_DMRX(id)))
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700301 {
302 /* We can still continue reading before initializing RX transfer */
303 return MSM_BOOT_UART_DM_E_SUCCESS;
304 }
305
306 /* If we've reached here it means RX xfer end conditions been met */
307
308 /* Read UART_DM_RX_TOTAL_SNAP register to know how many valid chars
309 * we've read so far since last transfer */
Amol Jadic52c8a32011-07-12 11:27:04 -0700310 rx_last_snap_count = readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700311
312 }
313
314 /* If there are still data left in FIFO we'll read them before
315 * initializing RX Transfer again */
316 if ((rx_last_snap_count - rx_chars_read_since_last_xfer) >= 0 )
317 {
318 return MSM_BOOT_UART_DM_E_SUCCESS;
319 }
320
Amol Jadic52c8a32011-07-12 11:27:04 -0700321 msm_boot_uart_dm_init_rx_transfer(id);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700322 rx_last_snap_count = 0;
323 rx_chars_read_since_last_xfer = 0;
324
325 return MSM_BOOT_UART_DM_E_SUCCESS;
326}
327
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700328/*
329 * UART transmit operation
330 */
Amol Jadic52c8a32011-07-12 11:27:04 -0700331static unsigned int msm_boot_uart_dm_write(uint8_t id, char* data,
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700332 unsigned int num_of_chars)
333{
334 unsigned int tx_word_count = 0;
335 unsigned int tx_char_left = 0, tx_char = 0;
336 unsigned int tx_word = 0;
337 int i = 0;
338 char* tx_data = NULL;
339 char new_data[1024];
340
341 if ((data == NULL) || (num_of_chars <= 0))
342 {
343 return MSM_BOOT_UART_DM_E_INVAL;
344 }
345
346 /* Replace line-feed (/n) with carriage-return + line-feed (/r/n) */
347
348 msm_boot_uart_replace_lr_with_cr(data, num_of_chars, new_data, &i);
349
350 tx_data = new_data;
351 num_of_chars = i;
352
353 /* Write to NO_CHARS_FOR_TX register number of characters
354 * to be transmitted. However, before writing TX_FIFO must
355 * be empty as indicated by TX_READY interrupt in IMR register
356 */
357
358 /* Check if transmit FIFO is empty.
359 * If not we'll wait for TX_READY interrupt. */
Amol Jadic52c8a32011-07-12 11:27:04 -0700360 if (!(readl(MSM_BOOT_UART_DM_SR(id)) & MSM_BOOT_UART_DM_SR_TXEMT))
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700361 {
Amol Jadic52c8a32011-07-12 11:27:04 -0700362 while (!(readl(MSM_BOOT_UART_DM_ISR(id)) & MSM_BOOT_UART_DM_TX_READY))
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700363 {
364 udelay(1);
365 /* Kick watchdog? */
366 }
367 }
368
369 /* We are here. FIFO is ready to be written. */
370 /* Write number of characters to be written */
Amol Jadic52c8a32011-07-12 11:27:04 -0700371 writel(num_of_chars, MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700372
373 /* Clear TX_READY interrupt */
Amol Jadic52c8a32011-07-12 11:27:04 -0700374 writel(MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT, MSM_BOOT_UART_DM_CR(id));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700375
376 /* We use four-character word FIFO. So we need to divide data into
377 * four characters and write in UART_DM_TF register */
378 tx_word_count = (num_of_chars % 4)? ((num_of_chars / 4) + 1) :
379 (num_of_chars / 4);
380 tx_char_left = num_of_chars;
381
382 for (i = 0; i < (int)tx_word_count; i++)
383 {
384 tx_char = (tx_char_left < 4)? tx_char_left : 4;
385 PACK_CHARS_INTO_WORDS(tx_data, tx_char, tx_word);
386
387 /* Wait till TX FIFO has space */
Amol Jadic52c8a32011-07-12 11:27:04 -0700388 while (!(readl(MSM_BOOT_UART_DM_SR(id)) & MSM_BOOT_UART_DM_SR_TXRDY))
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700389 {
390 udelay(1);
391 }
392
393 /* TX FIFO has space. Write the chars */
Amol Jadic52c8a32011-07-12 11:27:04 -0700394 writel(tx_word, MSM_BOOT_UART_DM_TF(id, 0));
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700395 tx_char_left = num_of_chars - (i+1)*4;
396 tx_data = tx_data + 4;
397 }
398
399 return MSM_BOOT_UART_DM_E_SUCCESS;
400}
401
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700402/* Defining functions that's exposed to outside world and in coformance to
403 * existing uart implemention. These functions are being called to initialize
Amol Jadic52c8a32011-07-12 11:27:04 -0700404 * UART and print debug messages in bootloader.
405 */
406void uart_init(uint8_t gsbi_id)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700407{
Amol Jadic52c8a32011-07-12 11:27:04 -0700408 static uint8_t port = 0;
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700409 char *data = "Android Bootloader - UART_DM Initialized!!!\n";
410
Amol Jadic52c8a32011-07-12 11:27:04 -0700411 msm_boot_uart_dm_init(gsbi_id);
412 msm_boot_uart_dm_write(gsbi_id, data, 44);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700413
Amol Jadic52c8a32011-07-12 11:27:04 -0700414 ASSERT(port < ARRAY_SIZE(gsbi_lookup));
415 gsbi_lookup[port++] = gsbi_id;
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700416}
417
Amol Jadic52c8a32011-07-12 11:27:04 -0700418
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700419/* UART_DM uses four character word FIFO where as UART core
420 * uses a character FIFO. so it's really inefficient to try
421 * to write single character. But that's how dprintf has been
422 * implemented.
423 */
424int uart_putc(int port, char c)
425{
Amol Jadic52c8a32011-07-12 11:27:04 -0700426 uint8_t gsbi_id = gsbi_lookup[port];
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700427
Amol Jadic52c8a32011-07-12 11:27:04 -0700428 msm_boot_uart_dm_write(gsbi_id, &c, 1);
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700429
430 return 0;
431}
432
433/* UART_DM uses four character word FIFO whereas uart_getc
434 * is supposed to read only one character. So we need to
435 * read a word and keep track of each character in the word.
436 */
437int uart_getc(int port, bool wait)
438{
439 int byte;
440 static unsigned int word = 0;
Amol Jadic52c8a32011-07-12 11:27:04 -0700441 uint8_t gsbi_id = gsbi_lookup[port];
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700442
443 if (!word)
444 {
445 /* Read from FIFO only if it's a first read or all the four
446 * characters out of a word have been read */
Amol Jadic52c8a32011-07-12 11:27:04 -0700447 if (msm_boot_uart_dm_read(gsbi_id, &word, wait) !=
448 MSM_BOOT_UART_DM_E_SUCCESS)
Bikas Gurungd1aa5902010-10-01 23:45:33 -0700449 {
450 return -1;
451 }
452
453 }
454
455 byte = (int) word & 0xff;
456 word = word >> 8;
457
458 return byte;
459}
460