serial_scc.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * (C) Copyright 2003 Motorola Inc.
  3. * Xianghua Xiao (X.Xiao@motorola.com)
  4. * Modified based on 8260 for 8560.
  5. *
  6. * (C) Copyright 2000
  7. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  8. *
  9. * SPDX-License-Identifier: GPL-2.0+
  10. *
  11. * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
  12. */
  13. /*
  14. * Minimal serial functions needed to use one of the SCC ports
  15. * as serial console interface.
  16. */
  17. #include <common.h>
  18. #include <asm/cpm_85xx.h>
  19. #include <serial.h>
  20. #include <linux/compiler.h>
  21. DECLARE_GLOBAL_DATA_PTR;
  22. #if defined(CONFIG_CONS_ON_SCC)
  23. #if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
  24. #define SCC_INDEX 0
  25. #define PROFF_SCC PROFF_SCC1
  26. #define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  27. CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  28. #define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  29. #define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  30. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  31. #elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
  32. #define SCC_INDEX 1
  33. #define PROFF_SCC PROFF_SCC2
  34. #define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
  35. CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  36. #define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  37. #define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
  38. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
  39. #elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
  40. #define SCC_INDEX 2
  41. #define PROFF_SCC PROFF_SCC3
  42. #define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
  43. CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  44. #define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  45. #define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
  46. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
  47. #elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
  48. #define SCC_INDEX 3
  49. #define PROFF_SCC PROFF_SCC4
  50. #define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
  51. CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  52. #define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  53. #define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
  54. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
  55. #else
  56. #error "console not correctly defined"
  57. #endif
  58. static int mpc85xx_serial_init(void)
  59. {
  60. volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
  61. volatile ccsr_cpm_scc_t *sp;
  62. volatile scc_uart_t *up;
  63. volatile cbd_t *tbdf, *rbdf;
  64. volatile ccsr_cpm_cp_t *cp = &(cpm->im_cpm_cp);
  65. uint dpaddr;
  66. /* initialize pointers to SCC */
  67. sp = (ccsr_cpm_scc_t *) &(cpm->im_cpm_scc[SCC_INDEX]);
  68. up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
  69. /* Disable transmitter/receiver.
  70. */
  71. sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  72. /* put the SCC channel into NMSI (non multiplexd serial interface)
  73. * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  74. */
  75. cpm->im_cpm_mux.cmxscr = \
  76. (cpm->im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
  77. /* Set up the baud rate generator.
  78. */
  79. serial_setbrg ();
  80. /* Allocate space for two buffer descriptors in the DP ram.
  81. * damm: allocating space after the two buffers for rx/tx data
  82. */
  83. dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  84. /* Set the physical address of the host memory buffers in
  85. * the buffer descriptors.
  86. */
  87. rbdf = (cbd_t *)&(cpm->im_dprambase[dpaddr]);
  88. rbdf->cbd_bufaddr = (uint) (rbdf+2);
  89. rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
  90. tbdf = rbdf + 1;
  91. tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  92. tbdf->cbd_sc = BD_SC_WRAP;
  93. /* Set up the uart parameters in the parameter ram.
  94. */
  95. up->scc_genscc.scc_rbase = dpaddr;
  96. up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  97. up->scc_genscc.scc_rfcr = CPMFCR_EB;
  98. up->scc_genscc.scc_tfcr = CPMFCR_EB;
  99. up->scc_genscc.scc_mrblr = 1;
  100. up->scc_maxidl = 0;
  101. up->scc_brkcr = 1;
  102. up->scc_parec = 0;
  103. up->scc_frmec = 0;
  104. up->scc_nosec = 0;
  105. up->scc_brkec = 0;
  106. up->scc_uaddr1 = 0;
  107. up->scc_uaddr2 = 0;
  108. up->scc_toseq = 0;
  109. up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
  110. up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
  111. up->scc_rccm = 0xc0ff;
  112. /* Mask all interrupts and remove anything pending.
  113. */
  114. sp->sccm = 0;
  115. sp->scce = 0xffff;
  116. /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
  117. */
  118. sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
  119. sp->gsmrl = \
  120. SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
  121. /* Set CTS no flow control, 1 stop bit, 8 bit character length,
  122. * normal async UART mode, no parity
  123. */
  124. sp->psmr = SCU_PSMR_CL;
  125. /* execute the "Init Rx and Tx params" CP command.
  126. */
  127. while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
  128. ;
  129. cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
  130. 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  131. while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
  132. ;
  133. /* Enable transmitter/receiver.
  134. */
  135. sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  136. return (0);
  137. }
  138. static void mpc85xx_serial_setbrg(void)
  139. {
  140. #if defined(CONFIG_CONS_USE_EXTC)
  141. m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
  142. CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
  143. #else
  144. m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
  145. #endif
  146. }
  147. static void mpc85xx_serial_putc(const char c)
  148. {
  149. volatile scc_uart_t *up;
  150. volatile cbd_t *tbdf;
  151. volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
  152. if (c == '\n')
  153. serial_putc ('\r');
  154. up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
  155. tbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_tbase]);
  156. /* Wait for last character to go.
  157. */
  158. while (tbdf->cbd_sc & BD_SC_READY)
  159. ;
  160. /* Load the character into the transmit buffer.
  161. */
  162. *(volatile char *)tbdf->cbd_bufaddr = c;
  163. tbdf->cbd_datlen = 1;
  164. tbdf->cbd_sc |= BD_SC_READY;
  165. }
  166. static int mpc85xx_serial_getc(void)
  167. {
  168. volatile cbd_t *rbdf;
  169. volatile scc_uart_t *up;
  170. volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
  171. unsigned char c;
  172. up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
  173. rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
  174. /* Wait for character to show up.
  175. */
  176. while (rbdf->cbd_sc & BD_SC_EMPTY)
  177. ;
  178. /* Grab the char and clear the buffer again.
  179. */
  180. c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
  181. rbdf->cbd_sc |= BD_SC_EMPTY;
  182. return (c);
  183. }
  184. static int mpc85xx_serial_tstc(void)
  185. {
  186. volatile cbd_t *rbdf;
  187. volatile scc_uart_t *up;
  188. volatile ccsr_cpm_t *cpm = (ccsr_cpm_t *)CONFIG_SYS_MPC85xx_CPM_ADDR;
  189. up = (scc_uart_t *)&(cpm->im_dprambase[PROFF_SCC]);
  190. rbdf = (cbd_t *)&(cpm->im_dprambase[up->scc_genscc.scc_rbase]);
  191. return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
  192. }
  193. static struct serial_device mpc85xx_serial_drv = {
  194. .name = "mpc85xx_serial",
  195. .start = mpc85xx_serial_init,
  196. .stop = NULL,
  197. .setbrg = mpc85xx_serial_setbrg,
  198. .putc = mpc85xx_serial_putc,
  199. .puts = default_serial_puts,
  200. .getc = mpc85xx_serial_getc,
  201. .tstc = mpc85xx_serial_tstc,
  202. };
  203. void mpc85xx_serial_initialize(void)
  204. {
  205. serial_register(&mpc85xx_serial_drv);
  206. }
  207. __weak struct serial_device *default_serial_console(void)
  208. {
  209. return &mpc85xx_serial_drv;
  210. }
  211. #endif /* CONFIG_CONS_ON_SCC */