m8260_tty.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /* Minimal serial functions needed to send messages out the serial
  2. * port on SMC1.
  3. */
  4. #include <linux/types.h>
  5. #include <asm/mpc8260.h>
  6. #include <asm/cpm2.h>
  7. #include <asm/immap_cpm2.h>
  8. uint no_print;
  9. extern char *params[];
  10. extern int nparams;
  11. static u_char cons_hold[128], *sgptr;
  12. static int cons_hold_cnt;
  13. /* If defined, enables serial console. The value (1 through 4)
  14. * should designate which SCC is used, but this isn't complete. Only
  15. * SCC1 is known to work at this time.
  16. * We're only linked if SERIAL_CPM_CONSOLE=y, so we only need to test
  17. * SERIAL_CPM_SCC1.
  18. */
  19. #ifdef CONFIG_SERIAL_CPM_SCC1
  20. #define SCC_CONSOLE 1
  21. #endif
  22. unsigned long
  23. serial_init(int ignored, bd_t *bd)
  24. {
  25. #ifdef SCC_CONSOLE
  26. volatile scc_t *sccp;
  27. volatile scc_uart_t *sup;
  28. #else
  29. volatile smc_t *sp;
  30. volatile smc_uart_t *up;
  31. #endif
  32. volatile cbd_t *tbdf, *rbdf;
  33. volatile cpm2_map_t *ip;
  34. volatile iop_cpm2_t *io;
  35. volatile cpm_cpm2_t *cp;
  36. uint dpaddr, memaddr;
  37. ip = (cpm2_map_t *)CPM_MAP_ADDR;
  38. cp = &ip->im_cpm;
  39. io = &ip->im_ioport;
  40. /* Perform a reset.
  41. */
  42. cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
  43. /* Wait for it.
  44. */
  45. while (cp->cp_cpcr & CPM_CR_FLG);
  46. #ifdef CONFIG_ADS8260
  47. /* Enable the RS-232 transceivers.
  48. */
  49. *(volatile uint *)(BCSR_ADDR + 4) &=
  50. ~(BCSR1_RS232_EN1 | BCSR1_RS232_EN2);
  51. #endif
  52. #ifdef SCC_CONSOLE
  53. sccp = (scc_t *)&(ip->im_scc[SCC_CONSOLE-1]);
  54. sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
  55. sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
  56. sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  57. /* Use Port D for SCC1 instead of other functions.
  58. */
  59. io->iop_ppard |= 0x00000003;
  60. io->iop_psord &= ~0x00000001; /* Rx */
  61. io->iop_psord |= 0x00000002; /* Tx */
  62. io->iop_pdird &= ~0x00000001; /* Rx */
  63. io->iop_pdird |= 0x00000002; /* Tx */
  64. #else
  65. sp = (smc_t*)&(ip->im_smc[0]);
  66. *(ushort *)(&ip->im_dprambase[PROFF_SMC1_BASE]) = PROFF_SMC1;
  67. up = (smc_uart_t *)&ip->im_dprambase[PROFF_SMC1];
  68. /* Disable transmitter/receiver.
  69. */
  70. sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
  71. /* Use Port D for SMC1 instead of other functions.
  72. */
  73. io->iop_ppard |= 0x00c00000;
  74. io->iop_pdird |= 0x00400000;
  75. io->iop_pdird &= ~0x00800000;
  76. io->iop_psord &= ~0x00c00000;
  77. #endif
  78. /* Allocate space for two buffer descriptors in the DP ram.
  79. * For now, this address seems OK, but it may have to
  80. * change with newer versions of the firmware.
  81. */
  82. dpaddr = 0x0800;
  83. /* Grab a few bytes from the top of memory.
  84. */
  85. memaddr = (bd->bi_memsize - 256) & ~15;
  86. /* Set the physical address of the host memory buffers in
  87. * the buffer descriptors.
  88. */
  89. rbdf = (cbd_t *)&ip->im_dprambase[dpaddr];
  90. rbdf->cbd_bufaddr = memaddr;
  91. rbdf->cbd_sc = 0;
  92. tbdf = rbdf + 1;
  93. tbdf->cbd_bufaddr = memaddr+128;
  94. tbdf->cbd_sc = 0;
  95. /* Set up the uart parameters in the parameter ram.
  96. */
  97. #ifdef SCC_CONSOLE
  98. sup->scc_genscc.scc_rbase = dpaddr;
  99. sup->scc_genscc.scc_tbase = dpaddr + sizeof(cbd_t);
  100. /* Set up the uart parameters in the
  101. * parameter ram.
  102. */
  103. sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
  104. sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
  105. sup->scc_genscc.scc_mrblr = 128;
  106. sup->scc_maxidl = 8;
  107. sup->scc_brkcr = 1;
  108. sup->scc_parec = 0;
  109. sup->scc_frmec = 0;
  110. sup->scc_nosec = 0;
  111. sup->scc_brkec = 0;
  112. sup->scc_uaddr1 = 0;
  113. sup->scc_uaddr2 = 0;
  114. sup->scc_toseq = 0;
  115. sup->scc_char1 = 0x8000;
  116. sup->scc_char2 = 0x8000;
  117. sup->scc_char3 = 0x8000;
  118. sup->scc_char4 = 0x8000;
  119. sup->scc_char5 = 0x8000;
  120. sup->scc_char6 = 0x8000;
  121. sup->scc_char7 = 0x8000;
  122. sup->scc_char8 = 0x8000;
  123. sup->scc_rccm = 0xc0ff;
  124. /* Send the CPM an initialize command.
  125. */
  126. cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
  127. CPM_CR_INIT_TRX) | CPM_CR_FLG;
  128. while (cp->cp_cpcr & CPM_CR_FLG);
  129. /* Set UART mode, 8 bit, no parity, one stop.
  130. * Enable receive and transmit.
  131. */
  132. sccp->scc_gsmrh = 0;
  133. sccp->scc_gsmrl =
  134. (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
  135. /* Disable all interrupts and clear all pending
  136. * events.
  137. */
  138. sccp->scc_sccm = 0;
  139. sccp->scc_scce = 0xffff;
  140. sccp->scc_dsr = 0x7e7e;
  141. sccp->scc_psmr = 0x3000;
  142. /* Wire BRG1 to SCC1. The console driver will take care of
  143. * others.
  144. */
  145. ip->im_cpmux.cmx_scr = 0;
  146. #else
  147. up->smc_rbase = dpaddr;
  148. up->smc_tbase = dpaddr+sizeof(cbd_t);
  149. up->smc_rfcr = CPMFCR_EB;
  150. up->smc_tfcr = CPMFCR_EB;
  151. up->smc_brklen = 0;
  152. up->smc_brkec = 0;
  153. up->smc_brkcr = 0;
  154. up->smc_mrblr = 128;
  155. up->smc_maxidl = 8;
  156. /* Set UART mode, 8 bit, no parity, one stop.
  157. * Enable receive and transmit.
  158. */
  159. sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
  160. /* Mask all interrupts and remove anything pending.
  161. */
  162. sp->smc_smcm = 0;
  163. sp->smc_smce = 0xff;
  164. /* Set up the baud rate generator.
  165. */
  166. ip->im_cpmux.cmx_smr = 0;
  167. #endif
  168. /* The baud rate divisor needs to be coordinated with clk_8260().
  169. */
  170. ip->im_brgc1 =
  171. (((bd->bi_brgfreq/16) / bd->bi_baudrate) << 1) |
  172. CPM_BRG_EN;
  173. /* Make the first buffer the only buffer.
  174. */
  175. tbdf->cbd_sc |= BD_SC_WRAP;
  176. rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
  177. /* Initialize Tx/Rx parameters.
  178. */
  179. #ifdef SCC_CONSOLE
  180. sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  181. #else
  182. cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  183. while (cp->cp_cpcr & CPM_CR_FLG);
  184. /* Enable transmitter/receiver.
  185. */
  186. sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
  187. #endif
  188. /* This is ignored.
  189. */
  190. return 0;
  191. }
  192. int
  193. serial_readbuf(u_char *cbuf)
  194. {
  195. volatile cbd_t *rbdf;
  196. volatile char *buf;
  197. #ifdef SCC_CONSOLE
  198. volatile scc_uart_t *sup;
  199. #else
  200. volatile smc_uart_t *up;
  201. #endif
  202. volatile cpm2_map_t *ip;
  203. int i, nc;
  204. ip = (cpm2_map_t *)CPM_MAP_ADDR;
  205. #ifdef SCC_CONSOLE
  206. sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
  207. rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
  208. #else
  209. up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
  210. rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
  211. #endif
  212. /* Wait for character to show up.
  213. */
  214. buf = (char *)rbdf->cbd_bufaddr;
  215. while (rbdf->cbd_sc & BD_SC_EMPTY);
  216. nc = rbdf->cbd_datlen;
  217. for (i=0; i<nc; i++)
  218. *cbuf++ = *buf++;
  219. rbdf->cbd_sc |= BD_SC_EMPTY;
  220. return(nc);
  221. }
  222. void
  223. serial_putc(void *ignored, const char c)
  224. {
  225. volatile cbd_t *tbdf;
  226. volatile char *buf;
  227. #ifdef SCC_CONSOLE
  228. volatile scc_uart_t *sup;
  229. #else
  230. volatile smc_uart_t *up;
  231. #endif
  232. volatile cpm2_map_t *ip;
  233. ip = (cpm2_map_t *)CPM_MAP_ADDR;
  234. #ifdef SCC_CONSOLE
  235. sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
  236. tbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_tbase];
  237. #else
  238. up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
  239. tbdf = (cbd_t *)&ip->im_dprambase[up->smc_tbase];
  240. #endif
  241. /* Wait for last character to go.
  242. */
  243. buf = (char *)tbdf->cbd_bufaddr;
  244. while (tbdf->cbd_sc & BD_SC_READY);
  245. *buf = c;
  246. tbdf->cbd_datlen = 1;
  247. tbdf->cbd_sc |= BD_SC_READY;
  248. }
  249. char
  250. serial_getc(void *ignored)
  251. {
  252. char c;
  253. if (cons_hold_cnt <= 0) {
  254. cons_hold_cnt = serial_readbuf(cons_hold);
  255. sgptr = cons_hold;
  256. }
  257. c = *sgptr++;
  258. cons_hold_cnt--;
  259. return(c);
  260. }
  261. int
  262. serial_tstc(void *ignored)
  263. {
  264. volatile cbd_t *rbdf;
  265. #ifdef SCC_CONSOLE
  266. volatile scc_uart_t *sup;
  267. #else
  268. volatile smc_uart_t *up;
  269. #endif
  270. volatile cpm2_map_t *ip;
  271. ip = (cpm2_map_t *)CPM_MAP_ADDR;
  272. #ifdef SCC_CONSOLE
  273. sup = (scc_uart_t *)&ip->im_dprambase[PROFF_SCC1 + ((SCC_CONSOLE-1) << 8)];
  274. rbdf = (cbd_t *)&ip->im_dprambase[sup->scc_genscc.scc_rbase];
  275. #else
  276. up = (smc_uart_t *)&(ip->im_dprambase[PROFF_SMC1]);
  277. rbdf = (cbd_t *)&ip->im_dprambase[up->smc_rbase];
  278. #endif
  279. return(!(rbdf->cbd_sc & BD_SC_EMPTY));
  280. }