File indexing completed on 2025-05-11 08:23:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <bsp.h>
0024 #include <bsp/raspberrypi.h>
0025 #include <bsp/gpio.h>
0026 #include <bsp/rpi-gpio.h>
0027 #include <bsp/irq.h>
0028 #include <bsp/i2c.h>
0029 #include <assert.h>
0030
0031 #define TRANSFER_COUNT(buffer_size) (buffer_size + 0xFFFE) / 0xFFFF
0032
0033 #define ADJUST_TRANSFER_SIZE(transfer_count, remaining_bytes) \
0034 transfer_count > 1 ? 0xFFFF : (remaining_bytes & 0xFFFF)
0035
0036 #define I2C_POLLING(condition) \
0037 while ( condition ) { \
0038 ; \
0039 }
0040
0041
0042
0043
0044
0045
0046 typedef struct
0047 {
0048 i2c_bus base;
0049 uint32_t input_clock;
0050 rtems_id task_id;
0051
0052
0053 uint32_t remaining_bytes;
0054
0055
0056
0057 uint32_t remaining_transfers;
0058
0059 uint8_t *current_buffer;
0060 uint32_t current_buffer_size;
0061
0062 bool read_transfer;
0063 } rpi_i2c_bus;
0064
0065 static int rpi_i2c_bus_transfer(rpi_i2c_bus *bus)
0066 {
0067 while ( bus->remaining_bytes >= 1 ) {
0068
0069 if ( bus->read_transfer ) {
0070
0071 I2C_POLLING((BCM2835_REG(BCM2835_I2C_S) & (1 << 5)) == 0);
0072
0073
0074 (*(uint8_t *) bus->current_buffer) = BCM2835_REG(BCM2835_I2C_FIFO) & 0xFF;
0075
0076 ++bus->current_buffer;
0077
0078
0079 if (
0080 (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) ||
0081 (BCM2835_REG(BCM2835_I2C_S) & (1 << 9))
0082 ) {
0083 return -EIO;
0084 }
0085 }
0086
0087 else {
0088
0089 #if I2C_IO_MODE == 1
0090
0091 BCM2835_REG(BCM2835_I2C_C) |= (1 << 9);
0092
0093
0094 bus->task_id = rtems_task_self();
0095 if (
0096 rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout) !=
0097 RTEMS_SUCCESSFUL
0098 ) {
0099 rtems_event_transient_clear();
0100
0101 return -ETIMEDOUT;
0102 }
0103
0104
0105 #else
0106
0107 I2C_POLLING((BCM2835_REG(BCM2835_I2C_S) & (1 << 2)) == 0);
0108 #endif
0109
0110
0111 BCM2835_REG(BCM2835_I2C_FIFO) = (*(uint8_t *) bus->current_buffer);
0112
0113 ++bus->current_buffer;
0114
0115
0116 if (
0117 (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) ||
0118 (BCM2835_REG(BCM2835_I2C_S) & (1 << 9))
0119 ) {
0120 return -EIO;
0121 }
0122 }
0123
0124 --bus->remaining_bytes;
0125 --bus->current_buffer_size;
0126 }
0127
0128 return 0;
0129 }
0130
0131 static int rpi_i2c_setup_transfer(rpi_i2c_bus *bus)
0132 {
0133 int rv;
0134
0135 while ( bus->remaining_transfers > 0 ) {
0136
0137 bus->remaining_bytes = ADJUST_TRANSFER_SIZE(
0138 bus->remaining_transfers,
0139 bus->current_buffer_size
0140 );
0141
0142
0143
0144 BCM2835_REG(BCM2835_I2C_DLEN) = bus->remaining_bytes;
0145
0146
0147 BCM2835_REG(BCM2835_I2C_S) |= (3 << 8);
0148
0149
0150 BCM2835_REG(BCM2835_I2C_C) |= (1 << 7);
0151
0152
0153 if ( (BCM2835_REG(BCM2835_I2C_S) & (1 << 8)) != 0 ) {
0154 return -EIO;
0155 }
0156
0157 rv = rpi_i2c_bus_transfer(bus);
0158
0159 if ( rv < 0 ) {
0160 return rv;
0161 }
0162
0163
0164
0165
0166 #if I2C_IO_MODE == 1
0167
0168 BCM2835_REG(BCM2835_I2C_C) |= (1 << 8);
0169
0170 if (
0171 rtems_event_transient_receive(RTEMS_WAIT, bus->base.timeout) !=
0172 RTEMS_SUCCESSFUL
0173 ) {
0174 rtems_event_transient_clear();
0175
0176 return -ETIMEDOUT;
0177 }
0178
0179 #else
0180
0181 I2C_POLLING((BCM2835_REG(BCM2835_I2C_S) & (1 << 1)) == 0);
0182 #endif
0183
0184 --bus->remaining_transfers;
0185 }
0186
0187 return 0;
0188 }
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 #if I2C_IO_MODE == 1
0221 static void i2c_handler(void *arg)
0222 {
0223 rpi_i2c_bus *bus = (rpi_i2c_bus *) arg;
0224
0225
0226 if ( (BCM2835_REG(BCM2835_I2C_C) & (1 << 9)) ) {
0227 BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 9);
0228 }
0229
0230 else if ( (BCM2835_REG(BCM2835_I2C_C) & (1 << 8)) ) {
0231 BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 8);
0232 }
0233
0234
0235 rtems_event_transient_send(bus->task_id);
0236 }
0237 #endif
0238
0239 static int rpi_i2c_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
0240 {
0241 rpi_i2c_bus *bus = (rpi_i2c_bus *) base;
0242 int rv = 0;
0243 uint32_t i;
0244
0245
0246
0247
0248
0249
0250
0251
0252 for ( i = 0; i < msg_count; ++i ) {
0253 if ( msgs[i].flags & I2C_M_RECV_LEN ) {
0254 return -EINVAL;
0255 }
0256 }
0257
0258 for ( i = 0; i < msg_count; ++i ) {
0259
0260 BCM2835_REG(BCM2835_I2C_C) |= (3 << 4);
0261
0262
0263 bus->current_buffer = msgs[i].buf;
0264 bus->current_buffer_size = msgs[i].len;
0265 bus->remaining_transfers = TRANSFER_COUNT(bus->current_buffer_size);
0266
0267
0268 if ( msgs[i].flags & I2C_M_TEN ) {
0269
0270
0271 BCM2835_REG(BCM2835_I2C_FIFO) = msgs[i].addr & 0xFF;
0272
0273
0274 BCM2835_REG(BCM2835_I2C_A) = (0x1E << 2) | (msgs[i].addr >> 8);
0275 }
0276
0277 else {
0278
0279 BCM2835_REG(BCM2835_I2C_A) = msgs[i].addr;
0280 }
0281
0282 if ( msgs[i].flags & I2C_M_RD ) {
0283
0284 if ( msgs[i].flags & I2C_M_TEN ) {
0285
0286 BCM2835_REG(BCM2835_I2C_DLEN) = 1;
0287
0288
0289 BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 0);
0290
0291
0292 BCM2835_REG(BCM2835_I2C_C) |= (1 << 7);
0293
0294
0295 I2C_POLLING((BCM2835_REG(BCM2835_I2C_S) & (1 << 0)) == 0);
0296 }
0297
0298
0299 BCM2835_REG(BCM2835_I2C_C) |= (1 << 0);
0300
0301 bus->read_transfer = true;
0302 }
0303 else if ( msgs[i].flags == 0 || msgs[i].flags == I2C_M_TEN ) {
0304
0305 if ( msgs[i].flags & I2C_M_TEN ) {
0306
0307 bus->current_buffer_size += 1;
0308
0309 bus->remaining_transfers = TRANSFER_COUNT(bus->current_buffer_size);
0310 }
0311
0312
0313 BCM2835_REG(BCM2835_I2C_C) &= ~(1 << 0);
0314
0315 bus->read_transfer = false;
0316 }
0317
0318 rv = rpi_i2c_setup_transfer(bus);
0319
0320 if ( rv < 0 ) {
0321 return rv;
0322 }
0323 }
0324
0325 return rv;
0326 }
0327
0328
0329
0330 static int rpi_i2c_set_clock(i2c_bus *base, unsigned long clock)
0331 {
0332 rpi_i2c_bus *bus = (rpi_i2c_bus *) base;
0333 uint32_t clock_rate;
0334 uint16_t divider;
0335
0336
0337 divider = BSC_CORE_CLK_HZ / clock;
0338
0339 clock_rate = BSC_CORE_CLK_HZ / divider;
0340
0341
0342
0343 while ( clock_rate > clock ) {
0344 ++divider;
0345
0346 clock_rate = BSC_CORE_CLK_HZ / divider;
0347 }
0348
0349
0350 BCM2835_REG(BCM2835_I2C_DIV) = divider;
0351
0352 bus->input_clock = clock_rate;
0353
0354 return 0;
0355 }
0356
0357 static void rpi_i2c_destroy(i2c_bus *base)
0358 {
0359 rpi_i2c_bus *bus = (rpi_i2c_bus *) base;
0360
0361 i2c_bus_destroy_and_free(&bus->base);
0362 }
0363
0364 int rpi_i2c_register_bus(
0365 const char *bus_path,
0366 uint32_t bus_clock
0367 ) {
0368 #if I2C_IO_MODE == 1
0369 rtems_status_code sc;
0370 #endif
0371 rpi_i2c_bus *bus;
0372 int rv;
0373
0374 bus = (rpi_i2c_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
0375
0376 if ( bus == NULL ) {
0377 return -1;
0378 }
0379
0380
0381 BCM2835_REG(BCM2835_I2C_C) |= (1 << 15);
0382
0383
0384 #if I2C_IO_MODE == 1
0385 bus->task_id = rtems_task_self();
0386
0387 sc = rtems_interrupt_handler_install(
0388 BCM2835_IRQ_ID_I2C,
0389 NULL,
0390 RTEMS_INTERRUPT_UNIQUE,
0391 (rtems_interrupt_handler) i2c_handler,
0392 bus
0393 );
0394
0395 if ( sc != RTEMS_SUCCESSFUL ) {
0396 return -EIO;
0397 }
0398 #endif
0399
0400 rv = rpi_i2c_set_clock(&bus->base, bus_clock);
0401
0402 if ( rv < 0 ) {
0403 (*bus->base.destroy)(&bus->base);
0404
0405 return -1;
0406 }
0407
0408 bus->base.transfer = rpi_i2c_transfer;
0409 bus->base.set_clock = rpi_i2c_set_clock;
0410 bus->base.destroy = rpi_i2c_destroy;
0411 bus->base.functionality = I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
0412
0413 return i2c_bus_register(&bus->base, bus_path);
0414 }
0415
0416 void rpi_i2c_init(void)
0417 {
0418
0419 rtems_gpio_initialize();
0420
0421 assert ( rpi_gpio_select_i2c() == RTEMS_SUCCESSFUL );
0422 }