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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [serial/] [mcf52xx/] [mcf5272/] [v2_0/] [src/] [ser_mcf5272_uart.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      devs/serial/MCF52xx/MCF5282
4
//
5
//      MCF5272 UART 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
 
42
#include <cyg/io/io.h>
43
#include <cyg/io/devtab.h>
44
#include <cyg/io/serial.h>
45
#include <cyg/infra/diag.h>
46
#include <cyg/hal/hal_intr.h>
47
#include <cyg/hal/hal_memmap.h>
48
#include <cyg/infra/cyg_type.h>
49
#include <cyg/hal/hal_arch.h>
50
#include <cyg/hal/drv_api.h>
51
#include <pkgconf/hal.h>
52
#include <pkgconf/system.h>
53
#include <pkgconf/io_serial.h>
54
#include <pkgconf/io.h>
55
#include <pkgconf/io_serial_mcf5272_uart.h>
56
#include <cyg/io/ser_mcf5272_uart.h>
57
 
58
 
59
/* The UART priority level */
60
#define MCF5272_UART_PRIORITY_LEVEL 2
61
 
62
 
63
/* Autobaud states */
64
typedef enum autobaud_states_t
65
{
66
    AB_IDLE = 0,  /* Normal state. Autobaud process hasn't been initiated yet. */
67
    AB_BEGIN_BREAK, /* Detected a start of the break */
68
    AB_BEGIN,       /* Detected the end of the break and has set up the autobaud.*/
69
 
70
}autobaud_states_t;
71
 
72
#define FIELD_OFFSET(type,field) (cyg_uint32)(&(((type*)0)->field))
73
 
74
typedef struct MCF5272_uart_info_t
75
{
76
 
77
    volatile mcf5272_sim_uart_t*    base;                       // Base address of the UART registers
78
    uint32                          uart_vector;                // UART interrupt vector number
79
 
80
    cyg_interrupt                   serial_interrupt;           // Interrupt context
81
    cyg_handle_t                    serial_interrupt_handle;    // Interrupt handle
82
 
83
    volatile uint8                  imr_mirror;                 // Interrupt mask register mirror
84
 
85
    cyg_serial_info_t               config;                     // The channel configuration
86
 
87
    autobaud_states_t               autobaud_state;             // The autobaud state
88
 
89
 
90
} MCF5272_uart_info_t;
91
 
92
/* Function prtoftyps for the MCF5272 UART ISR and DSR. */
93
static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data);
94
static void       MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
95
 
96
 
97
/* Function prototypes for the serial functions. */
98
static bool MCF5272_uart_init(struct cyg_devtab_entry * tab);
99
static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab,
100
                  struct cyg_devtab_entry *sub_tab,
101
                  const char *name);
102
static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c);
103
static unsigned char MCF5272_uart_getc(serial_channel *chan);
104
Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, cyg_uint32 key,
105
                            const void *xbuf, cyg_uint32 *len);
106
static void MCF5272_uart_start_xmit(serial_channel *chan);
107
static void MCF5272_uart_stop_xmit(serial_channel * chan);
108
 
109
 
110
/* Declare the serial functions that are called by the common serial driver layer. */
111
static SERIAL_FUNS
112
(
113
    MCF5272_uart_funs,
114
    MCF5272_uart_putc,
115
    MCF5272_uart_getc,
116
    MCF5272_uart_set_config,
117
    MCF5272_uart_start_xmit,
118
    MCF5272_uart_stop_xmit
119
);
120
 
121
 
122
/* Definition for channel 0 UART configuration. */
123
/************************************************/
124
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
125
 
126
/* Data structure contains
127
   channel informtion.
128
 */
129
static MCF5272_uart_info_t MCF5272_uart_channel_info_0;
130
 
131
/* If the channel buffer size is zero, do not include interrupt UART processing */
132
#if CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE > 0
133
 
134
/*      Allocated receive and transmit buffer.   The size of the buffer  is */
135
/* configured by the configtool.                                            */
136
 
137
static unsigned char MCF5272_uart_out_buf0[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE];
138
static unsigned char MCF5272_uart_in_buf0[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE];
139
 
140
/*      Channel function table.   We register  the UART  functions here  so */
141
/* that uppper serial drivers can call the serial driver's routines.        */
142
 
