OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [mn10300/] [asb2305/] [v2_0/] [src/] [ser_asb.c] - Blame information for rev 773

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//=============================================================================
2
//
3
//      ser_asb.c
4
//
5
//      Simple driver for the serial controllers on the AM33 ASB305 board
6
//
7
//=============================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//=============================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):   dhowells
44
// Contributors:dmoseley, nickg, gthomas
45
// Date:        2001-05-18
46
// Description: Simple driver for the ASB2305 debug serial port
47
//
48
//####DESCRIPTIONEND####
49
//
50
//=============================================================================
51
 
52
#include <pkgconf/hal.h>
53
 
54
#include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP macros
55
#include <cyg/hal/hal_io.h>             // IO macros
56
#include <cyg/hal/hal_if.h>             // interface API
57
#include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
58
#include <cyg/hal/hal_misc.h>           // Helper functions
59
#include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
60
 
61
#if defined(CYGNUM_HAL_AM33_PLF_SERIAL_CHANNELS) && CYGNUM_HAL_AM33_PLF_SERIAL_CHANNELS > 0
62
 
63
/*---------------------------------------------------------------------------*/
64
/* From serial_16550.h */
65
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==9600
66
#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
67
#define CYG_DEVICE_SERIAL_BAUD_LSB        0x78
68
#endif
69
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==19200
70
#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
71
#define CYG_DEVICE_SERIAL_BAUD_LSB        0x3C
72
#endif
73
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==38400
74
#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
75
#define CYG_DEVICE_SERIAL_BAUD_LSB        0x1E
76
#endif
77
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==57600
78
#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
79
#define CYG_DEVICE_SERIAL_BAUD_LSB        0x14
80
#endif
81
#if CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD==115200
82
#define CYG_DEVICE_SERIAL_BAUD_MSB        0x00
83
#define CYG_DEVICE_SERIAL_BAUD_LSB        0x0A
84
#endif
85
 
86
#ifndef CYG_DEVICE_SERIAL_BAUD_MSB
87
#error Missing/incorrect serial baud rate defined - CDL error?
88
#endif
89
 
90
/*---------------------------------------------------------------------------*/
91
// Define the serial registers.
92
#define CYG_DEV_RBR 0x00   // receiver buffer register, read, dlab = 0
93
#define CYG_DEV_THR 0x00   // transmitter holding register, write, dlab = 0
94
#define CYG_DEV_DLL 0x00   // divisor latch (LS), read/write, dlab = 1
95
#define CYG_DEV_IER 0x04   // interrupt enable register, read/write, dlab = 0
96
#define CYG_DEV_DLM 0x04   // divisor latch (MS), read/write, dlab = 1
97
#define CYG_DEV_IIR 0x08   // interrupt identification register, read, dlab = 0
98
#define CYG_DEV_FCR 0x08   // fifo control register, write, dlab = 0
99
#define CYG_DEV_LCR 0x0C   // line control register, read/write
100
#define CYG_DEV_MCR 0x10   // modem control register, read/write
101
#define CYG_DEV_LSR 0x14   // line status register, read
102
#define CYG_DEV_MSR 0x18   // modem status register, read
103
 
104
// Interrupt Enable Register
105
#define SIO_IER_RCV 0x01
106
#define SIO_IER_XMT 0x02
107
#define SIO_IER_LS  0x04
108
#define SIO_IER_MS  0x08
109
 
110
// The line status register bits.
111
#define SIO_LSR_DR      0x01            // data ready
112
#define SIO_LSR_OE      0x02            // overrun error
113
#define SIO_LSR_PE      0x04            // parity error
114
#define SIO_LSR_FE      0x08            // framing error
115
#define SIO_LSR_BI      0x10            // break interrupt
116
#define SIO_LSR_THRE    0x20            // transmitter holding register empty
117
#define SIO_LSR_TEMT    0x40            // transmitter register empty
118
#define SIO_LSR_ERR     0x80            // any error condition
119
 
