114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi/* 214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Copyright (C) 2016 The Android Open Source Project 314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Licensed under the Apache License, Version 2.0 (the "License"); 514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * you may not use this file except in compliance with the License. 614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * You may obtain a copy of the License at 714986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 814986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * http://www.apache.org/licenses/LICENSE-2.0 914986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * 1014986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * Unless required by applicable law or agreed to in writing, software 1114986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * distributed under the License is distributed on an "AS IS" BASIS, 1214986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1314986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * See the License for the specific language governing permissions and 1414986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi * limitations under the License. 1514986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi */ 1614986b090cf259d3d9e6762520dfc276e30de911Ashutosh Joshi 174916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <errno.h> 184916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <string.h> 194916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 204916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <gpio.h> 214916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <spi.h> 224916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <spi_priv.h> 234916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#include <util.h> 2401ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema#include <atomicBitset.h> 2501ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema#include <atomic.h> 26ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema#include <platform.h> 274916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 28f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/cmsis.h> 29f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/dma.h> 30f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/gpio.h> 31f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/pwr.h> 32f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/exti.h> 33f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/syscfg.h> 34f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/spi.h> 35f805306b53d82eef67d8891a5dd5c32d3794a3abAlexey Polyudov#include <plat/plat.h> 364916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 374916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_CPHA (1 << 0) 384916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_CPOL (1 << 1) 394916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_MSTR (1 << 2) 404916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 414916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BR(x) ((LOG2_CEIL(x) - 1) << 3) 424916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BR_MIN 2 434916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BR_MAX 256 444916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BR_MASK (0x7 << 3) 454916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 464916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_SPE (1 << 6) 474916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_LSBFIRST (1 << 7) 488c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann#define SPI_CR1_SSI (1 << 8) 498c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann#define SPI_CR1_SSM (1 << 9) 504916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_RXONLY (1 << 10) 514916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_DFF (1 << 11) 524916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BIDIOE (1 << 14) 534916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR1_BIDIMODE (1 << 15) 544916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 554916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR2_TXEIE (1 << 7) 564916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR2_RXNEIE (1 << 6) 574916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR2_ERRIE (1 << 5) 5883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann#define SPI_CR2_TXDMAEN (1 << 1) 5983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann#define SPI_CR2_RXDMAEN (1 << 0) 604916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR2_INT_MASK (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE) 614916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 624916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_CR2_SSOE (1 << 2) 634916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 644916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_SR_RXNE (1 << 0) 654916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_SR_TXE (1 << 1) 664916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define SPI_SR_BSY (1 << 7) 674916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 6838d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergstruct StmSpi { 694916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t CR1; 704916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t CR2; 714916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t SR; 724916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t DR; 734916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t CRCPR; 744916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t RXCRCR; 754916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t TXCRCR; 764916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t I2SCFGR; 774916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann volatile uint32_t I2SPR; 784916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 794916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 8038d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergstruct StmSpiState { 8138d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg uint8_t bitsPerWord; 8201ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema uint8_t xferEnable; 83925bae58b5a27241ee56ca2de3e917798cb6ec77Greg Hackmann 84866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann uint16_t rxWord; 85925bae58b5a27241ee56ca2de3e917798cb6ec77Greg Hackmann uint16_t txWord; 86869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 8783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann bool rxDone; 8883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann bool txDone; 8983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 90869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct ChainedIsr isrNss; 9118398435228c803389784c0407280e745d5a9bdeBen Fennema 9218398435228c803389784c0407280e745d5a9bdeBen Fennema bool nssChange; 934916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 944916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 9538d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergstruct StmSpiCfg { 9638d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg struct StmSpi *regs; 974916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 981337f149cbf99cd9a52081f671f62dadcd3bb48cGreg Hackmann uint32_t clockBus; 9938d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg uint32_t clockUnit; 1004916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 1014916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann IRQn_Type irq; 10283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 10383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann uint8_t dmaBus; 1044916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 1054916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 10638d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergstruct StmSpiDev { 10738d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg struct SpiDevice *base; 10807139a2ed11599600356935068c28877db47f1feGreg Hackmann const struct StmSpiCfg *cfg; 109bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann const struct StmSpiBoardCfg *board; 11038d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg struct StmSpiState state; 1114916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 11271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *miso; 11371b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *mosi; 11471b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *sck; 11571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct Gpio *nss; 1164916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 1174916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 1183568682fec0484260cfe2b9ba0d1540f956c21cbDmitry Grinbergstatic inline struct Gpio *stmSpiGpioInit(uint32_t gpioNum, enum StmGpioSpeed speed, enum StmGpioAltFunc func) 1198c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann{ 1203568682fec0484260cfe2b9ba0d1540f956c21cbDmitry Grinberg struct Gpio *gpio = gpioRequest(gpioNum); 12184f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg 12284f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (gpio) 12384f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg gpioConfigAlt(gpio, speed, GPIO_PULL_NONE, GPIO_OUT_PUSH_PULL, func); 12471b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 12571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg return gpio; 1268c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann} 1278c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 1283568682fec0484260cfe2b9ba0d1540f956c21cbDmitry Grinbergstatic inline void stmSpiDataPullMode(struct StmSpiDev *pdev, enum StmGpioSpeed dataSpeed, enum GpioPullMode dataPull) 129a916fd8c0dce52dd6b219608d7481a11a01d44a7Greg Hackmann{ 13071b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioConfigAlt(pdev->miso, dataSpeed, dataPull, GPIO_OUT_PUSH_PULL, pdev->board->gpioFunc); 13171b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioConfigAlt(pdev->mosi, dataSpeed, dataPull, GPIO_OUT_PUSH_PULL, pdev->board->gpioFunc); 132a916fd8c0dce52dd6b219608d7481a11a01d44a7Greg Hackmann} 133a916fd8c0dce52dd6b219608d7481a11a01d44a7Greg Hackmann 1343568682fec0484260cfe2b9ba0d1540f956c21cbDmitry Grinbergstatic inline void stmSpiSckPullMode(struct StmSpiDev *pdev, enum StmGpioSpeed sckSpeed, enum GpioPullMode sckPull) 135ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann{ 13671b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioConfigAlt(pdev->sck, sckSpeed, sckPull, GPIO_OUT_PUSH_PULL, pdev->board->gpioFunc); 137ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann} 138ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann 13983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmannstatic inline void stmSpiStartDma(struct StmSpiDev *pdev, 14083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann const struct StmSpiDmaCfg *dmaCfg, const void *buf, uint8_t bitsPerWord, 14183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann bool minc, size_t size, DmaCallbackF callback, bool rx) 14283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann{ 14383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 14483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct dmaMode mode; 14583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 14683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann memset(&mode, 0, sizeof(mode)); 14783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 14883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (bitsPerWord == 8) { 14983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.psize = DMA_SIZE_8_BITS; 15083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.msize = DMA_SIZE_8_BITS; 15183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } else { 15283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.psize = DMA_SIZE_16_BITS; 15383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.msize = DMA_SIZE_16_BITS; 15483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 15583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.priority = DMA_PRIORITY_HIGH; 15683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.direction = rx ? DMA_DIRECTION_PERIPH_TO_MEM : 15783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann DMA_DIRECTION_MEM_TO_PERIPH; 15883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.periphAddr = (uintptr_t)®s->DR; 15983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.minc = minc; 16083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann mode.channel = dmaCfg->channel; 16183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 16283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann dmaStart(pdev->cfg->dmaBus, dmaCfg->stream, buf, size, &mode, callback, 16383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann pdev); 16483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann} 16583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 166ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic inline int stmSpiEnable(struct StmSpiDev *pdev, 167ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann const struct SpiMode *mode, bool master) 1684916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 16907139a2ed11599600356935068c28877db47f1feGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 17001ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema struct StmSpiState *state = &pdev->state; 1714916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 17238d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg if (mode->bitsPerWord != 8 && 17338d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg mode->bitsPerWord != 16) 1744916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann return -EINVAL; 1754916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 176ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann unsigned int div; 177ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann if (master) { 178ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann if (!mode->speed) 179ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann return -EINVAL; 180ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 181ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann uint32_t pclk = pwrGetBusSpeed(PERIPH_BUS_AHB1); 182ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann div = pclk / mode->speed; 183ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann if (div > SPI_CR1_BR_MAX) 184ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann return -EINVAL; 185ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann else if (div < SPI_CR1_BR_MIN) 186ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann div = SPI_CR1_BR_MIN; 187ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann } 1884916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 18901ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema atomicWriteByte(&state->xferEnable, false); 19001ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema 19183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann state->txWord = mode->txWord; 19283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann state->bitsPerWord = mode->bitsPerWord; 19383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 1941337f149cbf99cd9a52081f671f62dadcd3bb48cGreg Hackmann pwrUnitClock(pdev->cfg->clockBus, pdev->cfg->clockUnit, true); 1954916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 196ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann if (master) { 197ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann regs->CR1 &= ~SPI_CR1_BR_MASK; 198ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann regs->CR1 |= SPI_CR1_BR(div); 199ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann } 2004916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 2014916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann if (mode->cpol == SPI_CPOL_IDLE_LO) 2024916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 &= ~SPI_CR1_CPOL; 2034916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann else 2044916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 |= SPI_CR1_CPOL; 2054916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 2064916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann if (mode->cpha == SPI_CPHA_LEADING_EDGE) 2074916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 &= ~SPI_CR1_CPHA; 2084916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann else 2094916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 |= SPI_CR1_CPHA; 2104916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 21138d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg if (mode->bitsPerWord == 8) 2124916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 &= ~SPI_CR1_DFF; 2134916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann else 2144916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 |= SPI_CR1_DFF; 2154916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 2164916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann if (mode->format == SPI_FORMAT_MSB_FIRST) 2174916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 &= ~SPI_CR1_LSBFIRST; 2184916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann else 2194916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 |= SPI_CR1_LSBFIRST; 2204916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 2218c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann if (master) 2228c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann regs->CR1 |= SPI_CR1_SSI | SPI_CR1_SSM | SPI_CR1_MSTR; 2238c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann else 2248c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann regs->CR1 &= ~(SPI_CR1_SSM | SPI_CR1_MSTR); 2254916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 2264916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann return 0; 2274916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 2284916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 229ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic int stmSpiMasterStartSync(struct SpiDevice *dev, spi_cs_t cs, 230ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann const struct SpiMode *mode) 231ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann{ 232ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 2338c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 2348c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann int err = stmSpiEnable(pdev, mode, true); 2358c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann if (err < 0) 2368c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann return err; 2378c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 238bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiDataPullMode(pdev, pdev->board->gpioSpeed, pdev->board->gpioPull); 239bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiSckPullMode(pdev, pdev->board->gpioSpeed, mode->cpol ? GPIO_PULL_UP : GPIO_PULL_DOWN); 240ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann 24171b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg if (!pdev->nss) 24271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->nss = gpioRequest(cs); 24384f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (!pdev->nss) 24484f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg return -ENODEV; 24571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioConfigOutput(pdev->nss, pdev->board->gpioSpeed, pdev->board->gpioPull, GPIO_OUT_PUSH_PULL, 1); 2468c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 2478c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann return 0; 248ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann} 249ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 250ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic int stmSpiSlaveStartSync(struct SpiDevice *dev, 251ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann const struct SpiMode *mode) 252ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann{ 253ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 254a916fd8c0dce52dd6b219608d7481a11a01d44a7Greg Hackmann 255bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiDataPullMode(pdev, pdev->board->gpioSpeed, GPIO_PULL_NONE); 256bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiSckPullMode(pdev, pdev->board->gpioSpeed, GPIO_PULL_NONE); 257a916fd8c0dce52dd6b219608d7481a11a01d44a7Greg Hackmann 25871b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg if (!pdev->nss) 25971b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->nss = stmSpiGpioInit(pdev->board->gpioNss, pdev->board->gpioSpeed, pdev->board->gpioFunc); 26084f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (!pdev->nss) 26184f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg return -ENODEV; 26284f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg 263ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann return stmSpiEnable(pdev, mode, false); 264ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann} 265ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 266ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic inline bool stmSpiIsMaster(struct StmSpiDev *pdev) 267ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann{ 268ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 269ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann return !!(regs->CR1 & SPI_CR1_MSTR); 270ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann} 271ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 27283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmannstatic void stmSpiDone(struct StmSpiDev *pdev, int err) 2734916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 27407139a2ed11599600356935068c28877db47f1feGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 27518398435228c803389784c0407280e745d5a9bdeBen Fennema struct StmSpiState *state = &pdev->state; 27618398435228c803389784c0407280e745d5a9bdeBen Fennema 277287671677bb946b266dc4c8fc39582533272363cBen Fennema if (pdev->board->sleepDev >= 0) 278287671677bb946b266dc4c8fc39582533272363cBen Fennema platReleaseDevInSleepMode(pdev->board->sleepDev); 279ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema 28083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann while (regs->SR & SPI_SR_BSY) 28183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann ; 2824916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 28383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (stmSpiIsMaster(pdev)) { 28484f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (state->nssChange && pdev->nss) 28571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioSet(pdev->nss, 1); 28683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann spiMasterRxTxDone(pdev->base, err); 28783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } else { 28883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 = SPI_CR2_TXEIE; 28983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann spiSlaveRxTxDone(pdev->base, err); 29083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 29183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann} 292ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 29383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmannstatic void stmSpiRxDone(void *cookie, uint16_t bytesLeft, int err) 29483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann{ 29583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiDev *pdev = cookie; 29683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 29783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiState *state = &pdev->state; 2984916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 29983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 &= ~SPI_CR2_RXDMAEN; 30083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann state->rxDone = true; 3014916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 30283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (state->txDone) { 30383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann atomicWriteByte(&state->xferEnable, false); 30483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann stmSpiDone(pdev, err); 30583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 30683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann} 30701ca2d608831afaa5a2891339d9ad8cbd60bbd5aBen Fennema 30883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmannstatic void stmSpiTxDone(void *cookie, uint16_t bytesLeft, int err) 30983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann{ 31083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiDev *pdev = cookie; 31183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 31283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiState *state = &pdev->state; 313ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 31483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 &= ~SPI_CR2_TXDMAEN; 31583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann state->txDone = true; 316ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 31783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (state->rxDone) { 31883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann atomicWriteByte(&state->xferEnable, false); 31983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann stmSpiDone(pdev, err); 32083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 3214916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 3224916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 323ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic int stmSpiRxTx(struct SpiDevice *dev, void *rxBuf, const void *txBuf, 324ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann size_t size, const struct SpiMode *mode) 3254916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 32683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 32783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 32883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiState *state = &pdev->state; 329866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann bool rxMinc = true, txMinc = true; 33083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann uint32_t cr2 = SPI_CR2_TXDMAEN; 33183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 33283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (atomicXchgByte(&state->xferEnable, true) == true) 33383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann return -EBUSY; 33483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 33584f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (stmSpiIsMaster(pdev) && pdev->nss) 33671b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioSet(pdev->nss, 0); 33718398435228c803389784c0407280e745d5a9bdeBen Fennema 338866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann state->rxDone = false; 33983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann state->txDone = false; 34018398435228c803389784c0407280e745d5a9bdeBen Fennema state->nssChange = mode->nssChange; 34183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 342866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann /* In master mode, if RX is ignored at any point, then turning it on 343866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * later may cause the SPI/DMA controllers to "receive" a stale byte 344866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * sitting in a FIFO somewhere (even when their respective registers say 345866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * their FIFOs are empty, and even if the SPI FIFO is explicitly cleared). 346866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * Work around this by DMAing bytes we don't care about into a throwaway 347866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * 1-word buffer. 348866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * 349866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * In slave mode, this specific WAR sometimes causes bigger problems 350866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * (the first byte TXed is sometimes dropped or corrupted). Slave mode 351866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann * has its own WARs below. 352866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann */ 353866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann if (!rxBuf && stmSpiIsMaster(pdev)) { 354866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann rxBuf = &state->rxWord; 355866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann rxMinc = false; 356866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann } 357866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann 35883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (rxBuf) { 35983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann stmSpiStartDma(pdev, &pdev->board->dmaRx, rxBuf, mode->bitsPerWord, 360866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann rxMinc, size, stmSpiRxDone, true); 36183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann cr2 |= SPI_CR2_RXDMAEN; 362866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann } else { 363866a4f391bfb4bd207f890e41b9b305f9c3f179fGreg Hackmann state->rxDone = true; 36483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 36583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 36683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (!txBuf) { 36783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann txBuf = &state->txWord; 36883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann txMinc = false; 36983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 37083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann stmSpiStartDma(pdev, &pdev->board->dmaTx, txBuf, mode->bitsPerWord, txMinc, 37183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann size, stmSpiTxDone, false); 37283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 37383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann /* Ensure the TXE and RXNE bits are cleared; otherwise the DMA controller 37483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * may "receive" the byte sitting in the SPI controller's FIFO right now, 37583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * or drop/corrupt the first TX byte. Timing is crucial here, so do it 37683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * right before enabling DMA. 37783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann */ 37883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (!stmSpiIsMaster(pdev)) { 37983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 &= ~SPI_CR2_TXEIE; 380f22f291bd2bd29fd6c68f0a1208c196ab57c6be7Ben Fennema NVIC_ClearPendingIRQ(pdev->cfg->irq); 38183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 38283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (regs->SR & SPI_SR_RXNE) 38383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann (void)regs->DR; 38483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 38583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (regs->SR & SPI_SR_TXE) 38683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->DR = mode->txWord; 38783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann } 38883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 3891e917212d60ca09ce55ebd81ee7753313e112128Ben Fennema if (pdev->board->sleepDev >= 0) 3901e917212d60ca09ce55ebd81ee7753313e112128Ben Fennema platRequestDevInSleepMode(pdev->board->sleepDev, 12); 3911e917212d60ca09ce55ebd81ee7753313e112128Ben Fennema 39283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 = cr2; 39383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR1 |= SPI_CR1_SPE; 39483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 395ec0212a59091de0329e30b8a916f63fca519b946Ben Fennema 39683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann return 0; 397ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann} 3984916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 399ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic int stmSpiSlaveIdle(struct SpiDevice *dev, const struct SpiMode *mode) 400ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann{ 40183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 40283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 40383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann struct StmSpiState *state = &pdev->state; 40483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 40583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann if (atomicXchgByte(&state->xferEnable, true) == true) 40683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann return -EBUSY; 40783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 40883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 = SPI_CR2_TXEIE; 40983f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR1 |= SPI_CR1_SPE; 41083f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 41183f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann atomicXchgByte(&state->xferEnable, false); 41283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann return 0; 4134916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 4144916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 4158c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmannstatic inline void stmSpiDisable(struct SpiDevice *dev, bool master) 4164916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 417ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 41807139a2ed11599600356935068c28877db47f1feGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 4194916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 420925bae58b5a27241ee56ca2de3e917798cb6ec77Greg Hackmann while (regs->SR & SPI_SR_BSY) 421925bae58b5a27241ee56ca2de3e917798cb6ec77Greg Hackmann ; 4228c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 423ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann if (master) { 424bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiSckPullMode(pdev, pdev->board->gpioSpeed, pdev->board->gpioPull); 425ad1df726050591a13fa41fe450a40d80dca7a448Greg Hackmann } 4268c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 42783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 &= ~(SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN | SPI_CR2_TXEIE); 4284916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann regs->CR1 &= ~SPI_CR1_SPE; 429ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann pwrUnitClock(pdev->cfg->clockBus, pdev->cfg->clockUnit, false); 4308c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann} 4318c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann 4328c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmannstatic int stmSpiMasterStopSync(struct SpiDevice *dev) 4338c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann{ 43471b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct StmSpiDev *pdev = dev->pdata; 43571b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 43684f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (pdev->nss) { 43784f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg gpioSet(pdev->nss, 1); 43871b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->nss); 43984f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg } 44071b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 4418c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann stmSpiDisable(dev, true); 44284f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg pdev->nss = NULL; 4438c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann return 0; 4448c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann} 4454916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 4468c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmannstatic int stmSpiSlaveStopSync(struct SpiDevice *dev) 4478c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann{ 44871b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg struct StmSpiDev *pdev = dev->pdata; 44971b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 45071b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg if (pdev->nss) 45171b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg gpioRelease(pdev->nss); 45271b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg 4538c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann stmSpiDisable(dev, false); 45484f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg pdev->nss = NULL; 455ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann return 0; 4564916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 4574916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 458869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmannstatic bool stmSpiExtiIsr(struct ChainedIsr *isr) 459869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann{ 460869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct StmSpiState *state = container_of(isr, struct StmSpiState, isrNss); 461869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct StmSpiDev *pdev = container_of(state, struct StmSpiDev, state); 462869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 46384f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (pdev->nss && !extiIsPendingGpio(pdev->nss)) 464869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann return false; 465869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 466869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann spiSlaveCsInactive(pdev->base); 46784f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (pdev->nss) 46884f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg extiClearPendingGpio(pdev->nss); 469869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann return true; 470869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann} 471869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 472869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmannstatic void stmSpiSlaveSetCsInterrupt(struct SpiDevice *dev, bool enabled) 473869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann{ 474869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 475869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct ChainedIsr *isr = &pdev->state.isrNss; 476869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 477869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann if (enabled) { 478869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann isr->func = stmSpiExtiIsr; 479869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 48084f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (pdev->nss) { 48184f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg syscfgSetExtiPort(pdev->nss); 48284f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg extiEnableIntGpio(pdev->nss, EXTI_TRIGGER_RISING); 48384f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg } 484bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann extiChainIsr(pdev->board->irqNss, isr); 485869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann } else { 486bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann extiUnchainIsr(pdev->board->irqNss, isr); 48784f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg if (pdev->nss) 48884f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg extiDisableIntGpio(pdev->nss); 489869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann } 490869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann} 491869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 492869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmannstatic bool stmSpiSlaveCsIsActive(struct SpiDevice *dev) 493869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann{ 494869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann struct StmSpiDev *pdev = dev->pdata; 49584f82ecc7368fde3670b46e4b634f5c716ccdd70Dmitry Grinberg return pdev->nss && !gpioGet(pdev->nss); 496869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann} 497869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 498ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmannstatic inline void stmSpiTxe(struct StmSpiDev *pdev) 4994916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 50007139a2ed11599600356935068c28877db47f1feGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 5014916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 50283f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann /** 50383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * n.b.: if nothing handles the TXE interrupt in slave mode, the SPI 50483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * controller will just keep reading the existing value from DR anytime it 50583f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann * needs data 50683f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann */ 50783f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->DR = pdev->state.txWord; 50883f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann regs->CR2 &= ~SPI_CR2_TXEIE; 5094916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 5104916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 51138d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergstatic void stmSpiIsr(struct StmSpiDev *pdev) 5124916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 51307139a2ed11599600356935068c28877db47f1feGreg Hackmann struct StmSpi *regs = pdev->cfg->regs; 5144916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 515ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann if (regs->SR & SPI_SR_TXE) { 51638d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg stmSpiTxe(pdev); 5174916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann } 518ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 519ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann /* TODO: error conditions */ 5204916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 5214916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 5222fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennemastatic int stmSpiRelease(struct SpiDevice *dev) 5232fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema{ 5242fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema struct StmSpiDev *pdev = dev->pdata; 5252fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema 5262fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema NVIC_DisableIRQ(pdev->cfg->irq); 5272fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema 5282fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema pdev->base = NULL; 5292fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema return 0; 5302fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema} 5312fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema 5324916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann#define DECLARE_IRQ_HANDLER(_n) \ 5334916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann void SPI##_n##_IRQHandler(); \ 5344916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann void SPI##_n##_IRQHandler() \ 5354916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann { \ 53638d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg stmSpiIsr(&mStmSpiDevs[_n - 1]); \ 5374916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann } 5384916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 53938d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergconst struct SpiDevice_ops mStmSpiOps = { 54038d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg .masterStartSync = stmSpiMasterStartSync, 541ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann .masterRxTx = stmSpiRxTx, 5428c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann .masterStopSync = stmSpiMasterStopSync, 543ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 544ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann .slaveStartSync = stmSpiSlaveStartSync, 545ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann .slaveIdle = stmSpiSlaveIdle, 546ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann .slaveRxTx = stmSpiRxTx, 5478c49df92e18c9e828f85d0d05bff8d9e70a8e9fcGreg Hackmann .slaveStopSync = stmSpiSlaveStopSync, 548ead4eb3243c8f1a61ced9a97c3d91c9104bc1e9eGreg Hackmann 549869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann .slaveSetCsInterrupt = stmSpiSlaveSetCsInterrupt, 550869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann .slaveCsIsActive = stmSpiSlaveCsIsActive, 551869f1aee3d9d2833bd6739b441e2def728b7f40eGreg Hackmann 5522fd20a565b6792cf5fb6ca4485a8b0ffa62682e7Ben Fennema .release = stmSpiRelease, 5534916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 5544916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 55507139a2ed11599600356935068c28877db47f1feGreg Hackmannstatic const struct StmSpiCfg mStmSpiCfgs[] = { 5564916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann [0] = { 55707139a2ed11599600356935068c28877db47f1feGreg Hackmann .regs = (struct StmSpi *)SPI1_BASE, 5584916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 5591337f149cbf99cd9a52081f671f62dadcd3bb48cGreg Hackmann .clockBus = PERIPH_BUS_APB2, 56007139a2ed11599600356935068c28877db47f1feGreg Hackmann .clockUnit = PERIPH_APB2_SPI1, 5614916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 56207139a2ed11599600356935068c28877db47f1feGreg Hackmann .irq = SPI1_IRQn, 56383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 56483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann .dmaBus = SPI1_DMA_BUS, 5654916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann }, 56677eed017e95498248ff9ead1b5797d0f7fb601e2Sean Wan [1] = { 56794232616d933f90ae346844ec1022664eef780e0Ben Fennema .regs = (struct StmSpi *)SPI2_BASE, 56877eed017e95498248ff9ead1b5797d0f7fb601e2Sean Wan 56994232616d933f90ae346844ec1022664eef780e0Ben Fennema .clockBus = PERIPH_BUS_APB1, 57094232616d933f90ae346844ec1022664eef780e0Ben Fennema .clockUnit = PERIPH_APB1_SPI2, 57177eed017e95498248ff9ead1b5797d0f7fb601e2Sean Wan 57294232616d933f90ae346844ec1022664eef780e0Ben Fennema .irq = SPI2_IRQn, 57383f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann 57483f8ebde8294106d4474fc2fc5e0aa4c674ae48dGreg Hackmann .dmaBus = SPI2_DMA_BUS, 57577eed017e95498248ff9ead1b5797d0f7fb601e2Sean Wan }, 57643833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol [2] = { 57743833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol .regs = (struct StmSpi *)SPI3_BASE, 57843833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol 57943833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol .clockBus = PERIPH_BUS_APB1, 58043833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol .clockUnit = PERIPH_APB1_SPI3, 58143833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol 58243833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol .irq = SPI3_IRQn, 58343833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol 58443833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol .dmaBus = SPI3_DMA_BUS, 58543833ff041d8366e37e8fc18d535fc7a3cf90080Andrew Rossignol }, 5864916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann}; 58707139a2ed11599600356935068c28877db47f1feGreg Hackmann 58807139a2ed11599600356935068c28877db47f1feGreg Hackmannstatic struct StmSpiDev mStmSpiDevs[ARRAY_SIZE(mStmSpiCfgs)]; 5894916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg HackmannDECLARE_IRQ_HANDLER(1) 59077eed017e95498248ff9ead1b5797d0f7fb601e2Sean WanDECLARE_IRQ_HANDLER(2) 59143833ff041d8366e37e8fc18d535fc7a3cf90080Andrew RossignolDECLARE_IRQ_HANDLER(3) 5924916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 59307139a2ed11599600356935068c28877db47f1feGreg Hackmannstatic void stmSpiInit(struct StmSpiDev *pdev, const struct StmSpiCfg *cfg, 594bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann const struct StmSpiBoardCfg *board, struct SpiDevice *dev) 5954916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 59671b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->miso = stmSpiGpioInit(board->gpioMiso, board->gpioSpeed, board->gpioFunc); 59771b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->mosi = stmSpiGpioInit(board->gpioMosi, board->gpioSpeed, board->gpioFunc); 59871b642d969783c6514970587e30502db3ba112c3Dmitry Grinberg pdev->sck = stmSpiGpioInit(board->gpioSclk, board->gpioSpeed, board->gpioFunc); 5994916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 6004916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann NVIC_EnableIRQ(cfg->irq); 6014916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 6024916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann pdev->base = dev; 60307139a2ed11599600356935068c28877db47f1feGreg Hackmann pdev->cfg = cfg; 604bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann pdev->board = board; 6054916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 6064916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 60738d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinbergint spiRequest(struct SpiDevice *dev, uint8_t busId) 6084916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann{ 60938d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg if (busId >= ARRAY_SIZE(mStmSpiDevs)) 6104916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann return -ENODEV; 6114916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 612bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann const struct StmSpiBoardCfg *board = boardStmSpiCfg(busId); 613bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann if (!board) 614396f58ffc174cc626b1bd9df2290504c4525b936Greg Hackmann return -ENODEV; 615396f58ffc174cc626b1bd9df2290504c4525b936Greg Hackmann 61638d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg struct StmSpiDev *pdev = &mStmSpiDevs[busId]; 61707139a2ed11599600356935068c28877db47f1feGreg Hackmann const struct StmSpiCfg *cfg = &mStmSpiCfgs[busId]; 6184916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann if (!pdev->base) 619bfaf30a2f443d0a9d0bcf3a3f314aa0d023ae64eGreg Hackmann stmSpiInit(pdev, cfg, board, dev); 6204916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann 6214916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann memset(&pdev->state, 0, sizeof(pdev->state)); 62238d2948bf8eec7b52d8b24d532cc92b8c76bc0c7Dmitry Grinberg dev->ops = &mStmSpiOps; 6234916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann dev->pdata = pdev; 6244916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann return 0; 6254916eb0b0c0f8afbca2ed51d8dead799eae98a5bGreg Hackmann} 626b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 627b6ce271e41eef25e45ffb699e912801489028b47Ben Fennemaconst enum IRQn spiRxIrq(uint8_t busId) 628b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema{ 629b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema if (busId >= ARRAY_SIZE(mStmSpiDevs)) 630b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema return -ENODEV; 631b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 632b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema struct StmSpiDev *pdev = &mStmSpiDevs[busId]; 633b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 634b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema return dmaIrq(pdev->cfg->dmaBus, pdev->board->dmaRx.stream); 635b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema} 636b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 637b6ce271e41eef25e45ffb699e912801489028b47Ben Fennemaconst enum IRQn spiTxIrq(uint8_t busId) 638b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema{ 639b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema if (busId >= ARRAY_SIZE(mStmSpiDevs)) 640b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema return -ENODEV; 641b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 642b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema struct StmSpiDev *pdev = &mStmSpiDevs[busId]; 643b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema 644b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema return dmaIrq(pdev->cfg->dmaBus, pdev->board->dmaTx.stream); 645b6ce271e41eef25e45ffb699e912801489028b47Ben Fennema} 646