File indexing completed on 2025-05-11 08:23:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <stdlib.h>
0015 #include <rtems.h>
0016
0017 #include <libcpu/twiRegs.h>
0018 #include <libcpu/twi.h>
0019
0020
0021 #ifndef N_BFIN_TWI
0022 #define N_BFIN_TWI 1
0023 #endif
0024
0025 #define BFIN_REG16(base, offset) \
0026 (*((uint16_t volatile *) ((char *)(base) + (offset))))
0027
0028
0029 static struct {
0030 void *base;
0031 rtems_id irqSem;
0032 rtems_id mutex;
0033 bfin_twi_callback_t callback;
0034 void *callbackArg;
0035 bfin_twi_request_t volatile *req;
0036 uint8_t volatile *dataPtr;
0037 int volatile count;
0038 bool volatile masterActive;
0039 rtems_status_code volatile masterResult;
0040 bool volatile slaveActive;
0041 } twi[N_BFIN_TWI];
0042
0043
0044 rtems_status_code bfin_twi_init(int channel, bfin_twi_config_t *config) {
0045 rtems_status_code result;
0046 void *base;
0047
0048 if (channel < 0 || channel >= N_BFIN_TWI)
0049 return RTEMS_INVALID_NUMBER;
0050
0051 base = config->base;
0052 twi[channel].base = base;
0053
0054 result = rtems_semaphore_create(rtems_build_name('t','w','i','s'),
0055 0,
0056 RTEMS_FIFO |
0057 RTEMS_SIMPLE_BINARY_SEMAPHORE |
0058 RTEMS_NO_INHERIT_PRIORITY |
0059 RTEMS_NO_PRIORITY_CEILING |
0060 RTEMS_LOCAL,
0061 0,
0062 &twi[channel].irqSem);
0063 result = rtems_semaphore_create(rtems_build_name('t','w','i','m'),
0064 1,
0065 RTEMS_PRIORITY |
0066 RTEMS_SIMPLE_BINARY_SEMAPHORE |
0067 RTEMS_INHERIT_PRIORITY |
0068 RTEMS_NO_PRIORITY_CEILING |
0069 RTEMS_LOCAL,
0070 0,
0071 &twi[channel].mutex);
0072 BFIN_REG16(base, TWI_CONTROL_OFFSET) =
0073 (uint16_t) (((config->sclk +9999999) / 10000000) <<
0074 TWI_CONTROL_PRESCALE_SHIFT) |
0075 TWI_CONTROL_TWI_ENA;
0076 BFIN_REG16(base, TWI_CLKDIV_OFFSET) = config->fast ?
0077 ((8 << TWI_CLKDIV_CLKHI_SHIFT) |
0078 (17 << TWI_CLKDIV_CLKLOW_SHIFT)) :
0079 ((33 << TWI_CLKDIV_CLKHI_SHIFT) |
0080 (67 << TWI_CLKDIV_CLKLOW_SHIFT));
0081 BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET) = 0;
0082 BFIN_REG16(base, TWI_MASTER_CTL_OFFSET) = config->fast ?
0083 TWI_MASTER_CTL_FAST :
0084 0;
0085 BFIN_REG16(base, TWI_SLAVE_ADDR_OFFSET) = (uint16_t) config->slave_address <<
0086 TWI_SLAVE_ADDR_SADDR_SHIFT;
0087 BFIN_REG16(base, TWI_MASTER_STAT_OFFSET) = TWI_MASTER_STAT_BUFWRERR |
0088 TWI_MASTER_STAT_BUFRDERR |
0089 TWI_MASTER_STAT_DNAK |
0090 TWI_MASTER_STAT_ANAK |
0091 TWI_MASTER_STAT_LOSTARB;
0092 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = TWI_FIFO_CTL_XMTFLUSH |
0093 TWI_FIFO_CTL_RCVFLUSH;
0094 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = 0;
0095 BFIN_REG16(base, TWI_INT_STAT_OFFSET) = TWI_INT_STAT_RCVSERV |
0096 TWI_INT_STAT_XMTSERV |
0097 TWI_INT_STAT_MERR |
0098 TWI_INT_STAT_MCOMP |
0099 TWI_INT_STAT_SOVF |
0100 TWI_INT_STAT_SERR |
0101 TWI_INT_STAT_SCOMP |
0102 TWI_INT_STAT_SINIT;
0103 BFIN_REG16(base, TWI_INT_MASK_OFFSET) = TWI_INT_MASK_RCVSERVM |
0104 TWI_INT_MASK_XMTSERVM;
0105
0106 return result;
0107 }
0108
0109 rtems_status_code bfin_twi_register_callback(int channel,
0110 bfin_twi_callback_t callback,
0111 void *arg) {
0112 void *base;
0113 int level;
0114
0115 if (channel < 0 || channel >= N_BFIN_TWI)
0116 return RTEMS_INVALID_NUMBER;
0117
0118 base = twi[channel].base;
0119 if (callback == NULL)
0120 BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET) = 0;
0121 rtems_interrupt_disable(level);
0122 twi[channel].callback = callback;
0123 twi[channel].callbackArg = arg;
0124 rtems_interrupt_enable(level);
0125 if (callback != NULL)
0126 BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET) = TWI_SLAVE_CTL_GEN |
0127 TWI_SLAVE_CTL_SEN;
0128
0129 return RTEMS_SUCCESSFUL;
0130 }
0131
0132 void bfin_twi_isr(int source) {
0133 void *base;
0134 int i;
0135 uint16_t r;
0136 uint16_t stat;
0137
0138 for (i = 0; i < N_BFIN_TWI; i++) {
0139 base = twi[i].base;
0140 if (base) {
0141 stat = BFIN_REG16(base, TWI_INT_STAT_OFFSET);
0142 if (stat) {
0143 BFIN_REG16(base, TWI_INT_STAT_OFFSET) = stat;
0144 if ((stat & TWI_INT_STAT_SINIT) && !twi[i].slaveActive) {
0145 twi[i].slaveActive = true;
0146 r = BFIN_REG16(base, TWI_FIFO_CTL_OFFSET);
0147 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = r | TWI_FIFO_CTL_XMTFLUSH;
0148 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = r;
0149 r = BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET);
0150 BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET) = r | TWI_SLAVE_CTL_STDVAL;
0151 }
0152 if (twi[i].slaveActive) {
0153
0154
0155 if (stat & (TWI_INT_STAT_SCOMP | TWI_INT_STAT_SERR)) {
0156
0157
0158 r = BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET);
0159 BFIN_REG16(base, TWI_SLAVE_CTL_OFFSET) = r & ~TWI_SLAVE_CTL_STDVAL;
0160 twi[i].slaveActive = false;
0161
0162
0163 }
0164 }
0165 if (twi[i].masterActive && !twi[i].slaveActive) {
0166
0167
0168 if (stat & (TWI_INT_STAT_MCOMP | TWI_INT_STAT_MERR)) {
0169 if (!(stat & TWI_INT_STAT_MERR)) {
0170
0171
0172 rtems_semaphore_release(twi[i].irqSem);
0173
0174
0175 } else
0176 rtems_semaphore_release(twi[i].irqSem);
0177 }
0178 }
0179 }
0180 }
0181 }
0182 }
0183
0184 rtems_status_code bfin_twi_request(int channel, uint8_t address,
0185 bfin_twi_request_t *request,
0186 rtems_interval timeout) {
0187 rtems_status_code result;
0188 void *base;
0189 rtems_interrupt_level level;
0190 uint16_t r;
0191 uint16_t masterMode;
0192
0193 if (channel < 0 || channel >= N_BFIN_TWI)
0194 return RTEMS_INVALID_NUMBER;
0195 result = rtems_semaphore_obtain(twi[channel].mutex,
0196 RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0197 if (result == RTEMS_SUCCESSFUL) {
0198 base = twi[channel].base;
0199 twi[channel].req = request;
0200
0201 if (request->write) {
0202 twi[channel].dataPtr = request->data;
0203 twi[channel].count = request->count;
0204 } else
0205 twi[channel].count = 0;
0206
0207 BFIN_REG16(base, TWI_MASTER_ADDR_OFFSET) = (uint16_t) address <<
0208 TWI_MASTER_ADDR_MADDR_SHIFT;
0209 masterMode = BFIN_REG16(base, TWI_MASTER_CTL_OFFSET);
0210 masterMode |= (request->count << TWI_MASTER_CTL_DCNT_SHIFT);
0211 if (request->next)
0212 masterMode |= TWI_MASTER_CTL_RSTART;
0213 if (!request->write)
0214 masterMode |= TWI_MASTER_CTL_MDIR;
0215 masterMode |= TWI_MASTER_CTL_MEN;
0216 rtems_interrupt_disable(level);
0217 if (!twi[channel].slaveActive) {
0218 r = BFIN_REG16(base, TWI_FIFO_CTL_OFFSET);
0219 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = r | TWI_FIFO_CTL_XMTFLUSH;
0220 BFIN_REG16(base, TWI_FIFO_CTL_OFFSET) = r;
0221 if (request->write) {
0222 while (twi[channel].count &&
0223 (BFIN_REG16(base, TWI_FIFO_STAT_OFFSET) &
0224 TWI_FIFO_STAT_XMTSTAT_MASK) !=
0225 TWI_FIFO_STAT_XMTSTAT_FULL) {
0226 BFIN_REG16(base, TWI_XMT_DATA8_OFFSET) =
0227 (uint16_t) *twi[channel].dataPtr++;
0228 twi[channel].count--;
0229 }
0230 }
0231 twi[channel].masterActive = true;
0232 BFIN_REG16(base, TWI_MASTER_CTL_OFFSET) = masterMode;
0233 } else {
0234 twi[channel].masterActive = false;
0235 twi[channel].masterResult = -1;
0236 }
0237 rtems_interrupt_enable(level);
0238 while (result == RTEMS_SUCCESSFUL && twi[channel].masterActive)
0239 result = rtems_semaphore_obtain(twi[channel].irqSem,
0240 RTEMS_WAIT, timeout);
0241 if (result == RTEMS_SUCCESSFUL)
0242 result = twi[channel].masterResult;
0243 else {
0244
0245
0246
0247
0248 }
0249 rtems_semaphore_release(twi[channel].mutex);
0250 }
0251 return result;
0252 }
0253