From d7173967087e022d20d1f9c812b1b668e9d3f71b Mon Sep 17 00:00:00 2001 From: Stefan Kerkmann Date: Thu, 30 Jun 2022 13:19:27 +0200 Subject: [Core] Add Raspberry Pi RP2040 support (#14877) * Disable RESET keycode because of naming conflicts * Add Pico SDK as submodule * Add RP2040 build support to QMK * Adjust USB endpoint structs for RP2040 * Add RP2040 bootloader and double-tap reset routine * Add generic and pro micro RP2040 boards * Add RP2040 onekey keyboard * Add WS2812 PIO DMA enabled driver and documentation Supports regular and open-drain output configuration. RP2040 GPIOs are sadly not 5V tolerant, so this is a bit use-less or needs extra hardware or you take the risk to fry your hardware. * Adjust SIO Driver for RP2040 * Adjust I2C Driver for RP2040 * Adjust SPI Driver for RP2040 * Add PIO serial driver and documentation * Add general RP2040 documentation * Apply suggestions from code review Co-authored-by: Nick Brassel Co-authored-by: Nick Brassel --- platforms/chibios/drivers/spi_master.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'platforms/chibios/drivers/spi_master.c') diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c index ce69e7f0ac..f9974d9f6b 100644 --- a/platforms/chibios/drivers/spi_master.c +++ b/platforms/chibios/drivers/spi_master.c @@ -20,7 +20,7 @@ static pin_t currentSlavePin = NO_PIN; -#if defined(K20x) || defined(KL2x) +#if defined(K20x) || defined(KL2x) || defined(RP2040) static SPIConfig spiConfig = {NULL, 0, 0, 0}; #else static SPIConfig spiConfig = {false, NULL, 0, 0, 0, 0}; @@ -167,7 +167,36 @@ bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor) { spiConfig.SPI_CPOL = SPI_CPOL_High; break; } +#elif defined(MCU_RP) + if (lsbFirst) { + osalDbgAssert(lsbFirst == false, "RP2040s PrimeCell SPI implementation does not support sending LSB first."); + } + + // Motorola frame format and 8bit transfer data size. + spiConfig.SSPCR0 = SPI_SSPCR0_FRF_MOTOROLA | SPI_SSPCR0_DSS_8BIT; + // Serial output clock = (ck_sys or ck_peri) / (SSPCPSR->CPSDVSR * (1 + + // SSPCR0->SCR)). SCR is always set to zero, as QMK SPI API expects the + // passed divisor to be the only value to divide the input clock by. + spiConfig.SSPCPSR = roundedDivisor; // Even number from 2 to 254 + switch (mode) { + case 0: + spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low + spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge + break; + case 1: + spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPO; // Clock polarity: low + spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition + break; + case 2: + spiConfig.SSPCR0 |= SPI_SSPCR0_SPO; // Clock polarity: high + spiConfig.SSPCR0 &= ~SPI_SSPCR0_SPH; // Clock phase: sample on first edge + break; + case 3: + spiConfig.SSPCR0 |= SPI_SSPCR0_SPO; // Clock polarity: high + spiConfig.SSPCR0 |= SPI_SSPCR0_SPH; // Clock phase: sample on second edge transition + break; + } #else spiConfig.cr1 = 0; -- cgit v1.2.3