diff options
Diffstat (limited to 'c/src/lib/libcpu/bfin/serial/spi.c')
-rw-r--r-- | c/src/lib/libcpu/bfin/serial/spi.c | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/c/src/lib/libcpu/bfin/serial/spi.c b/c/src/lib/libcpu/bfin/serial/spi.c deleted file mode 100644 index e1024e8d10..0000000000 --- a/c/src/lib/libcpu/bfin/serial/spi.c +++ /dev/null @@ -1,240 +0,0 @@ -/* SPI driver for Blackfin - * - * Copyright (c) 2010 Kallisti Labs, Los Gatos, CA, USA - * written by Allan Hessenflow <allanh@kallisti.com> - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <stdlib.h> -#include <bsp.h> -#include <rtems/error.h> -#include <rtems/bspIo.h> -#include <errno.h> -#include <rtems/libi2c.h> -#include <libcpu/spiRegs.h> -#include <libcpu/spi.h> - - -#ifndef BFIN_REG16 -#define BFIN_REG16(base, offset) \ - (*((uint16_t volatile *) ((uint8_t *)(base) + (offset)))) -#endif - - -static bfin_spi_state_t *bfin_spi; - - -void bfin_spi_isr(int v) { - bfin_spi_state_t *state; - uint16_t r; - - state = bfin_spi; - if (state->len > state->bytes_per_word) { - if (state->wr_ptr) { - if (state->bytes_per_word == 2) - r = *(uint16_t *) state->wr_ptr; - else - r = (uint16_t) *state->wr_ptr; - state->wr_ptr += state->bytes_per_word; - } else - r = state->idle_pattern; - BFIN_REG16(state->base, SPI_TDBR_OFFSET) = r; - } - state->len -= state->bytes_per_word; - if (state->len <= 0) { - /* - The transfers are done, so I don't want to kick off another - transfer or get any more interrupts. Reading the last word from - SPI_SHADOW instead of SPI_RDBR should prevent it from triggering - another transfer, but that doesn't clear the interrupt flag. I - could mask the interrupt in the SIC, but that would preclude ever - using the DMA channel that shares the interrupt independently (and - they might just share it with something more important in some other - member of the Blackfin family). And who knows what problems it - might cause in this code potentially dealing with that still pended - interrupt at the beginning of the next transfer. - - So instead I disable the SPI interface, read the data from RDBR - (thus clearing the interrupt but not triggering another transfer - since the interface is disabled), then re-eanble the interface. - This has the problem that the bf537 tri-states the SPI signals - while the interface is disabled. Either adding pull-ups on at - least the chip select signals, or using GPIOs for them so they're - not controlled by the SPI module, would be correct fixes for that - (really pull-ups/downs should be added to the SPI CLK and MOSI - signals as well to insure they cannot float into some region that - causes input structures to consume excessive power). Or they can - all be left alone, assuming that there's enough capacitance on the - lines to prevent any problems for the short time they're being left - disabled. - - An alternative approach I attempted involved switching TIMOD - between RDBR and TDBR when starting and finishing a transfer, but - I didn't get anywhere with that. In my limited testing TIMOD TDBR - wasn't behaving as I expected it to, but maybe with more - experimentation I'd find some solution there. However I'm out - of time for this project, at least for now. - */ - - BFIN_REG16(state->base, SPI_CTL_OFFSET) &= ~SPI_CTL_SPE; - r = BFIN_REG16(state->base, SPI_RDBR_OFFSET); - BFIN_REG16(state->base, SPI_CTL_OFFSET) |= SPI_CTL_SPE; - rtems_semaphore_release(state->sem); - } else - r = BFIN_REG16(state->base, SPI_RDBR_OFFSET); - - if (state->rd_ptr) { - if (state->bytes_per_word == 2) - *(uint16_t *) state->rd_ptr = r; - else - *state->rd_ptr = (uint8_t) r; - state->rd_ptr += state->bytes_per_word; - } -} - -static rtems_status_code setTFRMode(rtems_libi2c_bus_t *bus, - const rtems_libi2c_tfr_mode_t *tfrMode) { - rtems_status_code result; - bfin_spi_state_t *state; - uint32_t divisor; - uint16_t ctrl; - - result = RTEMS_SUCCESSFUL; - state = &((bfin_spi_bus_t *) bus)->p; - - if (result == RTEMS_SUCCESSFUL) { - if (tfrMode->bits_per_char != 8 && - tfrMode->bits_per_char != 16) - result = RTEMS_INVALID_NUMBER; - if (tfrMode->baudrate <= 0) - result = RTEMS_INVALID_NUMBER; - } - if (result == RTEMS_SUCCESSFUL) { - divisor = (SCLK / 2 + tfrMode->baudrate - 1) / - tfrMode->baudrate; - if (divisor < 2) - divisor = 2; - else if (divisor > 65535) - result = RTEMS_INVALID_NUMBER; - } - if (result == RTEMS_SUCCESSFUL) { - state->idle_pattern = (uint16_t) tfrMode->idle_char; - state->bytes_per_word = (tfrMode->bits_per_char > 8) ? 2 : 1; - BFIN_REG16(state->base, SPI_BAUD_OFFSET) = divisor; - ctrl = BFIN_REG16(state->base, SPI_CTL_OFFSET); - if (tfrMode->lsb_first) - ctrl |= SPI_CTL_LSBF; - else - ctrl &= ~SPI_CTL_LSBF; - if (tfrMode->bits_per_char > 8) - ctrl |= SPI_CTL_SIZE; - else - ctrl &= ~SPI_CTL_SIZE; - if (tfrMode->clock_inv) - ctrl |= SPI_CTL_CPOL; - else - ctrl &= ~SPI_CTL_CPOL; - if (tfrMode->clock_phs) - ctrl |= SPI_CTL_CPHA; - else - ctrl &= ~SPI_CTL_CPHA; - BFIN_REG16(state->base, SPI_CTL_OFFSET) = ctrl; - } - - return result; -} - -static int readWrite(rtems_libi2c_bus_t *bus, uint8_t *rdBuf, - const uint8_t *wrBuf, int len) { - rtems_status_code result; - bfin_spi_state_t *state; - uint16_t r; - - result = RTEMS_SUCCESSFUL; - state = &((bfin_spi_bus_t *) bus)->p; - - if (len) { - state->rd_ptr = rdBuf; - state->wr_ptr = wrBuf; - state->len = len; - if (state->wr_ptr) { - if (state->bytes_per_word == 2) - r = *(uint16_t *) state->wr_ptr; - else - r = (uint16_t) *state->wr_ptr; - state->wr_ptr += state->bytes_per_word; - } else - r = state->idle_pattern; - BFIN_REG16(state->base, SPI_TDBR_OFFSET) = r; - BFIN_REG16(state->base, SPI_RDBR_OFFSET); /* trigger */ - /* wait until done */ - do { - result = rtems_semaphore_obtain(state->sem, RTEMS_WAIT, 100); - } while (result == RTEMS_SUCCESSFUL && state->len > 0); - } - - return (result == RTEMS_SUCCESSFUL) ? len : -result; -} - - -rtems_status_code bfin_spi_init(rtems_libi2c_bus_t *bus) { - rtems_status_code result; - bfin_spi_state_t *state; - - state = &((bfin_spi_bus_t *) bus)->p; - - BFIN_REG16(state->base, SPI_CTL_OFFSET) = SPI_CTL_SPE | - SPI_CTL_MSTR | - SPI_CTL_CPHA | - SPI_CTL_TIMOD_RDBR; - - result = rtems_semaphore_create(rtems_build_name('s','p','i','s'), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE, - 0, - &state->sem); - if (result == RTEMS_SUCCESSFUL) - bfin_spi = state; /* for isr */ - - return result; -} - -rtems_status_code bfin_spi_send_start(rtems_libi2c_bus_t *bus) { - - return RTEMS_SUCCESSFUL; -} - -int bfin_spi_read_bytes(rtems_libi2c_bus_t *bus, unsigned char *buf, int len) { - - return readWrite(bus, buf, NULL, len); -} - -int bfin_spi_write_bytes(rtems_libi2c_bus_t *bus, unsigned char *buf, int len) { - - return readWrite(bus, NULL, buf, len); -} - -int bfin_spi_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg) { - int result; - - result = -RTEMS_NOT_DEFINED; - switch(cmd) { - case RTEMS_LIBI2C_IOCTL_SET_TFRMODE: - result = -setTFRMode(bus, (const rtems_libi2c_tfr_mode_t *) arg); - break; - case RTEMS_LIBI2C_IOCTL_READ_WRITE: - result = readWrite(bus, - ((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: - break; - } - - return result; -} - |