162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// STMicroelectronics STM32 SPI Controller driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (C) 2017, STMicroelectronics - All Rights Reserved 662306a36Sopenharmony_ci// Author(s): Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics. 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitfield.h> 962306a36Sopenharmony_ci#include <linux/debugfs.h> 1062306a36Sopenharmony_ci#include <linux/clk.h> 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/dmaengine.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/iopoll.h> 1562306a36Sopenharmony_ci#include <linux/module.h> 1662306a36Sopenharmony_ci#include <linux/of_platform.h> 1762306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 1862306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1962306a36Sopenharmony_ci#include <linux/reset.h> 2062306a36Sopenharmony_ci#include <linux/spi/spi.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define DRIVER_NAME "spi_stm32" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* STM32F4 SPI registers */ 2562306a36Sopenharmony_ci#define STM32F4_SPI_CR1 0x00 2662306a36Sopenharmony_ci#define STM32F4_SPI_CR2 0x04 2762306a36Sopenharmony_ci#define STM32F4_SPI_SR 0x08 2862306a36Sopenharmony_ci#define STM32F4_SPI_DR 0x0C 2962306a36Sopenharmony_ci#define STM32F4_SPI_I2SCFGR 0x1C 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* STM32F4_SPI_CR1 bit fields */ 3262306a36Sopenharmony_ci#define STM32F4_SPI_CR1_CPHA BIT(0) 3362306a36Sopenharmony_ci#define STM32F4_SPI_CR1_CPOL BIT(1) 3462306a36Sopenharmony_ci#define STM32F4_SPI_CR1_MSTR BIT(2) 3562306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BR_SHIFT 3 3662306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BR GENMASK(5, 3) 3762306a36Sopenharmony_ci#define STM32F4_SPI_CR1_SPE BIT(6) 3862306a36Sopenharmony_ci#define STM32F4_SPI_CR1_LSBFRST BIT(7) 3962306a36Sopenharmony_ci#define STM32F4_SPI_CR1_SSI BIT(8) 4062306a36Sopenharmony_ci#define STM32F4_SPI_CR1_SSM BIT(9) 4162306a36Sopenharmony_ci#define STM32F4_SPI_CR1_RXONLY BIT(10) 4262306a36Sopenharmony_ci#define STM32F4_SPI_CR1_DFF BIT(11) 4362306a36Sopenharmony_ci#define STM32F4_SPI_CR1_CRCNEXT BIT(12) 4462306a36Sopenharmony_ci#define STM32F4_SPI_CR1_CRCEN BIT(13) 4562306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BIDIOE BIT(14) 4662306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BIDIMODE BIT(15) 4762306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BR_MIN 0 4862306a36Sopenharmony_ci#define STM32F4_SPI_CR1_BR_MAX (GENMASK(5, 3) >> 3) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* STM32F4_SPI_CR2 bit fields */ 5162306a36Sopenharmony_ci#define STM32F4_SPI_CR2_RXDMAEN BIT(0) 5262306a36Sopenharmony_ci#define STM32F4_SPI_CR2_TXDMAEN BIT(1) 5362306a36Sopenharmony_ci#define STM32F4_SPI_CR2_SSOE BIT(2) 5462306a36Sopenharmony_ci#define STM32F4_SPI_CR2_FRF BIT(4) 5562306a36Sopenharmony_ci#define STM32F4_SPI_CR2_ERRIE BIT(5) 5662306a36Sopenharmony_ci#define STM32F4_SPI_CR2_RXNEIE BIT(6) 5762306a36Sopenharmony_ci#define STM32F4_SPI_CR2_TXEIE BIT(7) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* STM32F4_SPI_SR bit fields */ 6062306a36Sopenharmony_ci#define STM32F4_SPI_SR_RXNE BIT(0) 6162306a36Sopenharmony_ci#define STM32F4_SPI_SR_TXE BIT(1) 6262306a36Sopenharmony_ci#define STM32F4_SPI_SR_CHSIDE BIT(2) 6362306a36Sopenharmony_ci#define STM32F4_SPI_SR_UDR BIT(3) 6462306a36Sopenharmony_ci#define STM32F4_SPI_SR_CRCERR BIT(4) 6562306a36Sopenharmony_ci#define STM32F4_SPI_SR_MODF BIT(5) 6662306a36Sopenharmony_ci#define STM32F4_SPI_SR_OVR BIT(6) 6762306a36Sopenharmony_ci#define STM32F4_SPI_SR_BSY BIT(7) 6862306a36Sopenharmony_ci#define STM32F4_SPI_SR_FRE BIT(8) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci/* STM32F4_SPI_I2SCFGR bit fields */ 7162306a36Sopenharmony_ci#define STM32F4_SPI_I2SCFGR_I2SMOD BIT(11) 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* STM32F4 SPI Baud Rate min/max divisor */ 7462306a36Sopenharmony_ci#define STM32F4_SPI_BR_DIV_MIN (2 << STM32F4_SPI_CR1_BR_MIN) 7562306a36Sopenharmony_ci#define STM32F4_SPI_BR_DIV_MAX (2 << STM32F4_SPI_CR1_BR_MAX) 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* STM32H7 SPI registers */ 7862306a36Sopenharmony_ci#define STM32H7_SPI_CR1 0x00 7962306a36Sopenharmony_ci#define STM32H7_SPI_CR2 0x04 8062306a36Sopenharmony_ci#define STM32H7_SPI_CFG1 0x08 8162306a36Sopenharmony_ci#define STM32H7_SPI_CFG2 0x0C 8262306a36Sopenharmony_ci#define STM32H7_SPI_IER 0x10 8362306a36Sopenharmony_ci#define STM32H7_SPI_SR 0x14 8462306a36Sopenharmony_ci#define STM32H7_SPI_IFCR 0x18 8562306a36Sopenharmony_ci#define STM32H7_SPI_TXDR 0x20 8662306a36Sopenharmony_ci#define STM32H7_SPI_RXDR 0x30 8762306a36Sopenharmony_ci#define STM32H7_SPI_I2SCFGR 0x50 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* STM32H7_SPI_CR1 bit fields */ 9062306a36Sopenharmony_ci#define STM32H7_SPI_CR1_SPE BIT(0) 9162306a36Sopenharmony_ci#define STM32H7_SPI_CR1_MASRX BIT(8) 9262306a36Sopenharmony_ci#define STM32H7_SPI_CR1_CSTART BIT(9) 9362306a36Sopenharmony_ci#define STM32H7_SPI_CR1_CSUSP BIT(10) 9462306a36Sopenharmony_ci#define STM32H7_SPI_CR1_HDDIR BIT(11) 9562306a36Sopenharmony_ci#define STM32H7_SPI_CR1_SSI BIT(12) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* STM32H7_SPI_CR2 bit fields */ 9862306a36Sopenharmony_ci#define STM32H7_SPI_CR2_TSIZE GENMASK(15, 0) 9962306a36Sopenharmony_ci#define STM32H7_SPI_TSIZE_MAX GENMASK(15, 0) 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* STM32H7_SPI_CFG1 bit fields */ 10262306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_DSIZE GENMASK(4, 0) 10362306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_FTHLV GENMASK(8, 5) 10462306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_RXDMAEN BIT(14) 10562306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_TXDMAEN BIT(15) 10662306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_MBR GENMASK(30, 28) 10762306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_MBR_SHIFT 28 10862306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_MBR_MIN 0 10962306a36Sopenharmony_ci#define STM32H7_SPI_CFG1_MBR_MAX (GENMASK(30, 28) >> 28) 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* STM32H7_SPI_CFG2 bit fields */ 11262306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_MIDI GENMASK(7, 4) 11362306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_COMM GENMASK(18, 17) 11462306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_SP GENMASK(21, 19) 11562306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_MASTER BIT(22) 11662306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_LSBFRST BIT(23) 11762306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_CPHA BIT(24) 11862306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_CPOL BIT(25) 11962306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_SSM BIT(26) 12062306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_SSIOP BIT(28) 12162306a36Sopenharmony_ci#define STM32H7_SPI_CFG2_AFCNTR BIT(31) 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* STM32H7_SPI_IER bit fields */ 12462306a36Sopenharmony_ci#define STM32H7_SPI_IER_RXPIE BIT(0) 12562306a36Sopenharmony_ci#define STM32H7_SPI_IER_TXPIE BIT(1) 12662306a36Sopenharmony_ci#define STM32H7_SPI_IER_DXPIE BIT(2) 12762306a36Sopenharmony_ci#define STM32H7_SPI_IER_EOTIE BIT(3) 12862306a36Sopenharmony_ci#define STM32H7_SPI_IER_TXTFIE BIT(4) 12962306a36Sopenharmony_ci#define STM32H7_SPI_IER_OVRIE BIT(6) 13062306a36Sopenharmony_ci#define STM32H7_SPI_IER_MODFIE BIT(9) 13162306a36Sopenharmony_ci#define STM32H7_SPI_IER_ALL GENMASK(10, 0) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* STM32H7_SPI_SR bit fields */ 13462306a36Sopenharmony_ci#define STM32H7_SPI_SR_RXP BIT(0) 13562306a36Sopenharmony_ci#define STM32H7_SPI_SR_TXP BIT(1) 13662306a36Sopenharmony_ci#define STM32H7_SPI_SR_EOT BIT(3) 13762306a36Sopenharmony_ci#define STM32H7_SPI_SR_OVR BIT(6) 13862306a36Sopenharmony_ci#define STM32H7_SPI_SR_MODF BIT(9) 13962306a36Sopenharmony_ci#define STM32H7_SPI_SR_SUSP BIT(11) 14062306a36Sopenharmony_ci#define STM32H7_SPI_SR_RXPLVL GENMASK(14, 13) 14162306a36Sopenharmony_ci#define STM32H7_SPI_SR_RXWNE BIT(15) 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* STM32H7_SPI_IFCR bit fields */ 14462306a36Sopenharmony_ci#define STM32H7_SPI_IFCR_ALL GENMASK(11, 3) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* STM32H7_SPI_I2SCFGR bit fields */ 14762306a36Sopenharmony_ci#define STM32H7_SPI_I2SCFGR_I2SMOD BIT(0) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* STM32H7 SPI Master Baud Rate min/max divisor */ 15062306a36Sopenharmony_ci#define STM32H7_SPI_MBR_DIV_MIN (2 << STM32H7_SPI_CFG1_MBR_MIN) 15162306a36Sopenharmony_ci#define STM32H7_SPI_MBR_DIV_MAX (2 << STM32H7_SPI_CFG1_MBR_MAX) 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* STM32H7 SPI Communication mode */ 15462306a36Sopenharmony_ci#define STM32H7_SPI_FULL_DUPLEX 0 15562306a36Sopenharmony_ci#define STM32H7_SPI_SIMPLEX_TX 1 15662306a36Sopenharmony_ci#define STM32H7_SPI_SIMPLEX_RX 2 15762306a36Sopenharmony_ci#define STM32H7_SPI_HALF_DUPLEX 3 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/* SPI Communication type */ 16062306a36Sopenharmony_ci#define SPI_FULL_DUPLEX 0 16162306a36Sopenharmony_ci#define SPI_SIMPLEX_TX 1 16262306a36Sopenharmony_ci#define SPI_SIMPLEX_RX 2 16362306a36Sopenharmony_ci#define SPI_3WIRE_TX 3 16462306a36Sopenharmony_ci#define SPI_3WIRE_RX 4 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#define STM32_SPI_AUTOSUSPEND_DELAY 1 /* 1 ms */ 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/* 16962306a36Sopenharmony_ci * use PIO for small transfers, avoiding DMA setup/teardown overhead for drivers 17062306a36Sopenharmony_ci * without fifo buffers. 17162306a36Sopenharmony_ci */ 17262306a36Sopenharmony_ci#define SPI_DMA_MIN_BYTES 16 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci/* STM32 SPI driver helpers */ 17562306a36Sopenharmony_ci#define STM32_SPI_MASTER_MODE(stm32_spi) (!(stm32_spi)->device_mode) 17662306a36Sopenharmony_ci#define STM32_SPI_DEVICE_MODE(stm32_spi) ((stm32_spi)->device_mode) 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci/** 17962306a36Sopenharmony_ci * struct stm32_spi_reg - stm32 SPI register & bitfield desc 18062306a36Sopenharmony_ci * @reg: register offset 18162306a36Sopenharmony_ci * @mask: bitfield mask 18262306a36Sopenharmony_ci * @shift: left shift 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_cistruct stm32_spi_reg { 18562306a36Sopenharmony_ci int reg; 18662306a36Sopenharmony_ci int mask; 18762306a36Sopenharmony_ci int shift; 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/** 19162306a36Sopenharmony_ci * struct stm32_spi_regspec - stm32 registers definition, compatible dependent data 19262306a36Sopenharmony_ci * @en: enable register and SPI enable bit 19362306a36Sopenharmony_ci * @dma_rx_en: SPI DMA RX enable register end SPI DMA RX enable bit 19462306a36Sopenharmony_ci * @dma_tx_en: SPI DMA TX enable register end SPI DMA TX enable bit 19562306a36Sopenharmony_ci * @cpol: clock polarity register and polarity bit 19662306a36Sopenharmony_ci * @cpha: clock phase register and phase bit 19762306a36Sopenharmony_ci * @lsb_first: LSB transmitted first register and bit 19862306a36Sopenharmony_ci * @cs_high: chips select active value 19962306a36Sopenharmony_ci * @br: baud rate register and bitfields 20062306a36Sopenharmony_ci * @rx: SPI RX data register 20162306a36Sopenharmony_ci * @tx: SPI TX data register 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_cistruct stm32_spi_regspec { 20462306a36Sopenharmony_ci const struct stm32_spi_reg en; 20562306a36Sopenharmony_ci const struct stm32_spi_reg dma_rx_en; 20662306a36Sopenharmony_ci const struct stm32_spi_reg dma_tx_en; 20762306a36Sopenharmony_ci const struct stm32_spi_reg cpol; 20862306a36Sopenharmony_ci const struct stm32_spi_reg cpha; 20962306a36Sopenharmony_ci const struct stm32_spi_reg lsb_first; 21062306a36Sopenharmony_ci const struct stm32_spi_reg cs_high; 21162306a36Sopenharmony_ci const struct stm32_spi_reg br; 21262306a36Sopenharmony_ci const struct stm32_spi_reg rx; 21362306a36Sopenharmony_ci const struct stm32_spi_reg tx; 21462306a36Sopenharmony_ci}; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistruct stm32_spi; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * struct stm32_spi_cfg - stm32 compatible configuration data 22062306a36Sopenharmony_ci * @regs: registers descriptions 22162306a36Sopenharmony_ci * @get_fifo_size: routine to get fifo size 22262306a36Sopenharmony_ci * @get_bpw_mask: routine to get bits per word mask 22362306a36Sopenharmony_ci * @disable: routine to disable controller 22462306a36Sopenharmony_ci * @config: routine to configure controller as SPI Master 22562306a36Sopenharmony_ci * @set_bpw: routine to configure registers to for bits per word 22662306a36Sopenharmony_ci * @set_mode: routine to configure registers to desired mode 22762306a36Sopenharmony_ci * @set_data_idleness: optional routine to configure registers to desired idle 22862306a36Sopenharmony_ci * time between frames (if driver has this functionality) 22962306a36Sopenharmony_ci * @set_number_of_data: optional routine to configure registers to desired 23062306a36Sopenharmony_ci * number of data (if driver has this functionality) 23162306a36Sopenharmony_ci * @transfer_one_dma_start: routine to start transfer a single spi_transfer 23262306a36Sopenharmony_ci * using DMA 23362306a36Sopenharmony_ci * @dma_rx_cb: routine to call after DMA RX channel operation is complete 23462306a36Sopenharmony_ci * @dma_tx_cb: routine to call after DMA TX channel operation is complete 23562306a36Sopenharmony_ci * @transfer_one_irq: routine to configure interrupts for driver 23662306a36Sopenharmony_ci * @irq_handler_event: Interrupt handler for SPI controller events 23762306a36Sopenharmony_ci * @irq_handler_thread: thread of interrupt handler for SPI controller 23862306a36Sopenharmony_ci * @baud_rate_div_min: minimum baud rate divisor 23962306a36Sopenharmony_ci * @baud_rate_div_max: maximum baud rate divisor 24062306a36Sopenharmony_ci * @has_fifo: boolean to know if fifo is used for driver 24162306a36Sopenharmony_ci * @has_device_mode: is this compatible capable to switch on device mode 24262306a36Sopenharmony_ci * @flags: compatible specific SPI controller flags used at registration time 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_cistruct stm32_spi_cfg { 24562306a36Sopenharmony_ci const struct stm32_spi_regspec *regs; 24662306a36Sopenharmony_ci int (*get_fifo_size)(struct stm32_spi *spi); 24762306a36Sopenharmony_ci int (*get_bpw_mask)(struct stm32_spi *spi); 24862306a36Sopenharmony_ci void (*disable)(struct stm32_spi *spi); 24962306a36Sopenharmony_ci int (*config)(struct stm32_spi *spi); 25062306a36Sopenharmony_ci void (*set_bpw)(struct stm32_spi *spi); 25162306a36Sopenharmony_ci int (*set_mode)(struct stm32_spi *spi, unsigned int comm_type); 25262306a36Sopenharmony_ci void (*set_data_idleness)(struct stm32_spi *spi, u32 length); 25362306a36Sopenharmony_ci int (*set_number_of_data)(struct stm32_spi *spi, u32 length); 25462306a36Sopenharmony_ci void (*transfer_one_dma_start)(struct stm32_spi *spi); 25562306a36Sopenharmony_ci void (*dma_rx_cb)(void *data); 25662306a36Sopenharmony_ci void (*dma_tx_cb)(void *data); 25762306a36Sopenharmony_ci int (*transfer_one_irq)(struct stm32_spi *spi); 25862306a36Sopenharmony_ci irqreturn_t (*irq_handler_event)(int irq, void *dev_id); 25962306a36Sopenharmony_ci irqreturn_t (*irq_handler_thread)(int irq, void *dev_id); 26062306a36Sopenharmony_ci unsigned int baud_rate_div_min; 26162306a36Sopenharmony_ci unsigned int baud_rate_div_max; 26262306a36Sopenharmony_ci bool has_fifo; 26362306a36Sopenharmony_ci bool has_device_mode; 26462306a36Sopenharmony_ci u16 flags; 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/** 26862306a36Sopenharmony_ci * struct stm32_spi - private data of the SPI controller 26962306a36Sopenharmony_ci * @dev: driver model representation of the controller 27062306a36Sopenharmony_ci * @ctrl: controller interface 27162306a36Sopenharmony_ci * @cfg: compatible configuration data 27262306a36Sopenharmony_ci * @base: virtual memory area 27362306a36Sopenharmony_ci * @clk: hw kernel clock feeding the SPI clock generator 27462306a36Sopenharmony_ci * @clk_rate: rate of the hw kernel clock feeding the SPI clock generator 27562306a36Sopenharmony_ci * @lock: prevent I/O concurrent access 27662306a36Sopenharmony_ci * @irq: SPI controller interrupt line 27762306a36Sopenharmony_ci * @fifo_size: size of the embedded fifo in bytes 27862306a36Sopenharmony_ci * @cur_midi: master inter-data idleness in ns 27962306a36Sopenharmony_ci * @cur_speed: speed configured in Hz 28062306a36Sopenharmony_ci * @cur_half_period: time of a half bit in us 28162306a36Sopenharmony_ci * @cur_bpw: number of bits in a single SPI data frame 28262306a36Sopenharmony_ci * @cur_fthlv: fifo threshold level (data frames in a single data packet) 28362306a36Sopenharmony_ci * @cur_comm: SPI communication mode 28462306a36Sopenharmony_ci * @cur_xferlen: current transfer length in bytes 28562306a36Sopenharmony_ci * @cur_usedma: boolean to know if dma is used in current transfer 28662306a36Sopenharmony_ci * @tx_buf: data to be written, or NULL 28762306a36Sopenharmony_ci * @rx_buf: data to be read, or NULL 28862306a36Sopenharmony_ci * @tx_len: number of data to be written in bytes 28962306a36Sopenharmony_ci * @rx_len: number of data to be read in bytes 29062306a36Sopenharmony_ci * @dma_tx: dma channel for TX transfer 29162306a36Sopenharmony_ci * @dma_rx: dma channel for RX transfer 29262306a36Sopenharmony_ci * @phys_addr: SPI registers physical base address 29362306a36Sopenharmony_ci * @device_mode: the controller is configured as SPI device 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_cistruct stm32_spi { 29662306a36Sopenharmony_ci struct device *dev; 29762306a36Sopenharmony_ci struct spi_controller *ctrl; 29862306a36Sopenharmony_ci const struct stm32_spi_cfg *cfg; 29962306a36Sopenharmony_ci void __iomem *base; 30062306a36Sopenharmony_ci struct clk *clk; 30162306a36Sopenharmony_ci u32 clk_rate; 30262306a36Sopenharmony_ci spinlock_t lock; /* prevent I/O concurrent access */ 30362306a36Sopenharmony_ci int irq; 30462306a36Sopenharmony_ci unsigned int fifo_size; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci unsigned int cur_midi; 30762306a36Sopenharmony_ci unsigned int cur_speed; 30862306a36Sopenharmony_ci unsigned int cur_half_period; 30962306a36Sopenharmony_ci unsigned int cur_bpw; 31062306a36Sopenharmony_ci unsigned int cur_fthlv; 31162306a36Sopenharmony_ci unsigned int cur_comm; 31262306a36Sopenharmony_ci unsigned int cur_xferlen; 31362306a36Sopenharmony_ci bool cur_usedma; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci const void *tx_buf; 31662306a36Sopenharmony_ci void *rx_buf; 31762306a36Sopenharmony_ci int tx_len; 31862306a36Sopenharmony_ci int rx_len; 31962306a36Sopenharmony_ci struct dma_chan *dma_tx; 32062306a36Sopenharmony_ci struct dma_chan *dma_rx; 32162306a36Sopenharmony_ci dma_addr_t phys_addr; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci bool device_mode; 32462306a36Sopenharmony_ci}; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic const struct stm32_spi_regspec stm32f4_spi_regspec = { 32762306a36Sopenharmony_ci .en = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE }, 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci .dma_rx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_RXDMAEN }, 33062306a36Sopenharmony_ci .dma_tx_en = { STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN }, 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci .cpol = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPOL }, 33362306a36Sopenharmony_ci .cpha = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_CPHA }, 33462306a36Sopenharmony_ci .lsb_first = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_LSBFRST }, 33562306a36Sopenharmony_ci .cs_high = {}, 33662306a36Sopenharmony_ci .br = { STM32F4_SPI_CR1, STM32F4_SPI_CR1_BR, STM32F4_SPI_CR1_BR_SHIFT }, 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci .rx = { STM32F4_SPI_DR }, 33962306a36Sopenharmony_ci .tx = { STM32F4_SPI_DR }, 34062306a36Sopenharmony_ci}; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic const struct stm32_spi_regspec stm32h7_spi_regspec = { 34362306a36Sopenharmony_ci /* SPI data transfer is enabled but spi_ker_ck is idle. 34462306a36Sopenharmony_ci * CFG1 and CFG2 registers are write protected when SPE is enabled. 34562306a36Sopenharmony_ci */ 34662306a36Sopenharmony_ci .en = { STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE }, 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci .dma_rx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_RXDMAEN }, 34962306a36Sopenharmony_ci .dma_tx_en = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN }, 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci .cpol = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPOL }, 35262306a36Sopenharmony_ci .cpha = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_CPHA }, 35362306a36Sopenharmony_ci .lsb_first = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_LSBFRST }, 35462306a36Sopenharmony_ci .cs_high = { STM32H7_SPI_CFG2, STM32H7_SPI_CFG2_SSIOP }, 35562306a36Sopenharmony_ci .br = { STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_MBR, 35662306a36Sopenharmony_ci STM32H7_SPI_CFG1_MBR_SHIFT }, 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci .rx = { STM32H7_SPI_RXDR }, 35962306a36Sopenharmony_ci .tx = { STM32H7_SPI_TXDR }, 36062306a36Sopenharmony_ci}; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic inline void stm32_spi_set_bits(struct stm32_spi *spi, 36362306a36Sopenharmony_ci u32 offset, u32 bits) 36462306a36Sopenharmony_ci{ 36562306a36Sopenharmony_ci writel_relaxed(readl_relaxed(spi->base + offset) | bits, 36662306a36Sopenharmony_ci spi->base + offset); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic inline void stm32_spi_clr_bits(struct stm32_spi *spi, 37062306a36Sopenharmony_ci u32 offset, u32 bits) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci writel_relaxed(readl_relaxed(spi->base + offset) & ~bits, 37362306a36Sopenharmony_ci spi->base + offset); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/** 37762306a36Sopenharmony_ci * stm32h7_spi_get_fifo_size - Return fifo size 37862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 37962306a36Sopenharmony_ci */ 38062306a36Sopenharmony_cistatic int stm32h7_spi_get_fifo_size(struct stm32_spi *spi) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci unsigned long flags; 38362306a36Sopenharmony_ci u32 count = 0; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci while (readl_relaxed(spi->base + STM32H7_SPI_SR) & STM32H7_SPI_SR_TXP) 39062306a36Sopenharmony_ci writeb_relaxed(++count, spi->base + STM32H7_SPI_TXDR); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci dev_dbg(spi->dev, "%d x 8-bit fifo size\n", count); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return count; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci/** 40262306a36Sopenharmony_ci * stm32f4_spi_get_bpw_mask - Return bits per word mask 40362306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_cistatic int stm32f4_spi_get_bpw_mask(struct stm32_spi *spi) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci dev_dbg(spi->dev, "8-bit or 16-bit data frame supported\n"); 40862306a36Sopenharmony_ci return SPI_BPW_MASK(8) | SPI_BPW_MASK(16); 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci/** 41262306a36Sopenharmony_ci * stm32h7_spi_get_bpw_mask - Return bits per word mask 41362306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 41462306a36Sopenharmony_ci */ 41562306a36Sopenharmony_cistatic int stm32h7_spi_get_bpw_mask(struct stm32_spi *spi) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci unsigned long flags; 41862306a36Sopenharmony_ci u32 cfg1, max_bpw; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci /* 42362306a36Sopenharmony_ci * The most significant bit at DSIZE bit field is reserved when the 42462306a36Sopenharmony_ci * maximum data size of periperal instances is limited to 16-bit 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_DSIZE); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci cfg1 = readl_relaxed(spi->base + STM32H7_SPI_CFG1); 42962306a36Sopenharmony_ci max_bpw = FIELD_GET(STM32H7_SPI_CFG1_DSIZE, cfg1) + 1; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci dev_dbg(spi->dev, "%d-bit maximum data frame\n", max_bpw); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return SPI_BPW_RANGE_MASK(4, max_bpw); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci/** 43962306a36Sopenharmony_ci * stm32_spi_prepare_mbr - Determine baud rate divisor value 44062306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 44162306a36Sopenharmony_ci * @speed_hz: requested speed 44262306a36Sopenharmony_ci * @min_div: minimum baud rate divisor 44362306a36Sopenharmony_ci * @max_div: maximum baud rate divisor 44462306a36Sopenharmony_ci * 44562306a36Sopenharmony_ci * Return baud rate divisor value in case of success or -EINVAL 44662306a36Sopenharmony_ci */ 44762306a36Sopenharmony_cistatic int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz, 44862306a36Sopenharmony_ci u32 min_div, u32 max_div) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci u32 div, mbrdiv; 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* Ensure spi->clk_rate is even */ 45362306a36Sopenharmony_ci div = DIV_ROUND_CLOSEST(spi->clk_rate & ~0x1, speed_hz); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* 45662306a36Sopenharmony_ci * SPI framework set xfer->speed_hz to ctrl->max_speed_hz if 45762306a36Sopenharmony_ci * xfer->speed_hz is greater than ctrl->max_speed_hz, and it returns 45862306a36Sopenharmony_ci * an error when xfer->speed_hz is lower than ctrl->min_speed_hz, so 45962306a36Sopenharmony_ci * no need to check it there. 46062306a36Sopenharmony_ci * However, we need to ensure the following calculations. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ci if ((div < min_div) || (div > max_div)) 46362306a36Sopenharmony_ci return -EINVAL; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* Determine the first power of 2 greater than or equal to div */ 46662306a36Sopenharmony_ci if (div & (div - 1)) 46762306a36Sopenharmony_ci mbrdiv = fls(div); 46862306a36Sopenharmony_ci else 46962306a36Sopenharmony_ci mbrdiv = fls(div) - 1; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci spi->cur_speed = spi->clk_rate / (1 << mbrdiv); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci spi->cur_half_period = DIV_ROUND_CLOSEST(USEC_PER_SEC, 2 * spi->cur_speed); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci return mbrdiv - 1; 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci/** 47962306a36Sopenharmony_ci * stm32h7_spi_prepare_fthlv - Determine FIFO threshold level 48062306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 48162306a36Sopenharmony_ci * @xfer_len: length of the message to be transferred 48262306a36Sopenharmony_ci */ 48362306a36Sopenharmony_cistatic u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci u32 packet, bpw; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* data packet should not exceed 1/2 of fifo space */ 48862306a36Sopenharmony_ci packet = clamp(xfer_len, 1U, spi->fifo_size / 2); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* align packet size with data registers access */ 49162306a36Sopenharmony_ci bpw = DIV_ROUND_UP(spi->cur_bpw, 8); 49262306a36Sopenharmony_ci return DIV_ROUND_UP(packet, bpw); 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/** 49662306a36Sopenharmony_ci * stm32f4_spi_write_tx - Write bytes to Transmit Data Register 49762306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * Read from tx_buf depends on remaining bytes to avoid to read beyond 50062306a36Sopenharmony_ci * tx_buf end. 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_cistatic void stm32f4_spi_write_tx(struct stm32_spi *spi) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci if ((spi->tx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) & 50562306a36Sopenharmony_ci STM32F4_SPI_SR_TXE)) { 50662306a36Sopenharmony_ci u32 offs = spi->cur_xferlen - spi->tx_len; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (spi->cur_bpw == 16) { 50962306a36Sopenharmony_ci const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci writew_relaxed(*tx_buf16, spi->base + STM32F4_SPI_DR); 51262306a36Sopenharmony_ci spi->tx_len -= sizeof(u16); 51362306a36Sopenharmony_ci } else { 51462306a36Sopenharmony_ci const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci writeb_relaxed(*tx_buf8, spi->base + STM32F4_SPI_DR); 51762306a36Sopenharmony_ci spi->tx_len -= sizeof(u8); 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len); 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci/** 52562306a36Sopenharmony_ci * stm32h7_spi_write_txfifo - Write bytes in Transmit Data Register 52662306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 52762306a36Sopenharmony_ci * 52862306a36Sopenharmony_ci * Read from tx_buf depends on remaining bytes to avoid to read beyond 52962306a36Sopenharmony_ci * tx_buf end. 53062306a36Sopenharmony_ci */ 53162306a36Sopenharmony_cistatic void stm32h7_spi_write_txfifo(struct stm32_spi *spi) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci while ((spi->tx_len > 0) && 53462306a36Sopenharmony_ci (readl_relaxed(spi->base + STM32H7_SPI_SR) & 53562306a36Sopenharmony_ci STM32H7_SPI_SR_TXP)) { 53662306a36Sopenharmony_ci u32 offs = spi->cur_xferlen - spi->tx_len; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci if (spi->tx_len >= sizeof(u32)) { 53962306a36Sopenharmony_ci const u32 *tx_buf32 = (const u32 *)(spi->tx_buf + offs); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci writel_relaxed(*tx_buf32, spi->base + STM32H7_SPI_TXDR); 54262306a36Sopenharmony_ci spi->tx_len -= sizeof(u32); 54362306a36Sopenharmony_ci } else if (spi->tx_len >= sizeof(u16)) { 54462306a36Sopenharmony_ci const u16 *tx_buf16 = (const u16 *)(spi->tx_buf + offs); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci writew_relaxed(*tx_buf16, spi->base + STM32H7_SPI_TXDR); 54762306a36Sopenharmony_ci spi->tx_len -= sizeof(u16); 54862306a36Sopenharmony_ci } else { 54962306a36Sopenharmony_ci const u8 *tx_buf8 = (const u8 *)(spi->tx_buf + offs); 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci writeb_relaxed(*tx_buf8, spi->base + STM32H7_SPI_TXDR); 55262306a36Sopenharmony_ci spi->tx_len -= sizeof(u8); 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->tx_len); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci/** 56062306a36Sopenharmony_ci * stm32f4_spi_read_rx - Read bytes from Receive Data Register 56162306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 56262306a36Sopenharmony_ci * 56362306a36Sopenharmony_ci * Write in rx_buf depends on remaining bytes to avoid to write beyond 56462306a36Sopenharmony_ci * rx_buf end. 56562306a36Sopenharmony_ci */ 56662306a36Sopenharmony_cistatic void stm32f4_spi_read_rx(struct stm32_spi *spi) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci if ((spi->rx_len > 0) && (readl_relaxed(spi->base + STM32F4_SPI_SR) & 56962306a36Sopenharmony_ci STM32F4_SPI_SR_RXNE)) { 57062306a36Sopenharmony_ci u32 offs = spi->cur_xferlen - spi->rx_len; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (spi->cur_bpw == 16) { 57362306a36Sopenharmony_ci u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci *rx_buf16 = readw_relaxed(spi->base + STM32F4_SPI_DR); 57662306a36Sopenharmony_ci spi->rx_len -= sizeof(u16); 57762306a36Sopenharmony_ci } else { 57862306a36Sopenharmony_ci u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs); 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci *rx_buf8 = readb_relaxed(spi->base + STM32F4_SPI_DR); 58162306a36Sopenharmony_ci spi->rx_len -= sizeof(u8); 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci dev_dbg(spi->dev, "%s: %d bytes left\n", __func__, spi->rx_len); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/** 58962306a36Sopenharmony_ci * stm32h7_spi_read_rxfifo - Read bytes in Receive Data Register 59062306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 59162306a36Sopenharmony_ci * 59262306a36Sopenharmony_ci * Write in rx_buf depends on remaining bytes to avoid to write beyond 59362306a36Sopenharmony_ci * rx_buf end. 59462306a36Sopenharmony_ci */ 59562306a36Sopenharmony_cistatic void stm32h7_spi_read_rxfifo(struct stm32_spi *spi) 59662306a36Sopenharmony_ci{ 59762306a36Sopenharmony_ci u32 sr = readl_relaxed(spi->base + STM32H7_SPI_SR); 59862306a36Sopenharmony_ci u32 rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci while ((spi->rx_len > 0) && 60162306a36Sopenharmony_ci ((sr & STM32H7_SPI_SR_RXP) || 60262306a36Sopenharmony_ci ((sr & STM32H7_SPI_SR_EOT) && 60362306a36Sopenharmony_ci ((sr & STM32H7_SPI_SR_RXWNE) || (rxplvl > 0))))) { 60462306a36Sopenharmony_ci u32 offs = spi->cur_xferlen - spi->rx_len; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if ((spi->rx_len >= sizeof(u32)) || 60762306a36Sopenharmony_ci (sr & STM32H7_SPI_SR_RXWNE)) { 60862306a36Sopenharmony_ci u32 *rx_buf32 = (u32 *)(spi->rx_buf + offs); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci *rx_buf32 = readl_relaxed(spi->base + STM32H7_SPI_RXDR); 61162306a36Sopenharmony_ci spi->rx_len -= sizeof(u32); 61262306a36Sopenharmony_ci } else if ((spi->rx_len >= sizeof(u16)) || 61362306a36Sopenharmony_ci (!(sr & STM32H7_SPI_SR_RXWNE) && 61462306a36Sopenharmony_ci (rxplvl >= 2 || spi->cur_bpw > 8))) { 61562306a36Sopenharmony_ci u16 *rx_buf16 = (u16 *)(spi->rx_buf + offs); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci *rx_buf16 = readw_relaxed(spi->base + STM32H7_SPI_RXDR); 61862306a36Sopenharmony_ci spi->rx_len -= sizeof(u16); 61962306a36Sopenharmony_ci } else { 62062306a36Sopenharmony_ci u8 *rx_buf8 = (u8 *)(spi->rx_buf + offs); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci *rx_buf8 = readb_relaxed(spi->base + STM32H7_SPI_RXDR); 62362306a36Sopenharmony_ci spi->rx_len -= sizeof(u8); 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci sr = readl_relaxed(spi->base + STM32H7_SPI_SR); 62762306a36Sopenharmony_ci rxplvl = FIELD_GET(STM32H7_SPI_SR_RXPLVL, sr); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci dev_dbg(spi->dev, "%s: %d bytes left (sr=%08x)\n", 63162306a36Sopenharmony_ci __func__, spi->rx_len, sr); 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/** 63562306a36Sopenharmony_ci * stm32_spi_enable - Enable SPI controller 63662306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 63762306a36Sopenharmony_ci */ 63862306a36Sopenharmony_cistatic void stm32_spi_enable(struct stm32_spi *spi) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci dev_dbg(spi->dev, "enable controller\n"); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci stm32_spi_set_bits(spi, spi->cfg->regs->en.reg, 64362306a36Sopenharmony_ci spi->cfg->regs->en.mask); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci/** 64762306a36Sopenharmony_ci * stm32f4_spi_disable - Disable SPI controller 64862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 64962306a36Sopenharmony_ci */ 65062306a36Sopenharmony_cistatic void stm32f4_spi_disable(struct stm32_spi *spi) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci unsigned long flags; 65362306a36Sopenharmony_ci u32 sr; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci dev_dbg(spi->dev, "disable controller\n"); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci if (!(readl_relaxed(spi->base + STM32F4_SPI_CR1) & 66062306a36Sopenharmony_ci STM32F4_SPI_CR1_SPE)) { 66162306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 66262306a36Sopenharmony_ci return; 66362306a36Sopenharmony_ci } 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* Disable interrupts */ 66662306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXEIE | 66762306a36Sopenharmony_ci STM32F4_SPI_CR2_RXNEIE | 66862306a36Sopenharmony_ci STM32F4_SPI_CR2_ERRIE); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci /* Wait until BSY = 0 */ 67162306a36Sopenharmony_ci if (readl_relaxed_poll_timeout_atomic(spi->base + STM32F4_SPI_SR, 67262306a36Sopenharmony_ci sr, !(sr & STM32F4_SPI_SR_BSY), 67362306a36Sopenharmony_ci 10, 100000) < 0) { 67462306a36Sopenharmony_ci dev_warn(spi->dev, "disabling condition timeout\n"); 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (spi->cur_usedma && spi->dma_tx) 67862306a36Sopenharmony_ci dmaengine_terminate_async(spi->dma_tx); 67962306a36Sopenharmony_ci if (spi->cur_usedma && spi->dma_rx) 68062306a36Sopenharmony_ci dmaengine_terminate_async(spi->dma_rx); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SPE); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_TXDMAEN | 68562306a36Sopenharmony_ci STM32F4_SPI_CR2_RXDMAEN); 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* Sequence to clear OVR flag */ 68862306a36Sopenharmony_ci readl_relaxed(spi->base + STM32F4_SPI_DR); 68962306a36Sopenharmony_ci readl_relaxed(spi->base + STM32F4_SPI_SR); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci/** 69562306a36Sopenharmony_ci * stm32h7_spi_disable - Disable SPI controller 69662306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 69762306a36Sopenharmony_ci * 69862306a36Sopenharmony_ci * RX-Fifo is flushed when SPI controller is disabled. 69962306a36Sopenharmony_ci */ 70062306a36Sopenharmony_cistatic void stm32h7_spi_disable(struct stm32_spi *spi) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci unsigned long flags; 70362306a36Sopenharmony_ci u32 cr1; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci dev_dbg(spi->dev, "disable controller\n"); 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci cr1 = readl_relaxed(spi->base + STM32H7_SPI_CR1); 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (!(cr1 & STM32H7_SPI_CR1_SPE)) { 71262306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 71362306a36Sopenharmony_ci return; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* Add a delay to make sure that transmission is ended. */ 71762306a36Sopenharmony_ci if (spi->cur_half_period) 71862306a36Sopenharmony_ci udelay(spi->cur_half_period); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci if (spi->cur_usedma && spi->dma_tx) 72162306a36Sopenharmony_ci dmaengine_terminate_async(spi->dma_tx); 72262306a36Sopenharmony_ci if (spi->cur_usedma && spi->dma_rx) 72362306a36Sopenharmony_ci dmaengine_terminate_async(spi->dma_rx); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_SPE); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32H7_SPI_CFG1, STM32H7_SPI_CFG1_TXDMAEN | 72862306a36Sopenharmony_ci STM32H7_SPI_CFG1_RXDMAEN); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci /* Disable interrupts and clear status flags */ 73162306a36Sopenharmony_ci writel_relaxed(0, spi->base + STM32H7_SPI_IER); 73262306a36Sopenharmony_ci writel_relaxed(STM32H7_SPI_IFCR_ALL, spi->base + STM32H7_SPI_IFCR); 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 73562306a36Sopenharmony_ci} 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci/** 73862306a36Sopenharmony_ci * stm32_spi_can_dma - Determine if the transfer is eligible for DMA use 73962306a36Sopenharmony_ci * @ctrl: controller interface 74062306a36Sopenharmony_ci * @spi_dev: pointer to the spi device 74162306a36Sopenharmony_ci * @transfer: pointer to spi transfer 74262306a36Sopenharmony_ci * 74362306a36Sopenharmony_ci * If driver has fifo and the current transfer size is greater than fifo size, 74462306a36Sopenharmony_ci * use DMA. Otherwise use DMA for transfer longer than defined DMA min bytes. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_cistatic bool stm32_spi_can_dma(struct spi_controller *ctrl, 74762306a36Sopenharmony_ci struct spi_device *spi_dev, 74862306a36Sopenharmony_ci struct spi_transfer *transfer) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci unsigned int dma_size; 75162306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci if (spi->cfg->has_fifo) 75462306a36Sopenharmony_ci dma_size = spi->fifo_size; 75562306a36Sopenharmony_ci else 75662306a36Sopenharmony_ci dma_size = SPI_DMA_MIN_BYTES; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci dev_dbg(spi->dev, "%s: %s\n", __func__, 75962306a36Sopenharmony_ci (transfer->len > dma_size) ? "true" : "false"); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return (transfer->len > dma_size); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/** 76562306a36Sopenharmony_ci * stm32f4_spi_irq_event - Interrupt handler for SPI controller events 76662306a36Sopenharmony_ci * @irq: interrupt line 76762306a36Sopenharmony_ci * @dev_id: SPI controller ctrl interface 76862306a36Sopenharmony_ci */ 76962306a36Sopenharmony_cistatic irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci struct spi_controller *ctrl = dev_id; 77262306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 77362306a36Sopenharmony_ci u32 sr, mask = 0; 77462306a36Sopenharmony_ci bool end = false; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci spin_lock(&spi->lock); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci sr = readl_relaxed(spi->base + STM32F4_SPI_SR); 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * BSY flag is not handled in interrupt but it is normal behavior when 78162306a36Sopenharmony_ci * this flag is set. 78262306a36Sopenharmony_ci */ 78362306a36Sopenharmony_ci sr &= ~STM32F4_SPI_SR_BSY; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX || 78662306a36Sopenharmony_ci spi->cur_comm == SPI_3WIRE_TX)) { 78762306a36Sopenharmony_ci /* OVR flag shouldn't be handled for TX only mode */ 78862306a36Sopenharmony_ci sr &= ~(STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE); 78962306a36Sopenharmony_ci mask |= STM32F4_SPI_SR_TXE; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->cur_comm == SPI_FULL_DUPLEX || 79362306a36Sopenharmony_ci spi->cur_comm == SPI_SIMPLEX_RX || 79462306a36Sopenharmony_ci spi->cur_comm == SPI_3WIRE_RX)) { 79562306a36Sopenharmony_ci /* TXE flag is set and is handled when RXNE flag occurs */ 79662306a36Sopenharmony_ci sr &= ~STM32F4_SPI_SR_TXE; 79762306a36Sopenharmony_ci mask |= STM32F4_SPI_SR_RXNE | STM32F4_SPI_SR_OVR; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (!(sr & mask)) { 80162306a36Sopenharmony_ci dev_dbg(spi->dev, "spurious IT (sr=0x%08x)\n", sr); 80262306a36Sopenharmony_ci spin_unlock(&spi->lock); 80362306a36Sopenharmony_ci return IRQ_NONE; 80462306a36Sopenharmony_ci } 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci if (sr & STM32F4_SPI_SR_OVR) { 80762306a36Sopenharmony_ci dev_warn(spi->dev, "Overrun: received value discarded\n"); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* Sequence to clear OVR flag */ 81062306a36Sopenharmony_ci readl_relaxed(spi->base + STM32F4_SPI_DR); 81162306a36Sopenharmony_ci readl_relaxed(spi->base + STM32F4_SPI_SR); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* 81462306a36Sopenharmony_ci * If overrun is detected, it means that something went wrong, 81562306a36Sopenharmony_ci * so stop the current transfer. Transfer can wait for next 81662306a36Sopenharmony_ci * RXNE but DR is already read and end never happens. 81762306a36Sopenharmony_ci */ 81862306a36Sopenharmony_ci end = true; 81962306a36Sopenharmony_ci goto end_irq; 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (sr & STM32F4_SPI_SR_TXE) { 82362306a36Sopenharmony_ci if (spi->tx_buf) 82462306a36Sopenharmony_ci stm32f4_spi_write_tx(spi); 82562306a36Sopenharmony_ci if (spi->tx_len == 0) 82662306a36Sopenharmony_ci end = true; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci if (sr & STM32F4_SPI_SR_RXNE) { 83062306a36Sopenharmony_ci stm32f4_spi_read_rx(spi); 83162306a36Sopenharmony_ci if (spi->rx_len == 0) 83262306a36Sopenharmony_ci end = true; 83362306a36Sopenharmony_ci else if (spi->tx_buf)/* Load data for discontinuous mode */ 83462306a36Sopenharmony_ci stm32f4_spi_write_tx(spi); 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ciend_irq: 83862306a36Sopenharmony_ci if (end) { 83962306a36Sopenharmony_ci /* Immediately disable interrupts to do not generate new one */ 84062306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR2, 84162306a36Sopenharmony_ci STM32F4_SPI_CR2_TXEIE | 84262306a36Sopenharmony_ci STM32F4_SPI_CR2_RXNEIE | 84362306a36Sopenharmony_ci STM32F4_SPI_CR2_ERRIE); 84462306a36Sopenharmony_ci spin_unlock(&spi->lock); 84562306a36Sopenharmony_ci return IRQ_WAKE_THREAD; 84662306a36Sopenharmony_ci } 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci spin_unlock(&spi->lock); 84962306a36Sopenharmony_ci return IRQ_HANDLED; 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci/** 85362306a36Sopenharmony_ci * stm32f4_spi_irq_thread - Thread of interrupt handler for SPI controller 85462306a36Sopenharmony_ci * @irq: interrupt line 85562306a36Sopenharmony_ci * @dev_id: SPI controller interface 85662306a36Sopenharmony_ci */ 85762306a36Sopenharmony_cistatic irqreturn_t stm32f4_spi_irq_thread(int irq, void *dev_id) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci struct spi_controller *ctrl = dev_id; 86062306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci spi_finalize_current_transfer(ctrl); 86362306a36Sopenharmony_ci stm32f4_spi_disable(spi); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci return IRQ_HANDLED; 86662306a36Sopenharmony_ci} 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci/** 86962306a36Sopenharmony_ci * stm32h7_spi_irq_thread - Thread of interrupt handler for SPI controller 87062306a36Sopenharmony_ci * @irq: interrupt line 87162306a36Sopenharmony_ci * @dev_id: SPI controller interface 87262306a36Sopenharmony_ci */ 87362306a36Sopenharmony_cistatic irqreturn_t stm32h7_spi_irq_thread(int irq, void *dev_id) 87462306a36Sopenharmony_ci{ 87562306a36Sopenharmony_ci struct spi_controller *ctrl = dev_id; 87662306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 87762306a36Sopenharmony_ci u32 sr, ier, mask; 87862306a36Sopenharmony_ci unsigned long flags; 87962306a36Sopenharmony_ci bool end = false; 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci sr = readl_relaxed(spi->base + STM32H7_SPI_SR); 88462306a36Sopenharmony_ci ier = readl_relaxed(spi->base + STM32H7_SPI_IER); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci mask = ier; 88762306a36Sopenharmony_ci /* 88862306a36Sopenharmony_ci * EOTIE enables irq from EOT, SUSP and TXC events. We need to set 88962306a36Sopenharmony_ci * SUSP to acknowledge it later. TXC is automatically cleared 89062306a36Sopenharmony_ci */ 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci mask |= STM32H7_SPI_SR_SUSP; 89362306a36Sopenharmony_ci /* 89462306a36Sopenharmony_ci * DXPIE is set in Full-Duplex, one IT will be raised if TXP and RXP 89562306a36Sopenharmony_ci * are set. So in case of Full-Duplex, need to poll TXP and RXP event. 89662306a36Sopenharmony_ci */ 89762306a36Sopenharmony_ci if ((spi->cur_comm == SPI_FULL_DUPLEX) && !spi->cur_usedma) 89862306a36Sopenharmony_ci mask |= STM32H7_SPI_SR_TXP | STM32H7_SPI_SR_RXP; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (!(sr & mask)) { 90162306a36Sopenharmony_ci dev_warn(spi->dev, "spurious IT (sr=0x%08x, ier=0x%08x)\n", 90262306a36Sopenharmony_ci sr, ier); 90362306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 90462306a36Sopenharmony_ci return IRQ_NONE; 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_SUSP) { 90862306a36Sopenharmony_ci static DEFINE_RATELIMIT_STATE(rs, 90962306a36Sopenharmony_ci DEFAULT_RATELIMIT_INTERVAL * 10, 91062306a36Sopenharmony_ci 1); 91162306a36Sopenharmony_ci ratelimit_set_flags(&rs, RATELIMIT_MSG_ON_RELEASE); 91262306a36Sopenharmony_ci if (__ratelimit(&rs)) 91362306a36Sopenharmony_ci dev_dbg_ratelimited(spi->dev, "Communication suspended\n"); 91462306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) 91562306a36Sopenharmony_ci stm32h7_spi_read_rxfifo(spi); 91662306a36Sopenharmony_ci /* 91762306a36Sopenharmony_ci * If communication is suspended while using DMA, it means 91862306a36Sopenharmony_ci * that something went wrong, so stop the current transfer 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci if (spi->cur_usedma) 92162306a36Sopenharmony_ci end = true; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_MODF) { 92562306a36Sopenharmony_ci dev_warn(spi->dev, "Mode fault: transfer aborted\n"); 92662306a36Sopenharmony_ci end = true; 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_OVR) { 93062306a36Sopenharmony_ci dev_err(spi->dev, "Overrun: RX data lost\n"); 93162306a36Sopenharmony_ci end = true; 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_EOT) { 93562306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) 93662306a36Sopenharmony_ci stm32h7_spi_read_rxfifo(spi); 93762306a36Sopenharmony_ci if (!spi->cur_usedma || 93862306a36Sopenharmony_ci (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX)) 93962306a36Sopenharmony_ci end = true; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_TXP) 94362306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->tx_buf && (spi->tx_len > 0))) 94462306a36Sopenharmony_ci stm32h7_spi_write_txfifo(spi); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci if (sr & STM32H7_SPI_SR_RXP) 94762306a36Sopenharmony_ci if (!spi->cur_usedma && (spi->rx_buf && (spi->rx_len > 0))) 94862306a36Sopenharmony_ci stm32h7_spi_read_rxfifo(spi); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci writel_relaxed(sr & mask, spi->base + STM32H7_SPI_IFCR); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci if (end) { 95562306a36Sopenharmony_ci stm32h7_spi_disable(spi); 95662306a36Sopenharmony_ci spi_finalize_current_transfer(ctrl); 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci return IRQ_HANDLED; 96062306a36Sopenharmony_ci} 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci/** 96362306a36Sopenharmony_ci * stm32_spi_prepare_msg - set up the controller to transfer a single message 96462306a36Sopenharmony_ci * @ctrl: controller interface 96562306a36Sopenharmony_ci * @msg: pointer to spi message 96662306a36Sopenharmony_ci */ 96762306a36Sopenharmony_cistatic int stm32_spi_prepare_msg(struct spi_controller *ctrl, 96862306a36Sopenharmony_ci struct spi_message *msg) 96962306a36Sopenharmony_ci{ 97062306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 97162306a36Sopenharmony_ci struct spi_device *spi_dev = msg->spi; 97262306a36Sopenharmony_ci struct device_node *np = spi_dev->dev.of_node; 97362306a36Sopenharmony_ci unsigned long flags; 97462306a36Sopenharmony_ci u32 clrb = 0, setb = 0; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci /* SPI slave device may need time between data frames */ 97762306a36Sopenharmony_ci spi->cur_midi = 0; 97862306a36Sopenharmony_ci if (np && !of_property_read_u32(np, "st,spi-midi-ns", &spi->cur_midi)) 97962306a36Sopenharmony_ci dev_dbg(spi->dev, "%dns inter-data idleness\n", spi->cur_midi); 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci if (spi_dev->mode & SPI_CPOL) 98262306a36Sopenharmony_ci setb |= spi->cfg->regs->cpol.mask; 98362306a36Sopenharmony_ci else 98462306a36Sopenharmony_ci clrb |= spi->cfg->regs->cpol.mask; 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci if (spi_dev->mode & SPI_CPHA) 98762306a36Sopenharmony_ci setb |= spi->cfg->regs->cpha.mask; 98862306a36Sopenharmony_ci else 98962306a36Sopenharmony_ci clrb |= spi->cfg->regs->cpha.mask; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci if (spi_dev->mode & SPI_LSB_FIRST) 99262306a36Sopenharmony_ci setb |= spi->cfg->regs->lsb_first.mask; 99362306a36Sopenharmony_ci else 99462306a36Sopenharmony_ci clrb |= spi->cfg->regs->lsb_first.mask; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (STM32_SPI_DEVICE_MODE(spi) && spi_dev->mode & SPI_CS_HIGH) 99762306a36Sopenharmony_ci setb |= spi->cfg->regs->cs_high.mask; 99862306a36Sopenharmony_ci else 99962306a36Sopenharmony_ci clrb |= spi->cfg->regs->cs_high.mask; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci dev_dbg(spi->dev, "cpol=%d cpha=%d lsb_first=%d cs_high=%d\n", 100262306a36Sopenharmony_ci !!(spi_dev->mode & SPI_CPOL), 100362306a36Sopenharmony_ci !!(spi_dev->mode & SPI_CPHA), 100462306a36Sopenharmony_ci !!(spi_dev->mode & SPI_LSB_FIRST), 100562306a36Sopenharmony_ci !!(spi_dev->mode & SPI_CS_HIGH)); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci /* On STM32H7, messages should not exceed a maximum size setted 100862306a36Sopenharmony_ci * afterward via the set_number_of_data function. In order to 100962306a36Sopenharmony_ci * ensure that, split large messages into several messages 101062306a36Sopenharmony_ci */ 101162306a36Sopenharmony_ci if (spi->cfg->set_number_of_data) { 101262306a36Sopenharmony_ci int ret; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci ret = spi_split_transfers_maxwords(ctrl, msg, 101562306a36Sopenharmony_ci STM32H7_SPI_TSIZE_MAX, 101662306a36Sopenharmony_ci GFP_KERNEL | GFP_DMA); 101762306a36Sopenharmony_ci if (ret) 101862306a36Sopenharmony_ci return ret; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* CPOL, CPHA and LSB FIRST bits have common register */ 102462306a36Sopenharmony_ci if (clrb || setb) 102562306a36Sopenharmony_ci writel_relaxed( 102662306a36Sopenharmony_ci (readl_relaxed(spi->base + spi->cfg->regs->cpol.reg) & 102762306a36Sopenharmony_ci ~clrb) | setb, 102862306a36Sopenharmony_ci spi->base + spi->cfg->regs->cpol.reg); 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci return 0; 103362306a36Sopenharmony_ci} 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci/** 103662306a36Sopenharmony_ci * stm32f4_spi_dma_tx_cb - dma callback 103762306a36Sopenharmony_ci * @data: pointer to the spi controller data structure 103862306a36Sopenharmony_ci * 103962306a36Sopenharmony_ci * DMA callback is called when the transfer is complete for DMA TX channel. 104062306a36Sopenharmony_ci */ 104162306a36Sopenharmony_cistatic void stm32f4_spi_dma_tx_cb(void *data) 104262306a36Sopenharmony_ci{ 104362306a36Sopenharmony_ci struct stm32_spi *spi = data; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { 104662306a36Sopenharmony_ci spi_finalize_current_transfer(spi->ctrl); 104762306a36Sopenharmony_ci stm32f4_spi_disable(spi); 104862306a36Sopenharmony_ci } 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci/** 105262306a36Sopenharmony_ci * stm32_spi_dma_rx_cb - dma callback 105362306a36Sopenharmony_ci * @data: pointer to the spi controller data structure 105462306a36Sopenharmony_ci * 105562306a36Sopenharmony_ci * DMA callback is called when the transfer is complete for DMA RX channel. 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_cistatic void stm32_spi_dma_rx_cb(void *data) 105862306a36Sopenharmony_ci{ 105962306a36Sopenharmony_ci struct stm32_spi *spi = data; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci spi_finalize_current_transfer(spi->ctrl); 106262306a36Sopenharmony_ci spi->cfg->disable(spi); 106362306a36Sopenharmony_ci} 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci/** 106662306a36Sopenharmony_ci * stm32_spi_dma_config - configure dma slave channel depending on current 106762306a36Sopenharmony_ci * transfer bits_per_word. 106862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 106962306a36Sopenharmony_ci * @dma_conf: pointer to the dma_slave_config structure 107062306a36Sopenharmony_ci * @dir: direction of the dma transfer 107162306a36Sopenharmony_ci */ 107262306a36Sopenharmony_cistatic void stm32_spi_dma_config(struct stm32_spi *spi, 107362306a36Sopenharmony_ci struct dma_slave_config *dma_conf, 107462306a36Sopenharmony_ci enum dma_transfer_direction dir) 107562306a36Sopenharmony_ci{ 107662306a36Sopenharmony_ci enum dma_slave_buswidth buswidth; 107762306a36Sopenharmony_ci u32 maxburst; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci if (spi->cur_bpw <= 8) 108062306a36Sopenharmony_ci buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; 108162306a36Sopenharmony_ci else if (spi->cur_bpw <= 16) 108262306a36Sopenharmony_ci buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 108362306a36Sopenharmony_ci else 108462306a36Sopenharmony_ci buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci if (spi->cfg->has_fifo) { 108762306a36Sopenharmony_ci /* Valid for DMA Half or Full Fifo threshold */ 108862306a36Sopenharmony_ci if (spi->cur_fthlv == 2) 108962306a36Sopenharmony_ci maxburst = 1; 109062306a36Sopenharmony_ci else 109162306a36Sopenharmony_ci maxburst = spi->cur_fthlv; 109262306a36Sopenharmony_ci } else { 109362306a36Sopenharmony_ci maxburst = 1; 109462306a36Sopenharmony_ci } 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci memset(dma_conf, 0, sizeof(struct dma_slave_config)); 109762306a36Sopenharmony_ci dma_conf->direction = dir; 109862306a36Sopenharmony_ci if (dma_conf->direction == DMA_DEV_TO_MEM) { /* RX */ 109962306a36Sopenharmony_ci dma_conf->src_addr = spi->phys_addr + spi->cfg->regs->rx.reg; 110062306a36Sopenharmony_ci dma_conf->src_addr_width = buswidth; 110162306a36Sopenharmony_ci dma_conf->src_maxburst = maxburst; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci dev_dbg(spi->dev, "Rx DMA config buswidth=%d, maxburst=%d\n", 110462306a36Sopenharmony_ci buswidth, maxburst); 110562306a36Sopenharmony_ci } else if (dma_conf->direction == DMA_MEM_TO_DEV) { /* TX */ 110662306a36Sopenharmony_ci dma_conf->dst_addr = spi->phys_addr + spi->cfg->regs->tx.reg; 110762306a36Sopenharmony_ci dma_conf->dst_addr_width = buswidth; 110862306a36Sopenharmony_ci dma_conf->dst_maxburst = maxburst; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci dev_dbg(spi->dev, "Tx DMA config buswidth=%d, maxburst=%d\n", 111162306a36Sopenharmony_ci buswidth, maxburst); 111262306a36Sopenharmony_ci } 111362306a36Sopenharmony_ci} 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci/** 111662306a36Sopenharmony_ci * stm32f4_spi_transfer_one_irq - transfer a single spi_transfer using 111762306a36Sopenharmony_ci * interrupts 111862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 111962306a36Sopenharmony_ci * 112062306a36Sopenharmony_ci * It must returns 0 if the transfer is finished or 1 if the transfer is still 112162306a36Sopenharmony_ci * in progress. 112262306a36Sopenharmony_ci */ 112362306a36Sopenharmony_cistatic int stm32f4_spi_transfer_one_irq(struct stm32_spi *spi) 112462306a36Sopenharmony_ci{ 112562306a36Sopenharmony_ci unsigned long flags; 112662306a36Sopenharmony_ci u32 cr2 = 0; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci /* Enable the interrupts relative to the current communication mode */ 112962306a36Sopenharmony_ci if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) { 113062306a36Sopenharmony_ci cr2 |= STM32F4_SPI_CR2_TXEIE; 113162306a36Sopenharmony_ci } else if (spi->cur_comm == SPI_FULL_DUPLEX || 113262306a36Sopenharmony_ci spi->cur_comm == SPI_SIMPLEX_RX || 113362306a36Sopenharmony_ci spi->cur_comm == SPI_3WIRE_RX) { 113462306a36Sopenharmony_ci /* In transmit-only mode, the OVR flag is set in the SR register 113562306a36Sopenharmony_ci * since the received data are never read. Therefore set OVR 113662306a36Sopenharmony_ci * interrupt only when rx buffer is available. 113762306a36Sopenharmony_ci */ 113862306a36Sopenharmony_ci cr2 |= STM32F4_SPI_CR2_RXNEIE | STM32F4_SPI_CR2_ERRIE; 113962306a36Sopenharmony_ci } else { 114062306a36Sopenharmony_ci return -EINVAL; 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR2, cr2); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci stm32_spi_enable(spi); 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /* starting data transfer when buffer is loaded */ 115062306a36Sopenharmony_ci if (spi->tx_buf) 115162306a36Sopenharmony_ci stm32f4_spi_write_tx(spi); 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci return 1; 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_ci/** 115962306a36Sopenharmony_ci * stm32h7_spi_transfer_one_irq - transfer a single spi_transfer using 116062306a36Sopenharmony_ci * interrupts 116162306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 116262306a36Sopenharmony_ci * 116362306a36Sopenharmony_ci * It must returns 0 if the transfer is finished or 1 if the transfer is still 116462306a36Sopenharmony_ci * in progress. 116562306a36Sopenharmony_ci */ 116662306a36Sopenharmony_cistatic int stm32h7_spi_transfer_one_irq(struct stm32_spi *spi) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci unsigned long flags; 116962306a36Sopenharmony_ci u32 ier = 0; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci /* Enable the interrupts relative to the current communication mode */ 117262306a36Sopenharmony_ci if (spi->tx_buf && spi->rx_buf) /* Full Duplex */ 117362306a36Sopenharmony_ci ier |= STM32H7_SPI_IER_DXPIE; 117462306a36Sopenharmony_ci else if (spi->tx_buf) /* Half-Duplex TX dir or Simplex TX */ 117562306a36Sopenharmony_ci ier |= STM32H7_SPI_IER_TXPIE; 117662306a36Sopenharmony_ci else if (spi->rx_buf) /* Half-Duplex RX dir or Simplex RX */ 117762306a36Sopenharmony_ci ier |= STM32H7_SPI_IER_RXPIE; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci /* Enable the interrupts relative to the end of transfer */ 118062306a36Sopenharmony_ci ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE | 118162306a36Sopenharmony_ci STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci stm32_spi_enable(spi); 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci /* Be sure to have data in fifo before starting data transfer */ 118862306a36Sopenharmony_ci if (spi->tx_buf) 118962306a36Sopenharmony_ci stm32h7_spi_write_txfifo(spi); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (STM32_SPI_MASTER_MODE(spi)) 119262306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci writel_relaxed(ier, spi->base + STM32H7_SPI_IER); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci return 1; 119962306a36Sopenharmony_ci} 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci/** 120262306a36Sopenharmony_ci * stm32f4_spi_transfer_one_dma_start - Set SPI driver registers to start 120362306a36Sopenharmony_ci * transfer using DMA 120462306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 120562306a36Sopenharmony_ci */ 120662306a36Sopenharmony_cistatic void stm32f4_spi_transfer_one_dma_start(struct stm32_spi *spi) 120762306a36Sopenharmony_ci{ 120862306a36Sopenharmony_ci /* In DMA mode end of transfer is handled by DMA TX or RX callback. */ 120962306a36Sopenharmony_ci if (spi->cur_comm == SPI_SIMPLEX_RX || spi->cur_comm == SPI_3WIRE_RX || 121062306a36Sopenharmony_ci spi->cur_comm == SPI_FULL_DUPLEX) { 121162306a36Sopenharmony_ci /* 121262306a36Sopenharmony_ci * In transmit-only mode, the OVR flag is set in the SR register 121362306a36Sopenharmony_ci * since the received data are never read. Therefore set OVR 121462306a36Sopenharmony_ci * interrupt only when rx buffer is available. 121562306a36Sopenharmony_ci */ 121662306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR2, STM32F4_SPI_CR2_ERRIE); 121762306a36Sopenharmony_ci } 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci stm32_spi_enable(spi); 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci/** 122362306a36Sopenharmony_ci * stm32h7_spi_transfer_one_dma_start - Set SPI driver registers to start 122462306a36Sopenharmony_ci * transfer using DMA 122562306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 122662306a36Sopenharmony_ci */ 122762306a36Sopenharmony_cistatic void stm32h7_spi_transfer_one_dma_start(struct stm32_spi *spi) 122862306a36Sopenharmony_ci{ 122962306a36Sopenharmony_ci uint32_t ier = STM32H7_SPI_IER_OVRIE | STM32H7_SPI_IER_MODFIE; 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* Enable the interrupts */ 123262306a36Sopenharmony_ci if (spi->cur_comm == SPI_SIMPLEX_TX || spi->cur_comm == SPI_3WIRE_TX) 123362306a36Sopenharmony_ci ier |= STM32H7_SPI_IER_EOTIE | STM32H7_SPI_IER_TXTFIE; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_IER, ier); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci stm32_spi_enable(spi); 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci if (STM32_SPI_MASTER_MODE(spi)) 124062306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_CSTART); 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/** 124462306a36Sopenharmony_ci * stm32_spi_transfer_one_dma - transfer a single spi_transfer using DMA 124562306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 124662306a36Sopenharmony_ci * @xfer: pointer to the spi_transfer structure 124762306a36Sopenharmony_ci * 124862306a36Sopenharmony_ci * It must returns 0 if the transfer is finished or 1 if the transfer is still 124962306a36Sopenharmony_ci * in progress. 125062306a36Sopenharmony_ci */ 125162306a36Sopenharmony_cistatic int stm32_spi_transfer_one_dma(struct stm32_spi *spi, 125262306a36Sopenharmony_ci struct spi_transfer *xfer) 125362306a36Sopenharmony_ci{ 125462306a36Sopenharmony_ci struct dma_slave_config tx_dma_conf, rx_dma_conf; 125562306a36Sopenharmony_ci struct dma_async_tx_descriptor *tx_dma_desc, *rx_dma_desc; 125662306a36Sopenharmony_ci unsigned long flags; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci rx_dma_desc = NULL; 126162306a36Sopenharmony_ci if (spi->rx_buf && spi->dma_rx) { 126262306a36Sopenharmony_ci stm32_spi_dma_config(spi, &rx_dma_conf, DMA_DEV_TO_MEM); 126362306a36Sopenharmony_ci dmaengine_slave_config(spi->dma_rx, &rx_dma_conf); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci /* Enable Rx DMA request */ 126662306a36Sopenharmony_ci stm32_spi_set_bits(spi, spi->cfg->regs->dma_rx_en.reg, 126762306a36Sopenharmony_ci spi->cfg->regs->dma_rx_en.mask); 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci rx_dma_desc = dmaengine_prep_slave_sg( 127062306a36Sopenharmony_ci spi->dma_rx, xfer->rx_sg.sgl, 127162306a36Sopenharmony_ci xfer->rx_sg.nents, 127262306a36Sopenharmony_ci rx_dma_conf.direction, 127362306a36Sopenharmony_ci DMA_PREP_INTERRUPT); 127462306a36Sopenharmony_ci } 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci tx_dma_desc = NULL; 127762306a36Sopenharmony_ci if (spi->tx_buf && spi->dma_tx) { 127862306a36Sopenharmony_ci stm32_spi_dma_config(spi, &tx_dma_conf, DMA_MEM_TO_DEV); 127962306a36Sopenharmony_ci dmaengine_slave_config(spi->dma_tx, &tx_dma_conf); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci tx_dma_desc = dmaengine_prep_slave_sg( 128262306a36Sopenharmony_ci spi->dma_tx, xfer->tx_sg.sgl, 128362306a36Sopenharmony_ci xfer->tx_sg.nents, 128462306a36Sopenharmony_ci tx_dma_conf.direction, 128562306a36Sopenharmony_ci DMA_PREP_INTERRUPT); 128662306a36Sopenharmony_ci } 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci if ((spi->tx_buf && spi->dma_tx && !tx_dma_desc) || 128962306a36Sopenharmony_ci (spi->rx_buf && spi->dma_rx && !rx_dma_desc)) 129062306a36Sopenharmony_ci goto dma_desc_error; 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci if (spi->cur_comm == SPI_FULL_DUPLEX && (!tx_dma_desc || !rx_dma_desc)) 129362306a36Sopenharmony_ci goto dma_desc_error; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci if (rx_dma_desc) { 129662306a36Sopenharmony_ci rx_dma_desc->callback = spi->cfg->dma_rx_cb; 129762306a36Sopenharmony_ci rx_dma_desc->callback_param = spi; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (dma_submit_error(dmaengine_submit(rx_dma_desc))) { 130062306a36Sopenharmony_ci dev_err(spi->dev, "Rx DMA submit failed\n"); 130162306a36Sopenharmony_ci goto dma_desc_error; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci /* Enable Rx DMA channel */ 130462306a36Sopenharmony_ci dma_async_issue_pending(spi->dma_rx); 130562306a36Sopenharmony_ci } 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci if (tx_dma_desc) { 130862306a36Sopenharmony_ci if (spi->cur_comm == SPI_SIMPLEX_TX || 130962306a36Sopenharmony_ci spi->cur_comm == SPI_3WIRE_TX) { 131062306a36Sopenharmony_ci tx_dma_desc->callback = spi->cfg->dma_tx_cb; 131162306a36Sopenharmony_ci tx_dma_desc->callback_param = spi; 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci if (dma_submit_error(dmaengine_submit(tx_dma_desc))) { 131562306a36Sopenharmony_ci dev_err(spi->dev, "Tx DMA submit failed\n"); 131662306a36Sopenharmony_ci goto dma_submit_error; 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci /* Enable Tx DMA channel */ 131962306a36Sopenharmony_ci dma_async_issue_pending(spi->dma_tx); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci /* Enable Tx DMA request */ 132262306a36Sopenharmony_ci stm32_spi_set_bits(spi, spi->cfg->regs->dma_tx_en.reg, 132362306a36Sopenharmony_ci spi->cfg->regs->dma_tx_en.mask); 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci spi->cfg->transfer_one_dma_start(spi); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci return 1; 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_cidma_submit_error: 133362306a36Sopenharmony_ci if (spi->dma_rx) 133462306a36Sopenharmony_ci dmaengine_terminate_sync(spi->dma_rx); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_cidma_desc_error: 133762306a36Sopenharmony_ci stm32_spi_clr_bits(spi, spi->cfg->regs->dma_rx_en.reg, 133862306a36Sopenharmony_ci spi->cfg->regs->dma_rx_en.mask); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci dev_info(spi->dev, "DMA issue: fall back to irq transfer\n"); 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci spi->cur_usedma = false; 134562306a36Sopenharmony_ci return spi->cfg->transfer_one_irq(spi); 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci/** 134962306a36Sopenharmony_ci * stm32f4_spi_set_bpw - Configure bits per word 135062306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 135162306a36Sopenharmony_ci */ 135262306a36Sopenharmony_cistatic void stm32f4_spi_set_bpw(struct stm32_spi *spi) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci if (spi->cur_bpw == 16) 135562306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF); 135662306a36Sopenharmony_ci else 135762306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_DFF); 135862306a36Sopenharmony_ci} 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci/** 136162306a36Sopenharmony_ci * stm32h7_spi_set_bpw - configure bits per word 136262306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 136362306a36Sopenharmony_ci */ 136462306a36Sopenharmony_cistatic void stm32h7_spi_set_bpw(struct stm32_spi *spi) 136562306a36Sopenharmony_ci{ 136662306a36Sopenharmony_ci u32 bpw, fthlv; 136762306a36Sopenharmony_ci u32 cfg1_clrb = 0, cfg1_setb = 0; 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci bpw = spi->cur_bpw - 1; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci cfg1_clrb |= STM32H7_SPI_CFG1_DSIZE; 137262306a36Sopenharmony_ci cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_DSIZE, bpw); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci spi->cur_fthlv = stm32h7_spi_prepare_fthlv(spi, spi->cur_xferlen); 137562306a36Sopenharmony_ci fthlv = spi->cur_fthlv - 1; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci cfg1_clrb |= STM32H7_SPI_CFG1_FTHLV; 137862306a36Sopenharmony_ci cfg1_setb |= FIELD_PREP(STM32H7_SPI_CFG1_FTHLV, fthlv); 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci writel_relaxed( 138162306a36Sopenharmony_ci (readl_relaxed(spi->base + STM32H7_SPI_CFG1) & 138262306a36Sopenharmony_ci ~cfg1_clrb) | cfg1_setb, 138362306a36Sopenharmony_ci spi->base + STM32H7_SPI_CFG1); 138462306a36Sopenharmony_ci} 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_ci/** 138762306a36Sopenharmony_ci * stm32_spi_set_mbr - Configure baud rate divisor in master mode 138862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 138962306a36Sopenharmony_ci * @mbrdiv: baud rate divisor value 139062306a36Sopenharmony_ci */ 139162306a36Sopenharmony_cistatic void stm32_spi_set_mbr(struct stm32_spi *spi, u32 mbrdiv) 139262306a36Sopenharmony_ci{ 139362306a36Sopenharmony_ci u32 clrb = 0, setb = 0; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci clrb |= spi->cfg->regs->br.mask; 139662306a36Sopenharmony_ci setb |= (mbrdiv << spi->cfg->regs->br.shift) & spi->cfg->regs->br.mask; 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci writel_relaxed((readl_relaxed(spi->base + spi->cfg->regs->br.reg) & 139962306a36Sopenharmony_ci ~clrb) | setb, 140062306a36Sopenharmony_ci spi->base + spi->cfg->regs->br.reg); 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci/** 140462306a36Sopenharmony_ci * stm32_spi_communication_type - return transfer communication type 140562306a36Sopenharmony_ci * @spi_dev: pointer to the spi device 140662306a36Sopenharmony_ci * @transfer: pointer to spi transfer 140762306a36Sopenharmony_ci */ 140862306a36Sopenharmony_cistatic unsigned int stm32_spi_communication_type(struct spi_device *spi_dev, 140962306a36Sopenharmony_ci struct spi_transfer *transfer) 141062306a36Sopenharmony_ci{ 141162306a36Sopenharmony_ci unsigned int type = SPI_FULL_DUPLEX; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci if (spi_dev->mode & SPI_3WIRE) { /* MISO/MOSI signals shared */ 141462306a36Sopenharmony_ci /* 141562306a36Sopenharmony_ci * SPI_3WIRE and xfer->tx_buf != NULL and xfer->rx_buf != NULL 141662306a36Sopenharmony_ci * is forbidden and unvalidated by SPI subsystem so depending 141762306a36Sopenharmony_ci * on the valid buffer, we can determine the direction of the 141862306a36Sopenharmony_ci * transfer. 141962306a36Sopenharmony_ci */ 142062306a36Sopenharmony_ci if (!transfer->tx_buf) 142162306a36Sopenharmony_ci type = SPI_3WIRE_RX; 142262306a36Sopenharmony_ci else 142362306a36Sopenharmony_ci type = SPI_3WIRE_TX; 142462306a36Sopenharmony_ci } else { 142562306a36Sopenharmony_ci if (!transfer->tx_buf) 142662306a36Sopenharmony_ci type = SPI_SIMPLEX_RX; 142762306a36Sopenharmony_ci else if (!transfer->rx_buf) 142862306a36Sopenharmony_ci type = SPI_SIMPLEX_TX; 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci return type; 143262306a36Sopenharmony_ci} 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci/** 143562306a36Sopenharmony_ci * stm32f4_spi_set_mode - configure communication mode 143662306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 143762306a36Sopenharmony_ci * @comm_type: type of communication to configure 143862306a36Sopenharmony_ci */ 143962306a36Sopenharmony_cistatic int stm32f4_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) 144062306a36Sopenharmony_ci{ 144162306a36Sopenharmony_ci if (comm_type == SPI_3WIRE_TX || comm_type == SPI_SIMPLEX_TX) { 144262306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR1, 144362306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIMODE | 144462306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIOE); 144562306a36Sopenharmony_ci } else if (comm_type == SPI_FULL_DUPLEX || 144662306a36Sopenharmony_ci comm_type == SPI_SIMPLEX_RX) { 144762306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, 144862306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIMODE | 144962306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIOE); 145062306a36Sopenharmony_ci } else if (comm_type == SPI_3WIRE_RX) { 145162306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR1, 145262306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIMODE); 145362306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_CR1, 145462306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIOE); 145562306a36Sopenharmony_ci } else { 145662306a36Sopenharmony_ci return -EINVAL; 145762306a36Sopenharmony_ci } 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci return 0; 146062306a36Sopenharmony_ci} 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci/** 146362306a36Sopenharmony_ci * stm32h7_spi_set_mode - configure communication mode 146462306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 146562306a36Sopenharmony_ci * @comm_type: type of communication to configure 146662306a36Sopenharmony_ci */ 146762306a36Sopenharmony_cistatic int stm32h7_spi_set_mode(struct stm32_spi *spi, unsigned int comm_type) 146862306a36Sopenharmony_ci{ 146962306a36Sopenharmony_ci u32 mode; 147062306a36Sopenharmony_ci u32 cfg2_clrb = 0, cfg2_setb = 0; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci if (comm_type == SPI_3WIRE_RX) { 147362306a36Sopenharmony_ci mode = STM32H7_SPI_HALF_DUPLEX; 147462306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR); 147562306a36Sopenharmony_ci } else if (comm_type == SPI_3WIRE_TX) { 147662306a36Sopenharmony_ci mode = STM32H7_SPI_HALF_DUPLEX; 147762306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CR1, STM32H7_SPI_CR1_HDDIR); 147862306a36Sopenharmony_ci } else if (comm_type == SPI_SIMPLEX_RX) { 147962306a36Sopenharmony_ci mode = STM32H7_SPI_SIMPLEX_RX; 148062306a36Sopenharmony_ci } else if (comm_type == SPI_SIMPLEX_TX) { 148162306a36Sopenharmony_ci mode = STM32H7_SPI_SIMPLEX_TX; 148262306a36Sopenharmony_ci } else { 148362306a36Sopenharmony_ci mode = STM32H7_SPI_FULL_DUPLEX; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci cfg2_clrb |= STM32H7_SPI_CFG2_COMM; 148762306a36Sopenharmony_ci cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_COMM, mode); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci writel_relaxed( 149062306a36Sopenharmony_ci (readl_relaxed(spi->base + STM32H7_SPI_CFG2) & 149162306a36Sopenharmony_ci ~cfg2_clrb) | cfg2_setb, 149262306a36Sopenharmony_ci spi->base + STM32H7_SPI_CFG2); 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci return 0; 149562306a36Sopenharmony_ci} 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci/** 149862306a36Sopenharmony_ci * stm32h7_spi_data_idleness - configure minimum time delay inserted between two 149962306a36Sopenharmony_ci * consecutive data frames in master mode 150062306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 150162306a36Sopenharmony_ci * @len: transfer len 150262306a36Sopenharmony_ci */ 150362306a36Sopenharmony_cistatic void stm32h7_spi_data_idleness(struct stm32_spi *spi, u32 len) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci u32 cfg2_clrb = 0, cfg2_setb = 0; 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci cfg2_clrb |= STM32H7_SPI_CFG2_MIDI; 150862306a36Sopenharmony_ci if ((len > 1) && (spi->cur_midi > 0)) { 150962306a36Sopenharmony_ci u32 sck_period_ns = DIV_ROUND_UP(NSEC_PER_SEC, spi->cur_speed); 151062306a36Sopenharmony_ci u32 midi = min_t(u32, 151162306a36Sopenharmony_ci DIV_ROUND_UP(spi->cur_midi, sck_period_ns), 151262306a36Sopenharmony_ci FIELD_GET(STM32H7_SPI_CFG2_MIDI, 151362306a36Sopenharmony_ci STM32H7_SPI_CFG2_MIDI)); 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci dev_dbg(spi->dev, "period=%dns, midi=%d(=%dns)\n", 151762306a36Sopenharmony_ci sck_period_ns, midi, midi * sck_period_ns); 151862306a36Sopenharmony_ci cfg2_setb |= FIELD_PREP(STM32H7_SPI_CFG2_MIDI, midi); 151962306a36Sopenharmony_ci } 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci writel_relaxed((readl_relaxed(spi->base + STM32H7_SPI_CFG2) & 152262306a36Sopenharmony_ci ~cfg2_clrb) | cfg2_setb, 152362306a36Sopenharmony_ci spi->base + STM32H7_SPI_CFG2); 152462306a36Sopenharmony_ci} 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci/** 152762306a36Sopenharmony_ci * stm32h7_spi_number_of_data - configure number of data at current transfer 152862306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 152962306a36Sopenharmony_ci * @nb_words: transfer length (in words) 153062306a36Sopenharmony_ci */ 153162306a36Sopenharmony_cistatic int stm32h7_spi_number_of_data(struct stm32_spi *spi, u32 nb_words) 153262306a36Sopenharmony_ci{ 153362306a36Sopenharmony_ci if (nb_words <= STM32H7_SPI_TSIZE_MAX) { 153462306a36Sopenharmony_ci writel_relaxed(FIELD_PREP(STM32H7_SPI_CR2_TSIZE, nb_words), 153562306a36Sopenharmony_ci spi->base + STM32H7_SPI_CR2); 153662306a36Sopenharmony_ci } else { 153762306a36Sopenharmony_ci return -EMSGSIZE; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci return 0; 154162306a36Sopenharmony_ci} 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci/** 154462306a36Sopenharmony_ci * stm32_spi_transfer_one_setup - common setup to transfer a single 154562306a36Sopenharmony_ci * spi_transfer either using DMA or 154662306a36Sopenharmony_ci * interrupts. 154762306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 154862306a36Sopenharmony_ci * @spi_dev: pointer to the spi device 154962306a36Sopenharmony_ci * @transfer: pointer to spi transfer 155062306a36Sopenharmony_ci */ 155162306a36Sopenharmony_cistatic int stm32_spi_transfer_one_setup(struct stm32_spi *spi, 155262306a36Sopenharmony_ci struct spi_device *spi_dev, 155362306a36Sopenharmony_ci struct spi_transfer *transfer) 155462306a36Sopenharmony_ci{ 155562306a36Sopenharmony_ci unsigned long flags; 155662306a36Sopenharmony_ci unsigned int comm_type; 155762306a36Sopenharmony_ci int nb_words, ret = 0; 155862306a36Sopenharmony_ci int mbr; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci spi->cur_xferlen = transfer->len; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci spi->cur_bpw = transfer->bits_per_word; 156562306a36Sopenharmony_ci spi->cfg->set_bpw(spi); 156662306a36Sopenharmony_ci 156762306a36Sopenharmony_ci /* Update spi->cur_speed with real clock speed */ 156862306a36Sopenharmony_ci if (STM32_SPI_MASTER_MODE(spi)) { 156962306a36Sopenharmony_ci mbr = stm32_spi_prepare_mbr(spi, transfer->speed_hz, 157062306a36Sopenharmony_ci spi->cfg->baud_rate_div_min, 157162306a36Sopenharmony_ci spi->cfg->baud_rate_div_max); 157262306a36Sopenharmony_ci if (mbr < 0) { 157362306a36Sopenharmony_ci ret = mbr; 157462306a36Sopenharmony_ci goto out; 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci transfer->speed_hz = spi->cur_speed; 157862306a36Sopenharmony_ci stm32_spi_set_mbr(spi, mbr); 157962306a36Sopenharmony_ci } 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci comm_type = stm32_spi_communication_type(spi_dev, transfer); 158262306a36Sopenharmony_ci ret = spi->cfg->set_mode(spi, comm_type); 158362306a36Sopenharmony_ci if (ret < 0) 158462306a36Sopenharmony_ci goto out; 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci spi->cur_comm = comm_type; 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci if (STM32_SPI_MASTER_MODE(spi) && spi->cfg->set_data_idleness) 158962306a36Sopenharmony_ci spi->cfg->set_data_idleness(spi, transfer->len); 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci if (spi->cur_bpw <= 8) 159262306a36Sopenharmony_ci nb_words = transfer->len; 159362306a36Sopenharmony_ci else if (spi->cur_bpw <= 16) 159462306a36Sopenharmony_ci nb_words = DIV_ROUND_UP(transfer->len * 8, 16); 159562306a36Sopenharmony_ci else 159662306a36Sopenharmony_ci nb_words = DIV_ROUND_UP(transfer->len * 8, 32); 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci if (spi->cfg->set_number_of_data) { 159962306a36Sopenharmony_ci ret = spi->cfg->set_number_of_data(spi, nb_words); 160062306a36Sopenharmony_ci if (ret < 0) 160162306a36Sopenharmony_ci goto out; 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci dev_dbg(spi->dev, "transfer communication mode set to %d\n", 160562306a36Sopenharmony_ci spi->cur_comm); 160662306a36Sopenharmony_ci dev_dbg(spi->dev, 160762306a36Sopenharmony_ci "data frame of %d-bit, data packet of %d data frames\n", 160862306a36Sopenharmony_ci spi->cur_bpw, spi->cur_fthlv); 160962306a36Sopenharmony_ci if (STM32_SPI_MASTER_MODE(spi)) 161062306a36Sopenharmony_ci dev_dbg(spi->dev, "speed set to %dHz\n", spi->cur_speed); 161162306a36Sopenharmony_ci dev_dbg(spi->dev, "transfer of %d bytes (%d data frames)\n", 161262306a36Sopenharmony_ci spi->cur_xferlen, nb_words); 161362306a36Sopenharmony_ci dev_dbg(spi->dev, "dma %s\n", 161462306a36Sopenharmony_ci (spi->cur_usedma) ? "enabled" : "disabled"); 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ciout: 161762306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci return ret; 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci/** 162362306a36Sopenharmony_ci * stm32_spi_transfer_one - transfer a single spi_transfer 162462306a36Sopenharmony_ci * @ctrl: controller interface 162562306a36Sopenharmony_ci * @spi_dev: pointer to the spi device 162662306a36Sopenharmony_ci * @transfer: pointer to spi transfer 162762306a36Sopenharmony_ci * 162862306a36Sopenharmony_ci * It must return 0 if the transfer is finished or 1 if the transfer is still 162962306a36Sopenharmony_ci * in progress. 163062306a36Sopenharmony_ci */ 163162306a36Sopenharmony_cistatic int stm32_spi_transfer_one(struct spi_controller *ctrl, 163262306a36Sopenharmony_ci struct spi_device *spi_dev, 163362306a36Sopenharmony_ci struct spi_transfer *transfer) 163462306a36Sopenharmony_ci{ 163562306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 163662306a36Sopenharmony_ci int ret; 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci spi->tx_buf = transfer->tx_buf; 163962306a36Sopenharmony_ci spi->rx_buf = transfer->rx_buf; 164062306a36Sopenharmony_ci spi->tx_len = spi->tx_buf ? transfer->len : 0; 164162306a36Sopenharmony_ci spi->rx_len = spi->rx_buf ? transfer->len : 0; 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci spi->cur_usedma = (ctrl->can_dma && 164462306a36Sopenharmony_ci ctrl->can_dma(ctrl, spi_dev, transfer)); 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci ret = stm32_spi_transfer_one_setup(spi, spi_dev, transfer); 164762306a36Sopenharmony_ci if (ret) { 164862306a36Sopenharmony_ci dev_err(spi->dev, "SPI transfer setup failed\n"); 164962306a36Sopenharmony_ci return ret; 165062306a36Sopenharmony_ci } 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_ci if (spi->cur_usedma) 165362306a36Sopenharmony_ci return stm32_spi_transfer_one_dma(spi, transfer); 165462306a36Sopenharmony_ci else 165562306a36Sopenharmony_ci return spi->cfg->transfer_one_irq(spi); 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci/** 165962306a36Sopenharmony_ci * stm32_spi_unprepare_msg - relax the hardware 166062306a36Sopenharmony_ci * @ctrl: controller interface 166162306a36Sopenharmony_ci * @msg: pointer to the spi message 166262306a36Sopenharmony_ci */ 166362306a36Sopenharmony_cistatic int stm32_spi_unprepare_msg(struct spi_controller *ctrl, 166462306a36Sopenharmony_ci struct spi_message *msg) 166562306a36Sopenharmony_ci{ 166662306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 166762306a36Sopenharmony_ci 166862306a36Sopenharmony_ci spi->cfg->disable(spi); 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci return 0; 167162306a36Sopenharmony_ci} 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci/** 167462306a36Sopenharmony_ci * stm32f4_spi_config - Configure SPI controller as SPI master 167562306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 167662306a36Sopenharmony_ci */ 167762306a36Sopenharmony_cistatic int stm32f4_spi_config(struct stm32_spi *spi) 167862306a36Sopenharmony_ci{ 167962306a36Sopenharmony_ci unsigned long flags; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci /* Ensure I2SMOD bit is kept cleared */ 168462306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32F4_SPI_I2SCFGR, 168562306a36Sopenharmony_ci STM32F4_SPI_I2SCFGR_I2SMOD); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_ci /* 168862306a36Sopenharmony_ci * - SS input value high 168962306a36Sopenharmony_ci * - transmitter half duplex direction 169062306a36Sopenharmony_ci * - Set the master mode (default Motorola mode) 169162306a36Sopenharmony_ci * - Consider 1 master/n slaves configuration and 169262306a36Sopenharmony_ci * SS input value is determined by the SSI bit 169362306a36Sopenharmony_ci */ 169462306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32F4_SPI_CR1, STM32F4_SPI_CR1_SSI | 169562306a36Sopenharmony_ci STM32F4_SPI_CR1_BIDIOE | 169662306a36Sopenharmony_ci STM32F4_SPI_CR1_MSTR | 169762306a36Sopenharmony_ci STM32F4_SPI_CR1_SSM); 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci return 0; 170262306a36Sopenharmony_ci} 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci/** 170562306a36Sopenharmony_ci * stm32h7_spi_config - Configure SPI controller 170662306a36Sopenharmony_ci * @spi: pointer to the spi controller data structure 170762306a36Sopenharmony_ci */ 170862306a36Sopenharmony_cistatic int stm32h7_spi_config(struct stm32_spi *spi) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci unsigned long flags; 171162306a36Sopenharmony_ci u32 cr1 = 0, cfg2 = 0; 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci spin_lock_irqsave(&spi->lock, flags); 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci /* Ensure I2SMOD bit is kept cleared */ 171662306a36Sopenharmony_ci stm32_spi_clr_bits(spi, STM32H7_SPI_I2SCFGR, 171762306a36Sopenharmony_ci STM32H7_SPI_I2SCFGR_I2SMOD); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci if (STM32_SPI_DEVICE_MODE(spi)) { 172062306a36Sopenharmony_ci /* Use native device select */ 172162306a36Sopenharmony_ci cfg2 &= ~STM32H7_SPI_CFG2_SSM; 172262306a36Sopenharmony_ci } else { 172362306a36Sopenharmony_ci /* 172462306a36Sopenharmony_ci * - Transmitter half duplex direction 172562306a36Sopenharmony_ci * - Automatic communication suspend when RX-Fifo is full 172662306a36Sopenharmony_ci * - SS input value high 172762306a36Sopenharmony_ci */ 172862306a36Sopenharmony_ci cr1 |= STM32H7_SPI_CR1_HDDIR | STM32H7_SPI_CR1_MASRX | STM32H7_SPI_CR1_SSI; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci /* 173162306a36Sopenharmony_ci * - Set the master mode (default Motorola mode) 173262306a36Sopenharmony_ci * - Consider 1 master/n devices configuration and 173362306a36Sopenharmony_ci * SS input value is determined by the SSI bit 173462306a36Sopenharmony_ci * - keep control of all associated GPIOs 173562306a36Sopenharmony_ci */ 173662306a36Sopenharmony_ci cfg2 |= STM32H7_SPI_CFG2_MASTER | STM32H7_SPI_CFG2_SSM | STM32H7_SPI_CFG2_AFCNTR; 173762306a36Sopenharmony_ci } 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CR1, cr1); 174062306a36Sopenharmony_ci stm32_spi_set_bits(spi, STM32H7_SPI_CFG2, cfg2); 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci spin_unlock_irqrestore(&spi->lock, flags); 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci return 0; 174562306a36Sopenharmony_ci} 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_cistatic const struct stm32_spi_cfg stm32f4_spi_cfg = { 174862306a36Sopenharmony_ci .regs = &stm32f4_spi_regspec, 174962306a36Sopenharmony_ci .get_bpw_mask = stm32f4_spi_get_bpw_mask, 175062306a36Sopenharmony_ci .disable = stm32f4_spi_disable, 175162306a36Sopenharmony_ci .config = stm32f4_spi_config, 175262306a36Sopenharmony_ci .set_bpw = stm32f4_spi_set_bpw, 175362306a36Sopenharmony_ci .set_mode = stm32f4_spi_set_mode, 175462306a36Sopenharmony_ci .transfer_one_dma_start = stm32f4_spi_transfer_one_dma_start, 175562306a36Sopenharmony_ci .dma_tx_cb = stm32f4_spi_dma_tx_cb, 175662306a36Sopenharmony_ci .dma_rx_cb = stm32_spi_dma_rx_cb, 175762306a36Sopenharmony_ci .transfer_one_irq = stm32f4_spi_transfer_one_irq, 175862306a36Sopenharmony_ci .irq_handler_event = stm32f4_spi_irq_event, 175962306a36Sopenharmony_ci .irq_handler_thread = stm32f4_spi_irq_thread, 176062306a36Sopenharmony_ci .baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN, 176162306a36Sopenharmony_ci .baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX, 176262306a36Sopenharmony_ci .has_fifo = false, 176362306a36Sopenharmony_ci .has_device_mode = false, 176462306a36Sopenharmony_ci .flags = SPI_CONTROLLER_MUST_TX, 176562306a36Sopenharmony_ci}; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_cistatic const struct stm32_spi_cfg stm32h7_spi_cfg = { 176862306a36Sopenharmony_ci .regs = &stm32h7_spi_regspec, 176962306a36Sopenharmony_ci .get_fifo_size = stm32h7_spi_get_fifo_size, 177062306a36Sopenharmony_ci .get_bpw_mask = stm32h7_spi_get_bpw_mask, 177162306a36Sopenharmony_ci .disable = stm32h7_spi_disable, 177262306a36Sopenharmony_ci .config = stm32h7_spi_config, 177362306a36Sopenharmony_ci .set_bpw = stm32h7_spi_set_bpw, 177462306a36Sopenharmony_ci .set_mode = stm32h7_spi_set_mode, 177562306a36Sopenharmony_ci .set_data_idleness = stm32h7_spi_data_idleness, 177662306a36Sopenharmony_ci .set_number_of_data = stm32h7_spi_number_of_data, 177762306a36Sopenharmony_ci .transfer_one_dma_start = stm32h7_spi_transfer_one_dma_start, 177862306a36Sopenharmony_ci .dma_rx_cb = stm32_spi_dma_rx_cb, 177962306a36Sopenharmony_ci /* 178062306a36Sopenharmony_ci * dma_tx_cb is not necessary since in case of TX, dma is followed by 178162306a36Sopenharmony_ci * SPI access hence handling is performed within the SPI interrupt 178262306a36Sopenharmony_ci */ 178362306a36Sopenharmony_ci .transfer_one_irq = stm32h7_spi_transfer_one_irq, 178462306a36Sopenharmony_ci .irq_handler_thread = stm32h7_spi_irq_thread, 178562306a36Sopenharmony_ci .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, 178662306a36Sopenharmony_ci .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, 178762306a36Sopenharmony_ci .has_fifo = true, 178862306a36Sopenharmony_ci .has_device_mode = true, 178962306a36Sopenharmony_ci}; 179062306a36Sopenharmony_ci 179162306a36Sopenharmony_cistatic const struct of_device_id stm32_spi_of_match[] = { 179262306a36Sopenharmony_ci { .compatible = "st,stm32h7-spi", .data = (void *)&stm32h7_spi_cfg }, 179362306a36Sopenharmony_ci { .compatible = "st,stm32f4-spi", .data = (void *)&stm32f4_spi_cfg }, 179462306a36Sopenharmony_ci {}, 179562306a36Sopenharmony_ci}; 179662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_spi_of_match); 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_cistatic int stm32h7_spi_device_abort(struct spi_controller *ctrl) 179962306a36Sopenharmony_ci{ 180062306a36Sopenharmony_ci spi_finalize_current_transfer(ctrl); 180162306a36Sopenharmony_ci return 0; 180262306a36Sopenharmony_ci} 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_cistatic int stm32_spi_probe(struct platform_device *pdev) 180562306a36Sopenharmony_ci{ 180662306a36Sopenharmony_ci struct spi_controller *ctrl; 180762306a36Sopenharmony_ci struct stm32_spi *spi; 180862306a36Sopenharmony_ci struct resource *res; 180962306a36Sopenharmony_ci struct reset_control *rst; 181062306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 181162306a36Sopenharmony_ci bool device_mode; 181262306a36Sopenharmony_ci int ret; 181362306a36Sopenharmony_ci const struct stm32_spi_cfg *cfg = of_device_get_match_data(&pdev->dev); 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci device_mode = of_property_read_bool(np, "spi-slave"); 181662306a36Sopenharmony_ci if (!cfg->has_device_mode && device_mode) { 181762306a36Sopenharmony_ci dev_err(&pdev->dev, "spi-slave not supported\n"); 181862306a36Sopenharmony_ci return -EPERM; 181962306a36Sopenharmony_ci } 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci if (device_mode) 182262306a36Sopenharmony_ci ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi)); 182362306a36Sopenharmony_ci else 182462306a36Sopenharmony_ci ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(struct stm32_spi)); 182562306a36Sopenharmony_ci if (!ctrl) { 182662306a36Sopenharmony_ci dev_err(&pdev->dev, "spi controller allocation failed\n"); 182762306a36Sopenharmony_ci return -ENOMEM; 182862306a36Sopenharmony_ci } 182962306a36Sopenharmony_ci platform_set_drvdata(pdev, ctrl); 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci spi = spi_controller_get_devdata(ctrl); 183262306a36Sopenharmony_ci spi->dev = &pdev->dev; 183362306a36Sopenharmony_ci spi->ctrl = ctrl; 183462306a36Sopenharmony_ci spi->device_mode = device_mode; 183562306a36Sopenharmony_ci spin_lock_init(&spi->lock); 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci spi->cfg = cfg; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 184062306a36Sopenharmony_ci if (IS_ERR(spi->base)) 184162306a36Sopenharmony_ci return PTR_ERR(spi->base); 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci spi->phys_addr = (dma_addr_t)res->start; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci spi->irq = platform_get_irq(pdev, 0); 184662306a36Sopenharmony_ci if (spi->irq <= 0) 184762306a36Sopenharmony_ci return spi->irq; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci ret = devm_request_threaded_irq(&pdev->dev, spi->irq, 185062306a36Sopenharmony_ci spi->cfg->irq_handler_event, 185162306a36Sopenharmony_ci spi->cfg->irq_handler_thread, 185262306a36Sopenharmony_ci IRQF_ONESHOT, pdev->name, ctrl); 185362306a36Sopenharmony_ci if (ret) { 185462306a36Sopenharmony_ci dev_err(&pdev->dev, "irq%d request failed: %d\n", spi->irq, 185562306a36Sopenharmony_ci ret); 185662306a36Sopenharmony_ci return ret; 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci spi->clk = devm_clk_get(&pdev->dev, NULL); 186062306a36Sopenharmony_ci if (IS_ERR(spi->clk)) { 186162306a36Sopenharmony_ci ret = PTR_ERR(spi->clk); 186262306a36Sopenharmony_ci dev_err(&pdev->dev, "clk get failed: %d\n", ret); 186362306a36Sopenharmony_ci return ret; 186462306a36Sopenharmony_ci } 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci ret = clk_prepare_enable(spi->clk); 186762306a36Sopenharmony_ci if (ret) { 186862306a36Sopenharmony_ci dev_err(&pdev->dev, "clk enable failed: %d\n", ret); 186962306a36Sopenharmony_ci return ret; 187062306a36Sopenharmony_ci } 187162306a36Sopenharmony_ci spi->clk_rate = clk_get_rate(spi->clk); 187262306a36Sopenharmony_ci if (!spi->clk_rate) { 187362306a36Sopenharmony_ci dev_err(&pdev->dev, "clk rate = 0\n"); 187462306a36Sopenharmony_ci ret = -EINVAL; 187562306a36Sopenharmony_ci goto err_clk_disable; 187662306a36Sopenharmony_ci } 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); 187962306a36Sopenharmony_ci if (rst) { 188062306a36Sopenharmony_ci if (IS_ERR(rst)) { 188162306a36Sopenharmony_ci ret = dev_err_probe(&pdev->dev, PTR_ERR(rst), 188262306a36Sopenharmony_ci "failed to get reset\n"); 188362306a36Sopenharmony_ci goto err_clk_disable; 188462306a36Sopenharmony_ci } 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci reset_control_assert(rst); 188762306a36Sopenharmony_ci udelay(2); 188862306a36Sopenharmony_ci reset_control_deassert(rst); 188962306a36Sopenharmony_ci } 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci if (spi->cfg->has_fifo) 189262306a36Sopenharmony_ci spi->fifo_size = spi->cfg->get_fifo_size(spi); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci ret = spi->cfg->config(spi); 189562306a36Sopenharmony_ci if (ret) { 189662306a36Sopenharmony_ci dev_err(&pdev->dev, "controller configuration failed: %d\n", 189762306a36Sopenharmony_ci ret); 189862306a36Sopenharmony_ci goto err_clk_disable; 189962306a36Sopenharmony_ci } 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci ctrl->dev.of_node = pdev->dev.of_node; 190262306a36Sopenharmony_ci ctrl->auto_runtime_pm = true; 190362306a36Sopenharmony_ci ctrl->bus_num = pdev->id; 190462306a36Sopenharmony_ci ctrl->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | 190562306a36Sopenharmony_ci SPI_3WIRE; 190662306a36Sopenharmony_ci ctrl->bits_per_word_mask = spi->cfg->get_bpw_mask(spi); 190762306a36Sopenharmony_ci ctrl->max_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_min; 190862306a36Sopenharmony_ci ctrl->min_speed_hz = spi->clk_rate / spi->cfg->baud_rate_div_max; 190962306a36Sopenharmony_ci ctrl->use_gpio_descriptors = true; 191062306a36Sopenharmony_ci ctrl->prepare_message = stm32_spi_prepare_msg; 191162306a36Sopenharmony_ci ctrl->transfer_one = stm32_spi_transfer_one; 191262306a36Sopenharmony_ci ctrl->unprepare_message = stm32_spi_unprepare_msg; 191362306a36Sopenharmony_ci ctrl->flags = spi->cfg->flags; 191462306a36Sopenharmony_ci if (STM32_SPI_DEVICE_MODE(spi)) 191562306a36Sopenharmony_ci ctrl->slave_abort = stm32h7_spi_device_abort; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci spi->dma_tx = dma_request_chan(spi->dev, "tx"); 191862306a36Sopenharmony_ci if (IS_ERR(spi->dma_tx)) { 191962306a36Sopenharmony_ci ret = PTR_ERR(spi->dma_tx); 192062306a36Sopenharmony_ci spi->dma_tx = NULL; 192162306a36Sopenharmony_ci if (ret == -EPROBE_DEFER) 192262306a36Sopenharmony_ci goto err_clk_disable; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci dev_warn(&pdev->dev, "failed to request tx dma channel\n"); 192562306a36Sopenharmony_ci } else { 192662306a36Sopenharmony_ci ctrl->dma_tx = spi->dma_tx; 192762306a36Sopenharmony_ci } 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci spi->dma_rx = dma_request_chan(spi->dev, "rx"); 193062306a36Sopenharmony_ci if (IS_ERR(spi->dma_rx)) { 193162306a36Sopenharmony_ci ret = PTR_ERR(spi->dma_rx); 193262306a36Sopenharmony_ci spi->dma_rx = NULL; 193362306a36Sopenharmony_ci if (ret == -EPROBE_DEFER) 193462306a36Sopenharmony_ci goto err_dma_release; 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci dev_warn(&pdev->dev, "failed to request rx dma channel\n"); 193762306a36Sopenharmony_ci } else { 193862306a36Sopenharmony_ci ctrl->dma_rx = spi->dma_rx; 193962306a36Sopenharmony_ci } 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci if (spi->dma_tx || spi->dma_rx) 194262306a36Sopenharmony_ci ctrl->can_dma = stm32_spi_can_dma; 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(&pdev->dev, 194562306a36Sopenharmony_ci STM32_SPI_AUTOSUSPEND_DELAY); 194662306a36Sopenharmony_ci pm_runtime_use_autosuspend(&pdev->dev); 194762306a36Sopenharmony_ci pm_runtime_set_active(&pdev->dev); 194862306a36Sopenharmony_ci pm_runtime_get_noresume(&pdev->dev); 194962306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci ret = spi_register_controller(ctrl); 195262306a36Sopenharmony_ci if (ret) { 195362306a36Sopenharmony_ci dev_err(&pdev->dev, "spi controller registration failed: %d\n", 195462306a36Sopenharmony_ci ret); 195562306a36Sopenharmony_ci goto err_pm_disable; 195662306a36Sopenharmony_ci } 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci pm_runtime_mark_last_busy(&pdev->dev); 195962306a36Sopenharmony_ci pm_runtime_put_autosuspend(&pdev->dev); 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci dev_info(&pdev->dev, "driver initialized (%s mode)\n", 196262306a36Sopenharmony_ci STM32_SPI_MASTER_MODE(spi) ? "master" : "device"); 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ci return 0; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_cierr_pm_disable: 196762306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 196862306a36Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 196962306a36Sopenharmony_ci pm_runtime_set_suspended(&pdev->dev); 197062306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 197162306a36Sopenharmony_cierr_dma_release: 197262306a36Sopenharmony_ci if (spi->dma_tx) 197362306a36Sopenharmony_ci dma_release_channel(spi->dma_tx); 197462306a36Sopenharmony_ci if (spi->dma_rx) 197562306a36Sopenharmony_ci dma_release_channel(spi->dma_rx); 197662306a36Sopenharmony_cierr_clk_disable: 197762306a36Sopenharmony_ci clk_disable_unprepare(spi->clk); 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci return ret; 198062306a36Sopenharmony_ci} 198162306a36Sopenharmony_ci 198262306a36Sopenharmony_cistatic void stm32_spi_remove(struct platform_device *pdev) 198362306a36Sopenharmony_ci{ 198462306a36Sopenharmony_ci struct spi_controller *ctrl = platform_get_drvdata(pdev); 198562306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci spi_unregister_controller(ctrl); 199062306a36Sopenharmony_ci spi->cfg->disable(spi); 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 199362306a36Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 199462306a36Sopenharmony_ci pm_runtime_set_suspended(&pdev->dev); 199562306a36Sopenharmony_ci pm_runtime_dont_use_autosuspend(&pdev->dev); 199662306a36Sopenharmony_ci 199762306a36Sopenharmony_ci if (ctrl->dma_tx) 199862306a36Sopenharmony_ci dma_release_channel(ctrl->dma_tx); 199962306a36Sopenharmony_ci if (ctrl->dma_rx) 200062306a36Sopenharmony_ci dma_release_channel(ctrl->dma_rx); 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci clk_disable_unprepare(spi->clk); 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci pinctrl_pm_select_sleep_state(&pdev->dev); 200662306a36Sopenharmony_ci} 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_cistatic int __maybe_unused stm32_spi_runtime_suspend(struct device *dev) 200962306a36Sopenharmony_ci{ 201062306a36Sopenharmony_ci struct spi_controller *ctrl = dev_get_drvdata(dev); 201162306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci clk_disable_unprepare(spi->clk); 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci return pinctrl_pm_select_sleep_state(dev); 201662306a36Sopenharmony_ci} 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_cistatic int __maybe_unused stm32_spi_runtime_resume(struct device *dev) 201962306a36Sopenharmony_ci{ 202062306a36Sopenharmony_ci struct spi_controller *ctrl = dev_get_drvdata(dev); 202162306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 202262306a36Sopenharmony_ci int ret; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci ret = pinctrl_pm_select_default_state(dev); 202562306a36Sopenharmony_ci if (ret) 202662306a36Sopenharmony_ci return ret; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci return clk_prepare_enable(spi->clk); 202962306a36Sopenharmony_ci} 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_cistatic int __maybe_unused stm32_spi_suspend(struct device *dev) 203262306a36Sopenharmony_ci{ 203362306a36Sopenharmony_ci struct spi_controller *ctrl = dev_get_drvdata(dev); 203462306a36Sopenharmony_ci int ret; 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci ret = spi_controller_suspend(ctrl); 203762306a36Sopenharmony_ci if (ret) 203862306a36Sopenharmony_ci return ret; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci return pm_runtime_force_suspend(dev); 204162306a36Sopenharmony_ci} 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_cistatic int __maybe_unused stm32_spi_resume(struct device *dev) 204462306a36Sopenharmony_ci{ 204562306a36Sopenharmony_ci struct spi_controller *ctrl = dev_get_drvdata(dev); 204662306a36Sopenharmony_ci struct stm32_spi *spi = spi_controller_get_devdata(ctrl); 204762306a36Sopenharmony_ci int ret; 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci ret = pm_runtime_force_resume(dev); 205062306a36Sopenharmony_ci if (ret) 205162306a36Sopenharmony_ci return ret; 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci ret = spi_controller_resume(ctrl); 205462306a36Sopenharmony_ci if (ret) { 205562306a36Sopenharmony_ci clk_disable_unprepare(spi->clk); 205662306a36Sopenharmony_ci return ret; 205762306a36Sopenharmony_ci } 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 206062306a36Sopenharmony_ci if (ret < 0) { 206162306a36Sopenharmony_ci dev_err(dev, "Unable to power device:%d\n", ret); 206262306a36Sopenharmony_ci return ret; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci spi->cfg->config(spi); 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 206862306a36Sopenharmony_ci pm_runtime_put_autosuspend(dev); 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci return 0; 207162306a36Sopenharmony_ci} 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_cistatic const struct dev_pm_ops stm32_spi_pm_ops = { 207462306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(stm32_spi_suspend, stm32_spi_resume) 207562306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(stm32_spi_runtime_suspend, 207662306a36Sopenharmony_ci stm32_spi_runtime_resume, NULL) 207762306a36Sopenharmony_ci}; 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_cistatic struct platform_driver stm32_spi_driver = { 208062306a36Sopenharmony_ci .probe = stm32_spi_probe, 208162306a36Sopenharmony_ci .remove_new = stm32_spi_remove, 208262306a36Sopenharmony_ci .driver = { 208362306a36Sopenharmony_ci .name = DRIVER_NAME, 208462306a36Sopenharmony_ci .pm = &stm32_spi_pm_ops, 208562306a36Sopenharmony_ci .of_match_table = stm32_spi_of_match, 208662306a36Sopenharmony_ci }, 208762306a36Sopenharmony_ci}; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_cimodule_platform_driver(stm32_spi_driver); 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_ciMODULE_ALIAS("platform:" DRIVER_NAME); 209262306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics STM32 SPI Controller driver"); 209362306a36Sopenharmony_ciMODULE_AUTHOR("Amelie Delaunay <amelie.delaunay@st.com>"); 209462306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2095