]> git.sur5r.net Git - u-boot/blob - cpu/mpc8260/serial_smc.c
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[u-boot] / cpu / mpc8260 / serial_smc.c
1 /*
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
37 DECLARE_GLOBAL_DATA_PTR;
38
39 #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 */
68 static 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
77 int serial_init (void)
78 {
79         volatile immap_t *im = (immap_t *)CFG_IMMR;
80         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
172 void
173 serial_setbrg (void)
174 {
175 #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
183 void
184 serial_putc(const char c)
185 {
186         volatile cbd_t          *tbdf;
187         volatile char           *buf;
188         volatile smc_uart_t     *up;
189         volatile immap_t        *im = (immap_t *)CFG_IMMR;
190
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
209 void
210 serial_puts (const char *s)
211 {
212         while (*s) {
213                 serial_putc (*s++);
214         }
215 }
216
217 int
218 serial_getc(void)
219 {
220         volatile cbd_t          *rbdf;
221         volatile unsigned char  *buf;
222         volatile smc_uart_t     *up;
223         volatile immap_t        *im = (immap_t *)CFG_IMMR;
224         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
241 int
242 serial_tstc()
243 {
244         volatile cbd_t          *rbdf;
245         volatile smc_uart_t     *up;
246         volatile immap_t        *im = (immap_t *)CFG_IMMR;
247
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
289 void
290 kgdb_serial_init (void)
291 {
292         volatile immap_t *im = (immap_t *)CFG_IMMR;
293         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)
363         m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
364                 CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
365 #else
366         m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
367 #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
398 void
399 putDebugChar(const char c)
400 {
401         volatile cbd_t          *tbdf;
402         volatile char           *buf;
403         volatile smc_uart_t     *up;
404         volatile immap_t        *im = (immap_t *)CFG_IMMR;
405
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
424 void
425 putDebugStr (const char *s)
426 {
427         while (*s) {
428                 putDebugChar (*s++);
429         }
430 }
431
432 int
433 getDebugChar(void)
434 {
435         volatile cbd_t          *rbdf;
436         volatile unsigned char  *buf;
437         volatile smc_uart_t     *up;
438         volatile immap_t        *im = (immap_t *)CFG_IMMR;
439         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
456 void
457 kgdb_interruptible(int yes)
458 {
459         return;
460 }
461
462 #endif  /* CONFIG_KGDB_ON_SMC */