File indexing completed on 2025-05-11 08:23:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <stdlib.h>
0012 #include <bsp.h>
0013 #include <rtems/error.h>
0014 #include <rtems/bspIo.h>
0015 #include <errno.h>
0016 #include <rtems/libi2c.h>
0017 #include <libcpu/spiRegs.h>
0018 #include <libcpu/spi.h>
0019
0020
0021 #ifndef BFIN_REG16
0022 #define BFIN_REG16(base, offset) \
0023 (*((uint16_t volatile *) ((uint8_t *)(base) + (offset))))
0024 #endif
0025
0026
0027 static bfin_spi_state_t *bfin_spi;
0028
0029
0030 void bfin_spi_isr(int v) {
0031 bfin_spi_state_t *state;
0032 uint16_t r;
0033
0034 state = bfin_spi;
0035 if (state->len > state->bytes_per_word) {
0036 if (state->wr_ptr) {
0037 if (state->bytes_per_word == 2)
0038 r = *(uint16_t *) state->wr_ptr;
0039 else
0040 r = (uint16_t) *state->wr_ptr;
0041 state->wr_ptr += state->bytes_per_word;
0042 } else
0043 r = state->idle_pattern;
0044 BFIN_REG16(state->base, SPI_TDBR_OFFSET) = r;
0045 }
0046 state->len -= state->bytes_per_word;
0047 if (state->len <= 0) {
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 BFIN_REG16(state->base, SPI_CTL_OFFSET) &= ~SPI_CTL_SPE;
0083 r = BFIN_REG16(state->base, SPI_RDBR_OFFSET);
0084 BFIN_REG16(state->base, SPI_CTL_OFFSET) |= SPI_CTL_SPE;
0085 rtems_semaphore_release(state->sem);
0086 } else
0087 r = BFIN_REG16(state->base, SPI_RDBR_OFFSET);
0088
0089 if (state->rd_ptr) {
0090 if (state->bytes_per_word == 2)
0091 *(uint16_t *) state->rd_ptr = r;
0092 else
0093 *state->rd_ptr = (uint8_t) r;
0094 state->rd_ptr += state->bytes_per_word;
0095 }
0096 }
0097
0098 static rtems_status_code setTFRMode(rtems_libi2c_bus_t *bus,
0099 const rtems_libi2c_tfr_mode_t *tfrMode) {
0100 rtems_status_code result;
0101 bfin_spi_state_t *state;
0102 uint32_t divisor;
0103 uint16_t ctrl;
0104
0105 result = RTEMS_SUCCESSFUL;
0106 state = &((bfin_spi_bus_t *) bus)->p;
0107
0108 if (result == RTEMS_SUCCESSFUL) {
0109 if (tfrMode->bits_per_char != 8 &&
0110 tfrMode->bits_per_char != 16)
0111 result = RTEMS_INVALID_NUMBER;
0112 if (tfrMode->baudrate <= 0)
0113 result = RTEMS_INVALID_NUMBER;
0114 }
0115 if (result == RTEMS_SUCCESSFUL) {
0116 divisor = (SCLK / 2 + tfrMode->baudrate - 1) /
0117 tfrMode->baudrate;
0118 if (divisor < 2)
0119 divisor = 2;
0120 else if (divisor > 65535)
0121 result = RTEMS_INVALID_NUMBER;
0122 }
0123 if (result == RTEMS_SUCCESSFUL) {
0124 state->idle_pattern = (uint16_t) tfrMode->idle_char;
0125 state->bytes_per_word = (tfrMode->bits_per_char > 8) ? 2 : 1;
0126 BFIN_REG16(state->base, SPI_BAUD_OFFSET) = divisor;
0127 ctrl = BFIN_REG16(state->base, SPI_CTL_OFFSET);
0128 if (tfrMode->lsb_first)
0129 ctrl |= SPI_CTL_LSBF;
0130 else
0131 ctrl &= ~SPI_CTL_LSBF;
0132 if (tfrMode->bits_per_char > 8)
0133 ctrl |= SPI_CTL_SIZE;
0134 else
0135 ctrl &= ~SPI_CTL_SIZE;
0136 if (tfrMode->clock_inv)
0137 ctrl |= SPI_CTL_CPOL;
0138 else
0139 ctrl &= ~SPI_CTL_CPOL;
0140 if (tfrMode->clock_phs)
0141 ctrl |= SPI_CTL_CPHA;
0142 else
0143 ctrl &= ~SPI_CTL_CPHA;
0144 BFIN_REG16(state->base, SPI_CTL_OFFSET) = ctrl;
0145 }
0146
0147 return result;
0148 }
0149
0150 static int readWrite(rtems_libi2c_bus_t *bus, uint8_t *rdBuf,
0151 const uint8_t *wrBuf, int len) {
0152 rtems_status_code result;
0153 bfin_spi_state_t *state;
0154 uint16_t r;
0155
0156 result = RTEMS_SUCCESSFUL;
0157 state = &((bfin_spi_bus_t *) bus)->p;
0158
0159 if (len) {
0160 state->rd_ptr = rdBuf;
0161 state->wr_ptr = wrBuf;
0162 state->len = len;
0163 if (state->wr_ptr) {
0164 if (state->bytes_per_word == 2)
0165 r = *(uint16_t *) state->wr_ptr;
0166 else
0167 r = (uint16_t) *state->wr_ptr;
0168 state->wr_ptr += state->bytes_per_word;
0169 } else
0170 r = state->idle_pattern;
0171 BFIN_REG16(state->base, SPI_TDBR_OFFSET) = r;
0172 BFIN_REG16(state->base, SPI_RDBR_OFFSET);
0173
0174 do {
0175 result = rtems_semaphore_obtain(state->sem, RTEMS_WAIT, 100);
0176 } while (result == RTEMS_SUCCESSFUL && state->len > 0);
0177 }
0178
0179 return (result == RTEMS_SUCCESSFUL) ? len : -result;
0180 }
0181
0182
0183 rtems_status_code bfin_spi_init(rtems_libi2c_bus_t *bus) {
0184 rtems_status_code result;
0185 bfin_spi_state_t *state;
0186
0187 state = &((bfin_spi_bus_t *) bus)->p;
0188
0189 BFIN_REG16(state->base, SPI_CTL_OFFSET) = SPI_CTL_SPE |
0190 SPI_CTL_MSTR |
0191 SPI_CTL_CPHA |
0192 SPI_CTL_TIMOD_RDBR;
0193
0194 result = rtems_semaphore_create(rtems_build_name('s','p','i','s'),
0195 0,
0196 RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE,
0197 0,
0198 &state->sem);
0199 if (result == RTEMS_SUCCESSFUL)
0200 bfin_spi = state;
0201
0202 return result;
0203 }
0204
0205 rtems_status_code bfin_spi_send_start(rtems_libi2c_bus_t *bus) {
0206
0207 return RTEMS_SUCCESSFUL;
0208 }
0209
0210 int bfin_spi_read_bytes(rtems_libi2c_bus_t *bus, unsigned char *buf, int len) {
0211
0212 return readWrite(bus, buf, NULL, len);
0213 }
0214
0215 int bfin_spi_write_bytes(rtems_libi2c_bus_t *bus, unsigned char *buf, int len) {
0216
0217 return readWrite(bus, NULL, buf, len);
0218 }
0219
0220 int bfin_spi_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg) {
0221 int result;
0222
0223 result = -RTEMS_NOT_DEFINED;
0224 switch(cmd) {
0225 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
0226 result = -setTFRMode(bus, (const rtems_libi2c_tfr_mode_t *) arg);
0227 break;
0228 case RTEMS_LIBI2C_IOCTL_READ_WRITE:
0229 result = readWrite(bus,
0230 ((rtems_libi2c_read_write_t *) arg)->rd_buf,
0231 ((rtems_libi2c_read_write_t *) arg)->wr_buf,
0232 ((rtems_libi2c_read_write_t *) arg)->byte_cnt);
0233 break;
0234 default:
0235 break;
0236 }
0237
0238 return result;
0239 }
0240