blob: f3dffeb11993d81c70aeccb0199b841a75d3613a [file] [log] [blame]
wdenk4a9cbbe2002-08-27 09:48:53 +00001/*
2 * (C) Copyright 2000, 2001, 2002
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, with
24 * changes based on the file arch/ppc/mbxboot/m8260_tty.c from the
25 * Linux/PPC sources (m8260_tty.c had no copyright info in it).
26 */
27
28/*
29 * Minimal serial functions needed to use one of the SMC ports
30 * as serial console interface.
31 */
32
33#include <common.h>
34#include <mpc8260.h>
35#include <asm/cpm_8260.h>
36
Wolfgang Denkd87080b2006-03-31 18:32:53 +020037DECLARE_GLOBAL_DATA_PTR;
38
wdenk4a9cbbe2002-08-27 09:48:53 +000039#if defined(CONFIG_CONS_ON_SMC)
40
41#if CONFIG_CONS_INDEX == 1 /* Console on SMC1 */
42
43#define SMC_INDEX 0
44#define PROFF_SMC_BASE PROFF_SMC1_BASE
45#define PROFF_SMC PROFF_SMC1
46#define CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
47#define CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
48#define CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
49#define CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
50
51#elif CONFIG_CONS_INDEX == 2 /* Console on SMC2 */
52
53#define SMC_INDEX 1
54#define PROFF_SMC_BASE PROFF_SMC2_BASE
55#define PROFF_SMC PROFF_SMC2
56#define CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
57#define CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
58#define CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
59#define CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
60
61#else
62
63#error "console not correctly defined"
64
65#endif
66
67/* map rs_table index to baud rate generator index */
68static unsigned char brg_map[] = {
69 6, /* BRG7 for SMC1 */
70 7, /* BRG8 for SMC2 */
71 0, /* BRG1 for SCC1 */
72 1, /* BRG1 for SCC2 */
73 2, /* BRG1 for SCC3 */
74 3, /* BRG1 for SCC4 */
75};
76
77int serial_init (void)
78{
wdenk8bde7f72003-06-27 21:31:46 +000079 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +000080 volatile smc_t *sp;
81 volatile smc_uart_t *up;
82 volatile cbd_t *tbdf, *rbdf;
83 volatile cpm8260_t *cp = &(im->im_cpm);
84 uint dpaddr;
85
86 /* initialize pointers to SMC */
87
88 sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
89 *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC;
90 up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
91
92 /* Disable transmitter/receiver.
93 */
94 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
95
96 /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
97
98 /* Allocate space for two buffer descriptors in the DP ram.
99 * damm: allocating space after the two buffers for rx/tx data
100 */
101
102 dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
103
104 /* Set the physical address of the host memory buffers in
105 * the buffer descriptors.
106 */
107 rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
108 rbdf->cbd_bufaddr = (uint) (rbdf+2);
109 rbdf->cbd_sc = 0;
110 tbdf = rbdf + 1;
111 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
112 tbdf->cbd_sc = 0;
113
114 /* Set up the uart parameters in the parameter ram.
115 */
116 up->smc_rbase = dpaddr;
117 up->smc_tbase = dpaddr+sizeof(cbd_t);
118 up->smc_rfcr = CPMFCR_EB;
119 up->smc_tfcr = CPMFCR_EB;
120 up->smc_brklen = 0;
121 up->smc_brkec = 0;
122 up->smc_brkcr = 0;
123
124 /* Set UART mode, 8 bit, no parity, one stop.
125 * Enable receive and transmit.
126 */
127 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
128
129 /* Mask all interrupts and remove anything pending.
130 */
131 sp->smc_smcm = 0;
132 sp->smc_smce = 0xff;
133
134 /* put the SMC channel into NMSI (non multiplexd serial interface)
135 * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
136 */
137 im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
138
139 /* Set up the baud rate generator.
140 */
141 serial_setbrg ();
142
143 /* Make the first buffer the only buffer.
144 */
145 tbdf->cbd_sc |= BD_SC_WRAP;
146 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
147
148 /* Single character receive.
149 */
150 up->smc_mrblr = 1;
151 up->smc_maxidl = 0;
152
153 /* Initialize Tx/Rx parameters.
154 */
155
156 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
157 ;
158
159 cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
160 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
161
162 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
163 ;
164
165 /* Enable transmitter/receiver.
166 */
167 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
168
169 return (0);
170}
171
172void
173serial_setbrg (void)
174{
wdenk4a9cbbe2002-08-27 09:48:53 +0000175#if defined(CONFIG_CONS_USE_EXTC)
176 m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
177 CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
178#else
179 m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
180#endif
181}
182
183void
184serial_putc(const char c)
185{
186 volatile cbd_t *tbdf;
187 volatile char *buf;
188 volatile smc_uart_t *up;
wdenk8bde7f72003-06-27 21:31:46 +0000189 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000190
191 if (c == '\n')
192 serial_putc ('\r');
193
194 up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
195
196 tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
197
198 /* Wait for last character to go.
199 */
200 buf = (char *)tbdf->cbd_bufaddr;
201 while (tbdf->cbd_sc & BD_SC_READY)
202 ;
203
204 *buf = c;
205 tbdf->cbd_datlen = 1;
206 tbdf->cbd_sc |= BD_SC_READY;
207}
208
209void
210serial_puts (const char *s)
211{
212 while (*s) {
213 serial_putc (*s++);
214 }
215}
216
217int
218serial_getc(void)
219{
220 volatile cbd_t *rbdf;
221 volatile unsigned char *buf;
222 volatile smc_uart_t *up;
wdenk8bde7f72003-06-27 21:31:46 +0000223 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000224 unsigned char c;
225
226 up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
227
228 rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
229
230 /* Wait for character to show up.
231 */
232 buf = (unsigned char *)rbdf->cbd_bufaddr;
233 while (rbdf->cbd_sc & BD_SC_EMPTY)
234 ;
235 c = *buf;
236 rbdf->cbd_sc |= BD_SC_EMPTY;
237
238 return(c);
239}
240
241int
242serial_tstc()
243{
244 volatile cbd_t *rbdf;
245 volatile smc_uart_t *up;
wdenk8bde7f72003-06-27 21:31:46 +0000246 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000247
248 up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
249
250 rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
251
252 return(!(rbdf->cbd_sc & BD_SC_EMPTY));
253}
254
255#endif /* CONFIG_CONS_ON_SMC */
256
257#if defined(CONFIG_KGDB_ON_SMC)
258
259#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
260#error Whoops! serial console and kgdb are on the same smc serial port
261#endif
262
263#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SMC1 */
264
265#define KGDB_SMC_INDEX 0
266#define KGDB_PROFF_SMC_BASE PROFF_SMC1_BASE
267#define KGDB_PROFF_SMC PROFF_SMC1
268#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
269#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
270#define KGDB_CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
271#define KGDB_CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
272
273#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SMC2 */
274
275#define KGDB_SMC_INDEX 1
276#define KGDB_PROFF_SMC_BASE PROFF_SMC2_BASE
277#define KGDB_PROFF_SMC PROFF_SMC2
278#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
279#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
280#define KGDB_CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
281#define KGDB_CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
282
283#else
284
285#error "console not correctly defined"
286
287#endif
288
289void
290kgdb_serial_init (void)
291{
wdenk8bde7f72003-06-27 21:31:46 +0000292 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000293 volatile smc_t *sp;
294 volatile smc_uart_t *up;
295 volatile cbd_t *tbdf, *rbdf;
296 volatile cpm8260_t *cp = &(im->im_cpm);
297 uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
298 char *s, *e;
299
300 if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
301 ulong rate = simple_strtoul(s, &e, 10);
302 if (e > s && *e == '\0')
303 speed = rate;
304 }
305
306 /* initialize pointers to SMC */
307
308 sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
309 *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC;
310 up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
311
312 /* Disable transmitter/receiver.
313 */
314 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
315
316 /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
317
318 /* Allocate space for two buffer descriptors in the DP ram.
319 * damm: allocating space after the two buffers for rx/tx data
320 */
321
322 dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
323
324 /* Set the physical address of the host memory buffers in
325 * the buffer descriptors.
326 */
327 rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
328 rbdf->cbd_bufaddr = (uint) (rbdf+2);
329 rbdf->cbd_sc = 0;
330 tbdf = rbdf + 1;
331 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
332 tbdf->cbd_sc = 0;
333
334 /* Set up the uart parameters in the parameter ram.
335 */
336 up->smc_rbase = dpaddr;
337 up->smc_tbase = dpaddr+sizeof(cbd_t);
338 up->smc_rfcr = CPMFCR_EB;
339 up->smc_tfcr = CPMFCR_EB;
340 up->smc_brklen = 0;
341 up->smc_brkec = 0;
342 up->smc_brkcr = 0;
343
344 /* Set UART mode, 8 bit, no parity, one stop.
345 * Enable receive and transmit.
346 */
347 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
348
349 /* Mask all interrupts and remove anything pending.
350 */
351 sp->smc_smcm = 0;
352 sp->smc_smce = 0xff;
353
354 /* put the SMC channel into NMSI (non multiplexd serial interface)
355 * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
356 */
357 im->im_cpmux.cmx_smr =
358 (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
359
360 /* Set up the baud rate generator.
361 */
362#if defined(CONFIG_KGDB_USE_EXTC)
Wolfgang Denk56337962005-08-06 01:21:19 +0200363 m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
wdenk4a9cbbe2002-08-27 09:48:53 +0000364 CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
365#else
Wolfgang Denk56337962005-08-06 01:21:19 +0200366 m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
wdenk4a9cbbe2002-08-27 09:48:53 +0000367#endif
368
369 /* Make the first buffer the only buffer.
370 */
371 tbdf->cbd_sc |= BD_SC_WRAP;
372 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
373
374 /* Single character receive.
375 */
376 up->smc_mrblr = 1;
377 up->smc_maxidl = 0;
378
379 /* Initialize Tx/Rx parameters.
380 */
381
382 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
383 ;
384
385 cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
386 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
387
388 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
389 ;
390
391 /* Enable transmitter/receiver.
392 */
393 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
394
395 printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
396}
397
398void
399putDebugChar(const char c)
400{
401 volatile cbd_t *tbdf;
402 volatile char *buf;
403 volatile smc_uart_t *up;
wdenk8bde7f72003-06-27 21:31:46 +0000404 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000405
406 if (c == '\n')
407 putDebugChar ('\r');
408
409 up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
410
411 tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
412
413 /* Wait for last character to go.
414 */
415 buf = (char *)tbdf->cbd_bufaddr;
416 while (tbdf->cbd_sc & BD_SC_READY)
417 ;
418
419 *buf = c;
420 tbdf->cbd_datlen = 1;
421 tbdf->cbd_sc |= BD_SC_READY;
422}
423
424void
425putDebugStr (const char *s)
426{
427 while (*s) {
428 putDebugChar (*s++);
429 }
430}
431
432int
433getDebugChar(void)
434{
435 volatile cbd_t *rbdf;
436 volatile unsigned char *buf;
437 volatile smc_uart_t *up;
wdenk8bde7f72003-06-27 21:31:46 +0000438 volatile immap_t *im = (immap_t *)CFG_IMMR;
wdenk4a9cbbe2002-08-27 09:48:53 +0000439 unsigned char c;
440
441 up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
442
443 rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
444
445 /* Wait for character to show up.
446 */
447 buf = (unsigned char *)rbdf->cbd_bufaddr;
448 while (rbdf->cbd_sc & BD_SC_EMPTY)
449 ;
450 c = *buf;
451 rbdf->cbd_sc |= BD_SC_EMPTY;
452
453 return(c);
454}
455
456void
457kgdb_interruptible(int yes)
458{
459 return;
460}
461
462#endif /* CONFIG_KGDB_ON_SMC */