#include "drv/spi.h"
#include "sys/port.h"
-//#include "drv_spi.h"
-//#include "sys_common.h"
-//#include "ti_drv_dmm.h"
#include "sys/ti_drv_dmm.h"
-
-static int spi_tms570_ctrl_fnc(spi_drv_t *ifc, int ctrl, void *p);
-
-
-/* Each SPI interface has its own static spi_tms570_drv_t struct
- Index to this array is "SPI Interface ID -1" */
-spi_tms570_drv_t spi_tms570_ifcs[4];
-
-/* Addresses of SPI devices (=chips) bound to particular interfaces */
-enum spi_ifc1_devices {
- SPIDEV_MC33972 = 0, SPIDEV_NCV7608_2x
-};
-enum spi_ifc2_devices {
- SPIDEV_SDCARD = 0
-};
-enum spi_ifc3_devices {
- SPIDEV_MCP4922_1 = 0, SPIDEV_MCP4922_2, SPIDEV_MCP4922_3
-};
-enum spi_ifc4_devices {
- SPIDEV_L99H01 = 0, SPIDEV_TJA1082_1, SPIDEV_TJA1082_2
+#include "drv/spi_def.h"
+#include "drv/spi_tms570.h"
+
+#define SPI_FLG_TXINT_m (1 << 9)
+#define SPI_FLG_RXINT_m (1 << 8)
+
+#define SPI_INT0_TXINTENA_m (1 << 9)
+#define SPI_INT0_RXINTENA_m (1 << 8)
+
+#define SPI_DAT1_CSHOLD_m (1 << 28)
+
+typedef volatile struct spiBase {
+ uint32_t GCR0; /**< 0x0000: Global Control 0 */
+#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
+ uint32_t GCR1 : 8U; /**< 0x0007: Global Control 1 */
+ uint32_t PD : 1U; /**< 0x0006: Power down bit */
+ uint32_t : 7U;
+ uint32_t LB : 1U; /**< 0x0005: Loop back bit */
+ uint32_t : 7U;
+ uint32_t ENA : 1U; /**< 0x0004: SPI Enable bit */
+ uint32_t : 7U;
+ uint32_t INT0 : 16U; /**< 0x000A: Interrupt Enable bits */
+ uint32_t DMAREQEN : 1U; /**< 0x0009: DMA Request enable */
+ uint32_t : 7U;
+ uint32_t ENAHIGHZ : 1U; /**< 0x0008: Enable HIGHZ outputs */
+ uint32_t : 7U;
+#else
+ uint32_t : 7U;
+ uint32_t ENA : 1U; /**< 0x0004: SPI Enable bit */
+ uint32_t : 7U;
+ uint32_t LB : 1U; /**< 0x0005: Loop back bit */
+ uint32_t : 7U;
+ uint32_t PD : 1U; /**< 0x0006: Power down bit */
+ uint32_t GCR1 : 8U; /**< 0x0007: Global Control 1 */
+ uint32_t : 7U;
+ uint32_t ENAHIGHZ : 1U; /**< 0x0008: Enable HIGHZ outputs */
+ uint32_t : 7U;
+ uint32_t DMAREQEN : 1U; /**< 0x0009: DMA Request enable */
+ uint32_t INT0 : 16U; /**< 0x000A: Interrupt Enable bits */
+#endif
+ uint32_t LVL; /**< 0x000C: Interrupt Level */
+#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
+ uint32_t FLG : 16U; /**< 0x0012: Interrupt flags */
+ uint32_t : 8U;
+ uint32_t BUFINIT : 1U; /**< 0x0010: Buffer initialization active flag */
+ uint32_t : 7U;
+#else
+ uint32_t : 7U;
+ uint32_t BUFINIT : 1U; /**< 0x0010: Buffer initialization active flag */
+ uint32_t : 8U;
+ uint32_t FLG : 16U; /**< 0x0012: Interrupt flags */
+#endif
+ uint32_t PCFUN; /**< 0x0014: Function Pin Enable */
+ uint32_t PCDIR; /**< 0x0018: Pin Direction */
+ uint32_t PCDIN; /**< 0x001C: Pin Input Latch */
+ uint32_t PCDOUT; /**< 0x0020: Pin Output Latch */
+ uint32_t PCSET; /**< 0x0024: Output Pin Set */
+ uint32_t PCCLR; /**< 0x0028: Output Pin Clr */
+ uint32_t PCPDR; /**< 0x002C: Open Drain Output Enable */
+ uint32_t PCDIS; /**< 0x0030: Pullup/Pulldown Disable */
+ uint32_t PCPSL; /**< 0x0034: Pullup/Pulldown Selection */
+ uint32_t DAT0; /**< 0x0038: Transmit Data */
+ uint32_t DAT1; /**< 0x003C: Transmit Data with Format and Chip Select */
+ uint32_t BUF; /**< 0x0040: Receive Buffer */
+ uint32_t EMU; /**< 0x0044: Emulation Receive Buffer */
+ uint32_t DELAY; /**< 0x0048: Delays */
+ uint32_t CSDEF; /**< 0x004C: Default Chip Select */
+ uint32_t FMT0; /**< 0x0050: Data Format 0 */
+ uint32_t FMT1; /**< 0x0054: Data Format 1 */
+ uint32_t FMT2; /**< 0x0058: Data Format 2 */
+ uint32_t FMT3; /**< 0x005C: Data Format 3 */
+ uint32_t INTVECT0; /**< 0x0060: Interrupt Vector 0 */
+ uint32_t INTVECT1; /**< 0x0064: Interrupt Vector 1 */
+ uint32_t SRSEL; /**< 0x0068: Slew Rate Select */
+
+ uint32_t PMCTRL; /**< 0x006C: Parallel Mode Control */
+#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
+ uint32_t MIBSPIE : 16U; /**< 0x0072: MibSPI Enable */
+ uint32_t RAMACCESS : 16U; /**< 0x0070: RX Ram Write Access Enable */
+#else
+ uint32_t RAMACCESS : 16U; /**< 0x0070: RX Ram Write Access Enable */
+ uint32_t MIBSPIE : 16U; /**< 0x0072: MibSPI Enable */
+#endif
+
+ uint32_t RESERVED[48U]; /**< 0x006C to 0x0130: Reserved */
+ uint32_t IOLPKTSTCR; /**< 0x0134: IO loopback */
+} spiBASE_compat_t;
+
+#define spi_compat_REG2 ((spiBASE_compat_t *)0xFFF7F600U)
+#define spi_compat_REG4 ((spiBASE_compat_t *)0xFFF7FA00U)
+#define mibspi_compat_REG1 ((spiBASE_compat_t *)0xFFF7F400U)
+#define mibspi_compat_REG3 ((spiBASE_compat_t *)0xFFF7F800U)
+#define mibspi_compat_REG5 ((spiBASE_compat_t *)0xFFF7FC00U) /* NOT USED ON RPP BOARD */
+
+/* SPI interface */
+struct spi_tms570_iface {
+ spi_drv_t spi_drv;
+ spiBASE_compat_t *reg; /* Base Reg. for SPI device register array */
+ unsigned txcnt; /* No. of transfered bytes for msg_act */
+ unsigned rxcnt; /* No. of received bytes for msg_act */
+ spi_dev_t *spi_devs; /* Pointer to table holding information about SPI devices bound to the interface */
+ uint32_t transfer_ctrl; /* Transfer configuration -- upper 16 bits of SPIDAT1 register */
+ /* TODO: Add FMT description here if we need different formats */
};
-spi_dev_t spi_ifc1_devs[] = {
- [SPIDEV_MC33972] = {
- .cs = SPI_CS_3,
- .dfsel = 0,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- },
- [SPIDEV_NCV7608_2x] = {
- .cs = SPI_CS_4,
- .dfsel = 0,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- }
-};
-
-spi_dev_t spi_ifc2_devs[] = {
- [SPIDEV_SDCARD] = {
- .cs = SPI_CS_0,
- .dfsel = 0,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- }
+spi_tms570_iface_t spi_iface[5] = {
+ [SPI_IFACE1] = { .reg = mibspi_compat_REG1, },
+ [SPI_IFACE2] = { .reg = spi_compat_REG2, },
+ [SPI_IFACE3] = { .reg = mibspi_compat_REG3, },
+ [SPI_IFACE4] = { .reg = spi_compat_REG4, },
+ [SPI_IFACE5] = { .reg = mibspi_compat_REG5, },
};
-spi_dev_t spi_ifc3_devs[] = {
- [SPIDEV_MCP4922_1] = {
- .cs = SPI_CS_0,
- .dfsel = 1,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- },
- [SPIDEV_MCP4922_2] = {
- .cs = SPI_CS_4,
- .dfsel = 1,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- },
- [SPIDEV_MCP4922_3] = {
- .cs = SPI_CS_5,
- .dfsel = 1,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- }
-};
+spi_drv_t *spi_tms570_get_iface(enum spi_device dev)
+{
+ return &spi_iface[spi_devs[dev].iface].spi_drv;
+}
-spi_dev_t spi_ifc4_devs[] = {
- [SPIDEV_L99H01] = {
- .cs = SPI_CS_0 | SPI_CS_DMM0,
- .dfsel = 1,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- },
- [SPIDEV_TJA1082_1] = {
- .cs = SPI_CS_0 | SPI_CS_DMM1,
- .dfsel = 0,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- },
- [SPIDEV_TJA1082_2] = {
- .cs = SPI_CS_0 | SPI_CS_DMM2,
- .dfsel = 0,
- .wdel = 0,
- .cshold = 1,
- .dlen = 0
- }
-};
+static int spi_tms570_ctrl_fnc(spi_drv_t *ifc, int ctrl, void *p);
/*
Universal piece of code initializing SPI or MibSPI
ENA register is set even on SPI devices which do not have it --
this should not be an issue
*/
-void spiInit(spiBASE_compat_t *spiREG)
+static void spiInit(spiBASE_compat_t *spiREG)
{
/** bring SPI out of reset */
spiREG->GCR0 = 1U;
| 0; /* C2EDELAY */
/** - Data Format 0 */
+ /* TODO: Set the formats from spi_tms570_iface_t if we need different formats */
spiREG->FMT0 = (0 << 24) /* wdelay */
| (0 << 23) /* parity Polarity */
| (0 << 22) /* parity enable */
spiREG->ENA = 1U;
}
-static boolean_t spi_initialized = FALSE;
+static void init_iface(spi_tms570_iface_t *iface)
+{
+ spiInit(iface->reg);
+ iface->spi_drv.ctrl_fnc = spi_tms570_ctrl_fnc;
+ spi_rq_queue_init_head(&(iface->spi_drv));
+ iface->spi_drv.msg_act = NULL;
+ iface->spi_drv.flags = 0;
+}
-int spi_tms570_init(void)
+void spi_tms570_init()
{
- if (spi_initialized == TRUE)
- return FAILURE;
- spi_initialized = TRUE;
int i;
- spi_tms570_ifcs[0].spi = mibspi_compat_REG1;
- spi_tms570_ifcs[1].spi = spi_compat_REG2;
- spi_tms570_ifcs[2].spi = mibspi_compat_REG3;
- spi_tms570_ifcs[3].spi = spi_compat_REG4;
-
- spi_tms570_ifcs[0].spi_devs = spi_ifc1_devs;
- spi_tms570_ifcs[1].spi_devs = spi_ifc2_devs;
- spi_tms570_ifcs[2].spi_devs = spi_ifc3_devs;
- spi_tms570_ifcs[3].spi_devs = spi_ifc4_devs;
-
-
- for (i = 0; i <= 3; i++) {
- spiInit(spi_tms570_ifcs[i].spi);
- spi_tms570_ifcs[i].spi_drv.ctrl_fnc = spi_tms570_ctrl_fnc;
- spi_rq_queue_init_head(&(spi_tms570_ifcs[i].spi_drv));
- spi_tms570_ifcs[i].spi_drv.msg_act = NULL;
- spi_tms570_ifcs[i].spi_drv.flags = SPI_IFC_ON;
- }
+ for (i = 0; i < ARRAY_SIZE(spi_iface); i++)
+ init_iface(&spi_iface[i]);
//dmmREG->PC5 = (1 << DMM_DATA5); /* Set to L */
//dmmREG->PC5 = (1 << DMM_DATA6); /* Set to L */
-
- return SUCCESS;
}
static int spi_tms570_ctrl_fnc(spi_drv_t *ifc, int ctrl, void *p)
{
- spi_tms570_drv_t *tms570_drv =
- UL_CONTAINEROF(ifc, spi_tms570_drv_t, spi_drv);
+ spi_tms570_iface_t *tms570_drv =
+ UL_CONTAINEROF(ifc, spi_tms570_iface_t, spi_drv);
switch (ctrl) {
case SPI_CTRL_WAKE_RQ:
- if (!(ifc->flags & SPI_IFC_ON))
- return -1;
if (spi_rq_queue_is_empty(ifc))
return 0;
- tms570_drv->spi->INT0 = SPI_INT0_TXINTENA_m;
+ tms570_drv->reg->INT0 = SPI_INT0_TXINTENA_m;
// Enable TXINT (Causes an interrupt
// to be generated every time data is written to the shift
// register, so that the next word can be written to TXBUF.
void spi_tms570_isr(int spi_ifc, uint32_t flags)
{
- spi_msg_head_t *msg;
- spi_tms570_drv_t *spi_tms570_drv;
-
- spi_tms570_drv = &spi_tms570_ifcs[spi_ifc];
+ spi_msg_t *msg;
+ spi_tms570_iface_t *iface = &spi_iface[spi_ifc];
+ const spi_dev_t *dev;
spi_isr_lock_level_t saveif;
uint8_t val_to_wr;
uint32_t cs;
if (flags & SPI_FLG_TXINT_m) {
do {
- msg = spi_tms570_drv->spi_drv.msg_act;
+ msg = iface->spi_drv.msg_act;
if (!msg) { /* Is there any MSG being processed? */
/* If not, get one from a queue */
spi_isr_lock(saveif);
- msg = spi_tms570_drv->spi_drv.msg_act =
- spi_rq_queue_first(&spi_tms570_drv->spi_drv);
+ msg = iface->spi_drv.msg_act =
+ spi_rq_queue_first(&iface->spi_drv);
spi_isr_unlock(saveif);
if (!msg) { /* Nothing to process */
volatile unsigned int dummy_read;
/* Disable TXEMPTY IRQ */
- spi_tms570_drv->spi->INT0 = 0x00;
- spi_tms570_drv->spi->FLG = 0x00;
- dummy_read = spi_tms570_drv->spi->BUF;
+ iface->reg->INT0 = 0x00;
+ iface->reg->FLG = 0x00;
+ dummy_read = iface->reg->BUF;
// FIXME "INT |= " with disabled IRQ ??
return;
}
- spi_tms570_drv->txcnt = 0;
- spi_tms570_drv->rxcnt = 0;
- cs = spi_tms570_drv->spi_devs[msg->addr].cs;
- spi_tms570_drv->transfer_ctrl =
+ iface->txcnt = 0;
+ iface->rxcnt = 0;
+ dev = &spi_devs[msg->dev];
+ cs = dev->cs;
+ iface->transfer_ctrl =
(cs & 0xff) << 16
- | (spi_tms570_drv->spi_devs[msg->addr].wdel & 0x1) << 26
- | (spi_tms570_drv->spi_devs[msg->addr].cshold & 0x1) << 28
- | (spi_tms570_drv->spi_devs[msg->addr].dfsel & 0x3) << 24;
+ | (dev->wdel & 0x1) << 26
+ | (dev->cshold & 0x1) << 28
+ | (dev->dfsel & 0x3) << 24;
+#if defined(TARGET_TMS570_RPP)
/* GPIO CS -- setting the multiplexer */
if (cs > 0xff) {
switch (cs & 0xFF00) {
break;
}
}
+#endif
}
rq_len = msg->rq_len;
- rxcnt = spi_tms570_drv->rxcnt;
- txcnt = spi_tms570_drv->txcnt;
+ rxcnt = iface->rxcnt;
+ txcnt = iface->txcnt;
/* RX/TX transfers */
do {
/* Receive all the incoming data */
- while (spi_tms570_drv->spi->FLG & SPI_FLG_RXINT_m) {
- rx_data = spi_tms570_drv->spi->BUF;
+ while (iface->reg->FLG & SPI_FLG_RXINT_m) {
+ rx_data = iface->reg->BUF;
- if (msg->rx_buf && (rxcnt < rq_len))
+ if (msg->rx_buf && (rxcnt < rq_len)) {
+ /* This relies on all FMTs having 8 bit CHARLEN */
msg->rx_buf[rxcnt++] = rx_data & 0xFF;
- //FIXME how to make sure we got only 8 bits
- else
+ } else
rxcnt++;
}
while (1) {
/* Tx buffer full or nothing to send */
stop_fl = ((txcnt >= rq_len) ||
- (!(spi_tms570_drv->spi->FLG & SPI_FLG_TXINT_m)));
+ (!(iface->reg->FLG & SPI_FLG_TXINT_m)));
if (stop_fl)
break;
/* Make it possible to write "empty data"
for "read transfers" */
- if (msg->tx_buf)
+ if (msg->tx_buf) {
+ /* This relies on all FMTs having 8 bit CHARLEN */
val_to_wr = msg->tx_buf[txcnt++];
- else {
+ } else {
val_to_wr = 0x00;
txcnt++;
}
- if (txcnt == rq_len) /* Disable CS for the last byte of the transfer */
- spi_tms570_drv->transfer_ctrl &= ~SPI_DAT1_CSHOLD_m;
+ if (txcnt == rq_len) /* Disable CS after last byte of the transfer */
+ iface->transfer_ctrl &= ~SPI_DAT1_CSHOLD_m;
- spi_tms570_drv->spi->DAT1 =
- (uint32_t)(spi_tms570_drv->transfer_ctrl | val_to_wr);
+ iface->reg->DAT1 =
+ (uint32_t)(iface->transfer_ctrl | val_to_wr);
/* We just received something */
- if (spi_tms570_drv->spi->FLG & SPI_FLG_RXINT_m)
+ if (iface->reg->FLG & SPI_FLG_RXINT_m)
break;
}
} while (!stop_fl);
- spi_tms570_drv->rxcnt = rxcnt;
- spi_tms570_drv->txcnt = txcnt;
+ iface->rxcnt = rxcnt;
+ iface->txcnt = txcnt;
if ((rxcnt >= rq_len) ||
(!msg->rx_buf && (txcnt >= rq_len) &&
- !(spi_tms570_drv->spi->FLG & SPI_FLG_RXINT_m))) { // FIXME
+ !(iface->reg->FLG & SPI_FLG_RXINT_m))) { // FIXME
/* Sending of the message successfully finished */
spi_isr_lock(saveif);
spi_rq_queue_del_item(msg);
msg->flags |= SPI_MSG_FINISHED;
- spi_tms570_drv->spi_drv.msg_act = NULL;
+ iface->spi_drv.msg_act = NULL;
spi_isr_unlock(saveif);
if (msg->callback)
- msg->callback(&spi_tms570_drv->spi_drv,
+ msg->callback(&iface->spi_drv,
SPI_MSG_FINISHED, msg);
continue;
}
if (txcnt < rq_len)
- spi_tms570_drv->spi->INT0 = SPI_INT0_TXINTENA_m;
+ iface->reg->INT0 = SPI_INT0_TXINTENA_m;
else
- spi_tms570_drv->spi->INT0 = SPI_INT0_RXINTENA_m;
+ iface->reg->INT0 = SPI_INT0_RXINTENA_m;
} while (1);
}
}
-spi_drv_t *spi_find_drv(char *name, int number)
-{
- if (number < 1 || number > (sizeof(spi_tms570_ifcs)/sizeof(spi_tms570_ifcs[0])))
- return NULL;
-
- return &spi_tms570_ifcs[number - 1].spi_drv;
-}
-
#pragma INTERRUPT(spi2LowLevelInterrupt, IRQ)
void spi2LowLevelInterrupt(void)
{