]>
Commit | Line | Data |
---|---|---|
4a9cbbe8 WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Wolfgang Denk, DENX Software Engineering, [email protected]. | |
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 [email protected], 19-Oct-00. | |
24 | */ | |
25 | ||
26 | /* | |
27 | * Minimal serial functions needed to use one of the SCC ports | |
28 | * as serial console interface. | |
29 | */ | |
30 | ||
31 | #include <common.h> | |
32 | #include <mpc8260.h> | |
33 | #include <asm/cpm_8260.h> | |
34 | ||
d87080b7 WD |
35 | DECLARE_GLOBAL_DATA_PTR; |
36 | ||
4a9cbbe8 WD |
37 | #if defined(CONFIG_CONS_ON_SCC) |
38 | ||
39 | #if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */ | |
40 | ||
41 | #define SCC_INDEX 0 | |
42 | #define PROFF_SCC PROFF_SCC1 | |
43 | #define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\ | |
44 | CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK) | |
45 | #define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1) | |
46 | #define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE | |
47 | #define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK | |
48 | ||
49 | #elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */ | |
50 | ||
51 | #define SCC_INDEX 1 | |
52 | #define PROFF_SCC PROFF_SCC2 | |
53 | #define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\ | |
54 | CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK) | |
55 | #define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2) | |
56 | #define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE | |
57 | #define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK | |
58 | ||
59 | #elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */ | |
60 | ||
61 | #define SCC_INDEX 2 | |
62 | #define PROFF_SCC PROFF_SCC3 | |
63 | #define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\ | |
64 | CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK) | |
65 | #define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3) | |
66 | #define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE | |
67 | #define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK | |
68 | ||
69 | #elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */ | |
70 | ||
71 | #define SCC_INDEX 3 | |
72 | #define PROFF_SCC PROFF_SCC4 | |
73 | #define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\ | |
74 | CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK) | |
75 | #define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4) | |
76 | #define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE | |
77 | #define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK | |
78 | ||
79 | #else | |
80 | ||
81 | #error "console not correctly defined" | |
82 | ||
83 | #endif | |
84 | ||
85 | int serial_init (void) | |
86 | { | |
8bde7f77 | 87 | volatile immap_t *im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
88 | volatile scc_t *sp; |
89 | volatile scc_uart_t *up; | |
90 | volatile cbd_t *tbdf, *rbdf; | |
91 | volatile cpm8260_t *cp = &(im->im_cpm); | |
92 | uint dpaddr; | |
93 | ||
94 | /* initialize pointers to SCC */ | |
95 | ||
96 | sp = (scc_t *) &(im->im_scc[SCC_INDEX]); | |
97 | up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC]; | |
98 | ||
99 | /* Disable transmitter/receiver. | |
100 | */ | |
101 | sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); | |
102 | ||
103 | /* put the SCC channel into NMSI (non multiplexd serial interface) | |
104 | * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15). | |
105 | */ | |
106 | im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE; | |
107 | ||
108 | /* Set up the baud rate generator. | |
109 | */ | |
110 | serial_setbrg (); | |
111 | ||
112 | /* Allocate space for two buffer descriptors in the DP ram. | |
113 | * damm: allocating space after the two buffers for rx/tx data | |
114 | */ | |
115 | ||
116 | dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16); | |
117 | ||
118 | /* Set the physical address of the host memory buffers in | |
119 | * the buffer descriptors. | |
120 | */ | |
121 | rbdf = (cbd_t *)&im->im_dprambase[dpaddr]; | |
122 | rbdf->cbd_bufaddr = (uint) (rbdf+2); | |
123 | rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP; | |
124 | tbdf = rbdf + 1; | |
125 | tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; | |
126 | tbdf->cbd_sc = BD_SC_WRAP; | |
127 | ||
128 | /* Set up the uart parameters in the parameter ram. | |
129 | */ | |
130 | up->scc_genscc.scc_rbase = dpaddr; | |
131 | up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t); | |
132 | up->scc_genscc.scc_rfcr = CPMFCR_EB; | |
133 | up->scc_genscc.scc_tfcr = CPMFCR_EB; | |
134 | up->scc_genscc.scc_mrblr = 1; | |
135 | up->scc_maxidl = 0; | |
136 | up->scc_brkcr = 1; | |
137 | up->scc_parec = 0; | |
138 | up->scc_frmec = 0; | |
139 | up->scc_nosec = 0; | |
140 | up->scc_brkec = 0; | |
141 | up->scc_uaddr1 = 0; | |
142 | up->scc_uaddr2 = 0; | |
143 | up->scc_toseq = 0; | |
144 | up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000; | |
145 | up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000; | |
146 | up->scc_rccm = 0xc0ff; | |
147 | ||
148 | /* Mask all interrupts and remove anything pending. | |
149 | */ | |
150 | sp->scc_sccm = 0; | |
151 | sp->scc_scce = 0xffff; | |
152 | ||
153 | /* Set 8 bit FIFO, 16 bit oversampling and UART mode. | |
154 | */ | |
155 | sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */ | |
156 | sp->scc_gsmrl = \ | |
157 | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART; | |
158 | ||
159 | /* Set CTS flow control, 1 stop bit, 8 bit character length, | |
160 | * normal async UART mode, no parity | |
161 | */ | |
162 | sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL; | |
163 | ||
164 | /* execute the "Init Rx and Tx params" CP command. | |
165 | */ | |
166 | ||
167 | while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ | |
168 | ; | |
169 | ||
170 | cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK, | |
171 | 0, CPM_CR_INIT_TRX) | CPM_CR_FLG; | |
172 | ||
173 | while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ | |
174 | ; | |
175 | ||
176 | /* Enable transmitter/receiver. | |
177 | */ | |
178 | sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT; | |
179 | ||
180 | return (0); | |
181 | } | |
182 | ||
183 | void | |
184 | serial_setbrg (void) | |
185 | { | |
4a9cbbe8 WD |
186 | #if defined(CONFIG_CONS_USE_EXTC) |
187 | m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate, | |
188 | CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL); | |
189 | #else | |
190 | m8260_cpm_setbrg(SCC_INDEX, gd->baudrate); | |
191 | #endif | |
192 | } | |
193 | ||
194 | void | |
195 | serial_putc(const char c) | |
196 | { | |
197 | volatile scc_uart_t *up; | |
198 | volatile cbd_t *tbdf; | |
8bde7f77 | 199 | volatile immap_t *im; |
4a9cbbe8 WD |
200 | |
201 | if (c == '\n') | |
202 | serial_putc ('\r'); | |
203 | ||
8bde7f77 | 204 | im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
205 | up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC]; |
206 | tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase]; | |
207 | ||
208 | /* Wait for last character to go. | |
209 | */ | |
210 | while (tbdf->cbd_sc & BD_SC_READY) | |
211 | ; | |
212 | ||
213 | /* Load the character into the transmit buffer. | |
214 | */ | |
215 | *(volatile char *)tbdf->cbd_bufaddr = c; | |
216 | tbdf->cbd_datlen = 1; | |
217 | tbdf->cbd_sc |= BD_SC_READY; | |
218 | } | |
219 | ||
220 | void | |
221 | serial_puts (const char *s) | |
222 | { | |
223 | while (*s) { | |
224 | serial_putc (*s++); | |
225 | } | |
226 | } | |
227 | ||
228 | int | |
229 | serial_getc(void) | |
230 | { | |
231 | volatile cbd_t *rbdf; | |
232 | volatile scc_uart_t *up; | |
8bde7f77 | 233 | volatile immap_t *im; |
4a9cbbe8 WD |
234 | unsigned char c; |
235 | ||
8bde7f77 | 236 | im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
237 | up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC]; |
238 | rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase]; | |
239 | ||
240 | /* Wait for character to show up. | |
241 | */ | |
242 | while (rbdf->cbd_sc & BD_SC_EMPTY) | |
243 | ; | |
244 | ||
245 | /* Grab the char and clear the buffer again. | |
246 | */ | |
247 | c = *(volatile unsigned char *)rbdf->cbd_bufaddr; | |
248 | rbdf->cbd_sc |= BD_SC_EMPTY; | |
249 | ||
250 | return (c); | |
251 | } | |
252 | ||
253 | int | |
254 | serial_tstc() | |
255 | { | |
256 | volatile cbd_t *rbdf; | |
257 | volatile scc_uart_t *up; | |
8bde7f77 | 258 | volatile immap_t *im; |
4a9cbbe8 | 259 | |
8bde7f77 | 260 | im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
261 | up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC]; |
262 | rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase]; | |
263 | ||
264 | return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0); | |
265 | } | |
266 | ||
267 | #endif /* CONFIG_CONS_ON_SCC */ | |
268 | ||
269 | #if defined(CONFIG_KGDB_ON_SCC) | |
270 | ||
271 | #if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX | |
272 | #error Whoops! serial console and kgdb are on the same scc serial port | |
273 | #endif | |
274 | ||
275 | #if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */ | |
276 | ||
277 | #define KGDB_SCC_INDEX 0 | |
278 | #define KGDB_PROFF_SCC PROFF_SCC1 | |
279 | #define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\ | |
280 | CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK) | |
281 | #define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1) | |
282 | #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE | |
283 | #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK | |
284 | ||
285 | #elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */ | |
286 | ||
287 | #define KGDB_SCC_INDEX 1 | |
288 | #define KGDB_PROFF_SCC PROFF_SCC2 | |
289 | #define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\ | |
290 | CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK) | |
291 | #define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2) | |
292 | #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE | |
293 | #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK | |
294 | ||
295 | #elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */ | |
296 | ||
297 | #define KGDB_SCC_INDEX 2 | |
298 | #define KGDB_PROFF_SCC PROFF_SCC3 | |
299 | #define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\ | |
300 | CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK) | |
301 | #define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3) | |
302 | #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE | |
303 | #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK | |
304 | ||
305 | #elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */ | |
306 | ||
307 | #define KGDB_SCC_INDEX 3 | |
308 | #define KGDB_PROFF_SCC PROFF_SCC4 | |
309 | #define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\ | |
310 | CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK) | |
311 | #define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4) | |
312 | #define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE | |
313 | #define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK | |
314 | ||
315 | #else | |
316 | ||
317 | #error "kgdb serial port not correctly defined" | |
318 | ||
319 | #endif | |
320 | ||
321 | void | |
322 | kgdb_serial_init (void) | |
323 | { | |
8bde7f77 | 324 | volatile immap_t *im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
325 | volatile scc_t *sp; |
326 | volatile scc_uart_t *up; | |
327 | volatile cbd_t *tbdf, *rbdf; | |
328 | volatile cpm8260_t *cp = &(im->im_cpm); | |
329 | uint dpaddr, speed = CONFIG_KGDB_BAUDRATE; | |
330 | char *s, *e; | |
331 | ||
332 | if ((s = getenv("kgdbrate")) != NULL && *s != '\0') { | |
333 | ulong rate = simple_strtoul(s, &e, 10); | |
334 | if (e > s && *e == '\0') | |
335 | speed = rate; | |
336 | } | |
337 | ||
338 | /* initialize pointers to SCC */ | |
339 | ||
340 | sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]); | |
341 | up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC]; | |
342 | ||
343 | /* Disable transmitter/receiver. | |
344 | */ | |
345 | sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); | |
346 | ||
347 | /* put the SCC channel into NMSI (non multiplexd serial interface) | |
348 | * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15). | |
349 | */ | |
350 | im->im_cpmux.cmx_scr = \ | |
351 | (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE; | |
352 | ||
353 | /* Set up the baud rate generator. | |
354 | */ | |
355 | #if defined(CONFIG_KGDB_USE_EXTC) | |
356 | m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed, | |
357 | CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL); | |
358 | #else | |
359 | m8260_cpm_setbrg(KGDB_SCC_INDEX, speed); | |
360 | #endif | |
361 | ||
362 | /* Allocate space for two buffer descriptors in the DP ram. | |
363 | * damm: allocating space after the two buffers for rx/tx data | |
364 | */ | |
365 | ||
366 | dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16); | |
367 | ||
368 | /* Set the physical address of the host memory buffers in | |
369 | * the buffer descriptors. | |
370 | */ | |
371 | rbdf = (cbd_t *)&im->im_dprambase[dpaddr]; | |
372 | rbdf->cbd_bufaddr = (uint) (rbdf+2); | |
373 | rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP; | |
374 | tbdf = rbdf + 1; | |
375 | tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1; | |
376 | tbdf->cbd_sc = BD_SC_WRAP; | |
377 | ||
378 | /* Set up the uart parameters in the parameter ram. | |
379 | */ | |
380 | up->scc_genscc.scc_rbase = dpaddr; | |
381 | up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t); | |
382 | up->scc_genscc.scc_rfcr = CPMFCR_EB; | |
383 | up->scc_genscc.scc_tfcr = CPMFCR_EB; | |
384 | up->scc_genscc.scc_mrblr = 1; | |
385 | up->scc_maxidl = 0; | |
386 | up->scc_brkcr = 1; | |
387 | up->scc_parec = 0; | |
388 | up->scc_frmec = 0; | |
389 | up->scc_nosec = 0; | |
390 | up->scc_brkec = 0; | |
391 | up->scc_uaddr1 = 0; | |
392 | up->scc_uaddr2 = 0; | |
393 | up->scc_toseq = 0; | |
394 | up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000; | |
395 | up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000; | |
396 | up->scc_rccm = 0xc0ff; | |
397 | ||
398 | /* Mask all interrupts and remove anything pending. | |
399 | */ | |
400 | sp->scc_sccm = 0; | |
401 | sp->scc_scce = 0xffff; | |
402 | ||
403 | /* Set 8 bit FIFO, 16 bit oversampling and UART mode. | |
404 | */ | |
405 | sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */ | |
406 | sp->scc_gsmrl = \ | |
407 | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART; | |
408 | ||
409 | /* Set CTS flow control, 1 stop bit, 8 bit character length, | |
410 | * normal async UART mode, no parity | |
411 | */ | |
412 | sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL; | |
413 | ||
414 | /* execute the "Init Rx and Tx params" CP command. | |
415 | */ | |
416 | ||
417 | while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ | |
418 | ; | |
419 | ||
420 | cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK, | |
421 | 0, CPM_CR_INIT_TRX) | CPM_CR_FLG; | |
422 | ||
423 | while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */ | |
424 | ; | |
425 | ||
426 | /* Enable transmitter/receiver. | |
427 | */ | |
428 | sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT; | |
429 | ||
430 | printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed); | |
431 | } | |
432 | ||
433 | void | |
434 | putDebugChar(const char c) | |
435 | { | |
436 | volatile scc_uart_t *up; | |
437 | volatile cbd_t *tbdf; | |
8bde7f77 | 438 | volatile immap_t *im; |
4a9cbbe8 WD |
439 | |
440 | if (c == '\n') | |
441 | putDebugChar ('\r'); | |
442 | ||
8bde7f77 | 443 | im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
444 | up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC]; |
445 | tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase]; | |
446 | ||
447 | /* Wait for last character to go. | |
448 | */ | |
449 | while (tbdf->cbd_sc & BD_SC_READY) | |
450 | ; | |
451 | ||
452 | /* Load the character into the transmit buffer. | |
453 | */ | |
454 | *(volatile char *)tbdf->cbd_bufaddr = c; | |
455 | tbdf->cbd_datlen = 1; | |
456 | tbdf->cbd_sc |= BD_SC_READY; | |
457 | } | |
458 | ||
459 | void | |
460 | putDebugStr (const char *s) | |
461 | { | |
462 | while (*s) { | |
463 | putDebugChar (*s++); | |
464 | } | |
465 | } | |
466 | ||
467 | int | |
468 | getDebugChar(void) | |
469 | { | |
470 | volatile cbd_t *rbdf; | |
471 | volatile scc_uart_t *up; | |
8bde7f77 | 472 | volatile immap_t *im; |
4a9cbbe8 WD |
473 | unsigned char c; |
474 | ||
8bde7f77 | 475 | im = (immap_t *)CFG_IMMR; |
4a9cbbe8 WD |
476 | up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC]; |
477 | rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase]; | |
478 | ||
479 | /* Wait for character to show up. | |
480 | */ | |
481 | while (rbdf->cbd_sc & BD_SC_EMPTY) | |
482 | ; | |
483 | ||
484 | /* Grab the char and clear the buffer again. | |
485 | */ | |
486 | c = *(volatile unsigned char *)rbdf->cbd_bufaddr; | |
487 | rbdf->cbd_sc |= BD_SC_EMPTY; | |
488 | ||
489 | return (c); | |
490 | } | |
491 | ||
492 | void | |
493 | kgdb_interruptible(int yes) | |
494 | { | |
495 | return; | |
496 | } | |
497 | ||
498 | #endif /* CONFIG_KGDB_ON_SCC */ |