143
static SERIAL_CHANNEL_USING_INTERRUPTS(
144
    MCF5272_uart_channel_0,
145
    MCF5272_uart_funs,
146
    MCF5272_uart_channel_info_0,
147
    CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
148
    CYG_SERIAL_STOP_DEFAULT,
149
    CYG_SERIAL_PARITY_DEFAULT,
150
    CYG_SERIAL_WORD_LENGTH_DEFAULT,
151
    CYG_SERIAL_FLAGS_DEFAULT,
152
    MCF5272_uart_out_buf0, sizeof(MCF5272_uart_out_buf0),
153
    MCF5272_uart_in_buf0, sizeof(MCF5272_uart_in_buf0)
154
);
155
#else
156
/* Don't use interrupt processing for the UART. */
157
static SERIAL_CHANNEL(
158
    MCF5272_uart_channel_0,
159
    MCF5272_uart_funs,
160
    MCF5272_uart_channel_info_0,
161
    CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
162
    CYG_SERIAL_STOP_DEFAULT,
163
    CYG_SERIAL_PARITY_DEFAULT,
164
    CYG_SERIAL_WORD_LENGTH_DEFAULT,
165
    CYG_SERIAL_FLAGS_DEFAULT
166
);
167
#endif
168
 
169
DEVTAB_ENTRY(
170
    MCF5272_uart_io0,
171
    CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL0_NAME,
172
    0,                       // Does not depend on a lower level interface
173
    &cyg_io_serial_devio,    // The table of I/O functions.
174
    MCF5272_uart_init,       // UART initialization function.
175
    MCF5272_uart_lookup,     // The UART lookup function. This function typically sets
176
                             // up the device for actual use, turing on interrupts, configuring the port, etc.
177
    &MCF5272_uart_channel_0
178
);
179
#endif //  CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0
180
 
181
/* Definition for channel 1 UART configuration. */
182
/************************************************/
183
 
184
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
185
 
186
 
187
/* Data structure contains
188
   channel informtion.
189
 */
190
static MCF5272_uart_info_t MCF5272_uart_channel_info_1;
191
 
192
/* If the channel buffer size is zero, do not include interrupt UART processing */
193
#if CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE > 0
194
 
195
/*      Allocated receive and transmit buffer.   The size of the buffer  is */
196
/* configured by the configtool.                                            */
197
 
198
static unsigned char MCF5272_uart_out_buf1[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE];
199
static unsigned char MCF5272_uart_in_buf1[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE];
200
 
201
/*      Channel function table.   We register  the UART  functions here  so */
202
/* that uppper serial drivers can call the serial driver's routines.        */
203
 
204
static SERIAL_CHANNEL_USING_INTERRUPTS(
205
    MCF5272_uart_channel_1,
206
    MCF5272_uart_funs,
207
    MCF5272_uart_channel_info_1,
208
    CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BAUD),
209
    CYG_SERIAL_STOP_DEFAULT,
210
    CYG_SERIAL_PARITY_DEFAULT,
211
    CYG_SERIAL_WORD_LENGTH_DEFAULT,
212
    CYG_SERIAL_FLAGS_DEFAULT,
213
    MCF5272_uart_out_buf1, sizeof(MCF5272_uart_out_buf1),
214
    MCF5272_uart_in_buf1, sizeof(MCF5272_uart_in_buf1)
215
);
216
 
217
#else
218
static SERIAL_CHANNEL(MCF5272_uart_channel_1,
219
                      MCF5272_uart_funs,
220
                      MCF5272_uart_channel_info_1,
221
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
222
                      CYG_SERIAL_STOP_DEFAULT,
223
                      CYG_SERIAL_PARITY_DEFAULT,
224
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
225
                      CYG_SERIAL_FLAGS_DEFAULT
226
    );
227
#endif
228
DEVTAB_ENTRY(
229
    MCF5272_uart_io1,
230
    CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL1_NAME,
231
    0,                     // Does not depend on a lower level interface
232
    &cyg_io_serial_devio,  // The table of I/O functions.
233
    MCF5272_uart_init,     // UART initialization function.
234
    MCF5272_uart_lookup,   // The UART lookup function. This function typically sets
235
                           // up the device for actual use, turing on interrupts, configuring the port, etc.
236
    &MCF5272_uart_channel_1
237
);
238
#endif //  CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1
239
 
