summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-21 13:54:50 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-10-21 13:54:50 +0000
commitea546eb72d155ed29ee35b02012fc865c4b0e37c (patch)
tree0df6d093018761686910992bd70333dc24579d97 /c
parentinterrupt handler type change (diff)
downloadrtems-ea546eb72d155ed29ee35b02012fc865c4b0e37c.tar.bz2
add missing file
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/spi/spi.c847
-rw-r--r--c/src/lib/libbsp/m68k/gen68360/spi/spi.h146
2 files changed, 993 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/gen68360/spi/spi.c b/c/src/lib/libbsp/m68k/gen68360/spi/spi.c
new file mode 100644
index 0000000000..1af82b9d31
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68360/spi/spi.c
@@ -0,0 +1,847 @@
+/*===============================================================*\
+| Project: RTEMS support for tqm8xx |
++-----------------------------------------------------------------+
+| Copyright (c) 2009 |
+| 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 MPC8xx SPI driver |
+\*===============================================================*/
+#include <stdlib.h>
+#include <bsp.h>
+#include <mpc8xx.h>
+#include "spi.h"
+#include <rtems/error.h>
+#include <rtems/bspIo.h>
+#include <errno.h>
+#include <rtems/libi2c.h>
+#include <bsp/irq.h>
+
+#define M8xx_PB_SPI_MISO_MSK (1<<(31-28))
+#define M8xx_PB_SPI_MOSI_MSK (1<<(31-29))
+#define M8xx_PB_SPI_CLK_MSK (1<<(31-30))
+
+#undef DEBUG
+static m8xx_spi_softc_t *m8xx_spi_softc_ptr;
+/*
+ * this is a dummy receive buffer for sequences,
+ * where only send data are available
+ */
+uint8_t m8xx_spi_dummy_rxbuf[2];
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m8xx_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 = BSP_bus_frequency/baudrate;
+ if (divider > 64) {
+ tmpmode = M8xx_SPMODE_DIV16;
+ divider /= 16;
+ }
+ if ((divider < 1) ||
+ (divider > 64)) {
+ return RTEMS_INVALID_NUMBER;
+ }
+ else {
+ tmpmode |= M8xx_SPMODE_PM(divider/4-1);
+ }
+ *spimode = tmpmode;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static rtems_status_code m8xx_spi_char_mode
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| determine proper value for character size |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m8xx_spi_softc_t *softc_ptr, /* handle */
+ uint32_t bits_per_char, /* bits per character */
+ bool 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 = M8xx_SPMODE_CLEN( bits_per_char-1);
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ *spimode = tmpmode;
+ return 0;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static int m8xx_spi_wait
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for spi to become idle |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m8xx_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("m8xx_spi_wait called... ");
+#endif
+ if (softc_ptr->initialized) {
+ /*
+ * allow interrupts, when receiver is not empty
+ */
+ m8xx.spim = (M8xx_SPIE_TXE | M8xx_SPIE_TXB |
+ M8xx_SPIE_BSY | M8xx_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 (!(m8xx.spie & M8xx_SPIE_TXB));
+ }
+
+ act_status = m8xx.spie;
+ if ((act_status & (M8xx_SPIE_TXE | M8xx_SPIE_TXB |
+ M8xx_SPIE_BSY | M8xx_SPIE_MME))!= M8xx_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 m8xx_spi_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| handle interrupts |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void *arg
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ m8xx_spi_softc_t *softc_ptr = arg;
+
+ /*
+ * disable interrupt mask
+ */
+ m8xx.spim = 0;
+ if (softc_ptr->initialized) {
+ rtems_semaphore_release(softc_ptr->irq_sema_id);
+ }
+}
+
+static void
+mpc8xx_spi_irq_on(const rtems_irq_connect_data *irq)
+{
+}
+
+static void
+mpc8xx_spi_irq_off(const rtems_irq_connect_data *irq)
+{
+}
+
+static int
+mpc8xx_spi_irq_isOn(const rtems_irq_connect_data *irq)
+{
+ return 1;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+static void m8xx_spi_install_irq_handler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| install the interrupt handler |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ m8xx_spi_softc_t *softc_ptr, /* ptr to control structure */
+ int install /* TRUE: install, FALSE: remove */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ /*
+ * install handler for SPI device
+ */
+ /*
+ * 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) {
+ rtems_irq_connect_data irq_conn_data = {
+ BSP_CPM_IRQ_SPI,
+ m8xx_spi_irq_handler, /* rtems_irq_hdl */
+ (rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */
+ mpc8xx_spi_irq_on, /* (rtems_irq_enable) */
+ mpc8xx_spi_irq_off, /* (rtems_irq_disable) */
+ mpc8xx_spi_irq_isOn /* (rtems_irq_is_enabled) */
+ };
+ if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
+ rtems_panic("SPI: cannot install IRQ handler");
+ }
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m8xx_spi_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize the driver |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ rtems_libi2c_bus_t *bh /* bus specifier structure */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| o = ok or error code |
+\*=========================================================================*/
+{
+ m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+#if defined(DEBUG)
+ printk("m8xx_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 = m8xx_bd_allocate (1);
+ softc_ptr->tx_bd = m8xx_bd_allocate (1);
+ if ((softc_ptr->rx_bd == NULL) ||
+ (softc_ptr->tx_bd == NULL)) {
+ rc = RTEMS_NO_MEMORY;
+ }
+ }
+ /*
+ * set parameter RAM
+ */
+ m8xx.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m8xx;
+ m8xx.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m8xx;
+ m8xx.spip.rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
+ m8xx.spip.tfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
+ m8xx.spip.mrblr = 2;
+
+ /*
+ * issue "InitRxTx" Command to CP
+ */
+ m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SPI);
+
+ /*
+ * init interrupt stuff
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ m8xx_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... */
+ m8xx.pbpar =
+ m8xx.pbpar
+ | M8xx_PB_SPI_MISO_MSK
+ | M8xx_PB_SPI_MOSI_MSK
+ | M8xx_PB_SPI_CLK_MSK;
+
+ /* set Port B Data Direction Register... */
+ m8xx.pbdir =
+ m8xx.pbdir
+ | M8xx_PB_SPI_MISO_MSK
+ | M8xx_PB_SPI_MOSI_MSK
+ | M8xx_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 m8xx_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 |
+\*=========================================================================*/
+{
+ m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ int bc = 0;
+
+#if defined(DEBUG)
+ printk("m8xx_spi_read_write_bytes called... ");
+#endif
+
+ /*
+ * prepare RxBD
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (rbuf == NULL) {
+ /*
+ * no Tx buffer: receive to dummy buffer
+ */
+ m8xx.spip.mrblr = sizeof(m8xx_spi_dummy_rxbuf);
+ softc_ptr->rx_bd->buffer = m8xx_spi_dummy_rxbuf;
+ softc_ptr->rx_bd->length = 0;
+ softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP |
+ M8xx_BD_CONTINUOUS);
+ }
+ else {
+ m8xx.spip.mrblr = len;
+ softc_ptr->rx_bd->buffer = rbuf;
+ softc_ptr->rx_bd->length = 0;
+ softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP);
+ }
+ }
+ /*
+ * prepare TxBD
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if (tbuf == NULL) {
+ /*
+ * no Tx buffer: transmit from dummy buffer
+ */
+ softc_ptr->tx_bd->buffer = m8xx_spi_dummy_rxbuf;
+ softc_ptr->tx_bd->length = len;
+ softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP |
+ M8xx_BD_CONTINUOUS);
+ }
+ else {
+ softc_ptr->tx_bd->buffer = (char *)tbuf;
+ softc_ptr->tx_bd->length = len;
+ softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP);
+ }
+ }
+
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * set START command
+ */
+ m8xx.spcom = M8xx_SPCOM_STR;
+ /*
+ * wait for SPI to finish
+ */
+ rc = m8xx_spi_wait(softc_ptr);
+ }
+#if defined(DEBUG)
+ printk("... exit OK, rc=%d\r\n",bc);
+#endif
+ return (rc == RTEMS_SUCCESSFUL) ? bc : -rc;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m8xx_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 m8xx_spi_read_write_bytes(bh,buf,NULL,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m8xx_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 m8xx_spi_read_write_bytes(bh,NULL,buf,len);
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m8xx_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 |
+\*=========================================================================*/
+{
+ m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
+ uint32_t spimode_baud;
+ uint16_t spimode;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ /*
+ * FIXME: set proper mode
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m8xx_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ rc = m8xx_spi_char_mode(softc_ptr,
+ tfr_mode->bits_per_char,
+ tfr_mode->lsb_first,
+ &spimode);
+ }
+ if (rc == RTEMS_SUCCESSFUL) {
+ spimode |= spimode_baud;
+ spimode |= M8xx_SPMODE_MASTER; /* set master mode */
+ if (!tfr_mode->lsb_first) {
+ spimode |= M8xx_SPMODE_REV;
+ }
+ if (tfr_mode->clock_inv) {
+ spimode |= M8xx_SPMODE_CI;
+ }
+ if (tfr_mode->clock_phs) {
+ spimode |= M8xx_SPMODE_CP;
+ }
+ }
+
+ if (rc == RTEMS_SUCCESSFUL) {
+ /*
+ * disable SPI
+ */
+ m8xx.spmode &= ~M8xx_SPMODE_EN;
+ /*
+ * set new mode and reenable SPI
+ */
+ m8xx.spmode = spimode | M8xx_SPMODE_EN;
+ }
+ return rc;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int m8xx_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 =
+ -m8xx_spi_set_tfr_mode(bh,
+ (const rtems_libi2c_tfr_mode_t *)arg);
+ break;
+ case RTEMS_LIBI2C_IOCTL_READ_WRITE:
+ ret_val =
+ m8xx_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:
+ m8xx.pbdat &= ~PGH360_PB_SPI_EEP_CE_MSK;
+ break;
+ case PGH360_SPI_ADDR_DISP4_DATA:
+ m8xx.pbdat = (m8xx.pbdat
+ & ~(PGH360_PB_SPI_DISP4_CE_MSK |
+ PGH360_PB_SPI_DISP4_RS_MSK));
+ break;
+ case PGH360_SPI_ADDR_DISP4_CTRL:
+ m8xx.pbdat = (m8xx.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)
+ m8xx.pbdat = (m8xx.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: m8xx_spi_init,
+ send_start: bsp_spi_send_start_dummy,
+ send_stop: bsp_spi_send_stop,
+ send_addr: bsp_spi_sel_addr,
+ read_bytes: m8xx_spi_read_bytes,
+ write_bytes: m8xx_spi_write_bytes,
+ ioctl: m8xx_spi_ioctl
+};
+
+static m8xx_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... */
+ m8xx.pbpar =
+ (m8xx.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... */
+ m8xx.pbdir =
+ m8xx.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 */
+ m8xx.pbdat =
+ m8xx.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/spi.h b/c/src/lib/libbsp/m68k/gen68360/spi/spi.h
new file mode 100644
index 0000000000..28bd7f1b16
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/gen68360/spi/spi.h
@@ -0,0 +1,146 @@
+/*===============================================================*\
+| Project: RTEMS support for MPC8xx |
++-----------------------------------------------------------------+
+| Copyright (c) 2009 |
+| 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 MPC8xx SPI driver declarations |
+\*===============================================================*/
+#ifndef _M8XX_SPIDRV_H
+#define _M8XX_SPIDRV_H
+
+#include <mpc8xx.h>
+#include <rtems/libi2c.h>
+#include <rtems/irq.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct m8xx_spi_softc {
+ int initialized;
+ rtems_id irq_sema_id;
+ rtems_isr_entry old_handler;
+ m8xxBufferDescriptor_t *rx_bd;
+ m8xxBufferDescriptor_t *tx_bd;
+} m8xx_spi_softc_t ;
+
+typedef struct {
+ rtems_libi2c_bus_t bus_desc;
+ m8xx_spi_softc_t softc;
+} m8xx_spi_desc_t;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+rtems_status_code m8xx_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 m8xx_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 m8xx_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 m8xx_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 m8xx_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 /* _M8XX_SPIDRV_H */