This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Serial - expand QUICC driver for SCCx
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at sources dot redhat dot com>
- Date: 17 Mar 2003 15:18:10 -0700
- Subject: Serial - expand QUICC driver for SCCx
Index: devs/serial/powerpc/quicc/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/serial/powerpc/quicc/current/ChangeLog,v
retrieving revision 1.14
diff -u -5 -p -r1.14 ChangeLog
--- devs/serial/powerpc/quicc/current/ChangeLog 5 Mar 2003 17:15:53 -0000 1.14
+++ devs/serial/powerpc/quicc/current/ChangeLog 17 Mar 2003 22:08:33 -0000
@@ -1,5 +1,12 @@
+2003-03-17 Gary Thomas <gary at mlbassoc dot 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 at delta-info dot com>
+
2003-03-05 Gary Thomas <gary at mlbassoc dot com>
* src/quicc_smc_serial.c: Use common routines to manage CPM/DPRAM
pointers - much nicer in a multi-driver environment.
Index: devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl,v
retrieving revision 1.7
diff -u -5 -p -r1.7 ser_quicc_smc.cdl
--- devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl 24 Feb 2003 14:18:55 -0000 1.7
+++ devs/serial/powerpc/quicc/current/cdl/ser_quicc_smc.cdl 17 Mar 2003 20:53:10 -0000
@@ -1,17 +1,17 @@
# ====================================================================
#
# 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
## Software Foundation; either version 2 or (at your option) any later version.
##
@@ -61,11 +61,11 @@ cdl_package CYGPKG_IO_SERIAL_POWERPC_QUI
requires CYGPKG_ERROR
include_dir cyg/io
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
define_proc {
puts $::cdl_system_header "/***** serial driver proc output start *****/"
@@ -74,11 +74,11 @@ 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
QUICC/SMC port 1."
@@ -165,11 +165,11 @@ 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
QUICC/SMC port 2."
@@ -283,9 +283,282 @@ cdl_component CYGPKG_IO_SERIAL_POWERPC_Q
description "
This option modifies the set of compiler flags for
building these serial device drivers. These flags are removed from
the set of global flags if present."
}
+ }
+}
+
+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
Index: devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c,v
retrieving revision 1.10
diff -u -5 -p -r1.10 quicc_smc_serial.c
--- devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c 5 Mar 2003 17:15:53 -0000 1.10
+++ devs/serial/powerpc/quicc/current/src/quicc_smc_serial.c 17 Mar 2003 22:16:09 -0000
@@ -1,10 +1,10 @@
//==========================================================================
//
// 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####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
@@ -66,102 +66,74 @@
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC
// 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,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT
@@ -169,105 +141,234 @@ static SERIAL_CHANNEL(quicc_smc_serial_c
#endif
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,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT
);
#endif
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;
}
return true;
}
// 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,
cyg_uint8 *TxBUF,
int RxBD, int RxNUM, int RxSIZE,
@@ -280,12 +381,12 @@ quicc_smc_serial_init_info(quicc_smc_ser
cyg_uint32 simode = 0;
int i;
// 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)
*/
eppc->dma_sdcr = 1;
@@ -380,36 +481,198 @@ quicc_smc_serial_init_info(quicc_smc_ser
*/
ctl->smc_smce = 0xFF;
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,
CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxNUM,
CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC1_TxSIZE,
@@ -420,28 +683,17 @@ quicc_smc_serial_init(struct cyg_devtab_
ALIGN_TO_CACHELINES(&quicc_smc1_rxbuf[0][0]),
0xC0, // PortB mask
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,
CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxNUM,
CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SMC2_TxSIZE,
@@ -452,53 +704,125 @@ quicc_smc_serial_init(struct cyg_devtab_
ALIGN_TO_CACHELINES(&quicc_smc2_rxbuf[0][0]),
0xC00, // PortB mask
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;
}
// 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)
{
serial_channel *chan = (serial_channel *)(*tab)->priv;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
return ENOERR;
}
// 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;
HAL_DCACHE_IS_ENABLED(cache_state);
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
if (txbd->ctrl & QUICC_BD_CTL_Wrap) {
txbd = smc_chan->tbase;
@@ -510,18 +834,20 @@ 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) {
// This buffer is busy, move to next one
if (txbd->ctrl & QUICC_BD_CTL_Wrap) {
@@ -535,11 +861,11 @@ quicc_smc_serial_putc(serial_channel *ch
if ((txbd->ctrl & (QUICC_BD_CTL_Ready|QUICC_BD_CTL_Int)) == 0) {
// Transmit buffer is not full/busy
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 {
// No space
res = false;
@@ -548,15 +874,16 @@ quicc_smc_serial_putc(serial_channel *ch
return res;
}
// 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;
rxbd->ctrl |= QUICC_BD_CTL_Ready;
if (rxbd->ctrl & QUICC_BD_CTL_Wrap) {
@@ -568,113 +895,97 @@ quicc_smc_serial_getc(serial_channel *ch
return c;
}
// 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;
}
return ENOERR;
}
// 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
(chan->callbacks->xmt_char)(chan);
}
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
}
if (txbd->ctrl & QUICC_BD_CTL_Wrap) {
txbd = smc_chan->tbase;
@@ -687,23 +998,13 @@ quicc_smc_serial_DSR(cyg_vector_t vector
}
while (ctl->smc_smce & QUICC_SMCE_RX) {
// 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]);
}
// Note: the MBX860 does not seem to snoop/invalidate the data cache properly!
HAL_DCACHE_IS_ENABLED(cache_state);
@@ -717,35 +1018,91 @@ quicc_smc_serial_DSR(cyg_vector_t vector
rxbd = smc_chan->rbase;
} else {
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
show_rxbd(int dump_all)
{
Index: devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h,v
retrieving revision 1.3
diff -u -5 -p -r1.3 quicc_smc_serial.h
--- devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h 23 May 2002 23:01:23 -0000 1.3
+++ devs/serial/powerpc/quicc/current/src/quicc_smc_serial.h 17 Mar 2003 22:15:44 -0000
@@ -10,10 +10,11 @@
// ====================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// 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
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -55,32 +56,104 @@
// Description of serial ports using QUICC/SMC
#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
0, // Mark 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[] = {
0, // Unused
50, // 50
@@ -106,7 +179,11 @@ static cyg_int32 select_baud[] = {
0, // 230400
};
#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
--
------------------------------------------------------------
Gary Thomas |
MLB Associates | Consulting for the
+1 (970) 229-1963 | Embedded world
http://www.mlbassoc.com/ |
email: <gary at mlbassoc dot com> |
gpg: http://www.chez-thomas.org/gary/gpg_key.asc
------------------------------------------------------------