240
 
241
 
242
/* Definition of macros that access the UART's SIM registers */
243
/* Read from a register */
244
 
245
#define MCF5272_UART_WRITE(_addr_,_value_) \
246
   *((volatile CYG_BYTE*)&(_addr_)) = (CYG_BYTE)(_value_)
247
/* Write to a register */
248
#define MCF5272_UART_READ(_addr_) \
249
   *(volatile CYG_BYTE*)&(_addr_)
250
 
251
 
252
/* Function Prototypes */
253
/* =================== */
254
/* Internal function to actually configure the hardware to desired baud rate, etc. */
255
static bool MCF5272_uart_config_port(serial_channel*, cyg_serial_info_t*);
256
static void MCF5272_uart_start_xmit(serial_channel*);
257
 
258
 
259
/* Baudrate conversion table. */
260
static unsigned long baud_rates_table[]=
261
{
262
    0,
263
    50,     // CYGNUM_SERIAL_BAUD_50 = 1
264
    75,     // CYGNUM_SERIAL_BAUD_75
265
    110,    // CYGNUM_SERIAL_BAUD_110
266
    134,    // CYGNUM_SERIAL_BAUD_134_5
267
    150,    // CYGNUM_SERIAL_BAUD_150
268
    200,    // CYGNUM_SERIAL_BAUD_200
269
    300,    // CYGNUM_SERIAL_BAUD_300
270
    600,    // CYGNUM_SERIAL_BAUD_600
271
    1200,   // CYGNUM_SERIAL_BAUD_1200
272
    1800,   // CYGNUM_SERIAL_BAUD_1800
273
    2400,   // CYGNUM_SERIAL_BAUD_2400
274
    3600,   // CYGNUM_SERIAL_BAUD_3600
275
    4800,   // CYGNUM_SERIAL_BAUD_4800
276
    7200,   // CYGNUM_SERIAL_BAUD_7200
277
    9600,   // CYGNUM_SERIAL_BAUD_9600
278
    14400,  // CYGNUM_SERIAL_BAUD_14400
279
    19200,  // CYGNUM_SERIAL_BAUD_19200
280
    38400,  // CYGNUM_SERIAL_BAUD_38400
281
    57600,  // CYGNUM_SERIAL_BAUD_57600
282
    115200, // CYGNUM_SERIAL_BAUD_115200
283
    230400  // CYGNUM_SERIAL_BAUD_230400
284
};
285
 
286
/*      The table contains  divers  to  divide  the  clock  to  configre  a */
287
/* approppriate for the UART.                                               */
288
 
289
static unsigned long dividers_table[]=
290
{
291
    0,
292
    46080,   // 50
293
    30720,   // 75
294
    20945,   // 110
295
    17130,   // 134_5
296
    15360,   // 150
297
    11520,   // 200
298
    7680,    // 300
299
    3840,    // 600
300
    1920,    // 1200
301
    1280,    // 1800
302
    960,     // 2400
303
    640,     // 3600
304
    480,     // 4800
305
    320,     // 7200
306
    240,     // 9600
307
    160,     // 14400
308
    120,     // 19200
309
    60,      // 38400
310
    40,      // 57600
311
    20,      // 115200
312
    10       // 230400
313
};
314
 
315
/*******************************************************************************
316
 MCF5272_uart_init() - This routine is called during bootstrap to set up the
317
                       UART driver.
318
 
319
 INPUT:
320
    Pointer to the the device table.
321
 
322
 RETURN:
323
    Returns true if the initialization is successful. Otherwise, it retuns false
324
*/
325
static bool MCF5272_uart_init(struct cyg_devtab_entry * tab)
326
{
327
    serial_channel *chan = (serial_channel *)tab->priv;
328
    MCF5272_uart_info_t *MCF5272_uart_chan = (MCF5272_uart_info_t *)chan->dev_priv;
329
 
330
    #ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
331
 
332
    /*   Instantiation of the  UART channel  0 data  strucutre.  This  data */
333
    /* structure contains channel information.                              */
334
 
335
    if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL0_NAME) == 0)
