ps2ser.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /***********************************************************************
  2. *
  3. * (C) Copyright 2004
  4. * DENX Software Engineering
  5. * Wolfgang Denk, wd@denx.de
  6. * All rights reserved.
  7. *
  8. * Simple 16550A serial driver
  9. *
  10. * Originally from linux source (drivers/char/ps2ser.c)
  11. *
  12. * Used by the PS/2 multiplexer driver (ps2mult.c)
  13. *
  14. ***********************************************************************/
  15. #include <common.h>
  16. #include <asm/io.h>
  17. #include <asm/atomic.h>
  18. #include <ps2mult.h>
  19. #if defined(CONFIG_SYS_NS16550) || defined(CONFIG_MPC85xx)
  20. #include <ns16550.h>
  21. #endif
  22. DECLARE_GLOBAL_DATA_PTR;
  23. /* #define DEBUG */
  24. #define PS2SER_BAUD 57600
  25. #ifdef CONFIG_MPC5xxx
  26. #if CONFIG_PS2SERIAL == 1
  27. #define PSC_BASE MPC5XXX_PSC1
  28. #elif CONFIG_PS2SERIAL == 2
  29. #define PSC_BASE MPC5XXX_PSC2
  30. #elif CONFIG_PS2SERIAL == 3
  31. #define PSC_BASE MPC5XXX_PSC3
  32. #elif defined(CONFIG_MGT5100)
  33. #error CONFIG_PS2SERIAL must be in 1, 2 or 3
  34. #elif CONFIG_PS2SERIAL == 4
  35. #define PSC_BASE MPC5XXX_PSC4
  36. #elif CONFIG_PS2SERIAL == 5
  37. #define PSC_BASE MPC5XXX_PSC5
  38. #elif CONFIG_PS2SERIAL == 6
  39. #define PSC_BASE MPC5XXX_PSC6
  40. #else
  41. #error CONFIG_PS2SERIAL must be in 1 ... 6
  42. #endif
  43. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  44. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  45. #if CONFIG_PS2SERIAL == 1
  46. #define COM_BASE (CONFIG_SYS_CCSRBAR+0x4500)
  47. #elif CONFIG_PS2SERIAL == 2
  48. #define COM_BASE (CONFIG_SYS_CCSRBAR+0x4600)
  49. #else
  50. #error CONFIG_PS2SERIAL must be in 1 ... 2
  51. #endif
  52. #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */
  53. static int ps2ser_getc_hw(void);
  54. static void ps2ser_interrupt(void *dev_id);
  55. extern struct serial_state rs_table[]; /* in serial.c */
  56. #if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && \
  57. !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8548) && \
  58. !defined(CONFIG_MPC8555)
  59. static struct serial_state *state;
  60. #endif
  61. static u_char ps2buf[PS2BUF_SIZE];
  62. static atomic_t ps2buf_cnt;
  63. static int ps2buf_in_idx;
  64. static int ps2buf_out_idx;
  65. #ifdef CONFIG_MPC5xxx
  66. int ps2ser_init(void)
  67. {
  68. volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
  69. unsigned long baseclk;
  70. int div;
  71. /* reset PSC */
  72. psc->command = PSC_SEL_MODE_REG_1;
  73. /* select clock sources */
  74. #if defined(CONFIG_MGT5100)
  75. psc->psc_clock_select = 0xdd00;
  76. baseclk = (CONFIG_SYS_MPC5XXX_CLKIN + 16) / 32;
  77. #elif defined(CONFIG_MPC5200)
  78. psc->psc_clock_select = 0;
  79. baseclk = (gd->ipb_clk + 16) / 32;
  80. #endif
  81. /* switch to UART mode */
  82. psc->sicr = 0;
  83. /* configure parity, bit length and so on */
  84. #if defined(CONFIG_MGT5100)
  85. psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE;
  86. #elif defined(CONFIG_MPC5200)
  87. psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
  88. #endif
  89. psc->mode = PSC_MODE_ONE_STOP;
  90. /* set up UART divisor */
  91. div = (baseclk + (PS2SER_BAUD/2)) / PS2SER_BAUD;
  92. psc->ctur = (div >> 8) & 0xff;
  93. psc->ctlr = div & 0xff;
  94. /* disable all interrupts */
  95. psc->psc_imr = 0;
  96. /* reset and enable Rx/Tx */
  97. psc->command = PSC_RST_RX;
  98. psc->command = PSC_RST_TX;
  99. psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
  100. return (0);
  101. }
  102. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  103. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  104. int ps2ser_init(void)
  105. {
  106. NS16550_t com_port = (NS16550_t)COM_BASE;
  107. com_port->ier = 0x00;
  108. com_port->lcr = LCR_BKSE | LCR_8N1;
  109. com_port->dll = (CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) & 0xff;
  110. com_port->dlm = ((CONFIG_SYS_NS16550_CLK / 16 / PS2SER_BAUD) >> 8) & 0xff;
  111. com_port->lcr = LCR_8N1;
  112. com_port->mcr = (MCR_DTR | MCR_RTS);
  113. com_port->fcr = (FCR_FIFO_EN | FCR_RXSR | FCR_TXSR);
  114. return (0);
  115. }
  116. #else /* !CONFIG_MPC5xxx && !CONFIG_MPC8540 / other */
  117. static inline unsigned int ps2ser_in(int offset)
  118. {
  119. return readb((unsigned long) state->iomem_base + offset);
  120. }
  121. static inline void ps2ser_out(int offset, int value)
  122. {
  123. writeb(value, (unsigned long) state->iomem_base + offset);
  124. }
  125. int ps2ser_init(void)
  126. {
  127. int quot;
  128. unsigned cval;
  129. state = rs_table + CONFIG_PS2SERIAL;
  130. quot = state->baud_base / PS2SER_BAUD;
  131. cval = 0x3; /* 8N1 - 8 data bits, no parity bits, 1 stop bit */
  132. /* Set speed, enable interrupts, enable FIFO
  133. */
  134. ps2ser_out(UART_LCR, cval | UART_LCR_DLAB);
  135. ps2ser_out(UART_DLL, quot & 0xff);
  136. ps2ser_out(UART_DLM, quot >> 8);
  137. ps2ser_out(UART_LCR, cval);
  138. ps2ser_out(UART_IER, UART_IER_RDI);
  139. ps2ser_out(UART_MCR, UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS);
  140. ps2ser_out(UART_FCR,
  141. UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
  142. /* If we read 0xff from the LSR, there is no UART here
  143. */
  144. if (ps2ser_in(UART_LSR) == 0xff) {
  145. printf ("ps2ser.c: no UART found\n");
  146. return -1;
  147. }
  148. irq_install_handler(state->irq, ps2ser_interrupt, NULL);
  149. return 0;
  150. }
  151. #endif /* CONFIG_MPC5xxx / CONFIG_MPC8540 / other */
  152. void ps2ser_putc(int chr)
  153. {
  154. #ifdef CONFIG_MPC5xxx
  155. volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
  156. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  157. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  158. NS16550_t com_port = (NS16550_t)COM_BASE;
  159. #endif
  160. #ifdef DEBUG
  161. printf(">>>> 0x%02x\n", chr);
  162. #endif
  163. #ifdef CONFIG_MPC5xxx
  164. while (!(psc->psc_status & PSC_SR_TXRDY));
  165. psc->psc_buffer_8 = chr;
  166. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  167. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  168. while ((com_port->lsr & LSR_THRE) == 0);
  169. com_port->thr = chr;
  170. #else
  171. while (!(ps2ser_in(UART_LSR) & UART_LSR_THRE));
  172. ps2ser_out(UART_TX, chr);
  173. #endif
  174. }
  175. static int ps2ser_getc_hw(void)
  176. {
  177. #ifdef CONFIG_MPC5xxx
  178. volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
  179. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  180. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  181. NS16550_t com_port = (NS16550_t)COM_BASE;
  182. #endif
  183. int res = -1;
  184. #ifdef CONFIG_MPC5xxx
  185. if (psc->psc_status & PSC_SR_RXRDY) {
  186. res = (psc->psc_buffer_8);
  187. }
  188. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  189. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  190. if (com_port->lsr & LSR_DR) {
  191. res = com_port->rbr;
  192. }
  193. #else
  194. if (ps2ser_in(UART_LSR) & UART_LSR_DR) {
  195. res = (ps2ser_in(UART_RX));
  196. }
  197. #endif
  198. return res;
  199. }
  200. int ps2ser_getc(void)
  201. {
  202. volatile int chr;
  203. int flags;
  204. #ifdef DEBUG
  205. printf("<< ");
  206. #endif
  207. flags = disable_interrupts();
  208. do {
  209. if (atomic_read(&ps2buf_cnt) != 0) {
  210. chr = ps2buf[ps2buf_out_idx++];
  211. ps2buf_out_idx &= (PS2BUF_SIZE - 1);
  212. atomic_dec(&ps2buf_cnt);
  213. } else {
  214. chr = ps2ser_getc_hw();
  215. }
  216. }
  217. while (chr < 0);
  218. if (flags) enable_interrupts();
  219. #ifdef DEBUG
  220. printf("0x%02x\n", chr);
  221. #endif
  222. return chr;
  223. }
  224. int ps2ser_check(void)
  225. {
  226. int flags;
  227. flags = disable_interrupts();
  228. ps2ser_interrupt(NULL);
  229. if (flags) enable_interrupts();
  230. return atomic_read(&ps2buf_cnt);
  231. }
  232. static void ps2ser_interrupt(void *dev_id)
  233. {
  234. #ifdef CONFIG_MPC5xxx
  235. volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
  236. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  237. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  238. NS16550_t com_port = (NS16550_t)COM_BASE;
  239. #endif
  240. int chr;
  241. int status;
  242. do {
  243. chr = ps2ser_getc_hw();
  244. #ifdef CONFIG_MPC5xxx
  245. status = psc->psc_status;
  246. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  247. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  248. status = com_port->lsr;
  249. #else
  250. status = ps2ser_in(UART_IIR);
  251. #endif
  252. if (chr < 0) continue;
  253. if (atomic_read(&ps2buf_cnt) < PS2BUF_SIZE) {
  254. ps2buf[ps2buf_in_idx++] = chr;
  255. ps2buf_in_idx &= (PS2BUF_SIZE - 1);
  256. atomic_inc(&ps2buf_cnt);
  257. } else {
  258. printf ("ps2ser.c: buffer overflow\n");
  259. }
  260. #ifdef CONFIG_MPC5xxx
  261. } while (status & PSC_SR_RXRDY);
  262. #elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \
  263. defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555)
  264. } while (status & LSR_DR);
  265. #else
  266. } while (status & UART_IIR_RDI);
  267. #endif
  268. if (atomic_read(&ps2buf_cnt)) {
  269. ps2mult_callback(atomic_read(&ps2buf_cnt));
  270. }
  271. }