]>
Commit | Line | Data |
---|---|---|
682011ff WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
682011ff WD |
6 | */ |
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> | |
52cb4d4f | 17 | #include <stdio_dev.h> |
682011ff WD |
18 | #include <lcd.h> |
19 | ||
d87080b7 WD |
20 | DECLARE_GLOBAL_DATA_PTR; |
21 | ||
682011ff WD |
22 | #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 | ||
33 | void smc1_setbrg (void) | |
34 | { | |
6d0f6bcf | 35 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
682011ff WD |
36 | 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 | ||
50 | int smc1_init (void) | |
51 | { | |
6d0f6bcf | 52 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
682011ff WD |
53 | 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 */ | |
6d0f6bcf JCPV |
73 | #ifdef CONFIG_SYS_SDSR |
74 | im->im_sdma.sdma_sdsr = CONFIG_SYS_SDSR; | |
682011ff WD |
75 | #else |
76 | im->im_sdma.sdma_sdsr = 0x83; | |
77 | #endif | |
78 | ||
79 | /* clear SDMA interrupt mask */ | |
6d0f6bcf JCPV |
80 | #ifdef CONFIG_SYS_SDMR |
81 | im->im_sdma.sdma_sdmr = CONFIG_SYS_SDMR; | |
682011ff WD |
82 | #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 | ||
6d0f6bcf | 96 | #ifdef CONFIG_SYS_ALLOC_DPRAM |
682011ff WD |
97 | 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 | ||
164 | void smc1_putc(const char c) | |
165 | { | |
166 | volatile cbd_t *tbdf; | |
167 | volatile char *buf; | |
168 | volatile smc_uart_t *up; | |
6d0f6bcf | 169 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
682011ff WD |
170 | 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 | ||
192 | int smc1_getc(void) | |
193 | { | |
194 | volatile cbd_t *rbdf; | |
195 | volatile unsigned char *buf; | |
196 | volatile smc_uart_t *up; | |
6d0f6bcf | 197 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
682011ff WD |
198 | 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 | ||
218 | int smc1_tstc(void) | |
219 | { | |
220 | volatile cbd_t *rbdf; | |
221 | volatile smc_uart_t *up; | |
6d0f6bcf | 222 | volatile immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
682011ff WD |
223 | 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 */ | |
233 | int drv_keyboard_init(void) | |
234 | { | |
235 | int error = 0; | |
52cb4d4f | 236 | struct stdio_dev kbd_dev; |
682011ff WD |
237 | |
238 | if (0) { | |
239 | /* register the keyboard */ | |
52cb4d4f | 240 | memset (&kbd_dev, 0, sizeof(struct stdio_dev)); |
682011ff WD |
241 | 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; | |
52cb4d4f | 247 | error = stdio_register (&kbd_dev); |
682011ff WD |
248 | } else { |
249 | lcd_is_enabled = 0; | |
250 | lcd_disable(); | |
251 | } | |
252 | return error; | |
253 | } |