File indexing completed on 2025-05-11 08:22:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <bsp/irq.h>
0037 #include <bsp/raspberrypi.h>
0038 #include <bsp/raspberrypi-spi.h>
0039 #include <bsp/rpi-gpio.h>
0040
0041 #include <dev/spi/spi.h>
0042 #include <bspopts.h>
0043
0044 typedef struct {
0045 spi_bus base;
0046 volatile raspberrypi_spi *regs;
0047 const spi_ioc_transfer *msg;
0048 uint32_t msg_todo;
0049 uint8_t *rx_buf;
0050 const uint8_t *tx_buf;
0051 uint32_t todo;
0052 uint8_t num_cs;
0053 uint32_t in_transfer;
0054 rtems_id task_id;
0055 rtems_vector_number irq;
0056 }raspberrypi_spi_bus;
0057
0058 static int raspberrypi_spi_check_msg(
0059 raspberrypi_spi_bus *bus,
0060 const spi_ioc_transfer *msg,
0061 uint32_t n
0062 )
0063 {
0064 while (n > 0) {
0065 if (msg->bits_per_word != 8) {
0066 return -EINVAL;
0067 }
0068
0069 if ((msg->mode &
0070 ~(SPI_CPHA | SPI_CPOL | SPI_NO_CS)) != 0) {
0071 return -EINVAL;
0072 }
0073
0074 if (msg->cs >= bus->num_cs) {
0075 return -EINVAL;
0076 }
0077
0078 ++msg;
0079 --n;
0080 }
0081
0082 return 0;
0083 }
0084
0085
0086
0087 static rtems_status_code rpi_spi_calculate_clock_divider(
0088 uint32_t clock_hz,
0089 uint16_t *clock_divider
0090 )
0091 {
0092 uint16_t divider;
0093 uint32_t clock_rate;
0094
0095
0096 divider = GPU_CORE_CLOCK_RATE / clock_hz;
0097
0098
0099
0100 --divider;
0101
0102 divider |= (divider >> 1);
0103 divider |= (divider >> 2);
0104 divider |= (divider >> 4);
0105 divider |= (divider >> 8);
0106
0107 ++divider;
0108
0109 clock_rate = GPU_CORE_CLOCK_RATE / divider;
0110
0111
0112
0113 while (clock_rate > clock_hz) {
0114 divider = (divider << 1);
0115
0116 clock_rate = GPU_CORE_CLOCK_RATE / divider;
0117 }
0118
0119 *clock_divider = divider;
0120
0121 return RTEMS_SUCCESSFUL;
0122 }
0123
0124 static int raspberrypi_spi_config(
0125 raspberrypi_spi_bus *bus,
0126 volatile raspberrypi_spi *regs,
0127 uint32_t speed_hz,
0128 uint32_t mode,
0129 uint8_t cs
0130 )
0131 {
0132 spi_bus *base = &bus->base;
0133 uint32_t spics = regs->spics;
0134 rtems_status_code sc;
0135 uint16_t clock_divider;
0136
0137
0138 sc = rpi_spi_calculate_clock_divider(speed_hz, &clock_divider);
0139 if (sc != RTEMS_SUCCESSFUL) {
0140 return sc;
0141 }
0142
0143 regs->spiclk = RPI_SPICLK_CDIV_SET(regs->spiclk, clock_divider);
0144
0145 if ((mode & SPI_CPHA) != 0) {
0146 spics |= RPI_SPICS_CPHA;
0147 } else {
0148 spics &= ~RPI_SPICS_CPHA;
0149 }
0150
0151 if ((mode & SPI_CPOL) != 0) {
0152 spics |= RPI_SPICS_CPOL;
0153 } else {
0154 spics &= ~RPI_SPICS_CPOL;
0155 }
0156
0157 if ((mode & SPI_CS_HIGH) != 0) {
0158 spics |= RPI_SPICS_CSPOL;
0159 } else {
0160 spics &= ~RPI_SPICS_CSPOL;
0161 }
0162
0163 spics = RPI_SPICS_CS_SET(spics, cs);
0164
0165 regs->spics = spics;
0166
0167 base->speed_hz = speed_hz;
0168 base->mode = mode;
0169 base->cs = cs;
0170 return 0;
0171 }
0172
0173 #ifdef BSP_SPI_USE_INTERRUPTS
0174 static void raspberrypi_spi_done(raspberrypi_spi_bus *bus)
0175 {
0176 volatile raspberrypi_spi *regs;
0177 regs = bus->regs;
0178 regs->spics = regs->spics & ~RPI_SPICS_TA;
0179 rtems_event_transient_send(bus->task_id);
0180 }
0181
0182 static bool raspberrpi_spi_TX_FULL(volatile raspberrypi_spi *regs)
0183 {
0184 return !(regs->spics & RPI_SPICS_TXD);
0185 }
0186
0187 static void raspberrypi_spi_push(
0188 raspberrypi_spi_bus *bus,
0189 volatile raspberrypi_spi *regs
0190 )
0191 {
0192 uint8_t val;
0193 while (bus->todo > 0 && !raspberrpi_spi_TX_FULL(regs)) {
0194 val = 0;
0195 if (bus->tx_buf != NULL) {
0196 val = *bus->tx_buf;
0197 ++bus->tx_buf;
0198 }
0199
0200 --bus->todo;
0201 regs->spififo = val;
0202 ++bus->in_transfer;
0203 }
0204 }
0205
0206 static void raspberrypi_spi_next_msg(raspberrypi_spi_bus *bus)
0207 {
0208 const spi_ioc_transfer *msg;
0209 spi_bus *base;
0210 volatile raspberrypi_spi *regs;
0211 regs=bus->regs;
0212
0213 if (bus->msg_todo > 0) {
0214 base = &bus->base;
0215 msg = bus->msg;
0216
0217 if (
0218 msg->speed_hz != base->speed_hz
0219 || msg->mode != base->mode
0220 || msg->cs != base->cs
0221 ) {
0222 raspberrypi_spi_config(
0223 bus,
0224 regs,
0225 msg->speed_hz,
0226 msg->mode,
0227 msg->cs
0228 );
0229 }
0230
0231 bus->todo = msg->len;
0232 bus->rx_buf = msg->rx_buf;
0233 bus->tx_buf = msg->tx_buf;
0234 raspberrypi_spi_push(bus, regs);
0235 } else {
0236 raspberrypi_spi_done(bus);
0237 }
0238 }
0239
0240 static void raspberrypi_spi_start(raspberrypi_spi_bus *bus)
0241 {
0242 volatile raspberrypi_spi *regs;
0243 regs = bus->regs;
0244
0245 regs->spics = regs->spics | RPI_SPICS_INTR | RPI_SPICS_INTD;
0246
0247
0248
0249
0250 regs->spics = regs->spics | RPI_SPICS_TA;
0251 }
0252
0253 static bool raspberrypi_spi_irq(volatile raspberrypi_spi *regs)
0254 {
0255
0256 if(regs->spics & RPI_SPICS_INTD && regs->spics & RPI_SPICS_DONE) {
0257 return 1;
0258 }
0259
0260 if(regs->spics & RPI_SPICS_INTR && regs->spics & RPI_SPICS_RXR) {
0261 return 1;
0262 }
0263
0264 return 0;
0265 }
0266
0267 static void raspberrypi_spi_interrupt(void *arg)
0268 {
0269 raspberrypi_spi_bus *bus;
0270 volatile raspberrypi_spi *regs;
0271 uint32_t val;
0272
0273 bus = arg;
0274 regs = bus->regs;
0275
0276 if (raspberrypi_spi_irq(regs)) {
0277
0278 if (bus->todo > 0) {
0279 raspberrypi_spi_push(bus, regs);
0280 } else {
0281 --bus->msg_todo;
0282 ++bus->msg;
0283 raspberrypi_spi_next_msg(bus);
0284 }
0285
0286 while (regs->spics & RPI_SPICS_RXD && bus->in_transfer > 0) {
0287
0288 val = regs->spififo;
0289 if (bus->rx_buf != NULL) {
0290 *bus->rx_buf = (uint8_t)val;
0291 ++bus->rx_buf;
0292 }
0293 --bus->in_transfer;
0294 }
0295
0296 }
0297 }
0298 #else
0299 static void raspberrypi_spi_polling_tx_rx(raspberrypi_spi_bus *bus)
0300 {
0301 volatile raspberrypi_spi *regs = bus->regs;
0302
0303 const unsigned char *sbuffer = bus->tx_buf;
0304 unsigned char *rbuffer;
0305 unsigned int size;
0306 unsigned int read_count, write_count;
0307 unsigned int data;
0308
0309 while (bus->msg_todo) {
0310 rbuffer = bus->rx_buf;
0311 size = bus->todo;
0312
0313 regs->spics = regs->spics | RPI_SPICS_CLEAR_RX | RPI_SPICS_CLEAR_TX
0314 | RPI_SPICS_TA;
0315
0316 read_count = 0;
0317 write_count = 0;
0318
0319 while (read_count < size || write_count < size) {
0320 if (write_count < size && regs->spics & RPI_SPICS_TXD) {
0321 if (sbuffer) {
0322 regs->spififo = *sbuffer++;
0323 } else {
0324 regs->spififo = 0;
0325 }
0326
0327 write_count++;
0328 }
0329
0330 if (read_count < size && regs->spics & RPI_SPICS_RXD) {
0331 data = regs->spififo;
0332
0333 if (rbuffer) {
0334 *rbuffer++ = data;
0335 }
0336
0337 read_count++;
0338 }
0339 }
0340
0341 while (!(regs->spics & RPI_SPICS_DONE)) {
0342
0343 }
0344 regs->spics = (regs->spics & ~RPI_SPICS_TA);
0345
0346 bus->msg_todo--;
0347
0348 bus->msg++;
0349 bus->rx_buf = bus->msg->rx_buf;
0350 bus->tx_buf = bus->msg->tx_buf;
0351 bus->todo = bus->msg->len;
0352 }
0353 }
0354
0355 static void raspberrypi_spi_transfer_msg(
0356 raspberrypi_spi_bus *bus
0357 )
0358 {
0359 volatile raspberrypi_spi *regs = bus->regs;
0360 uint32_t msg_todo = bus->msg_todo;
0361 const spi_ioc_transfer *msg = bus->msg;
0362
0363 if (msg_todo > 0) {
0364 if (
0365 msg->speed_hz != bus->base.speed_hz
0366 || msg->mode != bus->base.mode
0367 || msg->cs != bus->base.cs
0368 ) {
0369 raspberrypi_spi_config(
0370 bus,
0371 regs,
0372 msg->speed_hz,
0373 msg->mode,
0374 msg->cs
0375 );
0376 }
0377
0378 bus->todo = msg->len;
0379 bus->rx_buf = msg->rx_buf;
0380 bus->tx_buf = msg->tx_buf;
0381 raspberrypi_spi_polling_tx_rx(bus);
0382 }
0383 }
0384 #endif
0385
0386 static int raspberrypi_spi_transfer(
0387 spi_bus *base,
0388 const spi_ioc_transfer *msgs,
0389 uint32_t msg_count
0390 )
0391 {
0392 int rv = 0;
0393 raspberrypi_spi_bus *bus;
0394 bus = (raspberrypi_spi_bus *) base;
0395
0396 rv = raspberrypi_spi_check_msg(bus, msgs, msg_count);
0397 if (rv == 0) {
0398 bus->msg_todo = msg_count;
0399 bus->msg = msgs;
0400 #ifdef BSP_SPI_USE_INTERRUPTS
0401 bus->task_id = rtems_task_self();
0402
0403 raspberrypi_spi_start(bus);
0404 rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0405 #else
0406 raspberrypi_spi_transfer_msg(bus);
0407 #endif
0408 }
0409
0410 return rv;
0411 }
0412
0413 static void raspberrypi_spi_destroy(spi_bus *base)
0414 {
0415 raspberrypi_spi_bus *bus;
0416 bus = (raspberrypi_spi_bus *) base;
0417
0418 #ifdef BSP_SPI_USE_INTERRUPTS
0419 rtems_interrupt_handler_remove(
0420 bus->irq,
0421 raspberrypi_spi_interrupt,
0422 bus
0423 );
0424 #endif
0425
0426 spi_bus_destroy_and_free(&bus->base);
0427 }
0428
0429 static int raspberrypi_spi_setup(spi_bus *base)
0430 {
0431 raspberrypi_spi_bus *bus;
0432 uint32_t mode = base->mode;
0433
0434 bus = (raspberrypi_spi_bus *) base;
0435
0436 if (mode & SPI_LOOP) {
0437 return -EINVAL;
0438 }
0439
0440 return raspberrypi_spi_config(
0441 bus,
0442 bus->regs,
0443 bus->base.speed_hz,
0444 bus->base.mode,
0445 bus->base.cs
0446 );
0447 }
0448
0449 static rtems_status_code raspberrypi_spi_init_gpio(
0450 raspberrypi_spi_device device
0451 )
0452 {
0453 switch (device) {
0454 case raspberrypi_SPI0:
0455 raspberrypi_gpio_set_function(7, GPIO_AF0);
0456 raspberrypi_gpio_set_pull(7, GPIO_PULL_NONE);
0457 raspberrypi_gpio_set_function(8, GPIO_AF0);
0458 raspberrypi_gpio_set_pull(8, GPIO_PULL_NONE);
0459 raspberrypi_gpio_set_function(9, GPIO_AF0);
0460 raspberrypi_gpio_set_function(10, GPIO_AF0);
0461 raspberrypi_gpio_set_function(11, GPIO_AF0);
0462 break;
0463 case raspberrypi_SPI3:
0464 raspberrypi_gpio_set_function(24, GPIO_AF5);
0465 raspberrypi_gpio_set_pull(24, GPIO_PULL_NONE);
0466 raspberrypi_gpio_set_function(0, GPIO_AF3);
0467 raspberrypi_gpio_set_pull(0, GPIO_PULL_NONE);
0468 raspberrypi_gpio_set_function(1, GPIO_AF3);
0469 raspberrypi_gpio_set_function(2, GPIO_AF3);
0470 raspberrypi_gpio_set_function(3, GPIO_AF3);
0471 break;
0472 case raspberrypi_SPI4:
0473 raspberrypi_gpio_set_function(25, GPIO_AF5);
0474 raspberrypi_gpio_set_pull(25, GPIO_PULL_NONE);
0475 raspberrypi_gpio_set_function(4, GPIO_AF3);
0476 raspberrypi_gpio_set_pull(4, GPIO_PULL_NONE);
0477 raspberrypi_gpio_set_function(5, GPIO_AF3);
0478 raspberrypi_gpio_set_function(6, GPIO_AF3);
0479 raspberrypi_gpio_set_function(7, GPIO_AF3);
0480 break;
0481 case raspberrypi_SPI5:
0482 raspberrypi_gpio_set_function(26, GPIO_AF5);
0483 raspberrypi_gpio_set_pull(26, GPIO_PULL_NONE);
0484 raspberrypi_gpio_set_function(12, GPIO_AF3);
0485 raspberrypi_gpio_set_pull(12, GPIO_PULL_NONE);
0486 raspberrypi_gpio_set_function(13, GPIO_AF3);
0487 raspberrypi_gpio_set_function(14, GPIO_AF3);
0488 raspberrypi_gpio_set_function(15, GPIO_AF3);
0489 break;
0490 case raspberrypi_SPI6:
0491 raspberrypi_gpio_set_function(27, GPIO_AF5);
0492 raspberrypi_gpio_set_pull(27, GPIO_PULL_NONE);
0493 raspberrypi_gpio_set_function(18, GPIO_AF3);
0494 raspberrypi_gpio_set_pull(18, GPIO_PULL_NONE);
0495 raspberrypi_gpio_set_function(19, GPIO_AF3);
0496 raspberrypi_gpio_set_function(20, GPIO_AF3);
0497 raspberrypi_gpio_set_function(21, GPIO_AF3);
0498 break;
0499 default:
0500 return RTEMS_INVALID_NUMBER;
0501 break;
0502 }
0503 return RTEMS_SUCCESSFUL;
0504 }
0505
0506 rtems_status_code raspberrypi_spi_init(raspberrypi_spi_device device)
0507 {
0508 raspberrypi_spi_bus *bus;
0509 int eno;
0510 volatile raspberrypi_spi *regs;
0511 const char *bus_path;
0512
0513 bus = (raspberrypi_spi_bus *) spi_bus_alloc_and_init(sizeof(*bus));
0514 if (bus == NULL) {
0515 return RTEMS_UNSATISFIED;
0516 }
0517
0518 switch (device) {
0519 case raspberrypi_SPI0:
0520 regs = (volatile raspberrypi_spi *) BCM2711_SPI0_BASE;
0521 bus_path = "/dev/spidev0";
0522 break;
0523 case raspberrypi_SPI3:
0524 regs = (volatile raspberrypi_spi *) BCM2711_SPI3_BASE;
0525 bus_path = "/dev/spidev3";
0526 break;
0527 case raspberrypi_SPI4:
0528 regs = (volatile raspberrypi_spi *) BCM2711_SPI4_BASE;
0529 bus_path = "/dev/spidev4";
0530 break;
0531 case raspberrypi_SPI5:
0532 regs = (volatile raspberrypi_spi *) BCM2711_SPI5_BASE;
0533 bus_path = "/dev/spidev5";
0534 break;
0535 case raspberrypi_SPI6:
0536 regs = (volatile raspberrypi_spi *) BCM2711_SPI6_BASE;
0537 bus_path = "/dev/spidev6";
0538 break;
0539 default:
0540 spi_bus_destroy_and_free(&bus->base);
0541 return RTEMS_INVALID_NUMBER;
0542 break;
0543 }
0544
0545 bus->regs = regs;
0546 bus->num_cs = 2;
0547
0548 bus->base.transfer = raspberrypi_spi_transfer;
0549 bus->base.destroy = raspberrypi_spi_destroy;
0550 bus->base.setup = raspberrypi_spi_setup;
0551 bus->base.bits_per_word = 8;
0552 bus->base.max_speed_hz = 250000000;
0553 bus->base.cs = 0;
0554 #ifdef BSP_SPI_USE_INTERRUPTS
0555 bus->irq = BCM2711_IRQ_SPI;
0556
0557 eno = rtems_interrupt_handler_install(
0558 bus->irq,
0559 "SPI",
0560 RTEMS_INTERRUPT_SHARED,
0561 raspberrypi_spi_interrupt,
0562 bus
0563 );
0564 if (eno != RTEMS_SUCCESSFUL) {
0565 return EAGAIN;
0566 }
0567 #endif
0568
0569 eno = spi_bus_register(&bus->base, bus_path);
0570 if (eno != 0) {
0571 spi_bus_destroy_and_free(&bus->base);
0572 return RTEMS_UNSATISFIED;
0573 }
0574
0575 eno = raspberrypi_spi_init_gpio(device);
0576 if (eno != 0) {
0577 spi_bus_destroy_and_free(&bus->base);
0578 return RTEMS_INVALID_NUMBER;
0579 }
0580
0581 return RTEMS_SUCCESSFUL;
0582 }