serial_scc.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*
  2. * (C) Copyright 2000
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. *
  23. * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
  24. */
  25. /*
  26. * Minimal serial functions needed to use one of the SCC ports
  27. * as serial console interface.
  28. */
  29. #include <common.h>
  30. #include <mpc8260.h>
  31. #include <asm/cpm_8260.h>
  32. #if defined(CONFIG_CONS_ON_SCC)
  33. #if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
  34. #define SCC_INDEX 0
  35. #define PROFF_SCC PROFF_SCC1
  36. #define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  37. CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  38. #define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  39. #define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  40. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  41. #elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
  42. #define SCC_INDEX 1
  43. #define PROFF_SCC PROFF_SCC2
  44. #define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
  45. CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  46. #define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  47. #define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
  48. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
  49. #elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
  50. #define SCC_INDEX 2
  51. #define PROFF_SCC PROFF_SCC3
  52. #define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
  53. CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  54. #define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  55. #define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
  56. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
  57. #elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
  58. #define SCC_INDEX 3
  59. #define PROFF_SCC PROFF_SCC4
  60. #define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
  61. CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  62. #define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  63. #define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
  64. #define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
  65. #else
  66. #error "console not correctly defined"
  67. #endif
  68. int serial_init (void)
  69. {
  70. volatile immap_t *im = (immap_t *)CFG_IMMR;
  71. volatile scc_t *sp;
  72. volatile scc_uart_t *up;
  73. volatile cbd_t *tbdf, *rbdf;
  74. volatile cpm8260_t *cp = &(im->im_cpm);
  75. uint dpaddr;
  76. /* initialize pointers to SCC */
  77. sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
  78. up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  79. /* Disable transmitter/receiver.
  80. */
  81. sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  82. /* put the SCC channel into NMSI (non multiplexd serial interface)
  83. * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  84. */
  85. im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
  86. /* Set up the baud rate generator.
  87. */
  88. serial_setbrg ();
  89. /* Allocate space for two buffer descriptors in the DP ram.
  90. * damm: allocating space after the two buffers for rx/tx data
  91. */
  92. dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  93. /* Set the physical address of the host memory buffers in
  94. * the buffer descriptors.
  95. */
  96. rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  97. rbdf->cbd_bufaddr = (uint) (rbdf+2);
  98. rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
  99. tbdf = rbdf + 1;
  100. tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  101. tbdf->cbd_sc = BD_SC_WRAP;
  102. /* Set up the uart parameters in the parameter ram.
  103. */
  104. up->scc_genscc.scc_rbase = dpaddr;
  105. up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  106. up->scc_genscc.scc_rfcr = CPMFCR_EB;
  107. up->scc_genscc.scc_tfcr = CPMFCR_EB;
  108. up->scc_genscc.scc_mrblr = 1;
  109. up->scc_maxidl = 0;
  110. up->scc_brkcr = 1;
  111. up->scc_parec = 0;
  112. up->scc_frmec = 0;
  113. up->scc_nosec = 0;
  114. up->scc_brkec = 0;
  115. up->scc_uaddr1 = 0;
  116. up->scc_uaddr2 = 0;
  117. up->scc_toseq = 0;
  118. up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
  119. up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
  120. up->scc_rccm = 0xc0ff;
  121. /* Mask all interrupts and remove anything pending.
  122. */
  123. sp->scc_sccm = 0;
  124. sp->scc_scce = 0xffff;
  125. /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
  126. */
  127. sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
  128. sp->scc_gsmrl = \
  129. SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
  130. /* Set CTS flow control, 1 stop bit, 8 bit character length,
  131. * normal async UART mode, no parity
  132. */
  133. sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
  134. /* execute the "Init Rx and Tx params" CP command.
  135. */
  136. while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  137. ;
  138. cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
  139. 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  140. while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  141. ;
  142. /* Enable transmitter/receiver.
  143. */
  144. sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  145. return (0);
  146. }
  147. void
  148. serial_setbrg (void)
  149. {
  150. DECLARE_GLOBAL_DATA_PTR;
  151. #if defined(CONFIG_CONS_USE_EXTC)
  152. m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
  153. CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
  154. #else
  155. m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
  156. #endif
  157. }
  158. void
  159. serial_putc(const char c)
  160. {
  161. volatile scc_uart_t *up;
  162. volatile cbd_t *tbdf;
  163. volatile immap_t *im;
  164. if (c == '\n')
  165. serial_putc ('\r');
  166. im = (immap_t *)CFG_IMMR;
  167. up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  168. tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
  169. /* Wait for last character to go.
  170. */
  171. while (tbdf->cbd_sc & BD_SC_READY)
  172. ;
  173. /* Load the character into the transmit buffer.
  174. */
  175. *(volatile char *)tbdf->cbd_bufaddr = c;
  176. tbdf->cbd_datlen = 1;
  177. tbdf->cbd_sc |= BD_SC_READY;
  178. }
  179. void
  180. serial_puts (const char *s)
  181. {
  182. while (*s) {
  183. serial_putc (*s++);
  184. }
  185. }
  186. int
  187. serial_getc(void)
  188. {
  189. volatile cbd_t *rbdf;
  190. volatile scc_uart_t *up;
  191. volatile immap_t *im;
  192. unsigned char c;
  193. im = (immap_t *)CFG_IMMR;
  194. up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  195. rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  196. /* Wait for character to show up.
  197. */
  198. while (rbdf->cbd_sc & BD_SC_EMPTY)
  199. ;
  200. /* Grab the char and clear the buffer again.
  201. */
  202. c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
  203. rbdf->cbd_sc |= BD_SC_EMPTY;
  204. return (c);
  205. }
  206. int
  207. serial_tstc()
  208. {
  209. volatile cbd_t *rbdf;
  210. volatile scc_uart_t *up;
  211. volatile immap_t *im;
  212. im = (immap_t *)CFG_IMMR;
  213. up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
  214. rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  215. return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
  216. }
  217. #endif /* CONFIG_CONS_ON_SCC */
  218. #if defined(CONFIG_KGDB_ON_SCC)
  219. #if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
  220. #error Whoops! serial console and kgdb are on the same scc serial port
  221. #endif
  222. #if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */
  223. #define KGDB_SCC_INDEX 0
  224. #define KGDB_PROFF_SCC PROFF_SCC1
  225. #define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
  226. CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
  227. #define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
  228. #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
  229. #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
  230. #elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */
  231. #define KGDB_SCC_INDEX 1
  232. #define KGDB_PROFF_SCC PROFF_SCC2
  233. #define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
  234. CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
  235. #define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
  236. #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
  237. #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
  238. #elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */
  239. #define KGDB_SCC_INDEX 2
  240. #define KGDB_PROFF_SCC PROFF_SCC3
  241. #define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
  242. CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
  243. #define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
  244. #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
  245. #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
  246. #elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */
  247. #define KGDB_SCC_INDEX 3
  248. #define KGDB_PROFF_SCC PROFF_SCC4
  249. #define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
  250. CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
  251. #define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
  252. #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
  253. #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
  254. #else
  255. #error "kgdb serial port not correctly defined"
  256. #endif
  257. void
  258. kgdb_serial_init (void)
  259. {
  260. volatile immap_t *im = (immap_t *)CFG_IMMR;
  261. volatile scc_t *sp;
  262. volatile scc_uart_t *up;
  263. volatile cbd_t *tbdf, *rbdf;
  264. volatile cpm8260_t *cp = &(im->im_cpm);
  265. uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
  266. char *s, *e;
  267. if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
  268. ulong rate = simple_strtoul(s, &e, 10);
  269. if (e > s && *e == '\0')
  270. speed = rate;
  271. }
  272. /* initialize pointers to SCC */
  273. sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
  274. up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  275. /* Disable transmitter/receiver.
  276. */
  277. sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
  278. /* put the SCC channel into NMSI (non multiplexd serial interface)
  279. * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
  280. */
  281. im->im_cpmux.cmx_scr = \
  282. (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
  283. /* Set up the baud rate generator.
  284. */
  285. #if defined(CONFIG_KGDB_USE_EXTC)
  286. m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
  287. CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
  288. #else
  289. m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
  290. #endif
  291. /* Allocate space for two buffer descriptors in the DP ram.
  292. * damm: allocating space after the two buffers for rx/tx data
  293. */
  294. dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
  295. /* Set the physical address of the host memory buffers in
  296. * the buffer descriptors.
  297. */
  298. rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
  299. rbdf->cbd_bufaddr = (uint) (rbdf+2);
  300. rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
  301. tbdf = rbdf + 1;
  302. tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
  303. tbdf->cbd_sc = BD_SC_WRAP;
  304. /* Set up the uart parameters in the parameter ram.
  305. */
  306. up->scc_genscc.scc_rbase = dpaddr;
  307. up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
  308. up->scc_genscc.scc_rfcr = CPMFCR_EB;
  309. up->scc_genscc.scc_tfcr = CPMFCR_EB;
  310. up->scc_genscc.scc_mrblr = 1;
  311. up->scc_maxidl = 0;
  312. up->scc_brkcr = 1;
  313. up->scc_parec = 0;
  314. up->scc_frmec = 0;
  315. up->scc_nosec = 0;
  316. up->scc_brkec = 0;
  317. up->scc_uaddr1 = 0;
  318. up->scc_uaddr2 = 0;
  319. up->scc_toseq = 0;
  320. up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
  321. up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
  322. up->scc_rccm = 0xc0ff;
  323. /* Mask all interrupts and remove anything pending.
  324. */
  325. sp->scc_sccm = 0;
  326. sp->scc_scce = 0xffff;
  327. /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
  328. */
  329. sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
  330. sp->scc_gsmrl = \
  331. SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
  332. /* Set CTS flow control, 1 stop bit, 8 bit character length,
  333. * normal async UART mode, no parity
  334. */
  335. sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
  336. /* execute the "Init Rx and Tx params" CP command.
  337. */
  338. while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  339. ;
  340. cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
  341. 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
  342. while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
  343. ;
  344. /* Enable transmitter/receiver.
  345. */
  346. sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
  347. printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
  348. }
  349. void
  350. putDebugChar(const char c)
  351. {
  352. volatile scc_uart_t *up;
  353. volatile cbd_t *tbdf;
  354. volatile immap_t *im;
  355. if (c == '\n')
  356. putDebugChar ('\r');
  357. im = (immap_t *)CFG_IMMR;
  358. up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  359. tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
  360. /* Wait for last character to go.
  361. */
  362. while (tbdf->cbd_sc & BD_SC_READY)
  363. ;
  364. /* Load the character into the transmit buffer.
  365. */
  366. *(volatile char *)tbdf->cbd_bufaddr = c;
  367. tbdf->cbd_datlen = 1;
  368. tbdf->cbd_sc |= BD_SC_READY;
  369. }
  370. void
  371. putDebugStr (const char *s)
  372. {
  373. while (*s) {
  374. putDebugChar (*s++);
  375. }
  376. }
  377. int
  378. getDebugChar(void)
  379. {
  380. volatile cbd_t *rbdf;
  381. volatile scc_uart_t *up;
  382. volatile immap_t *im;
  383. unsigned char c;
  384. im = (immap_t *)CFG_IMMR;
  385. up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
  386. rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
  387. /* Wait for character to show up.
  388. */
  389. while (rbdf->cbd_sc & BD_SC_EMPTY)
  390. ;
  391. /* Grab the char and clear the buffer again.
  392. */
  393. c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
  394. rbdf->cbd_sc |= BD_SC_EMPTY;
  395. return (c);
  396. }
  397. void
  398. kgdb_interruptible(int yes)
  399. {
  400. return;
  401. }
  402. #endif /* CONFIG_KGDB_ON_SCC */