336
    {
337
 
338
        /*   Initiliaze the UART information data to all zeros.             */
339
 
340
        memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
341
 
342
        /*   Set the base  address of the  UART registers to  differentiate */
343
        /* itself from the different regusters for the other UART port.     */
344
 
345
        MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[0];
346
 
347
        /*   Set the UART interrupt vector number.                          */
348
 
349
        MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART1;
350
 
351
        /*   Set the autobaud state to idle.                                */
352
 
353
        MCF5272_uart_chan->autobaud_state = AB_IDLE;
354
 
355
        /* Initilize the UART 0 output pins */
356
 
357
        MCF5272_SIM->gpio.pbcnt =  MCF5272_GPIO_PBCNT_URT0_EN |
358
            ((MCF5272_SIM->gpio.pbcnt) & ~MCF5272_GPIO_PBCNT_URT0_MSK);
359
    }
360
    #endif
361
 
362
    #ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
363
 
364
    /* Instantiation of the UART channel 1 data strucutre. This data structure contains
365
       channel information.
366
     */
367
    if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL1_NAME) == 0)
368
    {
369
 
370
        /*   Initiliaze the UART information data to all zeros.             */
371
 
372
        memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
373
 
374
        /*   Set the base  address of the  UART registers to  differentiate */
375
        /* itself from the different regusters for the other UART port.     */
376
 
377
        MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[1];
378
 
379
         /*   Set the UART interrupt vector number.                          */
380
 
381
        MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART2;
382
 
383
        /*   Set the autobaud state to idle.                                */
384
 
385
        MCF5272_uart_chan->autobaud_state = AB_IDLE;
386
 
387
        /* Initilize the UART 1 output pins */
388
 
389
        MCF5272_SIM->gpio.pdcnt =  MCF5272_GPIO_PDCNT_URT1_EN |
390
            ((MCF5272_SIM->gpio.pdcnt) & ~MCF5272_GPIO_PDCNT_URT1_MSK);
391
 
392
    }
393
    #endif
394
 
395
 
396
    if (chan->out_cbuf.len > 0) {
397
 
398
        /*   If the the buffer is greater  than zero, then the driver  will */
399
        /* use  interrupt  driven  I/O.   Hence,  the  driver  creates   an */
400
        /* interrupt context for the UART device.                           */
401
 
402
        cyg_drv_interrupt_create(MCF5272_uart_chan->uart_vector,
403
                                 MCF5272_UART_PRIORITY_LEVEL,           // Priority - Level 2
404
                                 (cyg_addrword_t)chan,                  //  Data item passed to interrupt handler
405
                                 MCF5272_uart_ISR,
406
                                 MCF5272_uart_DSR,
407
                                 &MCF5272_uart_chan->serial_interrupt_handle,
408
                                 &MCF5272_uart_chan->serial_interrupt);
409
 
410
        cyg_drv_interrupt_attach(MCF5272_uart_chan->serial_interrupt_handle);
411
 
412
        (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
413
    }
414
 
415
    // Configure Serial device.
416
    return(MCF5272_uart_config_port(chan, &chan->config));
417
}
418
 
419
/******************************************************************************************************
420
 MCF5272_uart_config_port() - Configure the UART port.
421
 
422
 Internal function to actually configure the hardware to desired baud rate, etc.
423
 
424
 INPUT:
425
    chan        - The channel information
426
    new_confg   - The port configuration which include the desired baud rate, etc.
427
 
428
 RETURN:
429
    Returns true if the port configuration is successful. Otherwise, it retuns false
430
 
431
 */
432
static bool MCF5272_uart_config_port(serial_channel *chan,
433
                                     cyg_serial_info_t *new_config)
434
{
435
    MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
436
    uint8 mode_reg = 0;
437
    uint32 ubgs;
438
    unsigned int baud_divisor;
439
 
440
 
441
    /*   Get the  divisor  from  the  baudrate  table  which  will  use  to */
442
    /* configure the port's baud rate.                                      */
443
 
444
    baud_divisor = baud_rates_table[new_config->baud];
445
 
446
    /*   If the divisor is zeor, we dont' configure the port.               */
447
 
448
    if (baud_divisor == 0) return false;
449
 
450
    /*   Save the configuration value for later use.                        */
451
 
452
    port->config = *new_config;
453
 
454
    /*   We first write the reset values into the device and then configure */
455
    /* the device the we way we want to use it.                             */
456
 
457
        /* Reset Transmitter */
458
 
459
    MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_TX);