120
// The modem status register bits.
121
#define SIO_MSR_DCTS  0x01              // delta clear to send
122
#define SIO_MSR_DDSR  0x02              // delta data set ready
123
#define SIO_MSR_TERI  0x04              // trailing edge ring indicator
124
#define SIO_MSR_DDCD  0x08              // delta data carrier detect
125
#define SIO_MSR_CTS   0x10              // clear to send
126
#define SIO_MSR_DSR   0x20              // data set ready
127
#define SIO_MSR_RI    0x40              // ring indicator
128
#define SIO_MSR_DCD   0x80              // data carrier detect
129
 
130
// The line control register bits.
131
#define SIO_LCR_WLS0   0x01             // word length select bit 0
132
#define SIO_LCR_WLS1   0x02             // word length select bit 1
133
#define SIO_LCR_STB    0x04             // number of stop bits
134
#define SIO_LCR_PEN    0x08             // parity enable
135
#define SIO_LCR_EPS    0x10             // even parity select
136
#define SIO_LCR_SP     0x20             // stick parity
137
#define SIO_LCR_SB     0x40             // set break
138
#define SIO_LCR_DLAB   0x80             // divisor latch access bit
139
 
140
// Modem Control Register
141
#define SIO_MCR_DTR 0x01
142
#define SIO_MCR_RTS 0x02
143
#define SIO_MCR_INT 0x08   // Enable interrupts
144
 
145
#define LSR_WAIT_FOR(STATE) do { cyg_uint8 lsr; do { HAL_READ_UINT8(base+CYG_DEV_LSR, lsr); } while (!(lsr&SIO_LSR_##STATE)); } while(0)
146
#define LSR_QUERY(STATE) ({ cyg_uint8 lsr; HAL_READ_UINT8(base+CYG_DEV_LSR, lsr); (lsr&SIO_LSR_##STATE); })
147
 
148
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_RTSCTS
149
#define FLOWCTL_QUERY(LINE) ({ cyg_uint8 msr; HAL_READ_UINT8(base+CYG_DEV_MSR, msr); (msr&SIO_MSR_##LINE); })
150
#define FLOWCTL_WAIT_FOR(LINE) do { cyg_uint8 msr; do { HAL_READ_UINT8(base+CYG_DEV_MSR, msr); } while (!(msr&SIO_MSR_##LINE)); } while(0)
151
#define FLOWCTL_CLEAR(LINE) do { cyg_uint8 mcr; HAL_READ_UINT8(base+CYG_DEV_MCR,mcr); mcr &= ~SIO_MCR_##LINE; HAL_WRITE_UINT8(base+CYG_DEV_MCR, mcr); } while (0);
152
#define FLOWCTL_SET(LINE) do { cyg_uint8 mcr; HAL_READ_UINT8(base+CYG_DEV_MCR,mcr); mcr |= SIO_MCR_##LINE; HAL_WRITE_UINT8(base+CYG_DEV_MCR, mcr); } while (0);
153
 
154
#else
155
#define FLOWCTL_QUERY(LINE) 1
156
#define FLOWCTL_WAIT_FOR(LINE) do { ; } while(0)
157
#define FLOWCTL_CLEAR(LINE) do { ; } while(0)
158
#define FLOWCTL_SET(LINE) do { ; } while(0)
159
 
160
#endif
161
 
162
//-----------------------------------------------------------------------------
163
typedef struct {
164
    cyg_uint8* base;
165
    cyg_int32 msec_timeout;
166
    int isr_vector;
167
} channel_data_t;
168
 
169
static channel_data_t asb2305_serial_channels[] = {
170
    { (cyg_uint8*)0xA6FB0000, 1000, CYGNUM_HAL_INTERRUPT_SERIAL_0_RX }
171
};
172
 
173
//-----------------------------------------------------------------------------
174
 
