asc_serial.c 7.2 KB

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