comparison packages/hal/sh/sh4/current/src/sh4_scif.c @ 134:d2f49caf9e38 ecos-sw-2000-11-03

Merge from eCos master repository on 2000-11-03-09:00:49-GMT
author jlarmour
date Fri, 03 Nov 2000 21:17:40 +0000
parents
children 25e238959bae
comparison
equal deleted inserted replaced
133:98d71f4d8243 134:d2f49caf9e38
1 //=============================================================================
2 //
3 // sh4_scif.c
4 //
5 // Simple driver for the SH4 Serial Communication Interface with FIFO
6 //
7 //=============================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Red Hat eCos Public License
12 // Version 1.1 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://www.redhat.com/
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Configurable Operating System,
22 // released September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Red Hat.
25 // Portions created by Red Hat are
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
27 // All Rights Reserved.
28 // -------------------------------------------
29 //
30 //####COPYRIGHTEND####
31 //=============================================================================
32 //#####DESCRIPTIONBEGIN####
33 //
34 // Author(s): jskov
35 // Contributors:Haruki Kashiwaya
36 // Date: 2000-08-09
37 // Description: Simple driver for the SH Serial Communication Interface
38 // The driver can be used for the SCIF modules.
39 // Clients of this file can configure the behavior with:
40 // CYGNUM_SCIF_PORTS: number of SCI ports
41 //
42 //####DESCRIPTIONEND####
43 //
44 //=============================================================================
45
46 #include <pkgconf/hal.h>
47
48 #ifdef CYGNUM_HAL_SH_SH4_SCIF_PORTS
49
50 #include <cyg/hal/hal_io.h> // IO macros
51 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED
52 #include <cyg/hal/hal_misc.h> // Helper functions
53 #include <cyg/hal/hal_intr.h> // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
54 #include <cyg/hal/hal_arch.h> // SAVE/RESTORE GP
55 #include <cyg/hal/hal_if.h> // Calling-if API
56 #include <cyg/hal/sh_regs.h> // serial register definitions
57 #include <cyg/hal/sh_stub.h> // target_register_t
58
59 #include <cyg/hal/sh4_scif.h> // our header
60
61 //--------------------------------------------------------------------------
62
63 void
64 cyg_hal_plf_scif_init_channel(const channel_data_t* chan)
65 {
66 cyg_uint8* base = chan->base;
67 cyg_uint16 tmp;
68 cyg_uint16 sr;
69
70 // Disable everything.
71 HAL_WRITE_UINT16(base+_REG_SCSCR, 0);
72
73 // Reset FIFO.
74 HAL_WRITE_UINT16(base+_REG_SCFCR,
75 CYGARC_REG_SCFCR2_TFRST|CYGARC_REG_SCFCR2_RFRST);
76
77 // 8-1-no parity.
78 HAL_WRITE_UINT16(base+_REG_SCSMR, 0);
79
80 // Set speed to 38400
81 HAL_READ_UINT16(base+_REG_SCSMR, tmp);
82 tmp &= ~CYGARC_REG_SCSMR2_CKSx_MASK;
83 tmp |= CYGARC_SCBRR_CKSx(38400);
84 HAL_WRITE_UINT16(base+_REG_SCSMR, tmp);
85 HAL_WRITE_UINT8(base+_REG_SCBRR, CYGARC_SCBRR_N(38400));
86
87 // Let things settle: Here we should should wait the equivalent of
88 // one bit interval, i.e. 1/38400 second, but until we have
89 // something like the Linux delay loop, it's hard to do reliably. So
90 // just move on and hope for the best (this is unlikely to cause
91 // problems since the CPU has just come out of reset anyway).
92
93 // Clear status register (read back first).
94 HAL_READ_UINT16(base+_REG_SCFSR, sr);
95 HAL_WRITE_UINT16(base+_REG_SCFSR, 0);
96
97 // Bring FIFO out of reset and set to trigger on every char in
98 // FIFO (or C-c input would not be processed).
99 HAL_WRITE_UINT16(base+_REG_SCFCR,
100 CYGARC_REG_SCFCR2_RTRG_1|CYGARC_REG_SCFCR2_TTRG_1);
101
102 // Leave Tx/Rx interrupts disabled, but enable Tx/Rx
103 HAL_WRITE_UINT16(base+_REG_SCSCR,
104 CYGARC_REG_SCSCR2_TE|CYGARC_REG_SCSCR2_RE);
105 }
106
107 static cyg_bool
108 cyg_hal_plf_scif_getc_nonblock(void* __ch_data, cyg_uint8* ch)
109 {
110 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
111 cyg_uint16 fdr, sr;
112
113 HAL_READ_UINT16(base+_REG_SCFDR, fdr);
114 if ((fdr & CYGARC_REG_SCFDR2_RCOUNT_MASK) == 0)
115 return false;
116
117 HAL_READ_UINT8(base+_REG_SCFRDR, *ch);
118
119 // Clear FIFO full flag (read before clearing)
120 HAL_READ_UINT16(base+_REG_SCFSR, sr);
121 HAL_WRITE_UINT16(base+_REG_SCFSR,
122 CYGARC_REG_SCSSR2_CLEARMASK & ~CYGARC_REG_SCSSR2_RDF);
123
124 return true;
125 }
126
127 cyg_uint8
128 cyg_hal_plf_scif_getc(void* __ch_data)
129 {
130 cyg_uint8 ch;
131 CYGARC_HAL_SAVE_GP();
132
133 while(!cyg_hal_plf_scif_getc_nonblock(__ch_data, &ch));
134
135 CYGARC_HAL_RESTORE_GP();
136 return ch;
137 }
138
139 void
140 cyg_hal_plf_scif_putc(void* __ch_data, cyg_uint8 c)
141 {
142 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
143 cyg_uint16 fdr, sr;
144 CYGARC_HAL_SAVE_GP();
145
146 do {
147 HAL_READ_UINT16(base+_REG_SCFDR, fdr);
148 } while (((fdr & CYGARC_REG_SCFDR2_TCOUNT_MASK) >> CYGARC_REG_SCFDR2_TCOUNT_shift) == 16);
149
150 HAL_WRITE_UINT8(base+_REG_SCFTDR, c);
151
152 // Clear FIFO-empty/transmit end flags (read back SR first)
153 HAL_READ_UINT16(base+_REG_SCFSR, sr);
154 HAL_WRITE_UINT16(base+_REG_SCFSR, CYGARC_REG_SCSSR2_CLEARMASK
155 & ~(CYGARC_REG_SCSSR2_TDFE | CYGARC_REG_SCSSR2_TEND ));
156
157 // Hang around until the character has been safely sent.
158 do {
159 HAL_READ_UINT16(base+_REG_SCFDR, fdr);
160 } while ((fdr & CYGARC_REG_SCFDR2_TCOUNT_MASK) != 0);
161
162 CYGARC_HAL_RESTORE_GP();
163 }
164
165 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) \
166 || defined(CYGPRI_HAL_IMPLEMENTS_IF_SERVICES)
167
168 static channel_data_t channels[CYGNUM_HAL_SH_SH4_SCIF_PORTS];
169
170 static void
171 cyg_hal_plf_scif_write(void* __ch_data, const cyg_uint8* __buf,
172 cyg_uint32 __len)
173 {
174 CYGARC_HAL_SAVE_GP();
175
176 while(__len-- > 0)
177 cyg_hal_plf_scif_putc(__ch_data, *__buf++);
178
179 CYGARC_HAL_RESTORE_GP();
180 }
181
182 static void
183 cyg_hal_plf_scif_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
184 {
185 CYGARC_HAL_SAVE_GP();
186
187 while(__len-- > 0)
188 *__buf++ = cyg_hal_plf_scif_getc(__ch_data);
189
190 CYGARC_HAL_RESTORE_GP();
191 }
192
193 cyg_bool
194 cyg_hal_plf_scif_getc_timeout(void* __ch_data, cyg_uint8* ch)
195 {
196 channel_data_t* chan = (channel_data_t*)__ch_data;
197 int delay_count;
198 cyg_bool res;
199 CYGARC_HAL_SAVE_GP();
200
201 delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
202
203 for(;;) {
204 res = cyg_hal_plf_scif_getc_nonblock(__ch_data, ch);
205 if (res || 0 == delay_count--)
206 break;
207
208 CYGACC_CALL_IF_DELAY_US(100);
209 }
210
211 CYGARC_HAL_RESTORE_GP();
212 return res;
213 }
214
215 static int
216 cyg_hal_plf_scif_control(void *__ch_data, __comm_control_cmd_t __func, ...)
217 {
218 static int irq_state = 0;
219 channel_data_t* chan = (channel_data_t*)__ch_data;
220 cyg_uint8 scr;
221 int ret = 0;
222 CYGARC_HAL_SAVE_GP();
223
224 switch (__func) {
225 case __COMMCTL_IRQ_ENABLE:
226 irq_state = 1;
227 HAL_INTERRUPT_UNMASK(chan->isr_vector);
228 HAL_READ_UINT16(chan->base+_REG_SCSCR, scr);
229 scr |= CYGARC_REG_SCSCR2_RIE;
230 HAL_WRITE_UINT16(chan->base+_REG_SCSCR, scr);
231 break;
232 case __COMMCTL_IRQ_DISABLE:
233 ret = irq_state;
234 irq_state = 0;
235 HAL_INTERRUPT_UNMASK(chan->isr_vector);
236 HAL_READ_UINT16(chan->base+_REG_SCSCR, scr);
237 scr &= ~CYGARC_REG_SCSCR2_RIE;
238 HAL_WRITE_UINT16(chan->base+_REG_SCSCR, scr);
239 break;
240 case __COMMCTL_DBG_ISR_VECTOR:
241 ret = chan->isr_vector;
242 break;
243 case __COMMCTL_SET_TIMEOUT:
244 {
245 va_list ap;
246
247 va_start(ap, __func);
248
249 ret = chan->msec_timeout;
250 chan->msec_timeout = va_arg(ap, cyg_uint32);
251
252 va_end(ap);
253 }
254 default:
255 break;
256 }
257 CYGARC_HAL_RESTORE_GP();
258 return ret;
259 }
260
261 static int
262 cyg_hal_plf_scif_isr(void *__ch_data, int* __ctrlc,
263 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
264 {
265 cyg_uint8 c;
266 cyg_uint16 fdr, sr;
267 cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
268 int res = 0;
269 CYGARC_HAL_SAVE_GP();
270
271 *__ctrlc = 0;
272 HAL_READ_UINT16(base+_REG_SCFDR, fdr);
273 if ((fdr & CYGARC_REG_SCFDR2_RCOUNT_MASK) != 0) {
274 HAL_READ_UINT8(base+_REG_SCFRDR, c);
275
276 // Clear buffer full flag (read back first).
277 HAL_READ_UINT16(base+_REG_SCFSR, sr);
278 HAL_WRITE_UINT16(base+_REG_SCFSR,
279 CYGARC_REG_SCSSR2_CLEARMASK & ~CYGARC_REG_SCSSR2_RDF);
280
281 if( cyg_hal_is_break( &c , 1 ) )
282 *__ctrlc = 1;
283
284 res = CYG_ISR_HANDLED;
285 }
286
287 CYGARC_HAL_RESTORE_GP();
288 return res;
289 }
290
291 void
292 cyg_hal_plf_scif_init(int scif_index, int comm_index,
293 int rcv_vect, cyg_uint8* base)
294 {
295 channel_data_t* chan = &channels[scif_index];
296 hal_virtual_comm_table_t* comm;
297 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
298
299 // Initialize channel table
300 chan->base = base;
301 chan->isr_vector = rcv_vect;
302 chan->msec_timeout = 1000;
303
304 // Disable interrupts.
305 HAL_INTERRUPT_MASK(chan->isr_vector);
306
307 // Init channel
308 cyg_hal_plf_scif_init_channel(chan);
309
310 // Setup procs in the vector table
311
312 // Initialize channel procs
313 CYGACC_CALL_IF_SET_CONSOLE_COMM(comm_index);
314 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
315 CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
316 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_scif_write);
317 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_scif_read);
318 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_scif_putc);
319 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_scif_getc);
320 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_scif_control);
321 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_scif_isr);
322 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_scif_getc_timeout);
323
324 // Restore original console
325 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
326 }
327
328 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG || CYGPRI_HAL_IMPLEMENTS_IF_SERVICES
329
330 #endif // CYGNUM_HAL_SH_SH4_SCIF_PORTS
331
332 //-----------------------------------------------------------------------------
333 // end of sh4_scif.c