175
static void
176
cyg_hal_plf_serial_init_channel(const void* __ch_data)
177
{
178
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
179
    cyg_uint8 lcr;
180
 
181
    // 8-1-no parity.
182
    HAL_WRITE_UINT8(base+CYG_DEV_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
183
 
184
    HAL_READ_UINT8(base+CYG_DEV_LCR, lcr);
185
    lcr |= SIO_LCR_DLAB;
186
    HAL_WRITE_UINT8(base+CYG_DEV_LCR, lcr);
187
    HAL_WRITE_UINT8(base+CYG_DEV_DLL, CYG_DEVICE_SERIAL_BAUD_LSB);
188
    HAL_WRITE_UINT8(base+CYG_DEV_DLM, CYG_DEVICE_SERIAL_BAUD_MSB);
189
    lcr &= ~SIO_LCR_DLAB;
190
    HAL_WRITE_UINT8(base+CYG_DEV_LCR, lcr);
191
    HAL_WRITE_UINT8(base+CYG_DEV_FCR, 0x07);  // Enable & clear FIFO
192
 
193
    FLOWCTL_CLEAR(DTR);
194
    FLOWCTL_CLEAR(RTS);
195
}
196
 
197
static void
198
cyg_hal_plf_serial_putc_aux(cyg_uint8* base, char c)
199
{
200
    LSR_WAIT_FOR(THRE);
201
 
202
    FLOWCTL_WAIT_FOR(CTS);
203
 
204
    HAL_WRITE_UINT8(base+CYG_DEV_THR, c);
205
}
206
 
207
void
208
cyg_hal_plf_serial_putc(void *__ch_data, char c)
209
{
210
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
211
    CYGARC_HAL_SAVE_GP();
212
 
213
    FLOWCTL_SET(DTR);
214
 
215
    cyg_hal_plf_serial_putc_aux(base,c);
216
 
217
    FLOWCTL_CLEAR(DTR);
218
 
219
    CYGARC_HAL_RESTORE_GP();
220
}
221
 
222
static cyg_bool
223
cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
224
{
225
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
226
 
227
    if (!LSR_QUERY(DR))
228
        return false;
229
 
230
    HAL_READ_UINT8(base+CYG_DEV_RBR, *ch);
231
 
232
    return true;
233
}
234
 
235
cyg_uint8
236
cyg_hal_plf_serial_getc(void* __ch_data)
237
{
238
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
239
    cyg_uint8 ch;
240
    CYGARC_HAL_SAVE_GP();
241
 
242
    /* see if there's some cached data in the FIFO */
243
    if (!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)) {
244
        /* there isn't - open the flood gates */
245
        FLOWCTL_WAIT_FOR(DSR);
246
        FLOWCTL_SET(RTS);
247
 
248
        while (!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
249
 
250
        FLOWCTL_CLEAR(RTS);
251
    }
252
 
253
    CYGARC_HAL_RESTORE_GP();
254
    return ch;
255
}
256
 
257
static void
258
cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
259
                         cyg_uint32 __len)
260
{
261
    cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
262
    CYGARC_HAL_SAVE_GP();
263
 
264
    FLOWCTL_SET(DTR);
265
 
266
    while(__len-- > 0)
267
        cyg_hal_plf_serial_putc_aux(__ch_data, *__buf++);
268
 
269
    FLOWCTL_CLEAR(DTR);
270
 
271
    CYGARC_HAL_RESTORE_GP();
272
}
273
 
274
static void
275
cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
276
{
277
    CYGARC_HAL_SAVE_GP();
278
 
279
    while(__len-- > 0)
280
        *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
281
 
282
    CYGARC_HAL_RESTORE_GP();
283
}
284
 
285
#define TM0MD 0xD4003000
286
#define TM0BR 0xD4003010
287
#define TM0BC 0xD4003020
288
 
