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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [serial/] [mips/] [upd985xx/] [v2_0/] [src/] [upd985xx_serial.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      io/serial/mips/upd985xx/upd985xx_serial.c
4
//
5
//      NEC MIPS uPD985xx Serial I/O Interface Module (interrupt driven)
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):     hmt
44
// Contributors:  gthomas
45
// Date:          2001-07-17
46
// Purpose:       NEC MIPS uPD985xx Serial I/O module (interrupt driven version)
47
// Description: 
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/system.h>
54
#include <pkgconf/io_serial.h>
55
#include <pkgconf/io.h>
56
 
57
#include <cyg/io/io.h>
58
#include <cyg/hal/hal_intr.h>
59
#include <cyg/io/devtab.h>
60
#include <cyg/io/serial.h>
61
#include <cyg/infra/diag.h>
62
 
63
#include "upd985xx_serial.h"
64
 
65
typedef struct upd985xx_serial_info {
66
//    CYG_ADDRWORD   base;
67
    CYG_WORD       int_num;
68
    cyg_interrupt  serial_interrupt;
69
    cyg_handle_t   serial_interrupt_handle;
70
} upd985xx_serial_info;
71
 
72
static bool upd985xx_serial_init(struct cyg_devtab_entry *tab);
73
static bool upd985xx_serial_putc(serial_channel *chan, unsigned char c);
74
static Cyg_ErrNo upd985xx_serial_lookup(struct cyg_devtab_entry **tab,
75
                                   struct cyg_devtab_entry *sub_tab,
76
                                   const char *name);
77
static unsigned char upd985xx_serial_getc(serial_channel *chan);
78
static Cyg_ErrNo upd985xx_serial_set_config(serial_channel *chan, cyg_uint32 key,
79
                                          const void *xbuf, cyg_uint32 *len);
80
static void upd985xx_serial_start_xmit(serial_channel *chan);
81
static void upd985xx_serial_stop_xmit(serial_channel *chan);
82
 
83
static cyg_uint32 upd985xx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
84
static void       upd985xx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
85
 
86
static SERIAL_FUNS(upd985xx_serial_funs,
87
                   upd985xx_serial_putc,
88
                   upd985xx_serial_getc,
89
                   upd985xx_serial_set_config,
90
                   upd985xx_serial_start_xmit,
91
                   upd985xx_serial_stop_xmit
92
    );
93
 
94
#ifdef CYGPKG_IO_SERIAL_MIPS_UPD985XX_SERIAL0
95
static upd985xx_serial_info upd985xx_serial_info0 = {
96
    // base:    (CYG_ADDRWORD)UPD985XX_UART3_CONTROL0,
97
    int_num: CYGNUM_HAL_INTERRUPT_UART,
98
};
99
#if CYGNUM_IO_SERIAL_MIPS_UPD985XX_SERIAL0_BUFSIZE > 0
100
static unsigned char upd985xx_serial_out_buf0[CYGNUM_IO_SERIAL_MIPS_UPD985XX_SERIAL0_BUFSIZE];
101
static unsigned char upd985xx_serial_in_buf0[CYGNUM_IO_SERIAL_MIPS_UPD985XX_SERIAL0_BUFSIZE];
102
 
103
static SERIAL_CHANNEL_USING_INTERRUPTS(
104
    upd985xx_serial_channel0,
105
    upd985xx_serial_funs,
106
    upd985xx_serial_info0,
107
    CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MIPS_UPD985XX_SERIAL0_BAUD),
108
    CYG_SERIAL_STOP_DEFAULT,
109
    CYG_SERIAL_PARITY_DEFAULT,
110
    CYG_SERIAL_WORD_LENGTH_DEFAULT,
111
    CYG_SERIAL_FLAGS_DEFAULT,
112
    &upd985xx_serial_out_buf0[0], sizeof(upd985xx_serial_out_buf0),
113
    &upd985xx_serial_in_buf0[0], sizeof(upd985xx_serial_in_buf0)
114
    );
