Mercurial > flash_v2
changeset 832:71beb8096c67
Add support for SCC1/SCC2/SCC3
| author | gthomas |
|---|---|
| date | Mon, 17 Mar 2003 22:17:35 +0000 |
| parents | 0b41b42148e9 |
| children | da5d1a18f69c |
| files | packages/devs/serial/powerpc/quicc/current/ChangeLog packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h |
| diffstat | 4 files changed, 935 insertions(+), 221 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/devs/serial/powerpc/quicc/current/ChangeLog +++ b/packages/devs/serial/powerpc/quicc/current/ChangeLog @@ -1,3 +1,10 @@ +2003-03-17 Gary Thomas <gary@mlbassoc.com> + + * src/quicc_smc_serial.h: + * src/quicc_smc_serial.c: + * cdl/ser_quicc_smc.cdl: Add support for SCC1/SCC2/SCC3. Inspired + by Paul Randall <prandall@delta-info.com> + 2003-03-05 Gary Thomas <gary@mlbassoc.com> * src/quicc_smc_serial.c: Use common routines to manage CPM/DPRAM
--- a/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl +++ b/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl @@ -2,14 +2,14 @@ # # ser_quicc_smc.cdl # -# eCos serial PowerPC/QUICC SMC configuration data +# eCos serial PowerPC/QUICC SMC/SCC configuration data # # ==================================================================== #####ECOSGPLCOPYRIGHTBEGIN#### ## ------------------------------------------- ## This file is part of eCos, the Embedded Configurable Operating System. ## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -## Copyright (C) 2002 Gary Thomas +## Copyright (C) 2002, 2003 Gary Thomas ## ## eCos is free software; you can redistribute it and/or modify it under ## the terms of the GNU General Public License as published by the Free @@ -63,7 +63,7 @@ cdl_package CYGPKG_IO_SERIAL_POWERPC_QUI include_files ; # none _exported_ whatsoever description " This option enables the serial device drivers for the - PowerPC QUICC/SMC." + PowerPC QUICC/SMC/SCC." compile -library=libextras.a quicc_smc_serial.c @@ -76,7 +76,7 @@ cdl_package CYGPKG_IO_SERIAL_POWERPC_QUI cdl_component CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1 { display "PowerPC QUICC/SMC serial port 1 driver" flavor bool - requires CYGNUM_HAL_QUICC_SMC1 + active_if CYGNUM_HAL_QUICC_SMC1 default_value 1 description " This option includes the serial device driver for the PowerPC @@ -167,7 +167,7 @@ cdl_component CYGPKG_IO_SERIAL_POWERPC_Q cdl_component CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2 { display "PowerPC QUICC/SMC serial port 2 driver" flavor bool - requires CYGNUM_HAL_QUICC_SMC2 + active_if CYGNUM_HAL_QUICC_SMC2 default_value 1 description " This option includes the serial device driver for the PowerPC @@ -288,4 +288,277 @@ cdl_component CYGPKG_IO_SERIAL_POWERPC_Q } } +cdl_component CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1 { + display "PowerPC QUICC/SCC serial port 1 driver" + flavor bool + active_if CYGNUM_HAL_QUICC_SCC1 + default_value 1 + description " + This option includes the serial device driver for the PowerPC + QUICC/SCC port 1." + + cdl_option CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_NAME { + display "Device name for PowerPC QUICC/SCC serial port 1" + flavor data + default_value {"\"/dev/scc1\""} + description " + This option specifies the device name for the PowerPC + QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BAUD { + display "Baud rate for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 230400 + } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BUFSIZE { + display "Buffer size for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 0 to 8192 + default_value 256 + description " + This option specifies the size of the internal buffers used + for the PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BRG { + display "Which baud rate generator to use for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 1 to 4 + default_value 2 + description " + This option specifies which of the four baud rate generators + to use for the PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxSIZE { + display "Output buffer size for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per + transmit request to be used for the PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM { + display "Number of output buffers for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of output buffer packets + to be used for the PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxSIZE { + display "Input buffer size for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per receive + request to be used for the PowerPC QUICC/SCC port 1." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM { + display "Number of input buffers for the PowerPC QUICC/SCC serial port 1" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of input buffer packets + to be used for the PowerPC QUICC/SCC port 1." + } +} + +cdl_component CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2 { + display "PowerPC QUICC/SCC serial port 2 driver" + flavor bool + active_if CYGNUM_HAL_QUICC_SCC2 + default_value 1 + description " + This option includes the serial device driver for the PowerPC + QUICC/SCC port 2." + + cdl_option CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_NAME { + display "Device name for PowerPC QUICC/SCC serial port 2" + flavor data + default_value {"\"/dev/scc2\""} + description " + This option specifies the device name for the PowerPC + QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BAUD { + display "Baud rate for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 230400 + } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BUFSIZE { + display "Buffer size for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 0 to 8192 + default_value 256 + description " + This option specifies the size of the internal buffers used + for the PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BRG { + display "Which baud rate generator to use for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 1 to 4 + default_value 3 + description " + This option specifies which of the four baud rate generators + to use for the PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxSIZE { + display "Output buffer size for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per + transmit request to be used for the PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM { + display "Number of output buffers for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of output buffer packets + to be used for the PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxSIZE { + display "Input buffer size for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per receive + request to be used for the PowerPC QUICC/SCC port 2." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM { + display "Number of input buffers for the PowerPC QUICC/SCC serial port 2" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of input buffer packets + to be used for the PowerPC QUICC/SCC port 2." + } +} + +cdl_component CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3 { + display "PowerPC QUICC/SCC serial port 3 driver" + flavor bool + active_if CYGNUM_HAL_QUICC_SCC3 + default_value 1 + description " + This option includes the serial device driver for the PowerPC + QUICC/SCC port 3." + + cdl_option CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_NAME { + display "Device name for PowerPC QUICC/SCC serial port 3" + flavor data + default_value {"\"/dev/scc3\""} + description " + This option specifies the device name for the PowerPC + QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BAUD { + display "Baud rate for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values { 50 75 110 "134_5" 150 200 300 600 1200 1800 2400 3600 + 4800 7200 9600 14400 19200 38400 57600 115200 230400 + } + default_value 38400 + description " + This option specifies the default baud rate (speed) for the + PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE { + display "Buffer size for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 0 to 8192 + default_value 256 + description " + This option specifies the size of the internal buffers used + for the PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BRG { + display "Which baud rate generator to use for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 1 to 4 + default_value 4 + description " + This option specifies which of the four baud rate generators + to use for the PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE { + display "Output buffer size for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per + transmit request to be used for the PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM { + display "Number of output buffers for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of output buffer packets + to be used for the PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE { + display "Input buffer size for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 16 to 128 + default_value 16 + description " + This option specifies the maximum number of characters per receive + request to be used for the PowerPC QUICC/SCC port 3." + } + + cdl_option CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM { + display "Number of input buffers for the PowerPC QUICC/SCC serial port 3" + flavor data + legal_values 2 to 16 + default_value 4 + description " + This option specifies the number of input buffer packets + to be used for the PowerPC QUICC/SCC port 3." + } +} + # EOF ser_quicc_smc.cdl
--- a/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c +++ b/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c @@ -2,7 +2,7 @@ // // io/serial/powerpc/quicc_smc_serial.c // -// PowerPC QUICC (SMC) Serial I/O Interface Module (interrupt driven) +// PowerPC QUICC (SMC/SCC) Serial I/O Interface Module (interrupt driven) // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### @@ -68,98 +68,70 @@ // macro for aligning buffers to cache lines #define ALIGN_TO_CACHELINES(b) ((cyg_uint8 *)(((CYG_ADDRESS)(b) + (HAL_DCACHE_LINE_SIZE-1)) & ~(HAL_DCACHE_LINE_SIZE-1))) -// Buffer descriptor control bits -#define QUICC_BD_CTL_Ready 0x8000 // Buffer contains data (tx) or is empty (rx) -#define QUICC_BD_CTL_Wrap 0x2000 // Last buffer in list -#define QUICC_BD_CTL_Int 0x1000 // Generate interrupt when empty (tx) or full (rx) -#define QUICC_BD_CTL_MASK 0xB000 // User settable bits - -// SMC Mode Register -#define QUICC_SMCMR_CLEN(n) ((n+1)<<11) // Character length -#define QUICC_SMCMR_SB(n) ((n-1)<<10) // Stop bits (1 or 2) -#define QUICC_SMCMR_PE(n) (n<<9) // Parity enable (0=disable, 1=enable) -#define QUICC_SMCMR_PM(n) (n<<8) // Parity mode (0=odd, 1=even) -#define QUICC_SMCMR_UART (2<<4) // UART mode -#define QUICC_SMCMR_TEN (1<<1) // Enable transmitter -#define QUICC_SMCMR_REN (1<<0) // Enable receiver - -// SMC Events (interrupts) -#define QUICC_SMCE_BRK 0x10 // Break received -#define QUICC_SMCE_BSY 0x04 // Busy - receive buffer overrun -#define QUICC_SMCE_TX 0x02 // Tx interrupt -#define QUICC_SMCE_RX 0x01 // Rx interrupt - -// SMC Commands -#define QUICC_SMC_CMD_InitTxRx (0<<8) -#define QUICC_SMC_CMD_InitTx (1<<8) -#define QUICC_SMC_CMD_InitRx (2<<8) -#define QUICC_SMC_CMD_StopTx (4<<8) -#define QUICC_SMC_CMD_RestartTx (6<<8) -#define QUICC_SMC_CMD_Reset 0x8000 -#define QUICC_SMC_CMD_Go 0x0001 - #include "quicc_smc_serial.h" -typedef struct quicc_smc_serial_info { - CYG_ADDRWORD channel; // Which channel SMC1/SMC2 - CYG_WORD int_num; // Interrupt number +typedef struct quicc_sxx_serial_info { + CYG_ADDRWORD channel; // Which channel SMCx/SCCx + short int_num; // Interrupt number + short type; // Channel type - SCC or SMC cyg_uint32 *brg; // Which baud rate generator - volatile struct smc_uart_pram *pram; // Parameter RAM pointer - volatile struct smc_regs *ctl; // SMC control registers + void *pram; // Parameter RAM pointer + void *ctl; // SMC/SCC control registers volatile struct cp_bufdesc *txbd, *rxbd; // Next Tx,Rx descriptor to use struct cp_bufdesc *tbase, *rbase; // First Tx,Rx descriptor int txsize, rxsize; // Length of individual buffers cyg_interrupt serial_interrupt; cyg_handle_t serial_interrupt_handle; -} quicc_smc_serial_info; +} quicc_sxx_serial_info; -static bool quicc_smc_serial_init(struct cyg_devtab_entry *tab); -static bool quicc_smc_serial_putc(serial_channel *chan, unsigned char c); -static Cyg_ErrNo quicc_smc_serial_lookup(struct cyg_devtab_entry **tab, +static bool quicc_sxx_serial_init(struct cyg_devtab_entry *tab); +static bool quicc_sxx_serial_putc(serial_channel *chan, unsigned char c); +static Cyg_ErrNo quicc_sxx_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name); -static unsigned char quicc_smc_serial_getc(serial_channel *chan); -static Cyg_ErrNo quicc_smc_serial_set_config(serial_channel *chan, +static unsigned char quicc_sxx_serial_getc(serial_channel *chan); +static Cyg_ErrNo quicc_sxx_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); -static void quicc_smc_serial_start_xmit(serial_channel *chan); -static void quicc_smc_serial_stop_xmit(serial_channel *chan); +static void quicc_sxx_serial_start_xmit(serial_channel *chan); +static void quicc_sxx_serial_stop_xmit(serial_channel *chan); -static cyg_uint32 quicc_smc_serial_ISR(cyg_vector_t vector, cyg_addrword_t data); -static void quicc_smc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); +static cyg_uint32 quicc_sxx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data); +static void quicc_sxx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); -static SERIAL_FUNS(quicc_smc_serial_funs, - quicc_smc_serial_putc, - quicc_smc_serial_getc, - quicc_smc_serial_set_config, - quicc_smc_serial_start_xmit, - quicc_smc_serial_stop_xmit +static SERIAL_FUNS(quicc_sxx_serial_funs, + quicc_sxx_serial_putc, + quicc_sxx_serial_getc, + quicc_sxx_serial_set_config, + quicc_sxx_serial_start_xmit, + quicc_sxx_serial_stop_xmit ); #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1 -static quicc_smc_serial_info quicc_smc_serial_info1 = { - 0x90, // Channel indicator - CYGNUM_HAL_INTERRUPT_CPM_SMC1 // interrupt +static quicc_sxx_serial_info quicc_sxx_serial_info_smc1 = { + QUICC_CPM_SMC1, // Channel indicator + CYGNUM_HAL_INTERRUPT_CPM_SMC1, // interrupt + _SMC_CHAN }; #if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BUFSIZE > 0 -static unsigned char quicc_smc_serial_out_buf1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BUFSIZE]; -static unsigned char quicc_smc_serial_in_buf1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BUFSIZE]; +static unsigned char quicc_smc_serial_out_buf_smc1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BUFSIZE]; +static unsigned char quicc_smc_serial_in_buf_smc1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BUFSIZE]; -static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_smc_serial_channel1, - quicc_smc_serial_funs, - quicc_smc_serial_info1, +static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_smc1, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_smc1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, - &quicc_smc_serial_out_buf1[0], sizeof(quicc_smc_serial_out_buf1), - &quicc_smc_serial_in_buf1[0], sizeof(quicc_smc_serial_in_buf1) + &quicc_smc_serial_out_buf_smc1[0], sizeof(quicc_smc_serial_out_buf_smc1), + &quicc_smc_serial_in_buf_smc1[0], sizeof(quicc_smc_serial_in_buf_smc1) ); #else -static SERIAL_CHANNEL(quicc_smc_serial_channel1, - quicc_smc_serial_funs, - quicc_smc_serial_info1, +static SERIAL_CHANNEL(quicc_sxx_serial_channel_smc1, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_smc1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, @@ -171,40 +143,41 @@ static SERIAL_CHANNEL(quicc_smc_serial_c static unsigned char quicc_smc1_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxSIZE + HAL_DCACHE_LINE_SIZE-1]; static unsigned char quicc_smc1_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxSIZE + HAL_DCACHE_LINE_SIZE-1]; -DEVTAB_ENTRY(quicc_smc_serial_io1, +DEVTAB_ENTRY(quicc_smc_serial_io_smc1, CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, - quicc_smc_serial_init, - quicc_smc_serial_lookup, // Serial driver may need initializing - &quicc_smc_serial_channel1 + quicc_sxx_serial_init, + quicc_sxx_serial_lookup, // Serial driver may need initializing + &quicc_sxx_serial_channel_smc1 ); #endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1 #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2 -static quicc_smc_serial_info quicc_smc_serial_info2 = { - 0xD0, // Channel indicator - CYGNUM_HAL_INTERRUPT_CPM_SMC2_PIP // interrupt +static quicc_sxx_serial_info quicc_sxx_serial_info_smc2 = { + QUICC_CPM_SMC2, // Channel indicator + CYGNUM_HAL_INTERRUPT_CPM_SMC2_PIP, // interrupt + _SMC_CHAN }; #if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BUFSIZE > 0 -static unsigned char quicc_smc_serial_out_buf2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BUFSIZE]; -static unsigned char quicc_smc_serial_in_buf2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BUFSIZE]; +static unsigned char quicc_smc_serial_out_buf_smc2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BUFSIZE]; +static unsigned char quicc_smc_serial_in_buf_smc2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BUFSIZE]; -static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_smc_serial_channel2, - quicc_smc_serial_funs, - quicc_smc_serial_info2, +static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_smc2, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_smc2, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, - &quicc_smc_serial_out_buf2[0], sizeof(quicc_smc_serial_out_buf2), - &quicc_smc_serial_in_buf2[0], sizeof(quicc_smc_serial_in_buf2) + &quicc_smc_serial_out_buf_smc2[0], sizeof(quicc_smc_serial_out_buf_smc2), + &quicc_smc_serial_in_buf_smc2[0], sizeof(quicc_smc_serial_in_buf_smc2) ); #else -static SERIAL_CHANNEL(quicc_smc_serial_channel2, - quicc_smc_serial_funs, - quicc_smc_serial_info2, +static SERIAL_CHANNEL(quicc_sxx_serial_channel_smc2, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_smc2, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, @@ -215,47 +188,175 @@ static SERIAL_CHANNEL(quicc_smc_serial_c static unsigned char quicc_smc2_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxSIZE + HAL_DCACHE_LINE_SIZE-1]; static unsigned char quicc_smc2_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxSIZE + HAL_DCACHE_LINE_SIZE-1]; -DEVTAB_ENTRY(quicc_smc_serial_io2, +DEVTAB_ENTRY(quicc_smc_serial_io_smc2, CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, - quicc_smc_serial_init, - quicc_smc_serial_lookup, // Serial driver may need initializing - &quicc_smc_serial_channel2 + quicc_sxx_serial_init, + quicc_sxx_serial_lookup, // Serial driver may need initializing + &quicc_sxx_serial_channel_smc2 ); #endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2 -#ifdef CYGDBG_DIAG_BUF -extern int enable_diag_uart; -#endif // CYGDBG_DIAG_BUF +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1 +static quicc_sxx_serial_info quicc_sxx_serial_info_scc1 = { + QUICC_CPM_SCC1, // Channel indicator + CYGNUM_HAL_INTERRUPT_CPM_SCC1, // interrupt + _SCC_CHAN +}; +#if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BUFSIZE > 0 +static unsigned char quicc_smc_serial_out_buf_scc1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BUFSIZE]; +static unsigned char quicc_smc_serial_in_buf_scc1[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_scc1, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &quicc_smc_serial_out_buf_scc1[0], sizeof(quicc_smc_serial_out_buf_scc1), + &quicc_smc_serial_in_buf_scc1[0], sizeof(quicc_smc_serial_in_buf_scc1) + ); +#else +static SERIAL_CHANNEL(quicc_sxx_serial_channel_scc1, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc1, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif +static unsigned char quicc_scc1_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxSIZE + HAL_DCACHE_LINE_SIZE-1]; +static unsigned char quicc_scc1_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxSIZE + HAL_DCACHE_LINE_SIZE-1]; + +DEVTAB_ENTRY(quicc_smc_serial_io_scc1, + CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + quicc_sxx_serial_init, + quicc_sxx_serial_lookup, // Serial driver may need initializing + &quicc_sxx_serial_channel_scc1 + ); +#endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1 + +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2 +static quicc_sxx_serial_info quicc_sxx_serial_info_scc2 = { + QUICC_CPM_SCC2, // Channel indicator + CYGNUM_HAL_INTERRUPT_CPM_SCC2, // interrupt + _SCC_CHAN +}; +#if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BUFSIZE > 0 +static unsigned char quicc_smc_serial_out_buf_scc2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BUFSIZE]; +static unsigned char quicc_smc_serial_in_buf_scc2[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_scc2, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &quicc_smc_serial_out_buf_scc2[0], sizeof(quicc_smc_serial_out_buf_scc2), + &quicc_smc_serial_in_buf_scc2[0], sizeof(quicc_smc_serial_in_buf_scc2) + ); +#else +static SERIAL_CHANNEL(quicc_sxx_serial_channel_scc2, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc2, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif +static unsigned char quicc_scc2_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxSIZE + HAL_DCACHE_LINE_SIZE-1]; +static unsigned char quicc_scc2_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxSIZE + HAL_DCACHE_LINE_SIZE-1]; + +DEVTAB_ENTRY(quicc_smc_serial_io_scc2, + CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + quicc_sxx_serial_init, + quicc_sxx_serial_lookup, // Serial driver may need initializing + &quicc_sxx_serial_channel_scc2 + ); +#endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2 + +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3 +static quicc_sxx_serial_info quicc_sxx_serial_info_scc3 = { + QUICC_CPM_SCC3, // Channel indicator + CYGNUM_HAL_INTERRUPT_CPM_SCC3, // interrupt + _SCC_CHAN +}; +#if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE > 0 +static unsigned char quicc_smc_serial_out_buf_scc3[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE]; +static unsigned char quicc_smc_serial_in_buf_scc3[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE]; + +static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_scc3, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT, + &quicc_smc_serial_out_buf_scc3[0], sizeof(quicc_smc_serial_out_buf_scc3), + &quicc_smc_serial_in_buf_scc3[0], sizeof(quicc_smc_serial_in_buf_scc3) + ); +#else +static SERIAL_CHANNEL(quicc_sxx_serial_channel_scc3, + quicc_sxx_serial_funs, + quicc_sxx_serial_info_scc3, + CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BAUD), + CYG_SERIAL_STOP_DEFAULT, + CYG_SERIAL_PARITY_DEFAULT, + CYG_SERIAL_WORD_LENGTH_DEFAULT, + CYG_SERIAL_FLAGS_DEFAULT + ); +#endif +static unsigned char quicc_scc3_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE + HAL_DCACHE_LINE_SIZE-1]; +static unsigned char quicc_scc3_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM][CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE + HAL_DCACHE_LINE_SIZE-1]; + +DEVTAB_ENTRY(quicc_smc_serial_io_scc3, + CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_NAME, + 0, // Does not depend on a lower level interface + &cyg_io_serial_devio, + quicc_sxx_serial_init, + quicc_sxx_serial_lookup, // Serial driver may need initializing + &quicc_sxx_serial_channel_scc3 + ); +#endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3 // Internal function to actually configure the hardware to desired baud rate, etc. static bool quicc_smc_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init) { - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; unsigned int baud_divisor = select_baud[new_config->baud]; cyg_uint32 _lcr; EPPC *eppc = eppc_base(); + volatile struct smc_regs *ctl = (volatile struct smc_regs *)smc_chan->ctl; + if (baud_divisor == 0) return false; // Disable channel during setup - smc_chan->ctl->smc_smcmr = QUICC_SMCMR_UART; // Disabled, UART mode + ctl->smc_smcmr = QUICC_SMCMR_UART; // Disabled, UART mode // Disable port interrupts while changing hardware - _lcr = select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] | - select_stop_bits[new_config->stop] | - select_parity[new_config->parity]; + _lcr = smc_select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] | + smc_select_stop_bits[new_config->stop] | + smc_select_parity[new_config->parity]; // Stop transmitter while changing baud rate eppc->cp_cr = smc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_StopTx; // Set baud rate generator *smc_chan->brg = 0x10000 | (UART_BITRATE(baud_divisor)<<1); -#ifdef XX_CYGDBG_DIAG_BUF - enable_diag_uart = 0; - diag_printf("Set BAUD RATE[%x], %d = %x, tstate = %x\n", smc_chan->brg, baud_divisor, *smc_chan->brg, smc_chan->pram->tstate); - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF // Enable channel with new configuration - smc_chan->ctl->smc_smcmr = QUICC_SMCMR_UART|QUICC_SMCMR_TEN|QUICC_SMCMR_REN|_lcr; + ctl->smc_smcmr = QUICC_SMCMR_UART|QUICC_SMCMR_TEN|QUICC_SMCMR_REN|_lcr; eppc->cp_cr = smc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_RestartTx; if (new_config != &chan->config) { chan->config = *new_config; @@ -265,7 +366,7 @@ quicc_smc_serial_config_port(serial_chan // Function to set up internal tables for device. static void -quicc_smc_serial_init_info(quicc_smc_serial_info *smc_chan, +quicc_smc_serial_init_info(quicc_sxx_serial_info *smc_chan, volatile struct smc_uart_pram *uart_pram, volatile struct smc_regs *ctl, int TxBD, int TxNUM, int TxSIZE, @@ -282,8 +383,8 @@ quicc_smc_serial_init_info(quicc_smc_ser // Disable channel during setup ctl->smc_smcmr = QUICC_SMCMR_UART; // Disabled, UART mode - smc_chan->pram = uart_pram; - smc_chan->ctl = ctl; + smc_chan->pram = (void *)uart_pram; + smc_chan->ctl = (void *)ctl; /* * SDMA & LCD bus request level 5 * (Section 16.10.2.1) @@ -382,32 +483,194 @@ quicc_smc_serial_init_info(quicc_smc_ser ctl->smc_smcm = QUICC_SMCE_BSY|QUICC_SMCE_TX|QUICC_SMCE_RX; } +// Internal function to actually configure the hardware to desired baud rate, etc. +static bool +quicc_scc_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init) +{ + quicc_sxx_serial_info *scc_chan = (quicc_sxx_serial_info *)chan->dev_priv; + unsigned int baud_divisor = select_baud[new_config->baud]; + EPPC *eppc = eppc_base(); + volatile struct scc_regs *regs = (volatile struct scc_regs *)scc_chan->ctl; + + if (baud_divisor == 0) return false; + // Set baud rate generator + *scc_chan->brg = 0x10000 | (UART_BITRATE(baud_divisor)<<1); + // Disable channel during setup + regs->scc_gsmr_l = 0; + regs->scc_psmr = QUICC_SCC_PSMR_ASYNC | + scc_select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] | + scc_select_stop_bits[new_config->stop] | + scc_select_parity[new_config->parity]; + + // Enable channel with new configuration + regs->scc_gsmr_h = 0x20; // 8bit FIFO + regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART + + /* + * Init Rx & Tx params for SCCX + */ + eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | scc_chan->channel | QUICC_CPM_CR_BUSY; + + regs->scc_gsmr_l |= (QUICC_SCC_GSMR_L_Tx | QUICC_SCC_GSMR_L_Rx); // Enable Rx, Tx + if (new_config != &chan->config) { + chan->config = *new_config; + } + return true; +} + +// Function to set up internal tables for device. +static void +quicc_scc_serial_init_info(quicc_sxx_serial_info *scc_chan, + volatile struct uart_pram *uart_pram, + volatile struct scc_regs *ctl, + int TxBD, int TxNUM, int TxSIZE, + cyg_uint8 *TxBUF, + int RxBD, int RxNUM, int RxSIZE, + cyg_uint8 *RxBUF, + int portAmask, int portBmask, int portCmask, + int BRG, int SIpos) +{ + EPPC *eppc = eppc_base(); + struct cp_bufdesc *txbd, *rxbd; + cyg_uint32 simode = 0; + int i; + + // Disable channel during setup + ctl->scc_gsmr_l = 0; + scc_chan->pram = (void *)uart_pram; + scc_chan->ctl = (void *)ctl; + /* + * SDMA & LCD bus request level 5 + * (Section 16.10.2.1) + */ + eppc->dma_sdcr = 1; + switch (BRG) { + case 1: + scc_chan->brg = (cyg_uint32 *)&eppc->brgc1; + simode = 0; + break; + case 2: + scc_chan->brg = (cyg_uint32 *)&eppc->brgc2; + simode = 1; + break; + case 3: + scc_chan->brg = (cyg_uint32 *)&eppc->brgc3; + simode = 2; + break; + case 4: + scc_chan->brg = (cyg_uint32 *)&eppc->brgc4; + simode = 3; + break; + } + // Route baud rate generators + eppc->si_sicr = (eppc->si_sicr & ~(0xFF<<SIpos)) | (((simode<<3)|(simode<<0))<<SIpos); + /* + * Set up the PortA/B/C pins for UART operation. + */ + eppc->pio_papar |= portAmask; + eppc->pio_padir &= ~portAmask; + eppc->pio_paodr &= ~portAmask; + + eppc->pio_pcdir &= portCmask; + eppc->pio_pcpar &= portCmask; + eppc->pio_pcso |= portCmask; + + eppc->pip_pbpar |= portBmask; + eppc->pip_pbdir |= portBmask; + + /* + * SDMA & LCD bus request level 5 + * (Section 16.10.2.1) + */ + eppc->dma_sdcr = 1; + /* + * Set Rx and Tx function code + * (Section 16.15.4.2) + */ + uart_pram->rfcr = 0x18; + uart_pram->tfcr = 0x18; + /* + * Set pointers to buffer descriptors. + * (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13) + */ + uart_pram->rbase = RxBD; + uart_pram->tbase = TxBD; + /* tx and rx buffer descriptors */ + txbd = (struct cp_bufdesc *)((char *)eppc + TxBD); + rxbd = (struct cp_bufdesc *)((char *)eppc + RxBD); + scc_chan->txbd = txbd; + scc_chan->tbase = txbd; + scc_chan->txsize = TxSIZE; + scc_chan->rxbd = rxbd; + scc_chan->rbase = rxbd; + scc_chan->rxsize = RxSIZE; + /* max receive buffer length */ + uart_pram->mrblr = RxSIZE; + /* set max_idle feature - generate interrupt after 4 chars idle period */ + uart_pram->max_idl = 4; + /* no last brk char received */ + uart_pram->brkln = 0; + /* no break condition occurred */ + uart_pram->brkec = 0; + /* 1 break char sent on top XMIT */ + uart_pram->brkcr = 1; + /* character mask */ + uart_pram->rccm = 0xC0FF; + /* control characters */ + for (i = 0; i < 8; i++) { + uart_pram->cc[i] = 0x8000; // Mark unused + } + /* setup RX buffer descriptors */ + for (i = 0; i < RxNUM; i++) { + rxbd->length = 0; + rxbd->buffer = RxBUF; + rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; + if (i == (RxNUM-1)) rxbd->ctrl |= QUICC_BD_CTL_Wrap; // Last buffer + RxBUF += RxSIZE; + rxbd++; + } + /* setup TX buffer descriptors */ + for (i = 0; i < TxNUM; i++) { + txbd->length = 0; + txbd->buffer = TxBUF; + txbd->ctrl = 0; + if (i == (TxNUM-1)) txbd->ctrl |= QUICC_BD_CTL_Wrap; // Last buffer + TxBUF += TxSIZE; + txbd++; + } + /* + * Reset Rx & Tx params + */ + eppc->cp_cr = scc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_InitTxRx; + /* + * Clear any previous events. Enable interrupts. + * (Section 16.15.7.14 and 16.15.7.15) + */ + ctl->scc_scce = 0xFFFF; + ctl->scc_sccm = (QUICC_SCCE_BSY | QUICC_SCCE_TX | QUICC_SCCE_RX); +} + // Function to initialize the device. Called at bootstrap time. static bool -quicc_smc_serial_init(struct cyg_devtab_entry *tab) +quicc_sxx_serial_init(struct cyg_devtab_entry *tab) { serial_channel *chan = (serial_channel *)tab->priv; - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; volatile EPPC *eppc = (volatile EPPC *)eppc_base(); int TxBD, RxBD; - static int first_init = 1; int cache_state; HAL_DCACHE_IS_ENABLED(cache_state); HAL_DCACHE_SYNC(); HAL_DCACHE_DISABLE(); #ifdef CYGDBG_IO_INIT - diag_printf("QUICC_SMC SERIAL init - dev: %x.%d\n", smc_chan->channel, smc_chan->int_num); + diag_printf("QUICC_SMC SERIAL init - dev: %x.%d = %s\n", smc_chan->channel, smc_chan->int_num, tab->name); #endif - if (first_init) { - // Set up tables since many fields are dynamic [computed at runtime] - first_init = 0; #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC1 - eppc->cp_cr = QUICC_SMC_CMD_Reset | QUICC_SMC_CMD_Go; // Totally reset CP - while (eppc->cp_cr & QUICC_SMC_CMD_Reset) ; + if (chan == &quicc_sxx_serial_channel_smc1) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_RxNUM); - quicc_smc_serial_init_info(&quicc_smc_serial_info1, + quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc1, &eppc->pram[2].scc.pothers.smc_modem.psmc.u, // PRAM &eppc->smc_regs[0], // Control registers TxBD, @@ -422,24 +685,13 @@ quicc_smc_serial_init(struct cyg_devtab_ CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_BRG, 12 // SI mask position ); -#else -#ifdef CYGPKG_HAL_POWERPC_MBX - // Ensure the SMC1 side is initialized first and use shared mem - // above where it plays: - diag_init(); // (pull in constructor that inits diag channel) - TxBD = 0x2830; // Note: this should be inferred from the chip state -#else - // there is no diag device wanting to use the QUICC, so prepare it - // for SMC2 use only. - eppc->cp_cr = QUICC_SMC_CMD_Reset | QUICC_SMC_CMD_Go; // Totally reset CP - while (eppc->cp_cr & QUICC_SMC_CMD_Reset) ; - TxBD = 0x2800; // Note: this should be configurable -#endif + } #endif #ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SMC2 + if (chan == &quicc_sxx_serial_channel_smc2) { TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM); RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_RxNUM); - quicc_smc_serial_init_info(&quicc_smc_serial_info2, + quicc_smc_serial_init_info(&quicc_sxx_serial_info_smc2, &eppc->pram[3].scc.pothers.smc_modem.psmc.u, // PRAM &eppc->smc_regs[1], // Control registers TxBD, @@ -454,21 +706,94 @@ quicc_smc_serial_init(struct cyg_devtab_ CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_BRG, 28 // SI mask position ); + } #endif +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC1 + if (chan == &quicc_sxx_serial_channel_scc1) { + TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM); + RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM); + quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc1, + &eppc->pram[0].scc.pscc.u, // PRAM + &eppc->scc_regs[0], // Control registersn + TxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_TxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc1_txbuf[0][0]), + RxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_RxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc1_rxbuf[0][0]), + 0x0003, // PortA mask + 0x1000, // PortB mask + 0x0800, // PortC mask + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC1_BRG, + 0 // SI mask position + ); } +#endif +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2 + if (chan == &quicc_sxx_serial_channel_scc2) { + TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM); + RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM); + quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc2, + &eppc->pram[1].scc.pscc.u, // PRAM + &eppc->scc_regs[1], // Control registersn + TxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_TxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc2_txbuf[0][0]), + RxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_RxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc2_rxbuf[0][0]), + 0x000C, // PortA mask + 0x2000, // PortB mask + 0x0C00, // PortC mask + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC2_BRG, + 8 // SI mask position + ); + } +#endif +#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3 + if (chan == &quicc_sxx_serial_channel_scc3) { + TxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM); + RxBD = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM); + quicc_scc_serial_init_info(&quicc_sxx_serial_info_scc3, + &eppc->pram[2].scc.pscc.u, // PRAM + &eppc->scc_regs[2], // Control registersn + TxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc3_txbuf[0][0]), + RxBD, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM, + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE, + ALIGN_TO_CACHELINES(&quicc_scc3_rxbuf[0][0]), + 0x0000, // PortA mask + 0x00C0, // PortB mask + 0x0000, // PortC mask + CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BRG, + 16 // SI mask position + ); + } +#endif (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices if (chan->out_cbuf.len != 0) { cyg_drv_interrupt_create(smc_chan->int_num, CYGARC_SIU_PRIORITY_HIGH, // Priority - unused (but asserted) (cyg_addrword_t)chan, // Data item passed to interrupt handler - quicc_smc_serial_ISR, - quicc_smc_serial_DSR, + quicc_sxx_serial_ISR, + quicc_sxx_serial_DSR, &smc_chan->serial_interrupt_handle, &smc_chan->serial_interrupt); cyg_drv_interrupt_attach(smc_chan->serial_interrupt_handle); cyg_drv_interrupt_unmask(smc_chan->int_num); } - quicc_smc_serial_config_port(chan, &chan->config, true); + if (smc_chan->type == _SMC_CHAN) { + quicc_smc_serial_config_port(chan, &chan->config, true); + } else { + quicc_scc_serial_config_port(chan, &chan->config, true); + } if (cache_state) HAL_DCACHE_ENABLE(); return true; @@ -476,7 +801,7 @@ quicc_smc_serial_init(struct cyg_devtab_ // This routine is called when the device is "looked" up (i.e. attached) static Cyg_ErrNo -quicc_smc_serial_lookup(struct cyg_devtab_entry **tab, +quicc_sxx_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name) { @@ -487,7 +812,7 @@ quicc_smc_serial_lookup(struct cyg_devta // Force the current transmit buffer to be sent static void -quicc_smc_serial_flush(quicc_smc_serial_info *smc_chan) +quicc_sxx_serial_flush(quicc_sxx_serial_info *smc_chan) { volatile struct cp_bufdesc *txbd = smc_chan->txbd; int cache_state; @@ -496,7 +821,6 @@ quicc_smc_serial_flush(quicc_smc_serial_ if (cache_state) { HAL_DCACHE_FLUSH(txbd->buffer, smc_chan->txsize); } - if ((txbd->length > 0) && ((txbd->ctrl & (QUICC_BD_CTL_Ready|QUICC_BD_CTL_Int)) == 0)) { txbd->ctrl |= QUICC_BD_CTL_Ready|QUICC_BD_CTL_Int; // Signal buffer ready @@ -512,14 +836,16 @@ quicc_smc_serial_flush(quicc_smc_serial_ // Send a character to the device output buffer. // Return 'true' if character is sent to device static bool -quicc_smc_serial_putc(serial_channel *chan, unsigned char c) +quicc_sxx_serial_putc(serial_channel *chan, unsigned char c) { - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; volatile struct cp_bufdesc *txbd, *txfirst; + volatile struct smc_uart_pram *pram = (volatile struct smc_uart_pram *)smc_chan->pram; EPPC *eppc = eppc_base(); bool res; + cyg_drv_dsr_lock(); // Avoid race condition testing pointers - txbd = (struct cp_bufdesc *)((char *)eppc + smc_chan->pram->tbptr); + txbd = (struct cp_bufdesc *)((char *)eppc + pram->tbptr); txfirst = txbd; // Scan for a non-busy buffer while (txbd->ctrl & QUICC_BD_CTL_Ready) { @@ -537,7 +863,7 @@ quicc_smc_serial_putc(serial_channel *ch txbd->buffer[txbd->length++] = c; if (txbd->length == smc_chan->txsize) { // This buffer is now full, tell SMC to start processing it - quicc_smc_serial_flush(smc_chan); + quicc_sxx_serial_flush(smc_chan); } res = true; } else { @@ -550,11 +876,12 @@ quicc_smc_serial_putc(serial_channel *ch // Fetch a character from the device input buffer, waiting if necessary static unsigned char -quicc_smc_serial_getc(serial_channel *chan) +quicc_sxx_serial_getc(serial_channel *chan) { unsigned char c; - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; volatile struct cp_bufdesc *rxbd = smc_chan->rxbd; + while ((rxbd->ctrl & QUICC_BD_CTL_Ready) != 0) ; c = rxbd->buffer[0]; rxbd->length = smc_chan->rxsize; @@ -570,23 +897,31 @@ quicc_smc_serial_getc(serial_channel *ch // Set up the device characteristics; baud rate, etc. static Cyg_ErrNo -quicc_smc_serial_set_config(serial_channel *chan, cyg_uint32 key, +quicc_sxx_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len) { + int res; + switch (key) { case CYG_IO_SET_CONFIG_SERIAL_INFO: - { - // FIXME - The documentation says that you can't change the baud rate - // again until at least two BRG input clocks have occurred. + { + // FIXME - The documentation says that you can't change the baud rate + // again until at least two BRG input clocks have occurred. cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; if ( *len < sizeof(cyg_serial_info_t) ) { return -EINVAL; } *len = sizeof(cyg_serial_info_t); - if ( true != quicc_smc_serial_config_port(chan, config, false) ) + if (smc_chan->type == _SMC_CHAN) { + res = quicc_smc_serial_config_port(chan, config, true); + } else { + res = quicc_scc_serial_config_port(chan, config, true); + } + if ( true != res ) return -EINVAL; - } - break; + } + break; default: return -EINVAL; } @@ -595,9 +930,9 @@ quicc_smc_serial_set_config(serial_chann // Enable the transmitter (interrupt) on the device static void -quicc_smc_serial_start_xmit(serial_channel *chan) +quicc_sxx_serial_start_xmit(serial_channel *chan) { - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; cyg_drv_dsr_lock(); if (smc_chan->txbd->length == 0) { // See if there is anything to put in this buffer, just to get it going @@ -605,74 +940,50 @@ quicc_smc_serial_start_xmit(serial_chann } if (smc_chan->txbd->length != 0) { // Make sure it gets started - quicc_smc_serial_flush(smc_chan); + quicc_sxx_serial_flush(smc_chan); } cyg_drv_dsr_unlock(); } // Disable the transmitter on the device static void -quicc_smc_serial_stop_xmit(serial_channel *chan) +quicc_sxx_serial_stop_xmit(serial_channel *chan) { - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; // If anything is in the last buffer, need to get it started if (smc_chan->txbd->length != 0) { - quicc_smc_serial_flush(smc_chan); + quicc_sxx_serial_flush(smc_chan); } } // Serial I/O - low level interrupt handler (ISR) static cyg_uint32 -quicc_smc_serial_ISR(cyg_vector_t vector, cyg_addrword_t data) +quicc_sxx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data) { serial_channel *chan = (serial_channel *)data; - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(smc_chan->int_num); return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); // Cause DSR to be run } // Serial I/O - high level interrupt handler (DSR) -static void -quicc_smc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +static void +quicc_smc_serial_DSR(serial_channel *chan) { - serial_channel *chan = (serial_channel *)data; - quicc_smc_serial_info *smc_chan = (quicc_smc_serial_info *)chan->dev_priv; - volatile struct smc_regs *ctl = smc_chan->ctl; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; + volatile struct smc_regs *ctl = (volatile struct smc_regs *)smc_chan->ctl; volatile struct cp_bufdesc *txbd; volatile struct cp_bufdesc *rxbd = smc_chan->rxbd; + volatile struct smc_uart_pram *pram = (volatile struct smc_uart_pram *)smc_chan->pram; struct cp_bufdesc *rxlast; int i, cache_state; -#ifdef CYGDBG_DIAG_BUF - int _time, _stime; - externC cyg_tick_count_t cyg_current_time(void); - cyg_drv_isr_lock(); - enable_diag_uart = 0; - HAL_CLOCK_READ(&_time); - _stime = (int)cyg_current_time(); - diag_printf("DSR start - CE: %x, time: %x.%x\n", ctl->smc_smce, _stime, _time); - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF + if (ctl->smc_smce & QUICC_SMCE_TX) { -#ifdef XX_CYGDBG_DIAG_BUF - enable_diag_uart = 0; - txbd = smc_chan->tbase; - for (i = 0; i < CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM; i++, txbd++) { - diag_printf("Tx BD: %x, length: %d, ctl: %x\n", txbd, txbd->length, txbd->ctrl); - } - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF // Transmit interrupt ctl->smc_smce = QUICC_SMCE_TX; // Reset interrupt state; txbd = smc_chan->tbase; // First buffer while (true) { if ((txbd->ctrl & (QUICC_BD_CTL_Ready|QUICC_BD_CTL_Int)) == QUICC_BD_CTL_Int) { -#ifdef XX_CYGDBG_DIAG_BUF - enable_diag_uart = 0; - HAL_CLOCK_READ(&_time); - _stime = (int)cyg_current_time(); - diag_printf("TX Done - Tx: %x, length: %d, time: %x.%x\n", txbd, txbd->length, _stime, _time); - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF txbd->length = 0; txbd->ctrl &= ~QUICC_BD_CTL_Int; // Reset interrupt bit } @@ -689,19 +1000,9 @@ quicc_smc_serial_DSR(cyg_vector_t vector // Receive interrupt ctl->smc_smce = QUICC_SMCE_RX; // Reset interrupt state; rxlast = (struct cp_bufdesc *) ( - (char *)eppc_base() + smc_chan->pram->rbptr ); -#ifdef CYGDBG_DIAG_BUF - enable_diag_uart = 0; - HAL_CLOCK_READ(&_time); - _stime = (int)cyg_current_time(); - diag_printf("Scan RX - rxbd: %x, rbptr: %x, time: %x.%x\n", rxbd, rxlast, _stime, _time); -#endif // CYGDBG_DIAG_BUF + (char *)eppc_base() + pram->rbptr ); while (rxbd != rxlast) { if ((rxbd->ctrl & QUICC_BD_CTL_Ready) == 0) { -#ifdef CYGDBG_DIAG_BUF - diag_printf("rxbuf: %x, flags: %x, length: %d\n", rxbd, rxbd->ctrl, rxbd->length); - diag_dump_buf(rxbd->buffer, rxbd->length); -#endif // CYGDBG_DIAG_BUF for (i = 0; i < rxbd->length; i++) { (chan->callbacks->rcv_char)(chan, rxbd->buffer[i]); } @@ -719,31 +1020,87 @@ quicc_smc_serial_DSR(cyg_vector_t vector rxbd++; } } -#ifdef CYGDBG_DIAG_BUF - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF smc_chan->rxbd = (struct cp_bufdesc *)rxbd; } if (ctl->smc_smce & QUICC_SMCE_BSY) { -#ifdef CYGDBG_DIAG_BUF - enable_diag_uart = 0; - diag_printf("RX BUSY interrupt\n"); - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF ctl->smc_smce = QUICC_SMCE_BSY; // Reset interrupt state; } -#ifdef CYGDBG_DIAG_BUF - enable_diag_uart = 0; - HAL_CLOCK_READ(&_time); - _stime = (int)cyg_current_time(); - diag_printf("DSR done - CE: %x, time: %x.%x\n", ctl->smc_smce, _stime, _time); - enable_diag_uart = 1; -#endif // CYGDBG_DIAG_BUF cyg_drv_interrupt_acknowledge(smc_chan->int_num); cyg_drv_interrupt_unmask(smc_chan->int_num); -#ifdef CYGDBG_DIAG_BUF - cyg_drv_isr_unlock(); -#endif // CYGDBG_DIAG_BUF +} + +static void +quicc_scc_serial_DSR(serial_channel *chan) +{ + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; + volatile struct scc_regs *ctl = (volatile struct scc_regs *)smc_chan->ctl; + volatile struct cp_bufdesc *txbd; + volatile struct cp_bufdesc *rxbd = smc_chan->rxbd; + volatile struct uart_pram *pram = (volatile struct uart_pram *)smc_chan->pram; + struct cp_bufdesc *rxlast; + int i, cache_state; + + if (ctl->scc_scce & QUICC_SCCE_TX) { + // Transmit interrupt + ctl->scc_scce = QUICC_SCCE_TX; // Reset interrupt state; + txbd = smc_chan->tbase; // First buffer + while (true) { + if ((txbd->ctrl & (QUICC_BD_CTL_Ready|QUICC_BD_CTL_Int)) == QUICC_BD_CTL_Int) { + txbd->length = 0; + txbd->ctrl &= ~QUICC_BD_CTL_Int; // Reset interrupt bit + } + if (txbd->ctrl & QUICC_BD_CTL_Wrap) { + txbd = smc_chan->tbase; + break; + } else { + txbd++; + } + } + (chan->callbacks->xmt_char)(chan); + } + while (ctl->scc_scce & QUICC_SCCE_RX) { + // Receive interrupt + ctl->scc_scce = QUICC_SCCE_RX; // Reset interrupt state; + rxlast = (struct cp_bufdesc *) ((char *)eppc_base() + pram->rbptr); + while (rxbd != rxlast) { + if ((rxbd->ctrl & QUICC_BD_CTL_Ready) == 0) { + for (i = 0; i < rxbd->length; i++) { + (chan->callbacks->rcv_char)(chan, rxbd->buffer[i]); + } + // Note: the MBX860 does not seem to snoop/invalidate the data cache properly! + HAL_DCACHE_IS_ENABLED(cache_state); + if (cache_state) { + HAL_DCACHE_INVALIDATE(rxbd->buffer, smc_chan->rxsize); // Make sure no stale data + } + rxbd->length = 0; + rxbd->ctrl |= QUICC_BD_CTL_Ready; + } + if (rxbd->ctrl & QUICC_BD_CTL_Wrap) { + rxbd = smc_chan->rbase; + } else { + rxbd++; + } + } + smc_chan->rxbd = (struct cp_bufdesc *)rxbd; + } + if (ctl->scc_scce & QUICC_SCCE_BSY) { + ctl->scc_scce = QUICC_SCCE_BSY; // Reset interrupt state; + } + cyg_drv_interrupt_acknowledge(smc_chan->int_num); + cyg_drv_interrupt_unmask(smc_chan->int_num); +} + +static void +quicc_sxx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) +{ + serial_channel *chan = (serial_channel *)data; + quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv; + + if (smc_chan->type == _SMC_CHAN) { + quicc_smc_serial_DSR(chan); + } else { + quicc_scc_serial_DSR(chan); + } } void
--- a/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h +++ b/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h @@ -12,6 +12,7 @@ // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -57,21 +58,46 @@ #include <cyg/hal/quicc/ppc8xx.h> // QUICC structure definitions -static unsigned int select_word_length[] = { +// SMC Mode Register +#define QUICC_SMCMR_CLEN(n) ((n+1)<<11) // Character length +#define QUICC_SMCMR_SB(n) ((n-1)<<10) // Stop bits (1 or 2) +#define QUICC_SMCMR_PE(n) (n<<9) // Parity enable (0=disable, 1=enable) +#define QUICC_SMCMR_PM(n) (n<<8) // Parity mode (0=odd, 1=even) +#define QUICC_SMCMR_UART (2<<4) // UART mode +#define QUICC_SMCMR_TEN (1<<1) // Enable transmitter +#define QUICC_SMCMR_REN (1<<0) // Enable receiver + +// SMC Events (interrupts) +#define QUICC_SMCE_BRK 0x10 // Break received +#define QUICC_SMCE_BSY 0x04 // Busy - receive buffer overrun +#define QUICC_SMCE_TX 0x02 // Tx interrupt +#define QUICC_SMCE_RX 0x01 // Rx interrupt + +// SMC Commands +#define QUICC_SMC_CMD_InitTxRx (0<<8) +#define QUICC_SMC_CMD_InitTx (1<<8) +#define QUICC_SMC_CMD_InitRx (2<<8) +#define QUICC_SMC_CMD_StopTx (4<<8) +#define QUICC_SMC_CMD_RestartTx (6<<8) +#define QUICC_SMC_CMD_Reset 0x8000 +#define QUICC_SMC_CMD_Go 0x0001 + + +static unsigned int smc_select_word_length[] = { QUICC_SMCMR_CLEN(5), // 5 bits / word (char) QUICC_SMCMR_CLEN(6), QUICC_SMCMR_CLEN(7), QUICC_SMCMR_CLEN(8) }; -static unsigned int select_stop_bits[] = { +static unsigned int smc_select_stop_bits[] = { 0, QUICC_SMCMR_SB(1), // 1 stop bit QUICC_SMCMR_SB(1), // 1.5 stop bit QUICC_SMCMR_SB(2) // 2 stop bits }; -static unsigned int select_parity[] = { +static unsigned int smc_select_parity[] = { QUICC_SMCMR_PE(0), // No parity QUICC_SMCMR_PE(1)|QUICC_SMCMR_PM(1), // Even parity QUICC_SMCMR_PE(1)|QUICC_SMCMR_PM(0), // Odd parity @@ -79,6 +105,53 @@ static unsigned int select_parity[] = { 0, // Space parity }; +// SCC PSMR masks .... +#define QUICC_SCC_PSMR_ASYNC 0x8000 +#define QUICC_SCC_PSMR_SB(n) ((n-1)<<14) // Stop bits (1=1sb, 2=2sb) +#define QUICC_SCC_PSMR_CLEN(n) ((n-5)<<12) // Character Length (5-8) +#define QUICC_SCC_PSMR_PE(n) (n<<4) // Parity enable(0=disabled, 1=enabled) +#define QUICC_SCC_PSMR_RPM(n) (n<<2) // Rx Parity mode (0=odd, 1=low, 2=even, 3=high) +#define QUICC_SCC_PSMR_TPM(n) (n) // Tx Parity mode (0=odd, 1=low, 2=even, 3=high) + +// SCC DSR masks +#define QUICC_SCC_DSR_FULL 0x7e7e +#define QUICC_SCC_DSR_HALF 0x467e + +// SCC GSMR masks ... +#define QUICC_SCC_GSMR_H_INIT 0x00000060 +#define QUICC_SCC_GSMR_L_INIT 0x00028004 +#define QUICC_SCC_GSMR_L_Tx 0x00000010 +#define QUICC_SCC_GSMR_L_Rx 0x00000020 + +// SCC Events (interrupts) +#define QUICC_SCCE_BRK 0x0040 +#define QUICC_SCCE_BSY 0x0004 +#define QUICC_SCCE_TX 0x0002 +#define QUICC_SCCE_RX 0x0001 + +static unsigned int scc_select_word_length[] = { + QUICC_SCC_PSMR_CLEN(5), // 5 bits / word (char) + QUICC_SCC_PSMR_CLEN(6), + QUICC_SCC_PSMR_CLEN(7), + QUICC_SCC_PSMR_CLEN(8) +}; + +static unsigned int scc_select_stop_bits[] = { + QUICC_SCC_PSMR_SB(1), // 0.5 stop bit ?? + QUICC_SCC_PSMR_SB(1), // 1 stop bit + QUICC_SCC_PSMR_SB(2), // 1.5 stop bit + QUICC_SCC_PSMR_SB(2) // 2 stop bits +}; + + +static unsigned int scc_select_parity[] = { + QUICC_SCC_PSMR_PE(0), // No parity + QUICC_SCC_PSMR_PE(1)|QUICC_SCC_PSMR_TPM(2)|QUICC_SCC_PSMR_RPM(2), // Even parity + QUICC_SCC_PSMR_PE(1)|QUICC_SCC_PSMR_TPM(0)|QUICC_SCC_PSMR_RPM(0), // Odd parity + QUICC_SCC_PSMR_PE(1)|QUICC_SCC_PSMR_TPM(3)|QUICC_SCC_PSMR_RPM(3), // High (mark) parity + QUICC_SCC_PSMR_PE(1)|QUICC_SCC_PSMR_TPM(1)|QUICC_SCC_PSMR_RPM(1), // Low (space) parity +}; + // Baud rate values, based on board clock static cyg_int32 select_baud[] = { @@ -109,4 +182,8 @@ static cyg_int32 select_baud[] = { #define UART_BITRATE(n) (((CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000)/16)/n) #define UART_SLOW_BITRATE(n) ((CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000)/n)) +// Channel type select +#define _SCC_CHAN 0 +#define _SMC_CHAN 1 + #endif // CYGONCE_POWERPC_QUICC_SMC_SERIAL_H