289
cyg_bool
290
cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
291
{
292
#if 1
293
    int delay_count;
294
    channel_data_t* chan = (channel_data_t*)__ch_data;
295
    cyg_uint8* base = chan->base;
296
    cyg_uint8 last, val;
297
    cyg_bool res;
298
    CYGARC_HAL_SAVE_GP();
299
 
300
    /* see if there's any cached data in the FIFO */
301
    res = cyg_hal_plf_serial_getc_nonblock(__ch_data,ch);
302
    if (!res) {
303
        /* there isn't - open the flood gates */
304
        delay_count = chan->msec_timeout * 125; // want delay in 8uS steps
305
 
306
        HAL_WRITE_UINT8(TM0BR,200); // IOCLK is 25MHz, we want 125KHz
307
        HAL_WRITE_UINT8(TM0MD,0x40); // stop and load
308
        HAL_WRITE_UINT8(TM0MD,0x80); // set source to be IOCLK and go
309
        HAL_READ_UINT8(TM0BC,last);
310
 
311
        while (delay_count>0 && !FLOWCTL_QUERY(DSR)) {
312
                HAL_READ_UINT8(TM0BC,val);
313
                if (val==last) continue;
314
                if (val>last)
315
                        delay_count--; // count the underflows
316
                last = val;
317
        }
318
        if (delay_count==0)
319
            goto timeout;
320
 
321
        FLOWCTL_SET(RTS);
322
 
323
        while (delay_count>0 && !LSR_QUERY(DR)) {
324
                HAL_READ_UINT8(TM0BC,val);
325
                if (val==last) continue;
326
                if (val>last)
327
                        delay_count--; // count the underflows
328
                last = val;
329
        }
330
 
331
        FLOWCTL_CLEAR(RTS);
332
 
333
        if (LSR_QUERY(DR)) {
334
            HAL_READ_UINT8(base+CYG_DEV_RBR, *ch);
335
            res = true;
336
        }
337
 
338
    timeout:
339
        HAL_WRITE_UINT8(TM0MD,0x00); // stop h/w timer
340
    }
341
 
342
    CYGARC_HAL_RESTORE_GP();
343
    return res;
344
 
345
#else
346
    int delay_count;
347
    channel_data_t* chan = (channel_data_t*)__ch_data;
348
    cyg_uint8* base = chan->base;
349
    cyg_bool res;
350
    CYGARC_HAL_SAVE_GP();
351
 
352
    /* see if there's some cached data in the FIFO */
353
    res = cyg_hal_plf_serial_getc_nonblock(__ch_data,ch);
354
    if (!res) {
355
        /* there isn't - open the flood gates */
356
        delay_count = chan->msec_timeout * 1000; // want delay in uS steps
357
 
358
        for (; delay_count>0 && !FLOWCTL_QUERY(DSR); delay_count--)
359
            CYGACC_CALL_IF_DELAY_US(1);
360
        if (delay_count==0)
361
            goto timeout;
362
 
363
        FLOWCTL_SET(RTS);
364
 
365
        for (; delay_count>0 && !LSR_QUERY(DR); delay_count--)
366
            CYGACC_CALL_IF_DELAY_US(1);
367
 
368
        FLOWCTL_CLEAR(RTS);
369
 
370
        if (LSR_QUERY(DR)) {
371
            HAL_READ_UINT8(base+CYG_DEV_RBR, *ch);
372
            res = true;
373
        }
374
 
375
    }
376
 
377
timeout:
378
    CYGARC_HAL_RESTORE_GP();
379
    return res;
380
#endif
381
}
382
 