115
#else
116
static SERIAL_CHANNEL(
117
    upd985xx_serial_channel0,
118
    upd985xx_serial_funs,
119
    upd985xx_serial_info0,
120
    CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MIPS_UPD985XX_SERIAL0_BAUD),
121
    CYG_SERIAL_STOP_DEFAULT,
122
    CYG_SERIAL_PARITY_DEFAULT,
123
    CYG_SERIAL_WORD_LENGTH_DEFAULT,
124
    CYG_SERIAL_FLAGS_DEFAULT
125
    );
126
#endif
127
 
128
DEVTAB_ENTRY(upd985xx_serial_io0,
129
             CYGDAT_IO_SERIAL_MIPS_UPD985XX_SERIAL0_NAME,
130
             0,                     // Does not depend on a lower level interface
131
             &cyg_io_serial_devio,
132
             upd985xx_serial_init,
133
             upd985xx_serial_lookup,     // Serial driver may need initializing
134
             &upd985xx_serial_channel0
135
    );
136
#endif //  CYGPKG_IO_SERIAL_MIPS_UPD985XX_SERIAL1
137
 
138
// Internal function to actually configure the hardware to desired baud rate, etc.
139
static bool
140
upd985xx_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
141
{
142
    unsigned char parity;
143
    unsigned char word_length;
144
    unsigned char stop_bits;
145
    int baud;
146
 
147
    parity = select_parity[new_config->parity];
148
    word_length = select_word_length[new_config->word_length-CYGNUM_SERIAL_WORD_LENGTH_5];
149
    stop_bits = select_stop_bits[new_config->stop];
150
    baud = select_baud[new_config->baud];
151
 
152
    if ((word_length == 0xFF) ||
153
        (parity == 0xFF) ||
154
        (stop_bits == 0xFF)) {
155
        return false;  // Unsupported configuration
156
    }
157
 
158
    // First ensure we are accessing the right registers.
159
    // Clear the divisor latch access bit
160
    *UARTLCR &=~UARTLCR_DLAB;
161
 
162
    // Disable Receiver and Transmitter
163
    // No such thing in uPD985xx - but we can mask interrupts:
164
    *UARTIER = 0;
165
 
166
    // Clear sticky (writable) status bits.
167
    // Ensure it's in 16550 mode at least:
168
    *UARTFCR = UARTFCR_16550_MODE;
169
 
170
    // Set parity, word length, stop bits (keep DLAB clear)
171
    *UARTLCR = word_length | parity | stop_bits;
172
 
173
    // Set the desired baud rate.
174
    *UARTLCR |= UARTLCR_DLAB;
175
    *UARTDLM = (baud >> 8) & 0xff;
176
    *UARTDLL = baud & 0xff;
177
    *UARTLCR &=~UARTLCR_DLAB;
178
 
179
    // Enable the receiver (with interrupts) and the transmitter.
180
    *UARTIER = UARTIER_ERBFI;
181
 
182
    return true;
183
}
184
 
185
// Function to initialize the device.  Called at bootstrap time.
186
static bool
187
upd985xx_serial_init(struct cyg_devtab_entry *tab)
188
{
189
    serial_channel *chan = (serial_channel *)tab->priv;
190
    upd985xx_serial_info *upd985xx_chan = (upd985xx_serial_info *)chan->dev_priv;
191
    int res;
192
#ifdef CYGDBG_IO_INIT
193
    diag_printf("UPD985XX SERIAL init - dev: %x.%d\n", 0 /* upd985xx_chan->base */,
194
                upd985xx_chan->int_num);
195
#endif
196
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
197
    if (chan->out_cbuf.len != 0) {
198
        cyg_drv_interrupt_create(upd985xx_chan->int_num,
199
                                 99,                     // Priority - unused
200
                                 (cyg_addrword_t)chan,   // Data item passed to interrupt handler
201
                                 upd985xx_serial_ISR,
202
                                 upd985xx_serial_DSR,
203
                                 &upd985xx_chan->serial_interrupt_handle,
204
                                 &upd985xx_chan->serial_interrupt);
205
        cyg_drv_interrupt_attach(upd985xx_chan->serial_interrupt_handle);
206
        cyg_drv_interrupt_unmask(upd985xx_chan->int_num);
207
    }
208
    res = upd985xx_serial_config_port(chan, &chan->config, true);
209
    return res;
210
}
211
 
