serial.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * (INCA) ASC UART support
  3. */
  4. #include <common.h>
  5. #include <asm/inca-ip.h>
  6. #include "serial.h"
  7. #define SET_BIT(reg, mask) reg |= (mask)
  8. #define CLEAR_BIT(reg, mask) reg &= (~mask)
  9. #define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
  10. #define SET_BITS(reg, mask) SET_BIT(reg, mask)
  11. #define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
  12. extern uint incaip_get_fpiclk(void);
  13. static int serial_setopt (void);
  14. /* pointer to ASC register base address */
  15. static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
  16. /******************************************************************************
  17. *
  18. * serial_init - initialize a INCAASC channel
  19. *
  20. * This routine initializes the number of data bits, parity
  21. * and set the selected baud rate. Interrupts are disabled.
  22. * Set the modem control signals if the option is selected.
  23. *
  24. * RETURNS: N/A
  25. */
  26. int serial_init (void)
  27. {
  28. /* we have to set PMU.EN13 bit to enable an ASC device*/
  29. INCAASC_PMU_ENABLE(13);
  30. /* and we have to set CLC register*/
  31. CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
  32. SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
  33. /* initialy we are in async mode */
  34. pAsc->asc_con = ASCCON_M_8ASYNC;
  35. /* select input port */
  36. pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
  37. /* TXFIFO's filling level */
  38. SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
  39. ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
  40. /* enable TXFIFO */
  41. SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
  42. /* RXFIFO's filling level */
  43. SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
  44. ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
  45. /* enable RXFIFO */
  46. SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
  47. /* enable error signals */
  48. SET_BIT(pAsc->asc_con, ASCCON_FEN);
  49. SET_BIT(pAsc->asc_con, ASCCON_OEN);
  50. /* acknowledge ASC interrupts */
  51. ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
  52. /* disable ASC interrupts */
  53. ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
  54. /* set FIFOs into the transparent mode */
  55. SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
  56. SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
  57. /* set baud rate */
  58. serial_setbrg();
  59. /* set the options */
  60. serial_setopt();
  61. return 0;
  62. }
  63. void serial_setbrg (void)
  64. {
  65. ulong uiReloadValue, fdv;
  66. ulong f_ASC;
  67. f_ASC = incaip_get_fpiclk();
  68. #ifndef INCAASC_USE_FDV
  69. fdv = 2;
  70. uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
  71. #else
  72. fdv = INCAASC_FDV_HIGH_BAUDRATE;
  73. uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
  74. #endif /* INCAASC_USE_FDV */
  75. if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
  76. {
  77. #ifndef INCAASC_USE_FDV
  78. fdv = 3;
  79. uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
  80. #else
  81. fdv = INCAASC_FDV_LOW_BAUDRATE;
  82. uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
  83. #endif /* INCAASC_USE_FDV */
  84. if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
  85. {
  86. return; /* can't impossibly generate that baud rate */
  87. }
  88. }
  89. /* Disable Baud Rate Generator; BG should only be written when R=0 */
  90. CLEAR_BIT(pAsc->asc_con, ASCCON_R);
  91. #ifndef INCAASC_USE_FDV
  92. /*
  93. * Disable Fractional Divider (FDE)
  94. * Divide clock by reload-value + constant (BRS)
  95. */
  96. /* FDE = 0 */
  97. CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
  98. if ( fdv == 2 )
  99. CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
  100. else
  101. SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
  102. #else /* INCAASC_USE_FDV */
  103. /* Enable Fractional Divider */
  104. SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
  105. /* Set fractional divider value */
  106. pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
  107. #endif /* INCAASC_USE_FDV */
  108. /* Set reload value in BG */
  109. pAsc->asc_bg = uiReloadValue;
  110. /* Enable Baud Rate Generator */
  111. SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
  112. }
  113. /*******************************************************************************
  114. *
  115. * serial_setopt - set the serial options
  116. *
  117. * Set the channel operating mode to that specified. Following options
  118. * are supported: CREAD, CSIZE, PARENB, and PARODD.
  119. *
  120. * Note, this routine disables the transmitter. The calling routine
  121. * may have to re-enable it.
  122. *
  123. * RETURNS:
  124. * Returns 0 to indicate success, otherwise -1 is returned
  125. */
  126. static int serial_setopt (void)
  127. {
  128. ulong con;
  129. switch ( ASC_OPTIONS & ASCOPT_CSIZE )
  130. {
  131. /* 7-bit-data */
  132. case ASCOPT_CS7:
  133. con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
  134. break;
  135. /* 8-bit-data */
  136. case ASCOPT_CS8:
  137. if ( ASC_OPTIONS & ASCOPT_PARENB )
  138. con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
  139. else
  140. con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
  141. break;
  142. /*
  143. * only 7 and 8-bit frames are supported
  144. * if we don't use IOCTL extensions
  145. */
  146. default:
  147. return -1;
  148. }
  149. if ( ASC_OPTIONS & ASCOPT_STOPB )
  150. SET_BIT(con, ASCCON_STP); /* 2 stop bits */
  151. else
  152. CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
  153. if ( ASC_OPTIONS & ASCOPT_PARENB )
  154. SET_BIT(con, ASCCON_PEN); /* enable parity checking */
  155. else
  156. CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
  157. if ( ASC_OPTIONS & ASCOPT_PARODD )
  158. SET_BIT(con, ASCCON_ODD); /* odd parity */
  159. else
  160. CLEAR_BIT(con, ASCCON_ODD); /* even parity */
  161. if ( ASC_OPTIONS & ASCOPT_CREAD )
  162. SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
  163. pAsc->asc_con |= con;
  164. return 0;
  165. }
  166. void serial_putc (const char c)
  167. {
  168. uint txFl = 0;
  169. if (c == '\n') serial_putc ('\r');
  170. /* check do we have a free space in the TX FIFO */
  171. /* get current filling level */
  172. do
  173. {
  174. txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
  175. }
  176. while ( txFl == INCAASC_TXFIFO_FULL );
  177. pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
  178. /* check for errors */
  179. if ( pAsc->asc_con & ASCCON_OE )
  180. {
  181. SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
  182. return;
  183. }
  184. }
  185. void serial_puts (const char *s)
  186. {
  187. while (*s)
  188. {
  189. serial_putc (*s++);
  190. }
  191. }
  192. int serial_getc (void)
  193. {
  194. ulong symbol_mask;
  195. char c;
  196. while (!serial_tstc());
  197. symbol_mask =
  198. ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
  199. c = (char)(pAsc->asc_rbuf & symbol_mask);
  200. return c;
  201. }
  202. int serial_tstc (void)
  203. {
  204. int res = 1;
  205. if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
  206. {
  207. res = 0;
  208. }
  209. else if ( pAsc->asc_con & ASCCON_FE )
  210. {
  211. SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
  212. res = 0;
  213. }
  214. else if ( pAsc->asc_con & ASCCON_PE )
  215. {
  216. SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
  217. res = 0;
  218. }
  219. else if ( pAsc->asc_con & ASCCON_OE )
  220. {
  221. SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
  222. res = 0;
  223. }
  224. return res;
  225. }