383
static int
384
cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
385
{
386
    static int irq_state = 0;
387
    channel_data_t* chan = (channel_data_t*)__ch_data;
388
    int ret = 0;
389
    CYGARC_HAL_SAVE_GP();
390
 
391
    switch (__func) {
392
    case __COMMCTL_IRQ_ENABLE:
393
        irq_state = 1;
394
 
395
        HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, SIO_IER_RCV);
396
        HAL_WRITE_UINT8(chan->base+CYG_DEV_MCR, SIO_MCR_INT|SIO_MCR_DTR|SIO_MCR_RTS);
397
 
398
        HAL_INTERRUPT_UNMASK(chan->isr_vector);
399
        break;
400
    case __COMMCTL_IRQ_DISABLE:
401
        ret = irq_state;
402
        irq_state = 0;
403
 
404
        HAL_WRITE_UINT8(chan->base+CYG_DEV_IER, 0);
405
 
406
        HAL_INTERRUPT_MASK(chan->isr_vector);
407
        break;
408
    case __COMMCTL_DBG_ISR_VECTOR:
409
        ret = chan->isr_vector;
410
        break;
411
    case __COMMCTL_SET_TIMEOUT:
412
    {
413
        va_list ap;
414
 
415
        va_start(ap, __func);
416
 
417
        ret = chan->msec_timeout;
418
        chan->msec_timeout = va_arg(ap, cyg_uint32);
419
 
420
        va_end(ap);
421
    }
422
    default:
423
        break;
424
    }
425
    CYGARC_HAL_RESTORE_GP();
426
    return ret;
427
}
428
 
429
static int
430
cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
431
                       CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
432
{
433
    int res = 0;
434
    channel_data_t* chan = (channel_data_t*)__ch_data;
435
    char c;
436
    cyg_uint8 lsr;
437
    CYGARC_HAL_SAVE_GP();
438
 
439
    cyg_drv_interrupt_acknowledge(chan->isr_vector);
440
 
441
    *__ctrlc = 0;
442
    HAL_READ_UINT8(chan->base+CYG_DEV_LSR, lsr);
443
    if ( (lsr & SIO_LSR_DR) != 0 ) {
444
 
445
        HAL_READ_UINT8(chan->base+CYG_DEV_RBR, c);
446
        if( cyg_hal_is_break( &c , 1 ) )
447
            *__ctrlc = 1;
448
 
449
        res = CYG_ISR_HANDLED;
450
    }
451
 
452
    CYGARC_HAL_RESTORE_GP();
453
    return res;
454
}
455
 
456
static void
457
cyg_hal_plf_serial_init(void)
458
{
459
    hal_virtual_comm_table_t* comm;
460
    int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
461
 
462
    // Disable interrupts.
463
    HAL_INTERRUPT_MASK(asb2305_serial_channels[0].isr_vector);
464
 
465
    // Init channels
466
    cyg_hal_plf_serial_init_channel(&asb2305_serial_channels[0]);
467
 
468
    // Setup procs in the vector table
469
 
470
    // Set channel 0
471
    CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
472
    comm = CYGACC_CALL_IF_CONSOLE_PROCS();
473
    CYGACC_COMM_IF_CH_DATA_SET(*comm, &asb2305_serial_channels[0]);
474
    CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
475
    CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
476
    CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
477
    CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
478
    CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
479
    CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
480
    CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
481
 
482
    // Restore original console
483
    CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
484
}
485
 
486
void
487
cyg_hal_plf_comms_init(void)
488
{
489
    static int initialized = 0;
490
 
491
    if (initialized)
492
        return;
493
 
494
    initialized = 1;
495
 
496
    cyg_hal_plf_serial_init();
497
 
498
#if defined(CYGNUM_HAL_AM33_SERIAL_CHANNELS) && CYGNUM_HAL_AM33_SERIAL_CHANNELS > 0
499
    cyg_hal_am33_serial_init(1);
500
#endif
501
}
502
 
503
#endif // defined(CYGNUM_HAL_AM33_PLF_SERIAL_CHANNELS) && CYGNUM_HAL_AM33_PLF_SERIAL_CHANNELS > 0
504
 
505
/*---------------------------------------------------------------------------*/
506
/* End of ser_asb.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.