212
// This routine is called when the device is "looked" up (i.e. attached)
213
static Cyg_ErrNo
214
upd985xx_serial_lookup(struct cyg_devtab_entry **tab,
215
                  struct cyg_devtab_entry *sub_tab,
216
                  const char *name)
217
{
218
    serial_channel *chan = (serial_channel *)(*tab)->priv;
219
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
220
    return ENOERR;
221
}
222
 
223
// Send a character to the device output buffer.
224
// Return 'true' if character is sent to device
225
static bool
226
upd985xx_serial_putc(serial_channel *chan, unsigned char c)
227
{
228
    if ( 0 == (UARTLSR_THRE & *UARTLSR) )
229
        return false;
230
    *UARTTHR = (unsigned int)c;
231
    return true;
232
}
233
 
234
// Fetch a character from the device input buffer, waiting if necessary
235
static unsigned char
236
upd985xx_serial_getc(serial_channel *chan)
237
{
238
    while ( 0 == (UARTLSR_DR & *UARTLSR) )
239
        /* do nothing */ ;
240
 
241
    return (char)*UARTRBR;
242
}
243
 
244
// Set up the device characteristics; baud rate, etc.
245
static Cyg_ErrNo
246
upd985xx_serial_set_config(serial_channel *chan, cyg_uint32 key,
247
                         const void *xbuf, cyg_uint32 *len)
248
{
249
    switch (key) {
250
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
251
      {
252
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
253
        if ( *len < sizeof(cyg_serial_info_t) ) {
254
            return -EINVAL;
255
        }
256
        *len = sizeof(cyg_serial_info_t);
257
        if ( true != upd985xx_serial_config_port(chan, config, false) )
258
            return -EINVAL;
259
      }
260
      break;
261
    default:
262
        return -EINVAL;
263
    }
264
    return ENOERR;
265
}
266
 
267
// Enable the transmitter on the device
268
static void
269
upd985xx_serial_start_xmit(serial_channel *chan)
270
{
271
    (chan->callbacks->xmt_char)(chan);  // Kick transmitter (if necessary)
272
    *UARTIER |= UARTIER_ERBEI;          // enable interrupts
273
}
274
 
275
// Disable the transmitter on the device
276
static void
277
upd985xx_serial_stop_xmit(serial_channel *chan)
278
{
279
    *UARTIER &=~UARTIER_ERBEI;          // disable interrupts
280
}
281
 
282
// Serial I/O - low level interrupt handler (ISR)
283
static cyg_uint32
284
upd985xx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
285
{
286
    cyg_drv_interrupt_mask(vector);
287
    return CYG_ISR_CALL_DSR;  // Cause DSR to be run
288
}
289
 
290
// Serial I/O - high level interrupt handler (DSR)
291
static void
292
upd985xx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
293
{
294
    serial_channel *chan = (serial_channel *)data;
295
 
296
    int stat = *UARTIIR;
297
 
298
    stat &= UARTIIR_UIID_MASK;
299
 
300
    if (stat == UARTIIR_TX_EMPTY) {
301
        (chan->callbacks->xmt_char)(chan);
302
    }
303
    if (stat == UARTIIR_RXD_AVAIL) {
304
        while (0 != (UARTLSR_DR & *UARTLSR)) {
305
            (chan->callbacks->rcv_char)(chan, (char)*UARTRBR);
306
        }
307
    }
308
    cyg_drv_interrupt_acknowledge(vector);
309
    cyg_drv_interrupt_unmask(vector);
310
}
311
 
312
// ------------------------------------------------------------------------
313
// EOF upd985xx_serial.c

powered by: WebSVN 2.1.0

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