File indexing completed on 2025-05-11 08:22:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <bsp.h>
0019 #include <bsp/bbb-gpio.h>
0020 #include <bsp/spi.h>
0021 #include <errno.h>
0022 #include <rtems/bspIo.h>
0023 #include <rtems/error.h>
0024 #include <rtems/libi2c.h>
0025 #include <stdio.h>
0026 #include <stdlib.h>
0027
0028
0029
0030
0031 #define EVENT_TXEMPTY RTEMS_EVENT_0
0032 #define EVENT_RXFULL RTEMS_EVENT_1
0033
0034 static void SPI0ModuleClkConfig(void)
0035 {
0036
0037 REG( AM335X_CM_PER_ADDR + AM335X_CM_PER_SPI0_CLKCTRL ) |=
0038 AM335X_CM_PER_SPI0_CLKCTRL_MODULEMODE_ENABLE;
0039
0040
0041 while ( AM335X_CM_PER_SPI0_CLKCTRL_MODULEMODE_ENABLE !=
0042 ( REG( AM335X_CM_PER_ADDR + AM335X_CM_PER_SPI0_CLKCTRL ) &
0043 AM335X_CM_PER_SPI0_CLKCTRL_MODULEMODE ) )
0044 continue;
0045
0046
0047
0048
0049
0050 while ( ( AM335X_CM_PER_CONTROL_CLKCTRL_IDLEST_FUNC <<
0051 AM335X_CM_PER_CONTROL_CLKCTRL_IDLEST_SHIFT ) !=
0052 ( REG( AM335X_CM_PER_ADDR + AM335X_CM_PER_SPI0_CLKCTRL ) &
0053 AM335X_CM_PER_CONTROL_CLKCTRL_IDLEST ) )
0054 continue;
0055 }
0056
0057 static inline void am335x_spi_clear_irqstatus(uint32_t reg_base, uint32_t irqs)
0058 {
0059 REG(reg_base + AM335X_SPI_SYST) &= ~AM335X_SPI_SYST_SSB;
0060 REG(reg_base + AM335X_SPI_IRQSTATUS) = irqs;
0061 }
0062
0063 static void am335x_spi0_pinmux(void)
0064 {
0065 REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) =
0066 (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN);
0067
0068 REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) =
0069 (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN);
0070
0071 REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D1) =
0072 (BBB_RXACTIVE | BBB_SLEWCTRL | BBB_PU_EN);
0073
0074 REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_CS0) =
0075 (BBB_RXACTIVE | BBB_PU_EN);
0076 }
0077
0078 static void am335x_spi_reset(uint32_t reg_base)
0079 {
0080 int timeout = BBB_SPI_TIMEOUT;
0081
0082 REG(reg_base + AM335X_SPI_SYSCONFIG) |= AM335X_SPI_SYSCONFIG_SOFTRESET;
0083
0084 while ((REG(reg_base + AM335X_SPI_SYSSTATUS) & AM335X_SPI_SYSSTATUS_RESETDONE) == 0 && timeout--) {
0085 if (timeout <= 0) {
0086 puts("ERROR: Timeout in soft-reset\n");
0087
0088 return;
0089 }
0090
0091 udelay(1000);
0092 }
0093 }
0094
0095 static void beagle_spi_irq_handler(void *arg)
0096 {
0097 const uint32_t handled_irqs = AM335X_SPI_IRQSTATUS_TX0_EMPTY | AM335X_SPI_IRQSTATUS_RX0_FULL;
0098
0099 beagle_spi_softc_t *softc_ptr = arg;
0100
0101 rtems_status_code sc = -1;
0102
0103 uint32_t irq = 0;
0104 uint32_t events = 0;
0105
0106 uint32_t tmp;
0107 while ((tmp = (REG(softc_ptr->regs_base + AM335X_SPI_IRQSTATUS)) & handled_irqs) != 0) {
0108 irq |= tmp;
0109 am335x_spi_clear_irqstatus(softc_ptr->regs_base, tmp);
0110 }
0111
0112 #if defined(TRACE)
0113 printk("beagle_spi_irq_handler: AM335X_SPI_IRQSTATUS = 0x%04lx\r\n", irq);
0114 #endif
0115
0116 if (irq & AM335X_SPI_IRQSTATUS_TX0_EMPTY) {
0117 #if defined(TRACE)
0118 printk("beagle_spi_irq_handler: sending event TXEMPTY to task_id = %ld\r\n", softc_ptr->task_id);
0119 #endif
0120
0121 events |= EVENT_TXEMPTY;
0122 }
0123
0124 if (irq & AM335X_SPI_IRQSTATUS_RX0_FULL) {
0125 #if defined(TRACE)
0126 printk("beagle_spi_irq_handler: sending event RXFULL to task_id = %ld\r\n", softc_ptr->task_id);
0127 #endif
0128
0129 events |= EVENT_RXFULL;
0130 }
0131
0132 sc = rtems_event_send(softc_ptr->task_id, events);
0133 _Assert(sc == RTEMS_SUCCESSFUL);
0134 (void)sc;
0135 }
0136
0137
0138
0139
0140
0141 rtems_status_code beagle_spi_init
0142 (
0143 rtems_libi2c_bus_t *bh
0144 )
0145 {
0146 beagle_spi_softc_t *softc_ptr = &(((beagle_spi_desc_t *)(bh))->softc);
0147
0148 rtems_status_code rc = RTEMS_SUCCESSFUL;
0149
0150 #if defined(DEBUG)
0151 printk("beagle_spi_init called...\r\n");
0152 #endif
0153
0154 SPI0ModuleClkConfig();
0155 am335x_spi0_pinmux();
0156 am335x_spi_reset(softc_ptr->regs_base);
0157
0158 REG(softc_ptr->regs_base + AM335X_SPI_MODULCTRL) &= ~AM335X_SPI_MODULCTRL_PIN34;
0159 REG(softc_ptr->regs_base + AM335X_SPI_MODULCTRL) &= ~AM335X_SPI_MODULCTRL_MS;
0160 REG(softc_ptr->regs_base + AM335X_SPI_MODULCTRL) |= AM335X_SPI_MODULCTRL_SINGLE;
0161 REG(softc_ptr->regs_base + AM335X_SPI_MODULCTRL) &= ~AM335X_SPI_MODULCTRL_PIN34;
0162
0163
0164
0165
0166
0167
0168 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_TRM_MASK;
0169 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) |= AM335X_SPI_CH0CONF_DPE0;
0170 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_DPE1;
0171 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_IS;
0172
0173
0174
0175 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) |= AM335X_SPI_CH0CONF_WL(8 - 1);
0176
0177 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_PHA;
0178 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_POL;
0179
0180 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) |= AM335X_SPI_CH0CONF_EPOL;
0181 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) |= AM335X_SPI_CH0CONF_CLKD(0x1);
0182
0183
0184
0185 rc = rtems_interrupt_handler_install(
0186 softc_ptr->irq,
0187 NULL,
0188 RTEMS_INTERRUPT_UNIQUE,
0189 (rtems_interrupt_handler)beagle_spi_irq_handler,
0190 softc_ptr
0191 );
0192
0193 #if defined(DEBUG)
0194 printk("beagle_spi_init done\r\n");
0195 #endif
0196
0197 if (rc == RTEMS_SUCCESSFUL) {
0198 softc_ptr->initialized = TRUE;
0199 }
0200
0201 return rc;
0202 }
0203
0204 static int beagle_spi_read_write_bytes(
0205 rtems_libi2c_bus_t *bh,
0206 unsigned char *rx_buf,
0207 unsigned char *tx_buf,
0208 int len
0209 )
0210 {
0211 beagle_spi_softc_t *softc_ptr = &(((beagle_spi_desc_t *)(bh))->softc);
0212
0213 rtems_status_code sc;
0214 rtems_event_set received_events;
0215
0216 #if defined(TRACE)
0217 printk("beagle_spi_read_write_bytes called...\r\n");
0218 #endif
0219
0220 softc_ptr->task_id = rtems_task_self();
0221
0222
0223
0224 if (rx_buf) {
0225 am335x_spi_clear_irqstatus(softc_ptr->regs_base, AM335X_SPI_IRQSTATUS_RX0_FULL);
0226 REG(softc_ptr->regs_base + AM335X_SPI_IRQENABLE) |= AM335X_SPI_IRQENABLE_RX0_FULL;
0227 }
0228
0229 if (tx_buf) {
0230 am335x_spi_clear_irqstatus(softc_ptr->regs_base, AM335X_SPI_IRQSTATUS_TX0_EMPTY);
0231 REG(softc_ptr->regs_base + AM335X_SPI_IRQENABLE) |= AM335X_SPI_IRQENABLE_TX0_EMPTY;
0232 }
0233
0234
0235 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) |= AM335X_SPI_CH0CONF_FORCE;
0236 REG(softc_ptr->regs_base + AM335X_SPI_CH0CTRL) |= AM335X_SPI_CH0CTRL_EN;
0237
0238
0239 for (int i = 0; i < len; i++) {
0240 received_events = 0;
0241
0242 if (tx_buf) {
0243
0244 #if defined(TRACE)
0245 printk("beagle_spi_read_write_bytes: waiting (task_id = %ld)\r\n", softc_ptr->task_id);
0246 #endif
0247
0248 sc = rtems_event_receive(EVENT_TXEMPTY, RTEMS_WAIT, BBB_SPI_TIMEOUT, &received_events);
0249 if (sc != RTEMS_SUCCESSFUL) {
0250 printk("ERROR: beagle_spi_read_write_bytes timed out on tx byte number %d\n", i);
0251 return i > 0 ? i : -RTEMS_TIMEOUT;
0252 }
0253
0254 _Assert(received_events == EVENT_TXEMPTY);
0255
0256 #if defined(TRACE)
0257 printk("beagle_spi_read_write_bytes: sending byte: i = %d, tx_buf[i] = 0x%x\r\n", i, tx_buf[i]);
0258 #endif
0259
0260 REG(softc_ptr->regs_base + AM335X_SPI_TX0) = tx_buf[i];
0261 }
0262
0263 if (rx_buf) {
0264
0265 if ((received_events & EVENT_RXFULL) == 0) {
0266 sc = rtems_event_receive(EVENT_RXFULL, RTEMS_WAIT, BBB_SPI_TIMEOUT, &received_events);
0267 if (sc != RTEMS_SUCCESSFUL) {
0268 printk("ERROR: beagle_spi_read_write_bytes timed out on rx byte number %d\n", i);
0269 return i > 0 ? i : -RTEMS_TIMEOUT;
0270 }
0271
0272 _Assert(received_events == EVENT_RXFULL);
0273 }
0274
0275 rx_buf[i] = REG(softc_ptr->regs_base + AM335X_SPI_RX0);
0276
0277 #if defined(TRACE)
0278 printk("beagle_spi_read_write_bytes: received byte: i = %d, rx_buf[i] = 0x%x\r\n", i, rx_buf[i]);
0279 #endif
0280 }
0281 }
0282
0283
0284
0285
0286 REG(softc_ptr->regs_base + AM335X_SPI_CH0CTRL) &= ~AM335X_SPI_CH0CTRL_EN;
0287 REG(softc_ptr->regs_base + AM335X_SPI_CH0CONF) &= ~AM335X_SPI_CH0CONF_FORCE;
0288
0289 #if defined(TRACE)
0290 printk("beagle_spi_read_write_bytes done\r\n");
0291 #endif
0292
0293 return len;
0294 }
0295
0296
0297
0298
0299
0300
0301 int beagle_spi_read_bytes
0302 (
0303 rtems_libi2c_bus_t *bh,
0304 unsigned char *buf,
0305 int len
0306 )
0307 {
0308
0309 #if defined(DEBUG)
0310 printk("beagle_spi_read_bytes called...\r\n");
0311 #endif
0312
0313 int n = beagle_spi_read_write_bytes(bh, buf, NULL, len);
0314
0315 #if defined(DEBUG)
0316 printk("beagle_spi_read_bytes done\r\n");
0317 #endif
0318
0319 return n;
0320 }
0321
0322
0323
0324
0325
0326
0327 int beagle_spi_write_bytes
0328 (
0329 rtems_libi2c_bus_t *bh,
0330 unsigned char *buf,
0331 int len
0332 )
0333 {
0334 #if defined(DEBUG)
0335 printk("beagle_spi_write_bytes called...\r\n");
0336 #endif
0337
0338 int n = beagle_spi_read_write_bytes(bh, NULL, buf, len);
0339
0340 #if defined(DEBUG)
0341 printk("beagle_spi_write_bytes done\r\n");
0342 #endif
0343
0344 return n;
0345 }
0346
0347
0348
0349
0350
0351
0352 int beagle_spi_ioctl
0353 (
0354 rtems_libi2c_bus_t *bh,
0355 int cmd,
0356 void *arg
0357 )
0358 {
0359 int ret_val = -1;
0360
0361 #if defined(DEBUG)
0362 printk("beagle_spi_ioctl called...\r\n");
0363 #endif
0364
0365 switch(cmd) {
0366 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
0367 #if defined(TRACE)
0368 printk("cmd == RTEMS_LIBI2C_IOCTL_SET_TFRMODE\r\n");
0369 #endif
0370
0371
0372
0373
0374 break;
0375 case RTEMS_LIBI2C_IOCTL_READ_WRITE: {
0376 #if defined(TRACE)
0377 printk("cmd == RTEMS_LIBI2C_IOCTL_READ_WRITE\r\n");
0378 #endif
0379 const rtems_libi2c_read_write_t *cmd = (const rtems_libi2c_read_write_t *)arg;
0380
0381 ret_val = beagle_spi_read_write_bytes(
0382 bh,
0383 (unsigned char *)cmd->rd_buf,
0384 (unsigned char *)cmd->wr_buf,
0385 cmd->byte_cnt
0386 );
0387 break;
0388 }
0389 default:
0390 ret_val = -RTEMS_NOT_DEFINED;
0391 break;
0392 }
0393
0394 #if defined(DEBUG)
0395 printk("beagle_spi_ioctl done\r\n");
0396 #endif
0397
0398 return ret_val;
0399 }
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410 static rtems_status_code bsp_spi_sel_addr
0411 (
0412 rtems_libi2c_bus_t *bh,
0413 uint32_t addr,
0414 int rw
0415 )
0416 {
0417 if (addr != 0)
0418 return RTEMS_NOT_IMPLEMENTED;
0419
0420 return RTEMS_SUCCESSFUL;
0421 }
0422
0423
0424
0425
0426
0427
0428 static rtems_status_code bsp_spi_send_start_dummy
0429 (
0430 rtems_libi2c_bus_t *bh
0431 )
0432 {
0433 #if defined(DEBUG)
0434 printk("bsp_spi_send_start_dummy OK\r\n");
0435 #endif
0436
0437 return 0;
0438 }
0439
0440
0441
0442
0443
0444
0445 static rtems_status_code bsp_spi_send_stop
0446 (
0447 rtems_libi2c_bus_t *bh
0448 )
0449 {
0450 #if defined(DEBUG)
0451 printk("bsp_spi_send_stop called... ");
0452 #endif
0453
0454
0455
0456 #if defined(DEBUG)
0457 printk("... exit OK\r\n");
0458 #endif
0459 return 0;
0460 }
0461
0462
0463
0464
0465
0466 rtems_libi2c_bus_ops_t bsp_spi_ops = {
0467 init: beagle_spi_init,
0468 send_start: bsp_spi_send_start_dummy,
0469 send_stop: bsp_spi_send_stop,
0470 send_addr: bsp_spi_sel_addr,
0471 read_bytes: beagle_spi_read_bytes,
0472 write_bytes: beagle_spi_write_bytes,
0473 ioctl: beagle_spi_ioctl
0474 };
0475
0476 static beagle_spi_desc_t bsp_spi_bus_desc = {
0477 {
0478 ops: &bsp_spi_ops,
0479 size: sizeof(bsp_spi_bus_desc)
0480 },
0481 {
0482 initialized: FALSE,
0483 }
0484 };
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 rtems_status_code bsp_register_spi
0496 (
0497 const char *bus_path,
0498 uintptr_t register_base,
0499 rtems_vector_number irq
0500 )
0501 {
0502 int ret_code;
0503 int spi_busno;
0504
0505 beagle_spi_softc_t *softc_ptr = &bsp_spi_bus_desc.softc;
0506
0507 if (softc_ptr->initialized) {
0508 printk("ERROR: Only one SPI bus at a time is supported\n");
0509 return -RTEMS_RESOURCE_IN_USE;
0510 }
0511
0512 softc_ptr->regs_base = register_base;
0513 softc_ptr->irq = irq;
0514
0515
0516
0517
0518 rtems_libi2c_initialize();
0519
0520
0521
0522
0523 ret_code = rtems_libi2c_register_bus(bus_path,
0524 &(bsp_spi_bus_desc.bus_desc));
0525 if (ret_code < 0) {
0526 return -ret_code;
0527 }
0528 spi_busno = ret_code;
0529
0530 #if IS_AM335X
0531
0532 #endif
0533
0534 return spi_busno;
0535 }