Download firmware/hal/spi.c from Snapkitty/phaser-ags: direct link, hf CLI and curl.
- Browser
- Download file 4.03 kB
-
https://huggingface.co/Snapkitty/phaser-ags/resolve/main/firmware/hal/spi.c
- Command line
-
hf download hf://Snapkitty/phaser-ags/firmware/hal/spi.c
-
curl -L -o spi.c https://huggingface.co/Snapkitty/phaser-ags/resolve/main/firmware/hal/spi.c
4.03 kB
| /* | |
| * OMAP3530 McSPI driver | |
| */ | |
| int spi_init(spi_dev_t *dev, uint32_t base, uint8_t channel, | |
| uint32_t clock_hz, uint32_t speed_hz, uint8_t mode, uint8_t bpw) { | |
| dev->base = (hw_reg32_t)base; | |
| dev->channel = channel; | |
| dev->clock_hz = clock_hz; | |
| dev->speed_hz = speed_hz; | |
| dev->mode = mode; | |
| dev->bits_per_word = bpw; | |
| /* Reset McSPI module */ | |
| reg_write32(dev->base + MCSPI_SYSCONFIG, 0x02); | |
| delay_cycles(100); | |
| while (!(reg_read32(dev->base + MCSPI_SYSSTATUS) & 0x01)) | |
| ; | |
| /* Single-channel master mode */ | |
| reg_write32(dev->base + MCSPI_MODULCTRL, MCSPI_MODULCTRL_SINGLE); | |
| /* Configure channel */ | |
| uint32_t chconf = 0; | |
| /* Word length: value = (bpw - 1), 0 means 32-bit */ | |
| if (bpw < 32) | |
| chconf |= ((bpw - 1) << MCSPI_CHCONF_WL_SHIFT); | |
| /* Clock divider: f_spi = f_input / (2 * (CLKD + 1)) */ | |
| uint32_t clkdiv = (dev->clock_hz / (2 * dev->speed_hz)) - 1; | |
| if (clkdiv > 0xF) clkdiv = 0xF; | |
| chconf |= (clkdiv << MCSPI_CHCONF_CLKD_SHIFT); | |
| /* Clock polarity and phase */ | |
| if (mode & 2) chconf |= MCSPI_CHCONF_POL; | |
| if (mode & 1) chconf |= MCSPI_CHCONF_PHA; | |
| /* Enable TX on channel 0, RX enabled */ | |
| chconf &= ~MCSPI_CHCONF_DPE0; /* DPE0=0: TX enabled on SPIEN0 */ | |
| chconf |= MCSPI_CHCONF_DPE1; /* DPE1=1: TX disabled on SPIEN1 */ | |
| chconf &= ~MCSPI_CHCONF_IS; /* IS=0: data line 0 for RX */ | |
| reg_write32(dev->base + MCSPI_CHCONF(dev->channel), chconf); | |
| /* Disable FIFOs for simple polled mode */ | |
| chconf = reg_read32(dev->base + MCSPI_CHCONF(dev->channel)); | |
| chconf &= ~(MCSPI_CHCONF_FFER | MCSPI_CHCONF_FFEW); | |
| reg_write32(dev->base + MCSPI_CHCONF(dev->channel), chconf); | |
| /* Enable channel */ | |
| reg_write32(dev->base + MCSPI_CHCTRL(dev->channel), MCSPI_CHCTRL_EN); | |
| return 0; | |
| } | |
| void spi_set_speed(spi_dev_t *dev, uint32_t speed_hz) { | |
| dev->speed_hz = speed_hz; | |
| uint32_t clkdiv = (dev->clock_hz / (2 * dev->speed_hz)) - 1; | |
| if (clkdiv > 0xF) clkdiv = 0xF; | |
| uint32_t chconf = reg_read32(dev->base + MCSPI_CHCONF(dev->channel)); | |
| chconf &= ~(0xF << MCSPI_CHCONF_CLKD_SHIFT); | |
| chconf |= (clkdiv << MCSPI_CHCONF_CLKD_SHIFT); | |
| reg_write32(dev->base + MCSPI_CHCONF(dev->channel), chconf); | |
| } | |
| int spi_transfer(spi_dev_t *dev, const uint8_t *tx, uint8_t *rx, uint32_t len) { | |
| uint32_t ch = dev->channel; | |
| for (uint32_t i = 0; i < len; i++) { | |
| /* Force SPIEN active */ | |
| uint32_t chconf = reg_read32(dev->base + MCSPI_CHCONF(ch)); | |
| chconf |= MCSPI_CHCONF_FORCE; | |
| reg_write32(dev->base + MCSPI_CHCONF(ch), chconf); | |
| /* Wait for TX empty */ | |
| while (!(reg_read32(dev->base + MCSPI_CHSTAT(ch)) & MCSPI_CHSTAT_TXS)) | |
| ; | |
| /* Write TX data */ | |
| uint32_t data = tx ? tx[i] : 0xFF; | |
| reg_write32(dev->base + MCSPI_TX(ch), data); | |
| /* Wait for RX ready */ | |
| while (!(reg_read32(dev->base + MCSPI_CHSTAT(ch)) & MCSPI_CHSTAT_RXS)) | |
| ; | |
| /* Read RX data */ | |
| if (rx) | |
| rx[i] = (uint8_t)(reg_read32(dev->base + MCSPI_RX(ch)) & 0xFF); | |
| else | |
| reg_read32(dev->base + MCSPI_RX(ch)); /* Discard */ | |
| /* De-assert SPIEN on last byte */ | |
| if (i == len - 1) { | |
| chconf &= ~MCSPI_CHCONF_FORCE; | |
| reg_write32(dev->base + MCSPI_CHCONF(ch), chconf); | |
| } | |
| } | |
| return 0; | |
| } | |
| int spi_write_then_read(spi_dev_t *dev, const uint8_t *tx, uint32_t tx_len, | |
| uint8_t *rx, uint32_t rx_len) { | |
| if (spi_transfer(dev, tx, (uint8_t *)0, tx_len) != 0) | |
| return -1; | |
| return spi_transfer(dev, (const uint8_t *)0, rx, rx_len); | |
| } | |
| uint8_t spi_read_reg8(spi_dev_t *dev, uint8_t reg) { | |
| uint8_t tx = reg | 0x80; /* Read bit */ | |
| uint8_t rx; | |
| spi_write_then_read(dev, &tx, 1, &rx, 1); | |
| return rx; | |
| } | |
| void spi_write_reg8(spi_dev_t *dev, uint8_t reg, uint8_t val) { | |
| uint8_t tx[2] = { reg & 0x7F, val }; | |
| spi_transfer(dev, tx, (uint8_t *)0, 2); | |
| } | |