460
 
461
        /* Reset Receiver */
462
 
463
    MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_RX);
464
 
465
        /* Reset Mode Register */
466
 
467
    MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_MR);
468
 
469
    /* Translate the parity configuration to UART mode bits. */
470
 
471
    switch(port->config.parity)
472
    {
473
    default:
474
    case CYGNUM_SERIAL_PARITY_NONE:
475
        mode_reg = 0 | MCF5272_UART_UMR1_PM_NONE;
476
        break;
477
    case CYGNUM_SERIAL_PARITY_EVEN:
478
        mode_reg = 0 | MCF5272_UART_UMR1_PM_EVEN;
479
        break;
480
    case CYGNUM_SERIAL_PARITY_ODD:
481
        mode_reg = 0 | MCF5272_UART_UMR1_PM_ODD;
482
        break;
483
    case CYGNUM_SERIAL_PARITY_MARK:
484
        mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_HI;
485
        break;
486
    case CYGNUM_SERIAL_PARITY_SPACE:
487
        mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_LO;
488
        break;
489
    }
490
 
491
    /* Translate the number of bits per character configuration to UART mode bits. */
492
 
493
    switch(port->config.word_length)
494
    {
495
 
496
    case CYGNUM_SERIAL_WORD_LENGTH_5:
497
        mode_reg |= MCF5272_UART_UMR1_BC_5;
498
        break;
499
    case CYGNUM_SERIAL_WORD_LENGTH_6:
500
        mode_reg |= MCF5272_UART_UMR1_BC_6;
501
        break;
502
    case CYGNUM_SERIAL_WORD_LENGTH_7:
503
        mode_reg |= MCF5272_UART_UMR1_BC_7;
504
        break;
505
    default:
506
    case CYGNUM_SERIAL_WORD_LENGTH_8:
507
        mode_reg |= MCF5272_UART_UMR1_BC_8;
508
        break;
509
    }
510
 
511
        /* Configure the parity and the bits per character */
512
 
513
    MCF5272_UART_WRITE(port->base->umr, mode_reg);
514
 
515
    /* Translate the stop bit length to UART mode bits. */
516
 
517
    switch(port->config.stop)
518
    {
519
    default:
520
    case CYGNUM_SERIAL_STOP_1:
521
        mode_reg = MCF5272_UART_UMR2_STOP_BITS_1;
522
        break;
523
    case CYGNUM_SERIAL_STOP_1_5:
524
        mode_reg = MCF5272_UART_UMR2_STOP_BITS_15;
525
        break;
526
    case CYGNUM_SERIAL_STOP_2:
527
        mode_reg = MCF5272_UART_UMR2_STOP_BITS_2;
528
        break;
529
    }
530
 
531
        /* No echo or loopback */
532
 
533
    MCF5272_UART_WRITE(port->base->umr, 0 | MCF5272_UART_UMR2_CM_NORMAL | mode_reg);
534
 
535
        /* Set Rx and Tx baud by timer */
536
 
537
    MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCSR_RCS(0xD) |
538
                       MCF5272_UART_UCSR_TCS(0xD));
539
 
540
        /* Mask all USART interrupts */
541
 
542
    MCF5272_UART_WRITE(port->base->uisr_uimr, 0);
543
 
544
        /* Calculate baud settings */
545
 
546
    ubgs = (uint16)((CYGHWR_HAL_SYSTEM_CLOCK_MHZ*1000000)/
547
                    (baud_divisor * 32));
548
 
549
    /*   Program the baud settings to the device.                           */
550
 
551
        MCF5272_UART_WRITE(port->base->udu, (uint8)((ubgs & 0xFF00) >> 8));
552
        MCF5272_UART_WRITE(port->base->udl, (uint8)(ubgs & 0x00FF));
553
 
554
        /* Enable receiver and transmitter */
555
 
556
    MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCR_TXRXEN);
