blob: b35509ab399cc2aee4674d5a2bebbde3b573ca11 [file] [log] [blame]
wdenk682011f2003-06-03 23:54:09 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenk682011f2003-06-03 23:54:09 +00006 */
7
8/* Modified by Udi Finkelstein
9 *
10 * This file includes communication routines for SMC1 that can run even if
11 * SMC2 have already been initialized.
12 */
13
14#include <common.h>
15#include <watchdog.h>
16#include <commproc.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020017#include <stdio_dev.h>
wdenk682011f2003-06-03 23:54:09 +000018#include <lcd.h>
19
Wolfgang Denkd87080b2006-03-31 18:32:53 +020020DECLARE_GLOBAL_DATA_PTR;
21
wdenk682011f2003-06-03 23:54:09 +000022#define SMC_INDEX 0
23#define PROFF_SMC PROFF_SMC1
24#define CPM_CR_CH_SMC CPM_CR_CH_SMC1
25
26#define RBC823_KBD_BAUDRATE 38400
27#define CPM_KEYBOARD_BASE 0x1000
28/*
29 * Minimal serial functions needed to use one of the SMC ports
30 * as serial console interface.
31 */
32
33void smc1_setbrg (void)
34{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020035 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
wdenk682011f2003-06-03 23:54:09 +000036 volatile cpm8xx_t *cp = &(im->im_cpm);
37
38 /* Set up the baud rate generator.
39 * See 8xx_io/commproc.c for details.
40 *
41 * Wire BRG2 to SMC1, BRG1 to SMC2
42 */
43
44 cp->cp_simode = 0x00001000;
45
46 cp->cp_brgc2 =
47 (((gd->cpu_clk / 16 / RBC823_KBD_BAUDRATE)-1) << 1) | CPM_BRG_EN;
48}
49
50int smc1_init (void)
51{
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020052 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
wdenk682011f2003-06-03 23:54:09 +000053 volatile smc_t *sp;
54 volatile smc_uart_t *up;
55 volatile cbd_t *tbdf, *rbdf;
56 volatile cpm8xx_t *cp = &(im->im_cpm);
57 uint dpaddr;
58
59 /* initialize pointers to SMC */
60
61 sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
62 up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
63
64 /* Disable transmitter/receiver.
65 */
66 sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
67
68 /* Enable SDMA.
69 */
70 im->im_siu_conf.sc_sdcr = 1;
71
72 /* clear error conditions */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020073#ifdef CONFIG_SYS_SDSR
74 im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR;
wdenk682011f2003-06-03 23:54:09 +000075#else
76 im->im_sdma.sdma_sdsr = 0x83;
77#endif
78
79 /* clear SDMA interrupt mask */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020080#ifdef CONFIG_SYS_SDMR
81 im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR;
wdenk682011f2003-06-03 23:54:09 +000082#else
83 im->im_sdma.sdma_sdmr = 0x00;
84#endif
85
86 /* Use Port B for SMC1 instead of other functions.
87 */
88 cp->cp_pbpar |= 0x000000c0;
89 cp->cp_pbdir &= ~0x000000c0;
90 cp->cp_pbodr &= ~0x000000c0;
91
92 /* Set the physical address of the host memory buffers in
93 * the buffer descriptors.
94 */
95
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020096#ifdef CONFIG_SYS_ALLOC_DPRAM
wdenk682011f2003-06-03 23:54:09 +000097 dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
98#else
99 dpaddr = CPM_KEYBOARD_BASE ;
100#endif
101
102 /* Allocate space for two buffer descriptors in the DP ram.
103 * For now, this address seems OK, but it may have to
104 * change with newer versions of the firmware.
105 * damm: allocating space after the two buffers for rx/tx data
106 */
107
108 rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
109 rbdf->cbd_bufaddr = (uint) (rbdf+2);
110 rbdf->cbd_sc = 0;
111 tbdf = rbdf + 1;
112 tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
113 tbdf->cbd_sc = 0;
114
115 /* Set up the uart parameters in the parameter ram.
116 */
117 up->smc_rbase = dpaddr;
118 up->smc_tbase = dpaddr+sizeof(cbd_t);
119 up->smc_rfcr = SMC_EB;
120 up->smc_tfcr = SMC_EB;
121
122 /* Set UART mode, 8 bit, no parity, one stop.
123 * Enable receive and transmit.
124 */
125 sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
126
127 /* Mask all interrupts and remove anything pending.
128 */
129 sp->smc_smcm = 0;
130 sp->smc_smce = 0xff;
131
132 /* Set up the baud rate generator.
133 */
134 smc1_setbrg ();
135
136 /* Make the first buffer the only buffer.
137 */
138 tbdf->cbd_sc |= BD_SC_WRAP;
139 rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
140
141 /* Single character receive.
142 */
143 up->smc_mrblr = 1;
144 up->smc_maxidl = 0;
145
146 /* Initialize Tx/Rx parameters.
147 */
148
149 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
150 ;
151
152 cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
153
154 while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
155 ;
156
157 /* Enable transmitter/receiver.
158 */
159 sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
160
161 return (0);
162}
163
164void smc1_putc(const char c)
165{
166 volatile cbd_t *tbdf;
167 volatile char *buf;
168 volatile smc_uart_t *up;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200169 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
wdenk682011f2003-06-03 23:54:09 +0000170 volatile cpm8xx_t *cpmp = &(im->im_cpm);
171
172 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
173
174 tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
175
176 /* Wait for last character to go.
177 */
178
179 buf = (char *)tbdf->cbd_bufaddr;
180
181 *buf = c;
182 tbdf->cbd_datlen = 1;
183 tbdf->cbd_sc |= BD_SC_READY;
184 __asm__("eieio");
185
186 while (tbdf->cbd_sc & BD_SC_READY) {
187 WATCHDOG_RESET ();
188 __asm__("eieio");
189 }
190}
191
192int smc1_getc(void)
193{
194 volatile cbd_t *rbdf;
195 volatile unsigned char *buf;
196 volatile smc_uart_t *up;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200197 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
wdenk682011f2003-06-03 23:54:09 +0000198 volatile cpm8xx_t *cpmp = &(im->im_cpm);
199 unsigned char c;
200
201 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
202
203 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
204
205 /* Wait for character to show up.
206 */
207 buf = (unsigned char *)rbdf->cbd_bufaddr;
208
209 while (rbdf->cbd_sc & BD_SC_EMPTY)
210 WATCHDOG_RESET ();
211
212 c = *buf;
213 rbdf->cbd_sc |= BD_SC_EMPTY;
214
215 return(c);
216}
217
218int smc1_tstc(void)
219{
220 volatile cbd_t *rbdf;
221 volatile smc_uart_t *up;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200222 volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
wdenk682011f2003-06-03 23:54:09 +0000223 volatile cpm8xx_t *cpmp = &(im->im_cpm);
224
225 up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
226
227 rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
228
229 return(!(rbdf->cbd_sc & BD_SC_EMPTY));
230}
231
232/* search for keyboard and register it if found */
233int drv_keyboard_init(void)
234{
235 int error = 0;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200236 struct stdio_dev kbd_dev;
wdenk682011f2003-06-03 23:54:09 +0000237
238 if (0) {
239 /* register the keyboard */
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200240 memset (&kbd_dev, 0, sizeof(struct stdio_dev));
wdenk682011f2003-06-03 23:54:09 +0000241 strcpy(kbd_dev.name, "kbd");
242 kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
243 kbd_dev.putc = NULL;
244 kbd_dev.puts = NULL;
245 kbd_dev.getc = smc1_getc;
246 kbd_dev.tstc = smc1_tstc;
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +0200247 error = stdio_register (&kbd_dev);
wdenk682011f2003-06-03 23:54:09 +0000248 } else {
249 lcd_is_enabled = 0;
250 lcd_disable();
251 }
252 return error;
253}