serial_scc.c 6.6 KB

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