557
 
558
    /* Enable both transmit and receive interrupt. */
559
 
560
    port->imr_mirror = MCF5272_UART_UIMR_TXRDY | MCF5272_UART_UIMR_FFULL |
561
                       MCF5272_UART_UIMR_DB;
562
    MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
563
 
564
    return true; /* Returns true to indicate a successful configuration */
565
 
566
}
567
 
568
/*******************************************************************************
569
 MCF5272_uart_lookup() - This routine is called when the device is "looked" up
570
                        (i.e. attached)
571
 
572
 INPUT:
573
    tab - pointer to a pointer of the device table
574
    sub_tab - Pointer to the sub device table.
575
    name - name of the device
576
 
577
 RETURN:
578
    always return ENOERR
579
 
580
*/
581
static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab,
582
                  struct cyg_devtab_entry *sub_tab,
583
                  const char *name)
584
{
585
    serial_channel *chan = (serial_channel *)(*tab)->priv;
586
    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices
587
    return ENOERR;
588
}
589
 
590
/*******************************************************************************
591
 MCF5272_uart_putc() - Send a character to the device output buffer.
592
 
593
 INPUT:
594
    chan - pointer to the serial private data.
595
    c    - the character to output
596
 
597
 RETURN:
598
    'true' if character is sent to device, return 'false' when we've
599
    ran out of buffer space in the device itself.
600
 
601
*/
602
 
603
static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c)
604
{
605
    CYG_INTERRUPT_STATE int_state;
606
    MCF5272_uart_info_t *port = (MCF5272_uart_info_t *)chan->dev_priv;
607
 
608
    /* Make sure the transmitter is not full. If it is full, return false. */
609
    if  (!(MCF5272_UART_READ(port->base->usr_ucsr) & MCF5272_UART_USR_TXRDY))
610
        return false;
611
 
612
    /* Enable transmit interrupt. */
613
    HAL_DISABLE_INTERRUPTS(int_state);
614
    port->imr_mirror |= MCF5272_UART_UIMR_TXRDY;
615
    MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
616
    HAL_RESTORE_INTERRUPTS(int_state);
617
 
618
    /* Enable the UART transmit. */
619
    MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXRXEN);
620
 
621
        /* Send the character */
622
    MCF5272_UART_WRITE(port->base->urb_utb, c);
623
 
624
        return true ;
625
}
626
 
627
 
628
/******************************************************************************************************
629
 MCF5272_uart_getc() - Fetch a character from the device input bufferand return it to the alling
630
                       routine. Wait until there is a character ready.
631
 
632
 INPUT:
633
    chan - pointer to the serial private data.
634
 
635
 RETURN:
636
    the character read from the UART.
637
 
638
 */
639
static unsigned char MCF5272_uart_getc(serial_channel *chan)
640
{
641
    MCF5272_uart_info_t * port = (MCF5272_uart_info_t *)chan->dev_priv;
642
 
643
    /* Wait until character has been received */
644
 
645
        while (!(MCF5272_UART_READ(port->base->usr_ucsr) & MCF5272_UART_USR_RXRDY))
646
    {
647
        diag_printf("ready poll");
648
    }
649
 
650
    /* Read the character from the FIFO queue. */
651
 
652
    return MCF5272_UART_READ(port->base->urf);
653
 
654
}
655
 
656
 
657
/*******************************************************************************
658
 MCF5272_uart_set_config() - Set up the device characteristics; baud rate, etc.
659
 
660
 INPUT:
661
    chan - pointer to the serial private data.
662
    key  - configuration key (command).
663
    xbuf - pointer to the configuration buffer
664
    len  - the length of the configuration buffer
665
 
666
 RETURN:
667
    NOERR - If the configuration is successful
668
    EINVAL -  If the argument is invalid
669
 
670
*/
671
 
672
Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, cyg_uint32 key,
673
                            const void *xbuf, cyg_uint32 *len)
