tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / serial / serial_sc8800x.c
1 #include <config.h>
2 #include <common.h>
3 #include <linux/types.h>
4 #include <asm/arch/bits.h>
5 #include <asm/arch/migrate.h>
6 #include <asm/arch/chip_drv_config_extern.h>
7 #include <asm/arch/sio_drv.h>
8 #include <asm/arch/fdl_crc.h>
9 #include <asm/arch/packet.h>
10 #include <asm/arch/common.h>
11 #include <asm/arch/fdl_channel.h>
12 #include <asm/arch/mfp.h>
13
14 #define __REG(x)     (*((volatile u32 *)(x)))
15
16 #ifdef CONFIG_SERIAL_MULTI
17 #warning "SC8800X driver does not support MULTI serials."
18 #endif
19
20 #if defined(PLATFORM_SC6800H)
21 #define GR_CTRL_REG        0x8b000004
22 /* GEN0_UART0_EN    (0x1 << 1) */
23 /* GEN0_UART1_EN    (0x1 << 2) */
24 #define GR_UART_CTRL_EN    (0x3<<1)
25 #elif defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
26 #define GR_CTRL_REG        CTL_BASE_APB
27 #define GR_UART_CTRL_EN    (0x3 << 13 )
28 #elif defined(CONFIG_SC8825)
29 #define GR_CTRL_REG        0x4b000008
30 #define GR_UART_CTRL_EN    ((0x7 << 20 ) | (1))  /*UART0 UART1 UART2 UART3 enable*/
31 #elif defined(PLATFORM_SC8800G) || defined(CONFIG_SC8810)
32 #define GR_CTRL_REG        0x8b000004
33 /* GEN0_UART0_EN    (0x1 << 20) */
34 /* GEN0_UART1_EN    (0x1 << 21) */
35 #define GR_UART_CTRL_EN    (0x3 << 20 )
36 #else
37 #define GR_CTRL_REG        0x8b000018
38 #define GR_UART_CTRL_EN    0x00400000
39 #endif
40
41 #ifdef FPGA_VERIFICATION
42 #define ARM_APB_CLK    48000000UL
43 #else
44 #define ARM_APB_CLK    26000000UL
45 #endif
46
47 #if defined(CONFIG_SC7710G2)
48 #define GR_CTRL_REG1        0x8b0000b4
49 #define GR_UART3_CTRL_EN    1
50
51 #define UART_RX_FLOW_EN   BIT_7
52 #define UART_TX_FLOW_EN   BIT_8
53
54 #define UART_RX_THRESHOLD   120
55
56 #endif
57 typedef struct UartPort
58 {
59     unsigned int regBase;
60     unsigned int baudRate;
61 } UartPort_T;
62
63 UartPort_T gUart0PortInfo =
64 {
65     ARM_UART0_BASE,
66     115200
67 };
68
69 UartPort_T gUart1PortInfo =
70 {
71     ARM_UART1_BASE,
72     115200
73 };
74
75 #if defined(CONFIG_SC7710G2) || defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
76 UartPort_T gUart3PortInfo =
77 {
78     ARM_UART3_BASE,
79     115200
80 };
81 #endif
82
83 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
84 UartPort_T gUart2PortInfo =
85 {
86     ARM_UART2_BASE,
87     115200
88 };
89 #endif
90
91 LOCAL unsigned int SIO_GetHwDivider (unsigned int baudrate)
92 {
93     return (unsigned int) ( (ARM_APB_CLK + baudrate / 2) / baudrate);
94 }
95 LOCAL void SIO_HwOpen (struct FDL_ChannelHandler *channel, unsigned int divider)
96 {
97     UartPort_T *port  = (UartPort_T *) channel->priv;
98
99 #if defined(CONFIG_SC7710G2)
100     if(port->regBase == ARM_UART3_BASE){
101         /* Disable UART*/
102         * ( (volatile unsigned int *) (GR_CTRL_REG1)) &= ~ (GR_UART3_CTRL_EN);
103         /*Disable Interrupt */
104         * (volatile unsigned int *) (port->regBase + ARM_UART_IEN) = 0;
105         /* Enable UART*/
106         * (volatile unsigned int *) GR_CTRL_REG1 |= (GR_UART3_CTRL_EN);
107
108     } else
109 #endif
110     {
111         /* Disable UART*/
112         * ( (volatile unsigned int *) (GR_CTRL_REG)) &= ~ (GR_UART_CTRL_EN);
113         /*Disable Interrupt */
114         * (volatile unsigned int *) (port->regBase + ARM_UART_IEN) = 0;
115         /* Enable UART*/
116         * (volatile unsigned int *) GR_CTRL_REG |= (GR_UART_CTRL_EN);
117     }
118     /* Set baud rate  */
119     * (volatile unsigned int *) (port->regBase + ARM_UART_CLKD0) = LWORD (divider);
120     * (volatile unsigned int *) (port->regBase + ARM_UART_CLKD1) = HWORD (divider);
121
122
123     /* Set port for 8 bit, one stop, no parity  */
124     * (volatile unsigned int *) (port->regBase + ARM_UART_CTL0) = UARTCTL_BL8BITS | UARTCTL_SL1BITS;
125     * (volatile unsigned int *) (port->regBase+ ARM_UART_CTL1) = 0;
126     * (volatile unsigned int *) (port->regBase + ARM_UART_CTL2) = 0;
127 }
128
129 LOCAL int SIO_Open (struct FDL_ChannelHandler  *channel, unsigned int baudrate)
130 {
131     unsigned int divider;
132     unsigned int i = 0;
133
134     UartPort_T *port  = (UartPort_T *) channel->priv;
135
136     divider = SIO_GetHwDivider (baudrate);
137     SIO_HwOpen (channel, divider);
138
139     while(!SIO_TRANS_OVER(port->regBase))  /* Wait until all characters are sent out */
140     {
141         i++;
142         if(i >= UART_SET_BAUDRATE_TIMEOUT)
143         {
144             //  return -1;
145             break;
146         }
147     }
148
149     return 0;
150
151 }
152 LOCAL int SIO_Read (struct FDL_ChannelHandler  *channel, const unsigned char *buf, unsigned int len)
153 {
154 #ifndef CONFIG_NAND_SPL
155     unsigned char *pstart = (unsigned char *) buf;
156     const unsigned char *pend = pstart + len;
157     UartPort_T *port  = (UartPort_T *) channel->priv;
158
159     while ( (pstart < pend)
160             && SIO_RX_READY (SIO_GET_RX_STATUS (port->regBase)))
161     {
162         *pstart++ = SIO_GET_CHAR (port->regBase);
163     }
164
165     return pstart - (unsigned char *) buf;
166 #else
167     return 0;
168 #endif
169 }
170 LOCAL char SIO_GetChar (struct FDL_ChannelHandler  *channel)
171 {
172 #ifndef CONFIG_NAND_SPL
173     UartPort_T *port  = (UartPort_T *) channel->priv;
174
175     while (!SIO_RX_READY (SIO_GET_RX_STATUS (port->regBase)))
176     {
177
178     }
179
180     return SIO_GET_CHAR (port->regBase);
181 #else
182     return 0;
183 #endif
184 }
185 LOCAL int SIO_GetSingleChar (struct FDL_ChannelHandler  *channel)
186 {
187 #ifndef CONFIG_NAND_SPL
188     UartPort_T *port  = (UartPort_T *) channel->priv;
189     char ch;
190
191     if (!SIO_RX_READY (SIO_GET_RX_STATUS (port->regBase)))
192     {
193         return -1;
194
195     }
196     else
197     {
198         ch  = SIO_GET_CHAR (port->regBase);
199     }
200
201     return ch;
202 #else
203     return 0;
204 #endif
205 }
206 LOCAL int SIO_Write (struct FDL_ChannelHandler  *channel, const unsigned char *buf, unsigned int len)
207 {
208 #ifndef CONFIG_NAND_SPL
209     const unsigned char *pstart = (const unsigned char *) buf;
210     const unsigned char *pend = pstart + len;
211     UartPort_T *port  = (UartPort_T *) channel->priv;
212
213     while (pstart < pend)
214     {
215         /* Check if tx port is ready.*/
216         /*lint -save -e506 -e731*/
217         while (!SIO_TX_READY (SIO_GET_TX_STATUS (port->regBase)))
218         {
219
220             /* Do nothing */
221         }
222
223         SIO_PUT_CHAR (port->regBase, *pstart);
224         ++pstart;
225     }
226
227     /* Ensure the last byte is written successfully */
228     while (!SIO_TX_READY (SIO_GET_TX_STATUS (port->regBase)))
229     {
230         /* Do nothing */
231     }
232
233     return pstart - (const unsigned char *) buf;
234 #else
235     return 0;
236 #endif
237 }
238
239 LOCAL int SIO_PutChar (struct FDL_ChannelHandler  *channel, const unsigned char ch)
240 {
241 #ifndef CONFIG_NAND_SPL
242     UartPort_T *port  = (UartPort_T *) channel->priv;
243
244     while (!SIO_TX_READY (SIO_GET_TX_STATUS (port->regBase)))
245     {
246         /* Do nothing */
247     }
248
249     SIO_PUT_CHAR (port->regBase, ch);
250
251     /* Ensure the last byte is written successfully */
252     while (!SIO_TX_READY (SIO_GET_TX_STATUS (port->regBase)))
253     {
254         /* Do nothing */
255     }
256
257     return 0;
258 #else
259     return 0;
260 #endif
261 }
262 LOCAL int SIO_SetBaudrate (struct FDL_ChannelHandler  *channel,  unsigned int baudrate)
263 {
264 #if 0
265     channel->Open (channel, baudrate);
266 #else
267     unsigned int divider;
268     UartPort_T *port  = (UartPort_T *) channel->priv;
269
270     divider = SIO_GetHwDivider (baudrate);
271     /* Set baud rate  */
272     * (volatile unsigned int *) (port->regBase + ARM_UART_CLKD0) = LWORD (divider);
273     * (volatile unsigned int *) (port->regBase + ARM_UART_CLKD1) = HWORD (divider);
274
275 #endif
276     return 0;
277 }
278 LOCAL int SIO_Close (struct FDL_ChannelHandler  *channel)
279 {
280     return 0;
281 }
282
283 struct FDL_ChannelHandler gUart0Channel =
284 {
285     SIO_Open,
286     SIO_Read,
287     SIO_GetChar,
288     SIO_GetSingleChar,
289     SIO_Write,
290     SIO_PutChar,
291     SIO_SetBaudrate,
292     SIO_Close,
293     &gUart0PortInfo
294 };
295
296 struct FDL_ChannelHandler gUart1Channel =
297 {
298     SIO_Open,
299     SIO_Read,
300     SIO_GetChar,
301     SIO_GetSingleChar,
302     SIO_Write,
303     SIO_PutChar,
304     SIO_SetBaudrate,
305     SIO_Close,
306     &gUart1PortInfo
307 };
308
309 #if defined(CONFIG_SC7710G2) || defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
310 struct FDL_ChannelHandler gUart3Channel =
311 {
312     SIO_Open,
313     SIO_Read,
314     SIO_GetChar,
315     SIO_GetSingleChar,
316     SIO_Write,
317     SIO_PutChar,
318     SIO_SetBaudrate,
319     SIO_Close,
320     &gUart3PortInfo
321 };
322 #endif
323
324 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
325 struct FDL_ChannelHandler gUart2Channel =
326 {
327     SIO_Open,
328     SIO_Read,
329     SIO_GetChar,
330     SIO_GetSingleChar,
331     SIO_Write,
332     SIO_PutChar,
333     SIO_SetBaudrate,
334     SIO_Close,
335     &gUart2PortInfo
336 };
337 #endif
338
339 DECLARE_GLOBAL_DATA_PTR;
340 int __dl_log_share__ = 0;
341 void serial_setbrg(void)
342 {
343     SIO_SetBaudrate(&gUart1Channel, 115200);
344 }
345 int serial_getc(void)
346 {
347     return SIO_GetChar (&gUart1Channel);
348 }
349
350 void serial_putc(const char c)
351 {
352     SIO_PutChar(&gUart1Channel, c);
353
354     /* If \n, also do \r */
355     if(__dl_log_share__ == 0){
356         if (c == '\n')
357             serial_putc ('\r');
358     }
359 }
360
361 /*
362  *  * Test whether a character is in the RX buffer
363  *   */
364 int serial_tstc (void)
365 {
366     UartPort_T *port  = (&gUart1Channel)->priv;
367     /* If receive fifo is empty, return false */
368     return SIO_RX_READY( SIO_GET_RX_STATUS( port->regBase) ) ;
369 }
370
371 void serial_puts (const char *s)
372 {
373     if(__dl_log_share__ == 0){
374         while(*s!=0){
375             serial_putc(*s++);
376         }
377     }
378 }
379
380 /*
381  *  * Initialise the serial port with the given baudrate. The settings
382  *   * are always 8 data bits, no parity, 1 stop bit, no start bits.
383  *    *
384  *     */
385 int serial_init (void)
386 {
387     SIO_Open(&gUart1Channel, 115200);
388     /* clear input buffer */
389     if(serial_tstc())
390         serial_getc();
391     return 0;
392 }
393
394 /*
395  *   add UART0 driver for modem boot
396  */
397 #if defined(CONFIG_SC7710G2)
398 void serial3_setbrg(void)
399 {
400     SIO_SetBaudrate(&gUart3Channel, 115200);
401 }
402 int serial3_getc(void)
403 {
404     return SIO_GetChar (&gUart3Channel);
405 }
406
407 void serial3_putc(const char c)
408 {
409     SIO_PutChar(&gUart3Channel, c);
410 }
411
412 /*
413  *  * Test whether a character is in the RX buffer
414  *   */
415 int serial3_tstc (void)
416 {
417     UartPort_T *port  = (&gUart3Channel)->priv;
418     /* If receive fifo is empty, return false */
419     return SIO_RX_READY( SIO_GET_RX_STATUS( port->regBase) ) ;
420 }
421
422 void serial3_puts (const char *s)
423 {
424     while (*s) {
425         serial3_putc (*s++);
426     }
427 }
428
429 int serial3_init (void)
430 {
431     SIO_Open(&gUart3Channel, 115200);
432     /* clear input buffer */
433     if(serial3_tstc())
434         serial3_getc();
435     return 0;
436 }
437
438 int  serial3_flowctl_enable(void)
439 {
440     /*enable tx/rx flow control*/
441     * (volatile unsigned int *) (ARM_UART3_BASE + ARM_UART_CTL1)   |= UART_RX_FLOW_EN  | (UART_RX_THRESHOLD & 0x7F);
442     return 0;
443 }
444
445 int  serial1_SwitchToModem(void)
446 {
447     //Switch Uart1 from AP to CP
448     REG32(CHIPPIN_CTL_BEGIN + PIN_U1RXD_REG_OFFS) = 0x190;
449     REG32(CHIPPIN_CTL_BEGIN + PIN_U1TXD_REG_OFFS)  = 0x110;
450     return 0;
451 }
452
453 #endif
454
455