summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/gen68360
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-07-11 10:00:41 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-07-11 10:00:41 +0000
commit69effbb4e16db7e6c85cd9b2bb8ad648c700b0a6 (patch)
tree342616a26286d7378fdde5acdafe923003d0aa76 /c/src/lib/libbsp/m68k/gen68360
parentadded mcf548x BSP support (diff)
downloadrtems-69effbb4e16db7e6c85cd9b2bb8ad648c700b0a6.tar.bz2
added variant to gen68360 BSP
added genmcf548x BSP
Diffstat (limited to 'c/src/lib/libbsp/m68k/gen68360')
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/ChangeLog10
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/Makefile.am1
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/README11
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/include/bsp.h23
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.c852
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.h146
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/spi/mc68360_spidrv.c627
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/startup/init68360.c175
8 files changed, 1844 insertions, 1 deletions
diff --git a/c/src/lib/libbsp/m68k/gen68360/ChangeLog b/c/src/lib/libbsp/m68k/gen68360/ChangeLog
index 6bcdbed1ee..0853aa3311 100644
--- a/c/src/lib/libbsp/m68k/gen68360/ChangeLog
+++ b/c/src/lib/libbsp/m68k/gen68360/ChangeLog
@@ -1,3 +1,13 @@
+2008-07-09 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+
+ * Makefile.am, spi/m360_spidrv.c, spi/m360_spidrv.h:
+ added SPI driver
+
+2008-07-09 Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+
+ * README:
+ added pgh360 BSP variant
+
2008-05-23 Joel Sherrill <joel.sherrill@OARcorp.com>
* console/console.c: Eliminate copies of switches to convert termios
diff --git a/c/src/lib/libbsp/m68k/gen68360/Makefile.am b/c/src/lib/libbsp/m68k/gen68360/Makefile.am
index 93f1ee2061..e2c17fb2f3 100644
--- a/c/src/lib/libbsp/m68k/gen68360/Makefile.am
+++ b/c/src/lib/libbsp/m68k/gen68360/Makefile.am
@@ -11,7 +11,6 @@ dist_project_lib_DATA = bsp_specs
include_HEADERS = include/bsp.h
include_HEADERS += include/tm27.h
-
nodist_include_HEADERS = include/bspopts.h
DISTCLEANFILES = include/bspopts.h
noinst_PROGRAMS =
diff --git a/c/src/lib/libbsp/m68k/gen68360/README b/c/src/lib/libbsp/m68k/gen68360/README
index 471e55581f..c48fb20b84 100644
--- a/c/src/lib/libbsp/m68k/gen68360/README
+++ b/c/src/lib/libbsp/m68k/gen68360/README
@@ -29,6 +29,8 @@
# can be used with the Arnewsh SBC360 card.
# - If the preprocessor symbol M68360_ATLAS_HSB is defined,
# the BSP is compiled for an Atlas HSB card.
+# - If the preprocessor symbol M68360_IMD_PGH is defined,
+# the BSP is compiled for an IMD PGH360 card.
# - Otherwise, the BSP is compiled for a generic 68360 system
# as described in Chapter 9 of the MC68360 User's Manual. This
# version works with the Atlas ACE360 card.
@@ -39,6 +41,7 @@ BOARD: Generic 68360 as described in Motorola MC68360 User's Manual
BOARD: Atlas Computer Equipment Inc. High Speed Bridge (HSB)
BOARD: Atlas Computer Equipment Inc. Advanced Communication Engine (ACE)
BOARD: Arnewsh SBC360 68040/68360 card
+BOARD: IMD PGH Board (custom)
BUS: none
CPU FAMILY: Motorola CPU32+, Motorola 68040
COPROCESSORS: none
@@ -83,6 +86,13 @@ bus width: 8-bit PROM/FLASH, 32-bit DRAM
ROM: To 1 MByte, 180 nsec (3 wait states), chip select 0
RAM: 4 or 16 MBytes of 60 nsec parity DRAM (1Mx36) to RAS1*/CAS1*
+Board description (IMD PGH)
+---------------------------
+clock rate: 25 MHz
+bus width: 8-bit PROM/FLASH, 32-bit DRAM
+ROM: 512KByte, 180 nsec (3 wait states), chip select 0
+RAM: 16 MBytes of 60 nsec no-parity DRAM (1Mx32) to RAS1*/CAS1*
+
Host System
-----------
OPENSTEP 4.2 (Intel and Motorola), Solaris 2.5, Linux 2.0.29
@@ -292,3 +302,4 @@ The board support package has been tested with:
Arnewsh Inc.
P.O. Box 270352
Fort Collins, CO 80527-0352
+ A custom 68360 board (PGH360) produced by IMD
diff --git a/c/src/lib/libbsp/m68k/gen68360/include/bsp.h b/c/src/lib/libbsp/m68k/gen68360/include/bsp.h
index 7f84e5b26a..5f30586daa 100644
--- a/c/src/lib/libbsp/m68k/gen68360/include/bsp.h
+++ b/c/src/lib/libbsp/m68k/gen68360/include/bsp.h
@@ -90,6 +90,8 @@ void *M360AllocateBufferDescriptors( int count );
void *M360AllocateRiscTimers( int count );
extern char M360DefaultWatchdogFeeder;
+extern int m360_clock_rate; /* BRG clock rate, defined in console.c */
+
m68k_isr_entry set_vector(
rtems_isr_entry handler,
rtems_vector_number vector,
@@ -102,6 +104,7 @@ m68k_isr_entry set_vector(
extern char _RamBase[];
extern char _HeapSize[];
+
/*
* Definitions for Atlas Computer Equipment Inc. High Speed Bridge (HSB)
*/
@@ -111,6 +114,26 @@ extern char _HeapSize[];
#define ATLASHSB_LED4 0x20010004L
#define ATLASHSB_ROM_U6 0xFF080000L /* U6 flash ROM socket */
+
+ /*
+ * definitions for PGH360 board
+ */
+#if defined(PGH360)
+/*
+ * logical SPI addresses of SPI slaves available
+ */
+#define PGH360_SPI_ADDR_EEPROM 0
+#define PGH360_SPI_ADDR_DISP4_DATA 1
+#define PGH360_SPI_ADDR_DISP4_CTRL 2
+
+/*
+ * Port B bit locations of SPI slave selects
+ */
+#define PGH360_PB_SPI_DISP4_RS_MSK (1<<15)
+#define PGH360_PB_SPI_DISP4_CE_MSK (1<<14)
+#define PGH360_PB_SPI_EEP_CE_MSK (1<< 0)
+#endif /* defined(PGH360) */
+
#ifdef __cplusplus
}
#endif
diff --git a/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.c b/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.c
new file mode 100644
index 0000000000..38f80a5789
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.c
@@ -0,0 +1,852 @@
+/*===============================================================*\
+| Project: RTEMS support for PGH360 |
++-----------------------------------------------------------------+
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the M360 SPI driver |
+\*===============================================================*/
+#include <stdlib.h>
+#include <bsp.h>
+#include <rtems/m68k/m68360.h>
+#include <rtems/m68k/m360_spi.h>
+#include <rtems/error.h>
+#include <rtems/bspIo.h>
+#include <errno.h>
+#include <rtems/libi2c.h>
+
+#undef DEBUG
+static m360_spi_softc_t *m360_spi_softc_ptr;
+/*
+ * this is a dummy receive buffer for sequences,
+ * where only send data are available
+ */
+uint8_t m360_spi_dummy_rxbuf[2];
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m360_spi_baud_to_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| determine proper divider value |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ uint32_t baudrate, /* desired baudrate */
+ uint32_t *spimode /* result value */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint32_t divider;
+ uint16_t tmpmode = 0;
+ /*
+ * determine clock divider and DIV16 bit
+ */
+ divider = m360_clock_rate/baudrate;
+ if (divider > 64) {
+ tmpmode = M360_SPMODE_DIV16;
+ divider /= 16;
+ }
+ if ((divider < 1) ||
+ (divider > 64)) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ else {
+ tmpmode |= M360_SPMODE_PM(divider/4-1);
+ }
+ *spimode = tmpmode;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m360_spi_char_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| determine proper value for character size |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr, /* handle */
+ uint32_t bits_per_char, /* bits per character */
+ boolean lsb_first, /* TRUE: send LSB first */
+ uint16_t *spimode /* result value */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint16_t tmpmode;
+
+ /*
+ * calculate data format
+ */
+ if ((bits_per_char >= 4) &&
+ (bits_per_char <= 16)) {
+ tmpmode = M360_SPMODE_CLEN( bits_per_char-1);
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ *spimode = tmpmode;
+ return 0;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static int m360_spi_wait
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for spi to become idle |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr /* handle */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint16_t act_status;
+ rtems_status_code rc;
+ uint32_t tout;
+
+#if defined(DEBUG)
+ printk("m360_spi_wait called... ");
+#endif
+ if (softc_ptr->initialized) {
+ /*
+ * allow interrupts, when receiver is not empty
+ */
+ m360.spim = (M360_SPIE_TXE | M360_SPIE_TXB |
+ M360_SPIE_BSY | M360_SPIE_MME);
+
+ rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL) {
+ return rc;
+ }
+ }
+ else {
+ tout = 0;
+ do {
+ if (tout++ > 1000000) {
+#if defined(DEBUG)
+ printk("... exit with RTEMS_TIMEOUT\r\n");
+#endif
+ return RTEMS_TIMEOUT;
+ }
+ /*
+ * wait for SPI to terminate
+ */
+ } while (!(m360.spie & M360_SPIE_TXB));
+ }
+
+ act_status = m360.spie;
+ if ((act_status & (M360_SPIE_TXE | M360_SPIE_TXB |
+ M360_SPIE_BSY | M360_SPIE_MME))!= M360_SPIE_TXB) {
+#if defined(DEBUG)
+ printk("... exit with RTEMS_IO_ERROR,"
+ "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n",
+ act_status,status_mask,desired_status);
+#endif
+ return RTEMS_IO_ERROR;
+ }
+#if defined(DEBUG)
+ printk("... exit OK\r\n");
+#endif
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_isr m360_spi_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| handle interrupts |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_vector_number v /* vector number */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = m360_spi_softc_ptr;
+
+ /*
+ * disable interrupt mask
+ */
+ m360.spim = 0;
+ if (softc_ptr->initialized) {
+ rtems_semaphore_release(softc_ptr->irq_sema_id);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static void m360_spi_install_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| (un-)install the interrupt handler |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr, /* ptr to control structure */
+ int install /* TRUE: install, FALSE: remove */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ /*
+ * (un-)install handler for SPI device
+ */
+ if (install) {
+ /*
+ * create semaphore for IRQ synchronization
+ */
+ rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'),
+ 0,
+ RTEMS_FIFO
+ | RTEMS_SIMPLE_BINARY_SEMAPHORE,
+ 0,
+ &softc_ptr->irq_sema_id);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot create semaphore");
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = rtems_interrupt_catch (m360_spi_irq_handler,
+ (m360.cicr & 0xE0) | 0x05,
+ &softc_ptr->old_handler);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot install IRQ handler");
+ }
+ }
+ /*
+ * enable IRQ in CPIC
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ m360.cimr |= (1 << 5);
+ }
+ }
+ else {
+ rtems_isr_entry old_handler;
+ /*
+ * disable IRQ in CPIC
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ m360.cimr &= ~(1 << 5);
+ }
+ rc = rtems_interrupt_catch (softc_ptr->old_handler,
+ (m360.cicr & 0xE0) | 0x05,
+ &old_handler);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot uninstall IRQ handler");
+ }
+ /*
+ * delete sync semaphore
+ */
+ if (softc_ptr->irq_sema_id != 0) {
+ rc = rtems_semaphore_delete(softc_ptr->irq_sema_id);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot delete semaphore");
+ }
+ }
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize the driver |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+#if defined(DEBUG)
+ printk("m360_spi_init called... ");
+#endif
+ /*
+ * init HW registers:
+ */
+ /*
+ * FIXME: set default mode in SPMODE
+ */
+
+ /*
+ * allocate BDs (1x RX, 1x TX)
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ softc_ptr->rx_bd = M360AllocateBufferDescriptors (1);
+ softc_ptr->tx_bd = M360AllocateBufferDescriptors (1);
+ if ((softc_ptr->rx_bd == NULL) ||
+ (softc_ptr->tx_bd == NULL)) {
+ rc = RTEMS_NO_MEMORY;
+ }
+ }
+ /*
+ * set parameter RAM
+ */
+ m360.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m360;
+ m360.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m360;
+ m360.spip.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
+ m360.spip.tfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE;
+ m360.spip.mrblr = 2;
+
+ /*
+ * issue "InitRxTx" Command to CP
+ */
+ M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SPI);
+
+ /*
+ * init interrupt stuff
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ m360_spi_install_irq_handler(softc_ptr,TRUE);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * set up ports
+ * LINE PAR DIR DAT
+ * -----------------------
+ * MOSI 1 1 x
+ * MISO 1 1 x
+ * CLK 1 1 x
+ */
+
+ /* set Port B Pin Assignment Register... */
+ m360.pbpar =
+ m360.pbpar
+ | M360_PB_SPI_MISO_MSK
+ | M360_PB_SPI_MOSI_MSK
+ | M360_PB_SPI_CLK_MSK;
+
+ /* set Port B Data Direction Register... */
+ m360.pbdir =
+ m360.pbdir
+ | M360_PB_SPI_MISO_MSK
+ | M360_PB_SPI_MOSI_MSK
+ | M360_PB_SPI_CLK_MSK;
+ }
+ /*
+ * mark, that we have initialized
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ softc_ptr->initialized = TRUE;
+ }
+#if defined(DEBUG)
+ printk("... exit OK\r\n");
+#endif
+ return rc;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static int m360_spi_read_write_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| transmit/receive some bytes from SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *rbuf, /* buffer to store bytes */
+ const unsigned char *tbuf, /* buffer to send bytes */
+ int len /* number of bytes to transceive */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes received or (negative) error code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ int bc = 0;
+
+#if defined(DEBUG)
+ printk("m360_spi_read_write_bytes called... ");
+#endif
+
+ /*
+ * prepare RxBD
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (rbuf == NULL) {
+ /*
+ * no Tx buffer: receive to dummy buffer
+ */
+ m360.spip.mrblr = sizeof(m360_spi_dummy_rxbuf);
+ softc_ptr->rx_bd->buffer = m360_spi_dummy_rxbuf;
+ softc_ptr->rx_bd->length = 0;
+ softc_ptr->rx_bd->status = (M360_BD_EMPTY | M360_BD_WRAP |
+ M360_BD_CONTINUOUS);
+ }
+ else {
+ m360.spip.mrblr = len;
+ softc_ptr->rx_bd->buffer = rbuf;
+ softc_ptr->rx_bd->length = 0;
+ softc_ptr->rx_bd->status = (M360_BD_EMPTY | M360_BD_WRAP);
+ }
+ }
+ /*
+ * prepare TxBD
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (tbuf == NULL) {
+ /*
+ * FIXME: no Tx buffer: transmit from dummy buffer
+ */
+ softc_ptr->tx_bd->buffer = m360_spi_dummy_rxbuf;
+ softc_ptr->tx_bd->length = len;
+ softc_ptr->tx_bd->status = (M360_BD_READY | M360_BD_WRAP |
+ M360_BD_CONTINUOUS);
+ }
+ else {
+ softc_ptr->tx_bd->buffer = tbuf;
+ softc_ptr->tx_bd->length = len;
+ softc_ptr->tx_bd->status = (M360_BD_READY | M360_BD_WRAP);
+ }
+ }
+
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * set START command
+ */
+ m360.spcom = M360_SPCOM_STR;
+ /*
+ * wait for SPI to finish
+ */
+ rc = m360_spi_wait(softc_ptr);
+ }
+#if defined(DEBUG)
+ printk("... exit OK, rc=%d\r\n",bc);
+#endif
+ return (rc == RTEMS_SUCCESSFUL) ? bc : -rc;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_read_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| receive some bytes from SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to store bytes */
+ int len /* number of bytes to receive */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes received or (negative) error code |
+\*=========================================================================*/
+{
+ return m360_spi_read_write_bytes(bh,buf,NULL,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_write_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send some bytes to SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to send */
+ int len /* number of bytes to send */
+
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes sent or (negative) error code |
+\*=========================================================================*/
+{
+ return m360_spi_read_write_bytes(bh,NULL,buf,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_set_tfr_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| set SPI to desired baudrate/clock mode/character mode |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+ uint32_t spimode_baud,spimode;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ /*
+ * FIXME: set proper mode
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m360_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m360_spi_char_mode(softc_ptr,
+ tfr_mode->bits_per_char,
+ tfr_mode->lsb_first,
+ &spimode);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ spimode |= spimode_baud;
+ spimode |= M360_SPMODE_MASTER; /* set master mode */
+ if (!tfr_mode->lsb_first) {
+ spimode |= M360_SPMODE_REV;
+ }
+ if (tfr_mode->clock_inv) {
+ spimode |= M360_SPMODE_CI;
+ }
+ if (tfr_mode->clock_phs) {
+ spimode |= M360_SPMODE_CP;
+ }
+ }
+
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * disable SPI
+ */
+ m360.spmode &= ~M360_SPMODE_EN;
+ /*
+ * set new mode and reenable SPI
+ */
+ m360.spmode = spimode | M360_SPMODE_EN;
+ }
+ return rc;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_ioctl
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| perform selected ioctl function for SPI |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ int cmd, /* ioctl command code */
+ void *arg /* additional argument array */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ int ret_val = -1;
+
+ switch(cmd) {
+ case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
+ ret_val =
+ -m360_spi_set_tfr_mode(bh,
+ (const rtems_libi2c_tfr_mode_t *)arg);
+ break;
+ case RTEMS_LIBI2C_IOCTL_READ_WRITE:
+ ret_val =
+ m360_spi_read_write_bytes(bh,
+ ((rtems_libi2c_read_write_t *)arg)->rd_buf,
+ ((rtems_libi2c_read_write_t *)arg)->wr_buf,
+ ((rtems_libi2c_read_write_t *)arg)->byte_cnt);
+ break;
+ default:
+ ret_val = -RTEMS_NOT_DEFINED;
+ break;
+ }
+ return ret_val;
+}
+
+/*=========================================================================*\
+| Board-specific adaptation functions |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code bsp_spi_sel_addr
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| address a slave device on the bus |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ uint32_t addr, /* address to send on bus */
+ int rw /* 0=write,1=read */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+#if defined(PGH360)
+ /*
+ * select given device
+ */
+ /*
+ * GPIO1[24] is SPI_A0
+ * GPIO1[25] is SPI_A1
+ * GPIO1[26] is SPI_A2
+ * set pins to address
+ */
+ switch(addr) {
+ case PGH360_SPI_ADDR_EEPROM:
+ m360.pbdat &= ~PGH360_PB_SPI_EEP_CE_MSK;
+ break;
+ case PGH360_SPI_ADDR_DISP4_DATA:
+ m360.pbdat = (m360.pbdat
+ & ~(PGH360_PB_SPI_DISP4_CE_MSK |
+ PGH360_PB_SPI_DISP4_RS_MSK));
+ break;
+ case PGH360_SPI_ADDR_DISP4_CTRL:
+ m360.pbdat = (m360.pbdat
+ & ~(PGH360_PB_SPI_DISP4_CE_MSK)
+ | PGH360_PB_SPI_DISP4_RS_MSK);
+ break;
+ default:
+ return RTEMS_INVALID_NUMBER;
+ }
+#endif /* PGH360 */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code bsp_spi_send_start_dummy
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| dummy function, SPI has no start condition |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ return 0;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code bsp_spi_send_stop
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| deselect SPI |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+#if defined(DEBUG)
+ printk("bsp_spi_send_stop called... ");
+#endif
+#if defined(PGH360)
+ m360.pbdat = (m360.pbdat
+ | PGH360_PB_SPI_DISP4_CE_MSK
+ | PGH360_PB_SPI_EEP_CE_MSK);
+#endif
+#if defined(DEBUG)
+ printk("... exit OK\r\n");
+#endif
+ return 0;
+}
+
+/*=========================================================================*\
+| list of handlers |
+\*=========================================================================*/
+
+rtems_libi2c_bus_ops_t bsp_spi_ops = {
+ init: m360_spi_init,
+ send_start: bsp_spi_send_start_dummy,
+ send_stop: bsp_spi_send_stop,
+ send_addr: bsp_spi_sel_addr,
+ read_bytes: m360_spi_read_bytes,
+ write_bytes: m360_spi_write_bytes,
+ ioctl: m360_spi_ioctl
+};
+
+static m360_spi_desc_t bsp_spi_bus_desc = {
+ {/* public fields */
+ ops: &bsp_spi_ops,
+ size: sizeof(bsp_spi_bus_desc)
+ },
+ { /* our private fields */
+ initialized: FALSE
+ }
+};
+
+/*=========================================================================*\
+| initialization |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code bsp_register_spi
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| register SPI bus and devices |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void /* <none> */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 or error code |
+\*=========================================================================*/
+{
+ int ret_code;
+ int spi_busno;
+
+ /*
+ * init I2C library (if not already done)
+ */
+ rtems_libi2c_initialize ();
+
+ /*
+ * init port pins used to address/select SPI devices
+ */
+
+#if defined(PGH360)
+
+ /*
+ * set up ports
+ * LINE PAR DIR DAT
+ * -----------------------
+ * EEP_CE 0 1 act-high
+ * DISP4_CS 0 1 act-high
+ * DISP4_RS 0 1 active
+ */
+
+ /* set Port B Pin Assignment Register... */
+ m360.pbpar =
+ (m360.pbpar
+ & ~(PGH360_PB_SPI_EEP_CE_MSK
+ | PGH360_PB_SPI_DISP4_CE_MSK
+ | PGH360_PB_SPI_DISP4_RS_MSK));
+
+ /* set Port B Data Direction Register... */
+ m360.pbdir =
+ m360.pbdir
+ | PGH360_PB_SPI_EEP_CE_MSK
+ | PGH360_PB_SPI_DISP4_CE_MSK
+ | PGH360_PB_SPI_DISP4_RS_MSK;
+
+ /* set Port B Data Register to inactive CE state */
+ m360.pbdat =
+ m360.pbdat
+ | PGH360_PB_SPI_DISP4_CE_MSK
+ | PGH360_PB_SPI_DISP4_RS_MSK;
+#endif
+
+ /*
+ * register SPI bus
+ */
+ ret_code = rtems_libi2c_register_bus("/dev/spi",
+ &(bsp_spi_bus_desc.bus_desc));
+ if (ret_code < 0) {
+ return -ret_code;
+ }
+ spi_busno = ret_code;
+#if defined(PGH360)
+ /*
+ * register devices
+ */
+#if 0
+ ret_code = rtems_libi2c_register_drv(RTEMS_BSP_SPI_FLASH_DEVICE_NAME,
+ spi_flash_m25p40_rw_driver_descriptor,
+ spi_busno,0x00);
+ if (ret_code < 0) {
+ return -ret_code;
+ }
+#endif
+#endif /* defined(PGH360) */
+ /*
+ * FIXME: further drivers, when available
+ */
+ return 0;
+}
+
+
diff --git a/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.h b/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.h
new file mode 100644
index 0000000000..6974002364
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68360/spi/m360_spi.h
@@ -0,0 +1,146 @@
+/*===============================================================*\
+| Project: RTEMS support for MC68360 |
++-----------------------------------------------------------------+
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the MC68360 SPI driver declarations |
+\*===============================================================*/
+#ifndef _M360_SPIDRV_H
+#define _M360_SPIDRV_H
+
+#include <rtems/m68k/m68360.h>
+#include <rtems/libi2c.h>
+#include <rtems/irq.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct m360_spi_softc {
+ int initialized;
+ rtems_id irq_sema_id;
+ rtems_isr_entry old_handler;
+ m360BufferDescriptor_t *rx_bd;
+ m360BufferDescriptor_t *tx_bd;
+} m360_spi_softc_t ;
+
+typedef struct {
+ rtems_libi2c_bus_t bus_desc;
+ m360_spi_softc_t softc;
+} m360_spi_desc_t;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize the driver |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_read_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| receive some bytes from SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to store bytes */
+ int len /* number of bytes to receive */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes received or (negative) error code |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_write_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send some bytes to SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to send */
+ int len /* number of bytes to send */
+
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes sent or (negative) error code |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_set_tfr_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| set SPI to desired baudrate/clock mode/character mode |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_ioctl
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| perform selected ioctl function for SPI |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ int cmd, /* ioctl command code */
+ void *arg /* additional argument array */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _M360_SPIDRV_H */
diff --git a/c/src/lib/libbsp/m68k/gen68360/spi/mc68360_spidrv.c b/c/src/lib/libbsp/m68k/gen68360/spi/mc68360_spidrv.c
new file mode 100644
index 0000000000..9a6b01ce27
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68360/spi/mc68360_spidrv.c
@@ -0,0 +1,627 @@
+/*===============================================================*\
+| Project: RTEMS support for PGH360 |
++-----------------------------------------------------------------+
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the M360 SPI driver |
+\*===============================================================*/
+#include <stdlib.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/m68k/m68360.h>
+#include <m360/m360_spidrv.h>
+#include <rtems/error.h>
+#include <rtems/bspIo.h>
+#include <errno.h>
+#include <rtems/libi2c.h>
+
+#undef DEBUG
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m360_spi_baud_to_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| determine proper divider value |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ uint32_t baudrate, /* desired baudrate */
+ uint32_t *spimode /* result value */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint32_t divider;
+ uint16_t tmpmode = 0;
+ /*
+ * determine clock divider and DIV16 bit
+ */
+ divider = m360_clock_rate/baudrate;
+ if (divider > 64) {
+ tmpmode = M360_SPMODE_DIV16;
+ divider /= 16;
+ }
+ if ((divider < 1) ||
+ (divider > 64)) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ else {
+ tmpmode |= M360_SPMODE_PM(divider/4-1);
+ }
+ *spimode = tmpmode;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m360_spi_char_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| determine proper value for character size |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr, /* handle */
+ uint32_t bits_per_char, /* bits per character */
+ boolean lsb_first, /* TRUE: send LSB first */
+ uint16_t *spimode /* result value */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint32_t tmpmode;
+
+ if (bits_per_char == 32) {
+ tmpmode = 0;
+ softc_ptr->bytes_per_char = 4;
+ softc_ptr->bit_shift = 0;
+ }
+ else {
+ if (lsb_first) {
+ /*
+ * non-reversed data (LSB first): 4..16 bits valid
+ * always aligned to bit 16 of data register
+ */
+ if ((bits_per_char >= 4) &&
+ (bits_per_char <= 16)) {
+ tmpmode = M360_SPIMODE_LEN( bits_per_char-1);
+ softc_ptr->bytes_per_char = (bits_per_char > 8) ? 2 : 1;
+ softc_ptr->bit_shift = 16-bits_per_char;
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+ }
+ else {
+ /*
+ * reversed data (MSB first): only 8/16/32 bits valid,
+ * always in lowest bits of data register
+ */
+ if (bits_per_char == 8) {
+ tmpmode = M360_SPIMODE_LEN(8-1);
+ softc_ptr->bytes_per_char = 1;
+ softc_ptr->bit_shift = 0;
+ }
+ else if (bits_per_char == 16) {
+ tmpmode = M360_SPIMODE_LEN(16-1);
+ softc_ptr->bytes_per_char = 2;
+ softc_ptr->bit_shift = 0;
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+ }
+ }
+
+ *spimode = tmpmode;
+ return 0;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static int m360_spi_wait
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for spi to become idle |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr, /* handle */
+ uint32_t irq_mask, /* irq mask to use */
+ uint32_t desired_status, /* desired status word */
+ uint32_t status_mask /* status word mask */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ uint32_t act_status;
+ rtems_status_code rc;
+ uint32_t tout;
+
+#if defined(DEBUG)
+ printk("m360_spi_wait called... ");
+#endif
+ if (softc_ptr->initialized) {
+ /*
+ * allow interrupts, when receiver is not empty
+ */
+ softc_ptr->reg_ptr->spim = irq_mask;
+ rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,RTEMS_WAIT,100);
+ if (rc != RTEMS_SUCCESSFUL) {
+ return rc;
+ }
+ }
+ else {
+ tout = 0;
+ do {
+ if (tout++ > 1000000) {
+#if defined(DEBUG)
+ printk("... exit with RTEMS_TIMEOUT\r\n");
+#endif
+ return RTEMS_TIMEOUT;
+ }
+ /*
+ * wait for SPI to terminate
+ */
+ } while (!(softc_ptr->reg_ptr->spie & M360_SPIE_NE));
+ }
+
+ act_status = softc_ptr->reg_ptr->spie;
+ if ((act_status & status_mask)!= desired_status) {
+#if defined(DEBUG)
+ printk("... exit with RTEMS_IO_ERROR,"
+ "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n",
+ act_status,status_mask,desired_status);
+#endif
+ return RTEMS_IO_ERROR;
+ }
+#if defined(DEBUG)
+ printk("... exit OK\r\n");
+#endif
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static void m360_spi_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| handle interrupts |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_irq_hdl_param handle /* handle, is softc_ptr structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = (m360_spi_softc_t *)handle;
+
+ /*
+ * disable interrupt mask
+ */
+ softc_ptr->reg_ptr->spim = 0;
+ if (softc_ptr->initialized) {
+ rtems_semaphore_release(softc_ptr->irq_sema_id);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static void m360_spi_install_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| (un-)install the interrupt handler |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m360_spi_softc_t *softc_ptr, /* ptr to control structure */
+ int install /* TRUE: install, FALSE: remove */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ rtems_irq_connect_data irq_conn_data = {
+ softc_ptr->irq_number,
+ m360_spi_irq_handler, /* rtems_irq_hdl */
+ (rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */
+ m360_spi_irq_on_off, /* (rtems_irq_enable) */
+ m360_spi_irq_on_off, /* (rtems_irq_disable) */
+ m360_spi_irq_isOn /* (rtems_irq_is_enabled) */
+ };
+
+ /*
+ * (un-)install handler for SPI device
+ */
+ if (install) {
+ /*
+ * create semaphore for IRQ synchronization
+ */
+ rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'),
+ 0,
+ RTEMS_FIFO
+ | RTEMS_SIMPLE_BINARY_SEMAPHORE,
+ 0,
+ &softc_ptr->irq_sema_id);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot create semaphore");
+ }
+ if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
+ rtems_panic("SPI: cannot install IRQ handler");
+ }
+ }
+ else {
+ if (!BSP_remove_rtems_irq_handler (&irq_conn_data)) {
+ rtems_panic("SPI: cannot uninstall IRQ handler");
+ }
+ /*
+ * delete sync semaphore
+ */
+ if (softc_ptr->irq_sema_id != 0) {
+ rc = rtems_semaphore_delete(softc_ptr->irq_sema_id);
+ if (rc != RTEMS_SUCCESSFUL) {
+ rtems_panic("SPI: cannot delete semaphore");
+ }
+ }
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize the driver |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+#if defined(DEBUG)
+ printk("m360_spi_init called... ");
+#endif
+ /*
+ * init HW registers:
+ */
+ /*
+ * FIXME: set default mode in SPIM
+ */
+
+ /*
+ * FIXME: allocate BDs (1x RX, 1x TX)
+ */
+
+ /*
+ * init interrupt stuff
+ */
+ m360_spi_install_irq_handler(softc_ptr,TRUE);
+
+ /*
+ * mark, that we have initialized
+ */
+ softc_ptr->initialized = TRUE;
+#if defined(DEBUG)
+ printk("... exit OK\r\n");
+#endif
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_read_write_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| transmit/receive some bytes from SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *rbuf, /* buffer to store bytes */
+ const unsigned char *tbuf, /* buffer to send bytes */
+ int len /* number of bytes to transceive */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes received or (negative) error code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+ rtems_status_code rc;
+ int bc = 0;
+ int bytes_per_char = softc_ptr->bytes_per_char;
+ int bit_shift = softc_ptr->bit_shift;
+ uint32_t spird_val;
+
+#if defined(DEBUG)
+ printk("m360_spi_read_write_bytes called... ");
+#endif
+
+ while (len > bytes_per_char-1) {
+ len -= bytes_per_char;
+ /*
+ * mark last byte in SPCOM
+ */
+#if defined(USE_LAST_BIT)
+ softc_ptr->reg_ptr->spcom = (len < bytes_per_char) ? M360_SPCOM_LST : 0;
+#else
+ softc_ptr->reg_ptr->spcom = 0;
+#endif
+ if (tbuf == NULL) {
+ /*
+ * perform dummy write to read byte
+ */
+ softc_ptr->reg_ptr->spitd = 0;
+ }
+ else {
+ switch(bytes_per_char) {
+ case 1:
+ softc_ptr->reg_ptr->spitd = (*(uint8_t *)tbuf) << bit_shift;
+ break;
+ case 2:
+ softc_ptr->reg_ptr->spitd = (*(uint16_t *)tbuf) << bit_shift;
+ break;
+ case 4:
+ softc_ptr->reg_ptr->spitd = (*(uint32_t *)tbuf) << bit_shift;
+ break;
+ }
+ tbuf += softc_ptr->bytes_per_char;
+ }
+ /*
+ * wait 'til end of transfer
+ */
+#if defined(USE_LAST_BIT)
+ rc = m360_spi_wait(softc_ptr,
+ ((len == 0)
+ ? M360_SPIE_LT
+ : M360_SPIE_NE),
+ ((len == 0)
+ ? M360_SPIE_LT
+ : M360_SPIE_NF)
+ | M360_SPIE_NE,
+ M360_SPIE_LT
+ | M360_SPIE_OV
+ | M360_SPIE_UN
+ | M360_SPIE_NE
+ | M360_SPIE_NF);
+ if (len == 0) {
+ /*
+ * clear the "last transfer complete" event
+ */
+ softc_ptr->reg_ptr->spie = M360_SPIE_LT;
+ }
+#else
+ rc = m360_spi_wait(softc_ptr,
+ M360_SPIE_NE,
+ M360_SPIE_NF
+ | M360_SPIE_NE,
+ M360_SPIE_OV
+ | M360_SPIE_UN
+ | M360_SPIE_NE
+ | M360_SPIE_NF);
+#endif
+ if (rc != RTEMS_SUCCESSFUL) {
+#if defined(DEBUG)
+ printk("... exit rc=%d\r\n",-rc);
+#endif
+ return -rc;
+ }
+ spird_val = softc_ptr->reg_ptr->spird;
+ if (rbuf != NULL) {
+ switch(bytes_per_char) {
+ case 1:
+ (*(uint8_t *)rbuf) = spird_val >> bit_shift;
+ break;
+ case 2:
+ (*(uint16_t *)rbuf) = spird_val >> bit_shift;
+ break;
+ case 4:
+ (*(uint32_t *)rbuf) = spird_val >> bit_shift;
+ break;
+ }
+ rbuf += bytes_per_char;
+ }
+ bc += bytes_per_char;
+ }
+#if defined(DEBUG)
+ printk("... exit OK, rc=%d\r\n",bc);
+#endif
+ return bc;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_read_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| receive some bytes from SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to store bytes */
+ int len /* number of bytes to receive */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes received or (negative) error code |
+\*=========================================================================*/
+{
+ return m360_spi_read_write_bytes(bh,buf,NULL,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_write_bytes
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send some bytes to SPI device |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ unsigned char *buf, /* buffer to send */
+ int len /* number of bytes to send */
+
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| number of bytes sent or (negative) error code |
+\*=========================================================================*/
+{
+ return m360_spi_read_write_bytes(bh,NULL,buf,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m360_spi_set_tfr_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| set SPI to desired baudrate/clock mode/character mode |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc);
+ uint32_t spimode_baud,spimode;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ /*
+ * FIXME: set proper mode
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m360_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m360_spi_char_mode(softc_ptr,
+ tfr_mode->bits_per_char,
+ tfr_mode->lsb_first,
+ &spimode);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ spimode |= spimode_baud;
+ spimode |= M360_SPIMODE_M_S; /* set master mode */
+ if (!tfr_mode->lsb_first) {
+ spimode |= M360_SPIMODE_REV;
+ }
+ if (tfr_mode->clock_inv) {
+ spimode |= M360_SPIMODE_CI;
+ }
+ if (tfr_mode->clock_phs) {
+ spimode |= M360_SPIMODE_CP;
+ }
+ }
+
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * disable SPI
+ */
+ softc_ptr->reg_ptr->spmode &= ~M360_SPIMODE_EN;
+ /*
+ * set new mode and reenable SPI
+ */
+ softc_ptr->reg_ptr->spmode = spimode | M360_SPIMODE_EN;
+ }
+ return rc;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m360_spi_ioctl
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| perform selected ioctl function for SPI |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh, /* bus specifier structure */
+ int cmd, /* ioctl command code */
+ void *arg /* additional argument array */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ int ret_val = -1;
+
+ switch(cmd) {
+ case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
+ ret_val =
+ -m360_spi_set_tfr_mode(bh,
+ (const rtems_libi2c_tfr_mode_t *)arg);
+ break;
+ case RTEMS_LIBI2C_IOCTL_READ_WRITE:
+ ret_val =
+ m360_spi_read_write_bytes(bh,
+ ((rtems_libi2c_read_write_t *)arg)->rd_buf,
+ ((rtems_libi2c_read_write_t *)arg)->wr_buf,
+ ((rtems_libi2c_read_write_t *)arg)->byte_cnt);
+ break;
+ default:
+ ret_val = -RTEMS_NOT_DEFINED;
+ break;
+ }
+ return ret_val;
+}
+
+
+
diff --git a/c/src/lib/libbsp/m68k/gen68360/startup/init68360.c b/c/src/lib/libbsp/m68k/gen68360/startup/init68360.c
index 37fd35f5e2..f1f0f26dce 100644
--- a/c/src/lib/libbsp/m68k/gen68360/startup/init68360.c
+++ b/c/src/lib/libbsp/m68k/gen68360/startup/init68360.c
@@ -14,6 +14,13 @@
#include <bsp.h>
#include <rtems/m68k/m68360.h>
+
+/*
+ * Declare the m360 structure here for the benefit of the debugger
+ */
+
+volatile m360_t m360;
+
/*
* Send a command to the CPM RISC processer
*/
@@ -335,6 +342,174 @@ void _Init68360 (void)
* BCLRO* arbitration level 3
*/
+#elif defined(PGH360)
+ /*
+ * Step 6: Is this a power-up reset?
+ * For now we just ignore this and do *all* the steps
+ * Someday we might want to:
+ * if (Hard, Loss of Clock, Power-up)
+ * Do all steps
+ * else if (Double bus fault, watchdog or soft reset)
+ * Skip to step 12
+ * else (must be a CPU32+ reset command)
+ * Skip to step 14
+ */
+
+ /*
+ * Step 7: Deal with clock synthesizer
+ * HARDWARE:
+ * Change if you're not using an external 25 MHz oscillator.
+ */
+ m360.clkocr = 0x8e; /* No more writes, CLKO1=1/3, CLKO2=off */
+ /*
+ * adjust crystal to average between 4.19 MHz and 4.00 MHz
+ * reprogram pll
+ */
+ m360.pllcr = 0xA000+(24576000/((4000000+4194304)/2/128))-1;
+ /* LPSTOP slowdown, PLL /128*??? */
+ m360.cdvcr = 0x8000; /* No more writes, no clock division */
+
+ /*
+ * Step 8: Initialize system protection
+ * Enable watchdog
+ * Watchdog causes system reset
+ * 128 sec. watchdog timeout
+ * Enable double bus fault monitor
+ * Enable bus monitor external
+ * 128 clocks for external timeout
+ */
+ m360.sypcr = 0xEF;
+ /*
+ * also initialize the SWP bit in PITR to 1
+ */
+ m360.pitr |= 0x0200;
+ /*
+ * and trigger SWSR twice to ensure, that interval starts right now
+ */
+ m360.swsr = 0x55;
+ m360.swsr = 0xAA;
+ m360.swsr = 0x55;
+ m360.swsr = 0xAA;
+ /*
+ * Step 9: Clear parameter RAM and reset communication processor module
+ */
+ for (i = 0 ; i < 192 ; i += sizeof (long)) {
+ *((long *)((char *)&m360 + 0xC00 + i)) = 0;
+ *((long *)((char *)&m360 + 0xD00 + i)) = 0;
+ *((long *)((char *)&m360 + 0xE00 + i)) = 0;
+ *((long *)((char *)&m360 + 0xF00 + i)) = 0;
+ }
+ M360ExecuteRISC (M360_CR_RST);
+
+ /*
+ * Step 10: Write PEPAR
+ * SINTOUT not used (CPU32+ mode)
+ * CF1MODE=00 (CONFIG1 input)
+ * IPIPE1
+ * WE0-3
+ * OE* output
+ * CAS2* / CAS3*
+ * CAS0* / CAS1*
+ * CS7*
+ * AVEC*
+ * HARDWARE:
+ * Change if you are using a different memory configuration
+ * (static RAM, external address multiplexing, etc).
+ */
+ m360.pepar = 0x0080;
+ /*
+ * Step 11: Remap Chip Select 0 (CS0*), set up GMR
+ * no DRAM support
+ * HARDWARE:
+ * Change if you are using a different memory configuration
+ */
+ m360.gmr = M360_GMR_RCNT(23) | M360_GMR_RFEN | M360_GMR_RCYC(0) |
+ M360_GMR_PGS(6) | M360_GMR_DPS_32BIT | M360_GMR_DWQ |
+ M360_GMR_GAMX;
+
+ m360.memc[0].br = (unsigned long)&_RomBase | M360_MEMC_BR_WP |
+ M360_MEMC_BR_V;
+ m360.memc[0].or = M360_MEMC_OR_WAITS(3) | M360_MEMC_OR_512KB |
+ M360_MEMC_OR_8BIT;
+
+ /*
+ * Step 12: Initialize the system RAM
+ * Set up option/base registers
+ * 16 MB DRAM
+ * 1 wait state
+ * HARDWARE:
+ * Change if you are using a different memory configuration
+ * NOTE: no Page mode possible for EDO RAMs (?)
+ */
+ ramSize = 16 * 1024 * 1024;
+ m360.memc[7].or = M360_MEMC_OR_TCYC(1) | M360_MEMC_OR_16MB |
+ M360_MEMC_OR_FCMC(0) | /* M360_MEMC_OR_PGME | */
+ M360_MEMC_OR_32BIT | M360_MEMC_OR_DRAM;
+ m360.memc[7].br = (unsigned long)&_RamBase | M360_MEMC_BR_V;
+
+ /*
+ * FIXME: here we should wait for 8 refresh cycles...
+ */
+ /*
+ * Step 12a: test the ram, if wanted
+ * FIXME: when do we call this?
+ * -> only during firmware execution
+ * -> perform intesive test only on request
+ * -> ensure, that results are stored properly
+ */
+#if 0 /* FIXME: activate RAM tests again */
+ {
+ void *ram_base, *ram_end, *code_loc;
+ extern char ramtest_start,ramtest_end;
+ ram_base = &ramtest_start;
+ ram_end = &ramtest_end;
+ code_loc = (void *)ramtest_exec;
+ if ((ram_base < ram_end) &&
+ !((ram_base <= code_loc) && (code_loc < ram_end))) {
+ ramtest_exec(ram_base,ram_end);
+ }
+ }
+#endif
+ /*
+ * Step 13: Copy the exception vector table to system RAM
+ */
+ m68k_get_vbr (vbr);
+ for (i = 0; i < 256; ++i)
+ M68Kvec[i] = vbr[i];
+ m68k_set_vbr (M68Kvec);
+
+ /*
+ * Step 14: More system initialization
+ * SDCR (Serial DMA configuration register)
+ * Disable SDMA during FREEZE
+ * Give SDMA priority over all interrupt handlers
+ * Set DMA arbiration level to 4
+ * CICR (CPM interrupt configuration register):
+ * SCC1 requests at SCCa position
+ * SCC2 requests at SCCb position
+ * SCC3 requests at SCCc position
+ * SCC4 requests at SCCd position
+ * Interrupt request level 4
+ * Maintain original priority order
+ * Vector base 128
+ * SCCs priority grouped at top of table
+ */
+ m360.sdcr = M360_SDMA_SISM_7 | M360_SDMA_SAID_4;
+ m360.cicr = (3 << 22) | (2 << 20) | (1 << 18) | (0 << 16) |
+ (4 << 13) | (0x1F << 8) | (128);
+
+ /*
+ * Step 15: Set module configuration register
+ * Disable timers during FREEZE
+ * Enable bus monitor during FREEZE
+ * BCLRO* arbitration level 3
+ * No show cycles
+ * User/supervisor access
+ * Bus clear interupt service level 7
+ * SIM60 interrupt sources higher priority than CPM
+ */
+ m360.mcr = 0x4C7F;
+
#elif (defined (GEN68360_WITH_SRAM))
/*
***************************************************