674
{
675
    cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
676
    MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
677
 
678
 
679
    switch (key) {
680
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
681
      {
682
          /* Set serial configuration. */
683
              if ( *len < sizeof(cyg_serial_info_t) ) {
684
              return EINVAL;
685
          }
686
          *len = sizeof(cyg_serial_info_t);
687
 
688
          if (!MCF5272_uart_config_port(chan, config))
689
              return EINVAL;
690
      }
691
      break;
692
 
693
    case CYG_IO_GET_CONFIG_SERIAL_INFO:
694
        // Retrieve UART configuration
695
        *config = port->config;
696
        break;
697
 
698
    default:
699
        return EINVAL;
700
    }
701
    return ENOERR;
702
}
703
 
704
 
705
/*******************************************************************************
706
  MCF5272_uart_start_xmit() - Enable the transmitter on the device.
707
 
708
  INPUT:
709
    chan - pointer to the serial private data.
710
 
711
*/
712
static void MCF5272_uart_start_xmit(serial_channel *chan)
713
{
714
    CYG_INTERRUPT_STATE int_state;
715
    MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
716
 
717
    /* Enable the UART transmit. */
718
    MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXEN);
719
 
720
    /* Enable transmit interrupt */
721
    HAL_DISABLE_INTERRUPTS(int_state);
722
    port->imr_mirror |= MCF5272_UART_UIMR_TXRDY;
723
    MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
724
    HAL_RESTORE_INTERRUPTS(int_state);
725
 
726
 
727
}
728
 
729
 
730
/******************************************************************************************************
731
 MCF5272_uart_stop_xmit() - Disable the transmitter on the device
732
 
733
 INPUT:
734
    chan - pointer to the serial private data.
735
 
736
*/
737
static void MCF5272_uart_stop_xmit(serial_channel * chan)
738
{
739
   CYG_INTERRUPT_STATE int_state;
740
   MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
741
 
742
   /* Disable transmit interrupt */
743
   HAL_DISABLE_INTERRUPTS(int_state);
744
   port->imr_mirror &= ~MCF5272_UART_UIMR_TXRDY;
745
   MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
746
   HAL_RESTORE_INTERRUPTS(int_state);
747
 
748
   /* Disable the UART transmit.
749
      !!!!!!!!!!!!!
750
      !!!WARNING!!!
751
      !!!!!!!!!!!!!
752
      If the transmit the disabe
753
      the diag_printf routines will poll forever to transmit the
754
      a character. Hence, don't ever disable the transmit if
755
      we want it to work with diag_printf.
756
   */
757
   //MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXDE);
758
 
759
 
760
}
761
 
762
 
763
/******************************************************************************************************
764
 MCF5272_uart_ISR() - UART I/O interrupt interrupt service routine (ISR).
765
 
766
 INPUT:
767
    vector - the interrupt vector number
768
    data   - user parameter.
769
 
770
 
771
 RETURN:
772
     returns CYG_ISR_CALL_DSR to call the DSR.
773
 
774
 */
775
static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data)
776
{
777
    serial_channel *chan = (serial_channel *) data;
778
    MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
779
 
780
 
781
    /* Write the value in the interrupt status register back
782
       to the mask register to disable the interrupt temporarily.
783
     */
784
 
785
    MCF5272_UART_WRITE(port->base->uisr_uimr, 0);
786
 
787
    return CYG_ISR_CALL_DSR;  // Cause DSR to run
788
}
789
 
790
 
791
 
792
/******************************************************************************************************
793
 MCF5272_uart_DSR() - Defered Service Routine (DSR) - This routine processes the interrupt
794
                      from the device.
795
 
796
 INPUT:
797
    vector - The interrupt vector number
798
    count  - The nunber of DSR requests.
799
    data   - Device specific information
800
 
801
*/
802
 
803
static void MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
804
{
805
    serial_channel *chan = (serial_channel *)data;
806
    MCF5272_uart_info_t *port = (MCF5272_uart_info_t *)chan->dev_priv;
807
    volatile u8_t isr;
808
 
809
 
810
    /* Retrieve the interrupt status bits. We use these status bits to figure out
811
       what process shouled we perform: read from the UART or inform of a completion
812
       of a data transmission.
813
    */
814
 
815
    /* Retrieve the interrupt status register so
816
     * the DSR can look it up.
817
     */
818
 
819
 
820
    while((isr = (MCF5272_UART_READ(port->base->uisr_uimr) & port->imr_mirror)))
821
    {
822
       switch (port->autobaud_state)
823
       {
824
       default:
825
       case AB_IDLE:
826
           if (isr & MCF5272_UART_UISR_DB)
827
           {
828
               /* Detected the begin of a break, set the state to AB_BEGIN_BREAK
829
               */
830
               port->autobaud_state = AB_BEGIN_BREAK;
831
 
832
               /* Reset the Delta Break bit in the UISR */
833
               MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_BKCHGINT);
834
 
835
           }
836
           break;
837
       case AB_BEGIN_BREAK:
838
           if (isr & MCF5272_UART_UISR_DB)
839
           {
840
               /* Detected the end of a break, set the state to AB_BEGIN, and
841
                  setup autobaud detection.
842
               */
843
               port->autobaud_state = AB_BEGIN;
844
 
845
               /* Reset the Delta Break bit in the UISR and Enable autobaud */
846
               MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_BKCHGINT |
847
                                  MCF5272_UART_UCR_ENAB);
848
 
849
               /* Enable autobaud completion interrupt */
850
               port->imr_mirror |= MCF5272_UART_UIMR_ABC;
851
               /* Disable the delta break interrupt so we can't receive
852
                  anymore break interrupt.
853
               */
854
               port->imr_mirror &= ~MCF5272_UART_UIMR_DB;
855
 
856
           }
857
           break;
858
 
859
       case AB_BEGIN:
860
           if (isr & MCF5272_UART_UISR_ABC)
861
           {
862
               int count;
863
               // Retrieve the baudrate that we're using now.
864
               u16_t divider = (port->base->uabu << 8) + port->base->uabl;
865
               // Search in the list to find a match.
866
               for (count = sizeof(dividers_table)/sizeof(unsigned long) - 1;
867
                    count >= 0;
868
                    count--)
869
               {
870
                   if (divider < dividers_table[count]) break;
871
               }
872
 
873
               // Set the baud.
874
               port->config.baud = count;
875
 
876
               /* Autobaud completion */
877
               port->autobaud_state = AB_IDLE;
878
 
879
               /* Disable autobaud */
880
               MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_NONE);
881
 
882
               /* Ignore autobaud completion interrupt. */
883
               port->imr_mirror &= ~MCF5272_UART_UIMR_ABC;
884
 
885
               /* Reenable begin break change and receive interrupt. */
886
               port->imr_mirror |= MCF5272_UART_UIMR_DB;
887
 
888
           }
889
           break;
890
 
891
       }
892
 
893
 
894
        /* Receive character interrupt */
895
        if ((isr & MCF5272_UART_UISR_RXRDY))
896
            /* Ignore all receive interrupt when we're autobauding. */
897
        {
898
            // Read all the characters in the fifo.
899
            while ((MCF5272_UART_READ(port->base->uisr_uimr) & MCF5272_UART_UISR_RXRDY))
900
            {
901
                char c;
902
                /* Read the character from the UART. */
903
                c = MCF5272_UART_READ(port->base->urb_utb);
904
                /* Pass the read character to the upper layer. */
905
                (chan->callbacks->rcv_char)(chan, c);
906
            }
907
        }
908
 
909
        /* Transmit  complete interrupt */
910
 
911
        if ((isr & MCF5272_UART_UISR_TXRDY))
912
        {
913
 
914
            /*   Transmit holding register is empty                         */
915
           (chan->callbacks->xmt_char)(chan);
916
 
917
        }
918
 
919
    }
920
 
921
    /*   Unmask all the DUART interrupts  that were masked  in the ISR,  so */
922
    /* that we can receive the next interrupt.                              */
923
 
924
    MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
925
 
926
}
927
 
928
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
929
unsigned long MCF5272_uart_get_channel_0_baud_rate()
930
{
931
    /* return the baud rate for the first serial port */
932
 
933
    return baud_rates_table[MCF5272_uart_channel_info_0.config.baud];
934
}
935
#endif
936
 
937
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
938
unsigned long MCF5272_uart_get_channel_1_baud_rate()
939
{
940
    /* return the baud rate for the second serial port */
941
 
942
    return baud_rates_table[MCF5272_uart_channel_info_1.config.baud];
943
}
944
#endif
945
 
946
 

powered by: WebSVN 2.1.0

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