18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for Atmel AT32 and AT91 SPI Controllers
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2006 Atmel Corporation
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/clk.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
128c2ecf20Sopenharmony_ci#include <linux/delay.h>
138c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
148c2ecf20Sopenharmony_ci#include <linux/dmaengine.h>
158c2ecf20Sopenharmony_ci#include <linux/err.h>
168c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
178c2ecf20Sopenharmony_ci#include <linux/spi/spi.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/of.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <linux/io.h>
228c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h>
238c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h>
248c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
258c2ecf20Sopenharmony_ci#include <trace/events/spi.h>
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* SPI register offsets */
288c2ecf20Sopenharmony_ci#define SPI_CR					0x0000
298c2ecf20Sopenharmony_ci#define SPI_MR					0x0004
308c2ecf20Sopenharmony_ci#define SPI_RDR					0x0008
318c2ecf20Sopenharmony_ci#define SPI_TDR					0x000c
328c2ecf20Sopenharmony_ci#define SPI_SR					0x0010
338c2ecf20Sopenharmony_ci#define SPI_IER					0x0014
348c2ecf20Sopenharmony_ci#define SPI_IDR					0x0018
358c2ecf20Sopenharmony_ci#define SPI_IMR					0x001c
368c2ecf20Sopenharmony_ci#define SPI_CSR0				0x0030
378c2ecf20Sopenharmony_ci#define SPI_CSR1				0x0034
388c2ecf20Sopenharmony_ci#define SPI_CSR2				0x0038
398c2ecf20Sopenharmony_ci#define SPI_CSR3				0x003c
408c2ecf20Sopenharmony_ci#define SPI_FMR					0x0040
418c2ecf20Sopenharmony_ci#define SPI_FLR					0x0044
428c2ecf20Sopenharmony_ci#define SPI_VERSION				0x00fc
438c2ecf20Sopenharmony_ci#define SPI_RPR					0x0100
448c2ecf20Sopenharmony_ci#define SPI_RCR					0x0104
458c2ecf20Sopenharmony_ci#define SPI_TPR					0x0108
468c2ecf20Sopenharmony_ci#define SPI_TCR					0x010c
478c2ecf20Sopenharmony_ci#define SPI_RNPR				0x0110
488c2ecf20Sopenharmony_ci#define SPI_RNCR				0x0114
498c2ecf20Sopenharmony_ci#define SPI_TNPR				0x0118
508c2ecf20Sopenharmony_ci#define SPI_TNCR				0x011c
518c2ecf20Sopenharmony_ci#define SPI_PTCR				0x0120
528c2ecf20Sopenharmony_ci#define SPI_PTSR				0x0124
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci/* Bitfields in CR */
558c2ecf20Sopenharmony_ci#define SPI_SPIEN_OFFSET			0
568c2ecf20Sopenharmony_ci#define SPI_SPIEN_SIZE				1
578c2ecf20Sopenharmony_ci#define SPI_SPIDIS_OFFSET			1
588c2ecf20Sopenharmony_ci#define SPI_SPIDIS_SIZE				1
598c2ecf20Sopenharmony_ci#define SPI_SWRST_OFFSET			7
608c2ecf20Sopenharmony_ci#define SPI_SWRST_SIZE				1
618c2ecf20Sopenharmony_ci#define SPI_LASTXFER_OFFSET			24
628c2ecf20Sopenharmony_ci#define SPI_LASTXFER_SIZE			1
638c2ecf20Sopenharmony_ci#define SPI_TXFCLR_OFFSET			16
648c2ecf20Sopenharmony_ci#define SPI_TXFCLR_SIZE				1
658c2ecf20Sopenharmony_ci#define SPI_RXFCLR_OFFSET			17
668c2ecf20Sopenharmony_ci#define SPI_RXFCLR_SIZE				1
678c2ecf20Sopenharmony_ci#define SPI_FIFOEN_OFFSET			30
688c2ecf20Sopenharmony_ci#define SPI_FIFOEN_SIZE				1
698c2ecf20Sopenharmony_ci#define SPI_FIFODIS_OFFSET			31
708c2ecf20Sopenharmony_ci#define SPI_FIFODIS_SIZE			1
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/* Bitfields in MR */
738c2ecf20Sopenharmony_ci#define SPI_MSTR_OFFSET				0
748c2ecf20Sopenharmony_ci#define SPI_MSTR_SIZE				1
758c2ecf20Sopenharmony_ci#define SPI_PS_OFFSET				1
768c2ecf20Sopenharmony_ci#define SPI_PS_SIZE				1
778c2ecf20Sopenharmony_ci#define SPI_PCSDEC_OFFSET			2
788c2ecf20Sopenharmony_ci#define SPI_PCSDEC_SIZE				1
798c2ecf20Sopenharmony_ci#define SPI_FDIV_OFFSET				3
808c2ecf20Sopenharmony_ci#define SPI_FDIV_SIZE				1
818c2ecf20Sopenharmony_ci#define SPI_MODFDIS_OFFSET			4
828c2ecf20Sopenharmony_ci#define SPI_MODFDIS_SIZE			1
838c2ecf20Sopenharmony_ci#define SPI_WDRBT_OFFSET			5
848c2ecf20Sopenharmony_ci#define SPI_WDRBT_SIZE				1
858c2ecf20Sopenharmony_ci#define SPI_LLB_OFFSET				7
868c2ecf20Sopenharmony_ci#define SPI_LLB_SIZE				1
878c2ecf20Sopenharmony_ci#define SPI_PCS_OFFSET				16
888c2ecf20Sopenharmony_ci#define SPI_PCS_SIZE				4
898c2ecf20Sopenharmony_ci#define SPI_DLYBCS_OFFSET			24
908c2ecf20Sopenharmony_ci#define SPI_DLYBCS_SIZE				8
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/* Bitfields in RDR */
938c2ecf20Sopenharmony_ci#define SPI_RD_OFFSET				0
948c2ecf20Sopenharmony_ci#define SPI_RD_SIZE				16
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* Bitfields in TDR */
978c2ecf20Sopenharmony_ci#define SPI_TD_OFFSET				0
988c2ecf20Sopenharmony_ci#define SPI_TD_SIZE				16
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci/* Bitfields in SR */
1018c2ecf20Sopenharmony_ci#define SPI_RDRF_OFFSET				0
1028c2ecf20Sopenharmony_ci#define SPI_RDRF_SIZE				1
1038c2ecf20Sopenharmony_ci#define SPI_TDRE_OFFSET				1
1048c2ecf20Sopenharmony_ci#define SPI_TDRE_SIZE				1
1058c2ecf20Sopenharmony_ci#define SPI_MODF_OFFSET				2
1068c2ecf20Sopenharmony_ci#define SPI_MODF_SIZE				1
1078c2ecf20Sopenharmony_ci#define SPI_OVRES_OFFSET			3
1088c2ecf20Sopenharmony_ci#define SPI_OVRES_SIZE				1
1098c2ecf20Sopenharmony_ci#define SPI_ENDRX_OFFSET			4
1108c2ecf20Sopenharmony_ci#define SPI_ENDRX_SIZE				1
1118c2ecf20Sopenharmony_ci#define SPI_ENDTX_OFFSET			5
1128c2ecf20Sopenharmony_ci#define SPI_ENDTX_SIZE				1
1138c2ecf20Sopenharmony_ci#define SPI_RXBUFF_OFFSET			6
1148c2ecf20Sopenharmony_ci#define SPI_RXBUFF_SIZE				1
1158c2ecf20Sopenharmony_ci#define SPI_TXBUFE_OFFSET			7
1168c2ecf20Sopenharmony_ci#define SPI_TXBUFE_SIZE				1
1178c2ecf20Sopenharmony_ci#define SPI_NSSR_OFFSET				8
1188c2ecf20Sopenharmony_ci#define SPI_NSSR_SIZE				1
1198c2ecf20Sopenharmony_ci#define SPI_TXEMPTY_OFFSET			9
1208c2ecf20Sopenharmony_ci#define SPI_TXEMPTY_SIZE			1
1218c2ecf20Sopenharmony_ci#define SPI_SPIENS_OFFSET			16
1228c2ecf20Sopenharmony_ci#define SPI_SPIENS_SIZE				1
1238c2ecf20Sopenharmony_ci#define SPI_TXFEF_OFFSET			24
1248c2ecf20Sopenharmony_ci#define SPI_TXFEF_SIZE				1
1258c2ecf20Sopenharmony_ci#define SPI_TXFFF_OFFSET			25
1268c2ecf20Sopenharmony_ci#define SPI_TXFFF_SIZE				1
1278c2ecf20Sopenharmony_ci#define SPI_TXFTHF_OFFSET			26
1288c2ecf20Sopenharmony_ci#define SPI_TXFTHF_SIZE				1
1298c2ecf20Sopenharmony_ci#define SPI_RXFEF_OFFSET			27
1308c2ecf20Sopenharmony_ci#define SPI_RXFEF_SIZE				1
1318c2ecf20Sopenharmony_ci#define SPI_RXFFF_OFFSET			28
1328c2ecf20Sopenharmony_ci#define SPI_RXFFF_SIZE				1
1338c2ecf20Sopenharmony_ci#define SPI_RXFTHF_OFFSET			29
1348c2ecf20Sopenharmony_ci#define SPI_RXFTHF_SIZE				1
1358c2ecf20Sopenharmony_ci#define SPI_TXFPTEF_OFFSET			30
1368c2ecf20Sopenharmony_ci#define SPI_TXFPTEF_SIZE			1
1378c2ecf20Sopenharmony_ci#define SPI_RXFPTEF_OFFSET			31
1388c2ecf20Sopenharmony_ci#define SPI_RXFPTEF_SIZE			1
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* Bitfields in CSR0 */
1418c2ecf20Sopenharmony_ci#define SPI_CPOL_OFFSET				0
1428c2ecf20Sopenharmony_ci#define SPI_CPOL_SIZE				1
1438c2ecf20Sopenharmony_ci#define SPI_NCPHA_OFFSET			1
1448c2ecf20Sopenharmony_ci#define SPI_NCPHA_SIZE				1
1458c2ecf20Sopenharmony_ci#define SPI_CSAAT_OFFSET			3
1468c2ecf20Sopenharmony_ci#define SPI_CSAAT_SIZE				1
1478c2ecf20Sopenharmony_ci#define SPI_BITS_OFFSET				4
1488c2ecf20Sopenharmony_ci#define SPI_BITS_SIZE				4
1498c2ecf20Sopenharmony_ci#define SPI_SCBR_OFFSET				8
1508c2ecf20Sopenharmony_ci#define SPI_SCBR_SIZE				8
1518c2ecf20Sopenharmony_ci#define SPI_DLYBS_OFFSET			16
1528c2ecf20Sopenharmony_ci#define SPI_DLYBS_SIZE				8
1538c2ecf20Sopenharmony_ci#define SPI_DLYBCT_OFFSET			24
1548c2ecf20Sopenharmony_ci#define SPI_DLYBCT_SIZE				8
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci/* Bitfields in RCR */
1578c2ecf20Sopenharmony_ci#define SPI_RXCTR_OFFSET			0
1588c2ecf20Sopenharmony_ci#define SPI_RXCTR_SIZE				16
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/* Bitfields in TCR */
1618c2ecf20Sopenharmony_ci#define SPI_TXCTR_OFFSET			0
1628c2ecf20Sopenharmony_ci#define SPI_TXCTR_SIZE				16
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci/* Bitfields in RNCR */
1658c2ecf20Sopenharmony_ci#define SPI_RXNCR_OFFSET			0
1668c2ecf20Sopenharmony_ci#define SPI_RXNCR_SIZE				16
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci/* Bitfields in TNCR */
1698c2ecf20Sopenharmony_ci#define SPI_TXNCR_OFFSET			0
1708c2ecf20Sopenharmony_ci#define SPI_TXNCR_SIZE				16
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/* Bitfields in PTCR */
1738c2ecf20Sopenharmony_ci#define SPI_RXTEN_OFFSET			0
1748c2ecf20Sopenharmony_ci#define SPI_RXTEN_SIZE				1
1758c2ecf20Sopenharmony_ci#define SPI_RXTDIS_OFFSET			1
1768c2ecf20Sopenharmony_ci#define SPI_RXTDIS_SIZE				1
1778c2ecf20Sopenharmony_ci#define SPI_TXTEN_OFFSET			8
1788c2ecf20Sopenharmony_ci#define SPI_TXTEN_SIZE				1
1798c2ecf20Sopenharmony_ci#define SPI_TXTDIS_OFFSET			9
1808c2ecf20Sopenharmony_ci#define SPI_TXTDIS_SIZE				1
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/* Bitfields in FMR */
1838c2ecf20Sopenharmony_ci#define SPI_TXRDYM_OFFSET			0
1848c2ecf20Sopenharmony_ci#define SPI_TXRDYM_SIZE				2
1858c2ecf20Sopenharmony_ci#define SPI_RXRDYM_OFFSET			4
1868c2ecf20Sopenharmony_ci#define SPI_RXRDYM_SIZE				2
1878c2ecf20Sopenharmony_ci#define SPI_TXFTHRES_OFFSET			16
1888c2ecf20Sopenharmony_ci#define SPI_TXFTHRES_SIZE			6
1898c2ecf20Sopenharmony_ci#define SPI_RXFTHRES_OFFSET			24
1908c2ecf20Sopenharmony_ci#define SPI_RXFTHRES_SIZE			6
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/* Bitfields in FLR */
1938c2ecf20Sopenharmony_ci#define SPI_TXFL_OFFSET				0
1948c2ecf20Sopenharmony_ci#define SPI_TXFL_SIZE				6
1958c2ecf20Sopenharmony_ci#define SPI_RXFL_OFFSET				16
1968c2ecf20Sopenharmony_ci#define SPI_RXFL_SIZE				6
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci/* Constants for BITS */
1998c2ecf20Sopenharmony_ci#define SPI_BITS_8_BPT				0
2008c2ecf20Sopenharmony_ci#define SPI_BITS_9_BPT				1
2018c2ecf20Sopenharmony_ci#define SPI_BITS_10_BPT				2
2028c2ecf20Sopenharmony_ci#define SPI_BITS_11_BPT				3
2038c2ecf20Sopenharmony_ci#define SPI_BITS_12_BPT				4
2048c2ecf20Sopenharmony_ci#define SPI_BITS_13_BPT				5
2058c2ecf20Sopenharmony_ci#define SPI_BITS_14_BPT				6
2068c2ecf20Sopenharmony_ci#define SPI_BITS_15_BPT				7
2078c2ecf20Sopenharmony_ci#define SPI_BITS_16_BPT				8
2088c2ecf20Sopenharmony_ci#define SPI_ONE_DATA				0
2098c2ecf20Sopenharmony_ci#define SPI_TWO_DATA				1
2108c2ecf20Sopenharmony_ci#define SPI_FOUR_DATA				2
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci/* Bit manipulation macros */
2138c2ecf20Sopenharmony_ci#define SPI_BIT(name) \
2148c2ecf20Sopenharmony_ci	(1 << SPI_##name##_OFFSET)
2158c2ecf20Sopenharmony_ci#define SPI_BF(name, value) \
2168c2ecf20Sopenharmony_ci	(((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET)
2178c2ecf20Sopenharmony_ci#define SPI_BFEXT(name, value) \
2188c2ecf20Sopenharmony_ci	(((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1))
2198c2ecf20Sopenharmony_ci#define SPI_BFINS(name, value, old) \
2208c2ecf20Sopenharmony_ci	(((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \
2218c2ecf20Sopenharmony_ci	  | SPI_BF(name, value))
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/* Register access macros */
2248c2ecf20Sopenharmony_ci#define spi_readl(port, reg) \
2258c2ecf20Sopenharmony_ci	readl_relaxed((port)->regs + SPI_##reg)
2268c2ecf20Sopenharmony_ci#define spi_writel(port, reg, value) \
2278c2ecf20Sopenharmony_ci	writel_relaxed((value), (port)->regs + SPI_##reg)
2288c2ecf20Sopenharmony_ci#define spi_writew(port, reg, value) \
2298c2ecf20Sopenharmony_ci	writew_relaxed((value), (port)->regs + SPI_##reg)
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci/* use PIO for small transfers, avoiding DMA setup/teardown overhead and
2328c2ecf20Sopenharmony_ci * cache operations; better heuristics consider wordsize and bitrate.
2338c2ecf20Sopenharmony_ci */
2348c2ecf20Sopenharmony_ci#define DMA_MIN_BYTES	16
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci#define SPI_DMA_TIMEOUT		(msecs_to_jiffies(1000))
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci#define AUTOSUSPEND_TIMEOUT	2000
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistruct atmel_spi_caps {
2418c2ecf20Sopenharmony_ci	bool	is_spi2;
2428c2ecf20Sopenharmony_ci	bool	has_wdrbt;
2438c2ecf20Sopenharmony_ci	bool	has_dma_support;
2448c2ecf20Sopenharmony_ci	bool	has_pdc_support;
2458c2ecf20Sopenharmony_ci};
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci/*
2488c2ecf20Sopenharmony_ci * The core SPI transfer engine just talks to a register bank to set up
2498c2ecf20Sopenharmony_ci * DMA transfers; transfer queue progress is driven by IRQs.  The clock
2508c2ecf20Sopenharmony_ci * framework provides the base clock, subdivided for each spi_device.
2518c2ecf20Sopenharmony_ci */
2528c2ecf20Sopenharmony_cistruct atmel_spi {
2538c2ecf20Sopenharmony_ci	spinlock_t		lock;
2548c2ecf20Sopenharmony_ci	unsigned long		flags;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	phys_addr_t		phybase;
2578c2ecf20Sopenharmony_ci	void __iomem		*regs;
2588c2ecf20Sopenharmony_ci	int			irq;
2598c2ecf20Sopenharmony_ci	struct clk		*clk;
2608c2ecf20Sopenharmony_ci	struct platform_device	*pdev;
2618c2ecf20Sopenharmony_ci	unsigned long		spi_clk;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	struct spi_transfer	*current_transfer;
2648c2ecf20Sopenharmony_ci	int			current_remaining_bytes;
2658c2ecf20Sopenharmony_ci	int			done_status;
2668c2ecf20Sopenharmony_ci	dma_addr_t		dma_addr_rx_bbuf;
2678c2ecf20Sopenharmony_ci	dma_addr_t		dma_addr_tx_bbuf;
2688c2ecf20Sopenharmony_ci	void			*addr_rx_bbuf;
2698c2ecf20Sopenharmony_ci	void			*addr_tx_bbuf;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	struct completion	xfer_completion;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	struct atmel_spi_caps	caps;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	bool			use_dma;
2768c2ecf20Sopenharmony_ci	bool			use_pdc;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	bool			keep_cs;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	u32			fifo_size;
2818c2ecf20Sopenharmony_ci	u8			native_cs_free;
2828c2ecf20Sopenharmony_ci	u8			native_cs_for_gpio;
2838c2ecf20Sopenharmony_ci};
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/* Controller-specific per-slave state */
2868c2ecf20Sopenharmony_cistruct atmel_spi_device {
2878c2ecf20Sopenharmony_ci	u32			csr;
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci#define SPI_MAX_DMA_XFER	65535 /* true for both PDC and DMA */
2918c2ecf20Sopenharmony_ci#define INVALID_DMA_ADDRESS	0xffffffff
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci/*
2948c2ecf20Sopenharmony_ci * Version 2 of the SPI controller has
2958c2ecf20Sopenharmony_ci *  - CR.LASTXFER
2968c2ecf20Sopenharmony_ci *  - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero)
2978c2ecf20Sopenharmony_ci *  - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs)
2988c2ecf20Sopenharmony_ci *  - SPI_CSRx.CSAAT
2998c2ecf20Sopenharmony_ci *  - SPI_CSRx.SBCR allows faster clocking
3008c2ecf20Sopenharmony_ci */
3018c2ecf20Sopenharmony_cistatic bool atmel_spi_is_v2(struct atmel_spi *as)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	return as->caps.is_spi2;
3048c2ecf20Sopenharmony_ci}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci/*
3078c2ecf20Sopenharmony_ci * Earlier SPI controllers (e.g. on at91rm9200) have a design bug whereby
3088c2ecf20Sopenharmony_ci * they assume that spi slave device state will not change on deselect, so
3098c2ecf20Sopenharmony_ci * that automagic deselection is OK.  ("NPCSx rises if no data is to be
3108c2ecf20Sopenharmony_ci * transmitted")  Not so!  Workaround uses nCSx pins as GPIOs; or newer
3118c2ecf20Sopenharmony_ci * controllers have CSAAT and friends.
3128c2ecf20Sopenharmony_ci *
3138c2ecf20Sopenharmony_ci * Even controller newer than ar91rm9200, using GPIOs can make sens as
3148c2ecf20Sopenharmony_ci * it lets us support active-high chipselects despite the controller's
3158c2ecf20Sopenharmony_ci * belief that only active-low devices/systems exists.
3168c2ecf20Sopenharmony_ci *
3178c2ecf20Sopenharmony_ci * However, at91rm9200 has a second erratum whereby nCS0 doesn't work
3188c2ecf20Sopenharmony_ci * right when driven with GPIO.  ("Mode Fault does not allow more than one
3198c2ecf20Sopenharmony_ci * Master on Chip Select 0.")  No workaround exists for that ... so for
3208c2ecf20Sopenharmony_ci * nCS0 on that chip, we (a) don't use the GPIO, (b) can't support CS_HIGH,
3218c2ecf20Sopenharmony_ci * and (c) will trigger that first erratum in some cases.
3228c2ecf20Sopenharmony_ci */
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic void cs_activate(struct atmel_spi *as, struct spi_device *spi)
3258c2ecf20Sopenharmony_ci{
3268c2ecf20Sopenharmony_ci	struct atmel_spi_device *asd = spi->controller_state;
3278c2ecf20Sopenharmony_ci	int chip_select;
3288c2ecf20Sopenharmony_ci	u32 mr;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (spi->cs_gpiod)
3318c2ecf20Sopenharmony_ci		chip_select = as->native_cs_for_gpio;
3328c2ecf20Sopenharmony_ci	else
3338c2ecf20Sopenharmony_ci		chip_select = spi->chip_select;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (atmel_spi_is_v2(as)) {
3368c2ecf20Sopenharmony_ci		spi_writel(as, CSR0 + 4 * chip_select, asd->csr);
3378c2ecf20Sopenharmony_ci		/* For the low SPI version, there is a issue that PDC transfer
3388c2ecf20Sopenharmony_ci		 * on CS1,2,3 needs SPI_CSR0.BITS config as SPI_CSR1,2,3.BITS
3398c2ecf20Sopenharmony_ci		 */
3408c2ecf20Sopenharmony_ci		spi_writel(as, CSR0, asd->csr);
3418c2ecf20Sopenharmony_ci		if (as->caps.has_wdrbt) {
3428c2ecf20Sopenharmony_ci			spi_writel(as, MR,
3438c2ecf20Sopenharmony_ci					SPI_BF(PCS, ~(0x01 << chip_select))
3448c2ecf20Sopenharmony_ci					| SPI_BIT(WDRBT)
3458c2ecf20Sopenharmony_ci					| SPI_BIT(MODFDIS)
3468c2ecf20Sopenharmony_ci					| SPI_BIT(MSTR));
3478c2ecf20Sopenharmony_ci		} else {
3488c2ecf20Sopenharmony_ci			spi_writel(as, MR,
3498c2ecf20Sopenharmony_ci					SPI_BF(PCS, ~(0x01 << chip_select))
3508c2ecf20Sopenharmony_ci					| SPI_BIT(MODFDIS)
3518c2ecf20Sopenharmony_ci					| SPI_BIT(MSTR));
3528c2ecf20Sopenharmony_ci		}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci		mr = spi_readl(as, MR);
3558c2ecf20Sopenharmony_ci	} else {
3568c2ecf20Sopenharmony_ci		u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
3578c2ecf20Sopenharmony_ci		int i;
3588c2ecf20Sopenharmony_ci		u32 csr;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci		/* Make sure clock polarity is correct */
3618c2ecf20Sopenharmony_ci		for (i = 0; i < spi->master->num_chipselect; i++) {
3628c2ecf20Sopenharmony_ci			csr = spi_readl(as, CSR0 + 4 * i);
3638c2ecf20Sopenharmony_ci			if ((csr ^ cpol) & SPI_BIT(CPOL))
3648c2ecf20Sopenharmony_ci				spi_writel(as, CSR0 + 4 * i,
3658c2ecf20Sopenharmony_ci						csr ^ SPI_BIT(CPOL));
3668c2ecf20Sopenharmony_ci		}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci		mr = spi_readl(as, MR);
3698c2ecf20Sopenharmony_ci		mr = SPI_BFINS(PCS, ~(1 << chip_select), mr);
3708c2ecf20Sopenharmony_ci		spi_writel(as, MR, mr);
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	dev_dbg(&spi->dev, "activate NPCS, mr %08x\n", mr);
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_cistatic void cs_deactivate(struct atmel_spi *as, struct spi_device *spi)
3778c2ecf20Sopenharmony_ci{
3788c2ecf20Sopenharmony_ci	int chip_select;
3798c2ecf20Sopenharmony_ci	u32 mr;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	if (spi->cs_gpiod)
3828c2ecf20Sopenharmony_ci		chip_select = as->native_cs_for_gpio;
3838c2ecf20Sopenharmony_ci	else
3848c2ecf20Sopenharmony_ci		chip_select = spi->chip_select;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	/* only deactivate *this* device; sometimes transfers to
3878c2ecf20Sopenharmony_ci	 * another device may be active when this routine is called.
3888c2ecf20Sopenharmony_ci	 */
3898c2ecf20Sopenharmony_ci	mr = spi_readl(as, MR);
3908c2ecf20Sopenharmony_ci	if (~SPI_BFEXT(PCS, mr) & (1 << chip_select)) {
3918c2ecf20Sopenharmony_ci		mr = SPI_BFINS(PCS, 0xf, mr);
3928c2ecf20Sopenharmony_ci		spi_writel(as, MR, mr);
3938c2ecf20Sopenharmony_ci	}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	dev_dbg(&spi->dev, "DEactivate NPCS, mr %08x\n", mr);
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	if (!spi->cs_gpiod)
3988c2ecf20Sopenharmony_ci		spi_writel(as, CR, SPI_BIT(LASTXFER));
3998c2ecf20Sopenharmony_ci}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	spin_lock_irqsave(&as->lock, as->flags);
4048c2ecf20Sopenharmony_ci}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&as->lock, as->flags);
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf);
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_cistatic inline bool atmel_spi_use_dma(struct atmel_spi *as,
4178c2ecf20Sopenharmony_ci				struct spi_transfer *xfer)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	return as->use_dma && xfer->len >= DMA_MIN_BYTES;
4208c2ecf20Sopenharmony_ci}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_cistatic bool atmel_spi_can_dma(struct spi_master *master,
4238c2ecf20Sopenharmony_ci			      struct spi_device *spi,
4248c2ecf20Sopenharmony_ci			      struct spi_transfer *xfer)
4258c2ecf20Sopenharmony_ci{
4268c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5))
4298c2ecf20Sopenharmony_ci		return atmel_spi_use_dma(as, xfer) &&
4308c2ecf20Sopenharmony_ci			!atmel_spi_is_vmalloc_xfer(xfer);
4318c2ecf20Sopenharmony_ci	else
4328c2ecf20Sopenharmony_ci		return atmel_spi_use_dma(as, xfer);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic int atmel_spi_dma_slave_config(struct atmel_spi *as,
4378c2ecf20Sopenharmony_ci				struct dma_slave_config *slave_config,
4388c2ecf20Sopenharmony_ci				u8 bits_per_word)
4398c2ecf20Sopenharmony_ci{
4408c2ecf20Sopenharmony_ci	struct spi_master *master = platform_get_drvdata(as->pdev);
4418c2ecf20Sopenharmony_ci	int err = 0;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	if (bits_per_word > 8) {
4448c2ecf20Sopenharmony_ci		slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
4458c2ecf20Sopenharmony_ci		slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
4468c2ecf20Sopenharmony_ci	} else {
4478c2ecf20Sopenharmony_ci		slave_config->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
4488c2ecf20Sopenharmony_ci		slave_config->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	slave_config->dst_addr = (dma_addr_t)as->phybase + SPI_TDR;
4528c2ecf20Sopenharmony_ci	slave_config->src_addr = (dma_addr_t)as->phybase + SPI_RDR;
4538c2ecf20Sopenharmony_ci	slave_config->src_maxburst = 1;
4548c2ecf20Sopenharmony_ci	slave_config->dst_maxburst = 1;
4558c2ecf20Sopenharmony_ci	slave_config->device_fc = false;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/*
4588c2ecf20Sopenharmony_ci	 * This driver uses fixed peripheral select mode (PS bit set to '0' in
4598c2ecf20Sopenharmony_ci	 * the Mode Register).
4608c2ecf20Sopenharmony_ci	 * So according to the datasheet, when FIFOs are available (and
4618c2ecf20Sopenharmony_ci	 * enabled), the Transmit FIFO operates in Multiple Data Mode.
4628c2ecf20Sopenharmony_ci	 * In this mode, up to 2 data, not 4, can be written into the Transmit
4638c2ecf20Sopenharmony_ci	 * Data Register in a single access.
4648c2ecf20Sopenharmony_ci	 * However, the first data has to be written into the lowest 16 bits and
4658c2ecf20Sopenharmony_ci	 * the second data into the highest 16 bits of the Transmit
4668c2ecf20Sopenharmony_ci	 * Data Register. For 8bit data (the most frequent case), it would
4678c2ecf20Sopenharmony_ci	 * require to rework tx_buf so each data would actualy fit 16 bits.
4688c2ecf20Sopenharmony_ci	 * So we'd rather write only one data at the time. Hence the transmit
4698c2ecf20Sopenharmony_ci	 * path works the same whether FIFOs are available (and enabled) or not.
4708c2ecf20Sopenharmony_ci	 */
4718c2ecf20Sopenharmony_ci	slave_config->direction = DMA_MEM_TO_DEV;
4728c2ecf20Sopenharmony_ci	if (dmaengine_slave_config(master->dma_tx, slave_config)) {
4738c2ecf20Sopenharmony_ci		dev_err(&as->pdev->dev,
4748c2ecf20Sopenharmony_ci			"failed to configure tx dma channel\n");
4758c2ecf20Sopenharmony_ci		err = -EINVAL;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/*
4798c2ecf20Sopenharmony_ci	 * This driver configures the spi controller for master mode (MSTR bit
4808c2ecf20Sopenharmony_ci	 * set to '1' in the Mode Register).
4818c2ecf20Sopenharmony_ci	 * So according to the datasheet, when FIFOs are available (and
4828c2ecf20Sopenharmony_ci	 * enabled), the Receive FIFO operates in Single Data Mode.
4838c2ecf20Sopenharmony_ci	 * So the receive path works the same whether FIFOs are available (and
4848c2ecf20Sopenharmony_ci	 * enabled) or not.
4858c2ecf20Sopenharmony_ci	 */
4868c2ecf20Sopenharmony_ci	slave_config->direction = DMA_DEV_TO_MEM;
4878c2ecf20Sopenharmony_ci	if (dmaengine_slave_config(master->dma_rx, slave_config)) {
4888c2ecf20Sopenharmony_ci		dev_err(&as->pdev->dev,
4898c2ecf20Sopenharmony_ci			"failed to configure rx dma channel\n");
4908c2ecf20Sopenharmony_ci		err = -EINVAL;
4918c2ecf20Sopenharmony_ci	}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return err;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic int atmel_spi_configure_dma(struct spi_master *master,
4978c2ecf20Sopenharmony_ci				   struct atmel_spi *as)
4988c2ecf20Sopenharmony_ci{
4998c2ecf20Sopenharmony_ci	struct dma_slave_config	slave_config;
5008c2ecf20Sopenharmony_ci	struct device *dev = &as->pdev->dev;
5018c2ecf20Sopenharmony_ci	int err;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	dma_cap_mask_t mask;
5048c2ecf20Sopenharmony_ci	dma_cap_zero(mask);
5058c2ecf20Sopenharmony_ci	dma_cap_set(DMA_SLAVE, mask);
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	master->dma_tx = dma_request_chan(dev, "tx");
5088c2ecf20Sopenharmony_ci	if (IS_ERR(master->dma_tx)) {
5098c2ecf20Sopenharmony_ci		err = dev_err_probe(dev, PTR_ERR(master->dma_tx),
5108c2ecf20Sopenharmony_ci				    "No TX DMA channel, DMA is disabled\n");
5118c2ecf20Sopenharmony_ci		goto error_clear;
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	master->dma_rx = dma_request_chan(dev, "rx");
5158c2ecf20Sopenharmony_ci	if (IS_ERR(master->dma_rx)) {
5168c2ecf20Sopenharmony_ci		err = PTR_ERR(master->dma_rx);
5178c2ecf20Sopenharmony_ci		/*
5188c2ecf20Sopenharmony_ci		 * No reason to check EPROBE_DEFER here since we have already
5198c2ecf20Sopenharmony_ci		 * requested tx channel.
5208c2ecf20Sopenharmony_ci		 */
5218c2ecf20Sopenharmony_ci		dev_err(dev, "No RX DMA channel, DMA is disabled\n");
5228c2ecf20Sopenharmony_ci		goto error;
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	err = atmel_spi_dma_slave_config(as, &slave_config, 8);
5268c2ecf20Sopenharmony_ci	if (err)
5278c2ecf20Sopenharmony_ci		goto error;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	dev_info(&as->pdev->dev,
5308c2ecf20Sopenharmony_ci			"Using %s (tx) and %s (rx) for DMA transfers\n",
5318c2ecf20Sopenharmony_ci			dma_chan_name(master->dma_tx),
5328c2ecf20Sopenharmony_ci			dma_chan_name(master->dma_rx));
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	return 0;
5358c2ecf20Sopenharmony_cierror:
5368c2ecf20Sopenharmony_ci	if (!IS_ERR(master->dma_rx))
5378c2ecf20Sopenharmony_ci		dma_release_channel(master->dma_rx);
5388c2ecf20Sopenharmony_ci	if (!IS_ERR(master->dma_tx))
5398c2ecf20Sopenharmony_ci		dma_release_channel(master->dma_tx);
5408c2ecf20Sopenharmony_cierror_clear:
5418c2ecf20Sopenharmony_ci	master->dma_tx = master->dma_rx = NULL;
5428c2ecf20Sopenharmony_ci	return err;
5438c2ecf20Sopenharmony_ci}
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_cistatic void atmel_spi_stop_dma(struct spi_master *master)
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	if (master->dma_rx)
5488c2ecf20Sopenharmony_ci		dmaengine_terminate_all(master->dma_rx);
5498c2ecf20Sopenharmony_ci	if (master->dma_tx)
5508c2ecf20Sopenharmony_ci		dmaengine_terminate_all(master->dma_tx);
5518c2ecf20Sopenharmony_ci}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_cistatic void atmel_spi_release_dma(struct spi_master *master)
5548c2ecf20Sopenharmony_ci{
5558c2ecf20Sopenharmony_ci	if (master->dma_rx) {
5568c2ecf20Sopenharmony_ci		dma_release_channel(master->dma_rx);
5578c2ecf20Sopenharmony_ci		master->dma_rx = NULL;
5588c2ecf20Sopenharmony_ci	}
5598c2ecf20Sopenharmony_ci	if (master->dma_tx) {
5608c2ecf20Sopenharmony_ci		dma_release_channel(master->dma_tx);
5618c2ecf20Sopenharmony_ci		master->dma_tx = NULL;
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci}
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci/* This function is called by the DMA driver from tasklet context */
5668c2ecf20Sopenharmony_cistatic void dma_callback(void *data)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct spi_master	*master = data;
5698c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	if (is_vmalloc_addr(as->current_transfer->rx_buf) &&
5728c2ecf20Sopenharmony_ci	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
5738c2ecf20Sopenharmony_ci		memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf,
5748c2ecf20Sopenharmony_ci		       as->current_transfer->len);
5758c2ecf20Sopenharmony_ci	}
5768c2ecf20Sopenharmony_ci	complete(&as->xfer_completion);
5778c2ecf20Sopenharmony_ci}
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci/*
5808c2ecf20Sopenharmony_ci * Next transfer using PIO without FIFO.
5818c2ecf20Sopenharmony_ci */
5828c2ecf20Sopenharmony_cistatic void atmel_spi_next_xfer_single(struct spi_master *master,
5838c2ecf20Sopenharmony_ci				       struct spi_transfer *xfer)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
5868c2ecf20Sopenharmony_ci	unsigned long xfer_pos = xfer->len - as->current_remaining_bytes;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_pio\n");
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	/* Make sure data is not remaining in RDR */
5918c2ecf20Sopenharmony_ci	spi_readl(as, RDR);
5928c2ecf20Sopenharmony_ci	while (spi_readl(as, SR) & SPI_BIT(RDRF)) {
5938c2ecf20Sopenharmony_ci		spi_readl(as, RDR);
5948c2ecf20Sopenharmony_ci		cpu_relax();
5958c2ecf20Sopenharmony_ci	}
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8)
5988c2ecf20Sopenharmony_ci		spi_writel(as, TDR, *(u16 *)(xfer->tx_buf + xfer_pos));
5998c2ecf20Sopenharmony_ci	else
6008c2ecf20Sopenharmony_ci		spi_writel(as, TDR, *(u8 *)(xfer->tx_buf + xfer_pos));
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	dev_dbg(master->dev.parent,
6038c2ecf20Sopenharmony_ci		"  start pio xfer %p: len %u tx %p rx %p bitpw %d\n",
6048c2ecf20Sopenharmony_ci		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf,
6058c2ecf20Sopenharmony_ci		xfer->bits_per_word);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	/* Enable relevant interrupts */
6088c2ecf20Sopenharmony_ci	spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES));
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci/*
6128c2ecf20Sopenharmony_ci * Next transfer using PIO with FIFO.
6138c2ecf20Sopenharmony_ci */
6148c2ecf20Sopenharmony_cistatic void atmel_spi_next_xfer_fifo(struct spi_master *master,
6158c2ecf20Sopenharmony_ci				     struct spi_transfer *xfer)
6168c2ecf20Sopenharmony_ci{
6178c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
6188c2ecf20Sopenharmony_ci	u32 current_remaining_data, num_data;
6198c2ecf20Sopenharmony_ci	u32 offset = xfer->len - as->current_remaining_bytes;
6208c2ecf20Sopenharmony_ci	const u16 *words = (const u16 *)((u8 *)xfer->tx_buf + offset);
6218c2ecf20Sopenharmony_ci	const u8  *bytes = (const u8  *)((u8 *)xfer->tx_buf + offset);
6228c2ecf20Sopenharmony_ci	u16 td0, td1;
6238c2ecf20Sopenharmony_ci	u32 fifomr;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_fifo\n");
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci	/* Compute the number of data to transfer in the current iteration */
6288c2ecf20Sopenharmony_ci	current_remaining_data = ((xfer->bits_per_word > 8) ?
6298c2ecf20Sopenharmony_ci				  ((u32)as->current_remaining_bytes >> 1) :
6308c2ecf20Sopenharmony_ci				  (u32)as->current_remaining_bytes);
6318c2ecf20Sopenharmony_ci	num_data = min(current_remaining_data, as->fifo_size);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	/* Flush RX and TX FIFOs */
6348c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(RXFCLR) | SPI_BIT(TXFCLR));
6358c2ecf20Sopenharmony_ci	while (spi_readl(as, FLR))
6368c2ecf20Sopenharmony_ci		cpu_relax();
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	/* Set RX FIFO Threshold to the number of data to transfer */
6398c2ecf20Sopenharmony_ci	fifomr = spi_readl(as, FMR);
6408c2ecf20Sopenharmony_ci	spi_writel(as, FMR, SPI_BFINS(RXFTHRES, num_data, fifomr));
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	/* Clear FIFO flags in the Status Register, especially RXFTHF */
6438c2ecf20Sopenharmony_ci	(void)spi_readl(as, SR);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	/* Fill TX FIFO */
6468c2ecf20Sopenharmony_ci	while (num_data >= 2) {
6478c2ecf20Sopenharmony_ci		if (xfer->bits_per_word > 8) {
6488c2ecf20Sopenharmony_ci			td0 = *words++;
6498c2ecf20Sopenharmony_ci			td1 = *words++;
6508c2ecf20Sopenharmony_ci		} else {
6518c2ecf20Sopenharmony_ci			td0 = *bytes++;
6528c2ecf20Sopenharmony_ci			td1 = *bytes++;
6538c2ecf20Sopenharmony_ci		}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci		spi_writel(as, TDR, (td1 << 16) | td0);
6568c2ecf20Sopenharmony_ci		num_data -= 2;
6578c2ecf20Sopenharmony_ci	}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	if (num_data) {
6608c2ecf20Sopenharmony_ci		if (xfer->bits_per_word > 8)
6618c2ecf20Sopenharmony_ci			td0 = *words++;
6628c2ecf20Sopenharmony_ci		else
6638c2ecf20Sopenharmony_ci			td0 = *bytes++;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci		spi_writew(as, TDR, td0);
6668c2ecf20Sopenharmony_ci		num_data--;
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	dev_dbg(master->dev.parent,
6708c2ecf20Sopenharmony_ci		"  start fifo xfer %p: len %u tx %p rx %p bitpw %d\n",
6718c2ecf20Sopenharmony_ci		xfer, xfer->len, xfer->tx_buf, xfer->rx_buf,
6728c2ecf20Sopenharmony_ci		xfer->bits_per_word);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	/*
6758c2ecf20Sopenharmony_ci	 * Enable RX FIFO Threshold Flag interrupt to be notified about
6768c2ecf20Sopenharmony_ci	 * transfer completion.
6778c2ecf20Sopenharmony_ci	 */
6788c2ecf20Sopenharmony_ci	spi_writel(as, IER, SPI_BIT(RXFTHF) | SPI_BIT(OVRES));
6798c2ecf20Sopenharmony_ci}
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci/*
6828c2ecf20Sopenharmony_ci * Next transfer using PIO.
6838c2ecf20Sopenharmony_ci */
6848c2ecf20Sopenharmony_cistatic void atmel_spi_next_xfer_pio(struct spi_master *master,
6858c2ecf20Sopenharmony_ci				    struct spi_transfer *xfer)
6868c2ecf20Sopenharmony_ci{
6878c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (as->fifo_size)
6908c2ecf20Sopenharmony_ci		atmel_spi_next_xfer_fifo(master, xfer);
6918c2ecf20Sopenharmony_ci	else
6928c2ecf20Sopenharmony_ci		atmel_spi_next_xfer_single(master, xfer);
6938c2ecf20Sopenharmony_ci}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci/*
6968c2ecf20Sopenharmony_ci * Submit next transfer for DMA.
6978c2ecf20Sopenharmony_ci */
6988c2ecf20Sopenharmony_cistatic int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
6998c2ecf20Sopenharmony_ci				struct spi_transfer *xfer,
7008c2ecf20Sopenharmony_ci				u32 *plen)
7018c2ecf20Sopenharmony_ci	__must_hold(&as->lock)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
7048c2ecf20Sopenharmony_ci	struct dma_chan		*rxchan = master->dma_rx;
7058c2ecf20Sopenharmony_ci	struct dma_chan		*txchan = master->dma_tx;
7068c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *rxdesc;
7078c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *txdesc;
7088c2ecf20Sopenharmony_ci	struct dma_slave_config	slave_config;
7098c2ecf20Sopenharmony_ci	dma_cookie_t		cookie;
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	dev_vdbg(master->dev.parent, "atmel_spi_next_xfer_dma_submit\n");
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	/* Check that the channels are available */
7148c2ecf20Sopenharmony_ci	if (!rxchan || !txchan)
7158c2ecf20Sopenharmony_ci		return -ENODEV;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	/* release lock for DMA operations */
7188c2ecf20Sopenharmony_ci	atmel_spi_unlock(as);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	*plen = xfer->len;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (atmel_spi_dma_slave_config(as, &slave_config,
7238c2ecf20Sopenharmony_ci				       xfer->bits_per_word))
7248c2ecf20Sopenharmony_ci		goto err_exit;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/* Send both scatterlists */
7278c2ecf20Sopenharmony_ci	if (atmel_spi_is_vmalloc_xfer(xfer) &&
7288c2ecf20Sopenharmony_ci	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
7298c2ecf20Sopenharmony_ci		rxdesc = dmaengine_prep_slave_single(rxchan,
7308c2ecf20Sopenharmony_ci						     as->dma_addr_rx_bbuf,
7318c2ecf20Sopenharmony_ci						     xfer->len,
7328c2ecf20Sopenharmony_ci						     DMA_DEV_TO_MEM,
7338c2ecf20Sopenharmony_ci						     DMA_PREP_INTERRUPT |
7348c2ecf20Sopenharmony_ci						     DMA_CTRL_ACK);
7358c2ecf20Sopenharmony_ci	} else {
7368c2ecf20Sopenharmony_ci		rxdesc = dmaengine_prep_slave_sg(rxchan,
7378c2ecf20Sopenharmony_ci						 xfer->rx_sg.sgl,
7388c2ecf20Sopenharmony_ci						 xfer->rx_sg.nents,
7398c2ecf20Sopenharmony_ci						 DMA_DEV_TO_MEM,
7408c2ecf20Sopenharmony_ci						 DMA_PREP_INTERRUPT |
7418c2ecf20Sopenharmony_ci						 DMA_CTRL_ACK);
7428c2ecf20Sopenharmony_ci	}
7438c2ecf20Sopenharmony_ci	if (!rxdesc)
7448c2ecf20Sopenharmony_ci		goto err_dma;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	if (atmel_spi_is_vmalloc_xfer(xfer) &&
7478c2ecf20Sopenharmony_ci	    IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
7488c2ecf20Sopenharmony_ci		memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len);
7498c2ecf20Sopenharmony_ci		txdesc = dmaengine_prep_slave_single(txchan,
7508c2ecf20Sopenharmony_ci						     as->dma_addr_tx_bbuf,
7518c2ecf20Sopenharmony_ci						     xfer->len, DMA_MEM_TO_DEV,
7528c2ecf20Sopenharmony_ci						     DMA_PREP_INTERRUPT |
7538c2ecf20Sopenharmony_ci						     DMA_CTRL_ACK);
7548c2ecf20Sopenharmony_ci	} else {
7558c2ecf20Sopenharmony_ci		txdesc = dmaengine_prep_slave_sg(txchan,
7568c2ecf20Sopenharmony_ci						 xfer->tx_sg.sgl,
7578c2ecf20Sopenharmony_ci						 xfer->tx_sg.nents,
7588c2ecf20Sopenharmony_ci						 DMA_MEM_TO_DEV,
7598c2ecf20Sopenharmony_ci						 DMA_PREP_INTERRUPT |
7608c2ecf20Sopenharmony_ci						 DMA_CTRL_ACK);
7618c2ecf20Sopenharmony_ci	}
7628c2ecf20Sopenharmony_ci	if (!txdesc)
7638c2ecf20Sopenharmony_ci		goto err_dma;
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	dev_dbg(master->dev.parent,
7668c2ecf20Sopenharmony_ci		"  start dma xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
7678c2ecf20Sopenharmony_ci		xfer, xfer->len, xfer->tx_buf, (unsigned long long)xfer->tx_dma,
7688c2ecf20Sopenharmony_ci		xfer->rx_buf, (unsigned long long)xfer->rx_dma);
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	/* Enable relevant interrupts */
7718c2ecf20Sopenharmony_ci	spi_writel(as, IER, SPI_BIT(OVRES));
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	/* Put the callback on the RX transfer only, that should finish last */
7748c2ecf20Sopenharmony_ci	rxdesc->callback = dma_callback;
7758c2ecf20Sopenharmony_ci	rxdesc->callback_param = master;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	/* Submit and fire RX and TX with TX last so we're ready to read! */
7788c2ecf20Sopenharmony_ci	cookie = rxdesc->tx_submit(rxdesc);
7798c2ecf20Sopenharmony_ci	if (dma_submit_error(cookie))
7808c2ecf20Sopenharmony_ci		goto err_dma;
7818c2ecf20Sopenharmony_ci	cookie = txdesc->tx_submit(txdesc);
7828c2ecf20Sopenharmony_ci	if (dma_submit_error(cookie))
7838c2ecf20Sopenharmony_ci		goto err_dma;
7848c2ecf20Sopenharmony_ci	rxchan->device->device_issue_pending(rxchan);
7858c2ecf20Sopenharmony_ci	txchan->device->device_issue_pending(txchan);
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	/* take back lock */
7888c2ecf20Sopenharmony_ci	atmel_spi_lock(as);
7898c2ecf20Sopenharmony_ci	return 0;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_cierr_dma:
7928c2ecf20Sopenharmony_ci	spi_writel(as, IDR, SPI_BIT(OVRES));
7938c2ecf20Sopenharmony_ci	atmel_spi_stop_dma(master);
7948c2ecf20Sopenharmony_cierr_exit:
7958c2ecf20Sopenharmony_ci	atmel_spi_lock(as);
7968c2ecf20Sopenharmony_ci	return -ENOMEM;
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_cistatic void atmel_spi_next_xfer_data(struct spi_master *master,
8008c2ecf20Sopenharmony_ci				struct spi_transfer *xfer,
8018c2ecf20Sopenharmony_ci				dma_addr_t *tx_dma,
8028c2ecf20Sopenharmony_ci				dma_addr_t *rx_dma,
8038c2ecf20Sopenharmony_ci				u32 *plen)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	*rx_dma = xfer->rx_dma + xfer->len - *plen;
8068c2ecf20Sopenharmony_ci	*tx_dma = xfer->tx_dma + xfer->len - *plen;
8078c2ecf20Sopenharmony_ci	if (*plen > master->max_dma_len)
8088c2ecf20Sopenharmony_ci		*plen = master->max_dma_len;
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic int atmel_spi_set_xfer_speed(struct atmel_spi *as,
8128c2ecf20Sopenharmony_ci				    struct spi_device *spi,
8138c2ecf20Sopenharmony_ci				    struct spi_transfer *xfer)
8148c2ecf20Sopenharmony_ci{
8158c2ecf20Sopenharmony_ci	u32			scbr, csr;
8168c2ecf20Sopenharmony_ci	unsigned long		bus_hz;
8178c2ecf20Sopenharmony_ci	int chip_select;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	if (spi->cs_gpiod)
8208c2ecf20Sopenharmony_ci		chip_select = as->native_cs_for_gpio;
8218c2ecf20Sopenharmony_ci	else
8228c2ecf20Sopenharmony_ci		chip_select = spi->chip_select;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/* v1 chips start out at half the peripheral bus speed. */
8258c2ecf20Sopenharmony_ci	bus_hz = as->spi_clk;
8268c2ecf20Sopenharmony_ci	if (!atmel_spi_is_v2(as))
8278c2ecf20Sopenharmony_ci		bus_hz /= 2;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	/*
8308c2ecf20Sopenharmony_ci	 * Calculate the lowest divider that satisfies the
8318c2ecf20Sopenharmony_ci	 * constraint, assuming div32/fdiv/mbz == 0.
8328c2ecf20Sopenharmony_ci	 */
8338c2ecf20Sopenharmony_ci	scbr = DIV_ROUND_UP(bus_hz, xfer->speed_hz);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	/*
8368c2ecf20Sopenharmony_ci	 * If the resulting divider doesn't fit into the
8378c2ecf20Sopenharmony_ci	 * register bitfield, we can't satisfy the constraint.
8388c2ecf20Sopenharmony_ci	 */
8398c2ecf20Sopenharmony_ci	if (scbr >= (1 << SPI_SCBR_SIZE)) {
8408c2ecf20Sopenharmony_ci		dev_err(&spi->dev,
8418c2ecf20Sopenharmony_ci			"setup: %d Hz too slow, scbr %u; min %ld Hz\n",
8428c2ecf20Sopenharmony_ci			xfer->speed_hz, scbr, bus_hz/255);
8438c2ecf20Sopenharmony_ci		return -EINVAL;
8448c2ecf20Sopenharmony_ci	}
8458c2ecf20Sopenharmony_ci	if (scbr == 0) {
8468c2ecf20Sopenharmony_ci		dev_err(&spi->dev,
8478c2ecf20Sopenharmony_ci			"setup: %d Hz too high, scbr %u; max %ld Hz\n",
8488c2ecf20Sopenharmony_ci			xfer->speed_hz, scbr, bus_hz);
8498c2ecf20Sopenharmony_ci		return -EINVAL;
8508c2ecf20Sopenharmony_ci	}
8518c2ecf20Sopenharmony_ci	csr = spi_readl(as, CSR0 + 4 * chip_select);
8528c2ecf20Sopenharmony_ci	csr = SPI_BFINS(SCBR, scbr, csr);
8538c2ecf20Sopenharmony_ci	spi_writel(as, CSR0 + 4 * chip_select, csr);
8548c2ecf20Sopenharmony_ci	xfer->effective_speed_hz = bus_hz / scbr;
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	return 0;
8578c2ecf20Sopenharmony_ci}
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci/*
8608c2ecf20Sopenharmony_ci * Submit next transfer for PDC.
8618c2ecf20Sopenharmony_ci * lock is held, spi irq is blocked
8628c2ecf20Sopenharmony_ci */
8638c2ecf20Sopenharmony_cistatic void atmel_spi_pdc_next_xfer(struct spi_master *master,
8648c2ecf20Sopenharmony_ci					struct spi_transfer *xfer)
8658c2ecf20Sopenharmony_ci{
8668c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
8678c2ecf20Sopenharmony_ci	u32			len;
8688c2ecf20Sopenharmony_ci	dma_addr_t		tx_dma, rx_dma;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	len = as->current_remaining_bytes;
8738c2ecf20Sopenharmony_ci	atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
8748c2ecf20Sopenharmony_ci	as->current_remaining_bytes -= len;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	spi_writel(as, RPR, rx_dma);
8778c2ecf20Sopenharmony_ci	spi_writel(as, TPR, tx_dma);
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8)
8808c2ecf20Sopenharmony_ci		len >>= 1;
8818c2ecf20Sopenharmony_ci	spi_writel(as, RCR, len);
8828c2ecf20Sopenharmony_ci	spi_writel(as, TCR, len);
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci	dev_dbg(&master->dev,
8858c2ecf20Sopenharmony_ci		"  start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
8868c2ecf20Sopenharmony_ci		xfer, xfer->len, xfer->tx_buf,
8878c2ecf20Sopenharmony_ci		(unsigned long long)xfer->tx_dma, xfer->rx_buf,
8888c2ecf20Sopenharmony_ci		(unsigned long long)xfer->rx_dma);
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	if (as->current_remaining_bytes) {
8918c2ecf20Sopenharmony_ci		len = as->current_remaining_bytes;
8928c2ecf20Sopenharmony_ci		atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len);
8938c2ecf20Sopenharmony_ci		as->current_remaining_bytes -= len;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci		spi_writel(as, RNPR, rx_dma);
8968c2ecf20Sopenharmony_ci		spi_writel(as, TNPR, tx_dma);
8978c2ecf20Sopenharmony_ci
8988c2ecf20Sopenharmony_ci		if (xfer->bits_per_word > 8)
8998c2ecf20Sopenharmony_ci			len >>= 1;
9008c2ecf20Sopenharmony_ci		spi_writel(as, RNCR, len);
9018c2ecf20Sopenharmony_ci		spi_writel(as, TNCR, len);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci		dev_dbg(&master->dev,
9048c2ecf20Sopenharmony_ci			"  next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n",
9058c2ecf20Sopenharmony_ci			xfer, xfer->len, xfer->tx_buf,
9068c2ecf20Sopenharmony_ci			(unsigned long long)xfer->tx_dma, xfer->rx_buf,
9078c2ecf20Sopenharmony_ci			(unsigned long long)xfer->rx_dma);
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	/* REVISIT: We're waiting for RXBUFF before we start the next
9118c2ecf20Sopenharmony_ci	 * transfer because we need to handle some difficult timing
9128c2ecf20Sopenharmony_ci	 * issues otherwise. If we wait for TXBUFE in one transfer and
9138c2ecf20Sopenharmony_ci	 * then starts waiting for RXBUFF in the next, it's difficult
9148c2ecf20Sopenharmony_ci	 * to tell the difference between the RXBUFF interrupt we're
9158c2ecf20Sopenharmony_ci	 * actually waiting for and the RXBUFF interrupt of the
9168c2ecf20Sopenharmony_ci	 * previous transfer.
9178c2ecf20Sopenharmony_ci	 *
9188c2ecf20Sopenharmony_ci	 * It should be doable, though. Just not now...
9198c2ecf20Sopenharmony_ci	 */
9208c2ecf20Sopenharmony_ci	spi_writel(as, IER, SPI_BIT(RXBUFF) | SPI_BIT(OVRES));
9218c2ecf20Sopenharmony_ci	spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN));
9228c2ecf20Sopenharmony_ci}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci/*
9258c2ecf20Sopenharmony_ci * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
9268c2ecf20Sopenharmony_ci *  - The buffer is either valid for CPU access, else NULL
9278c2ecf20Sopenharmony_ci *  - If the buffer is valid, so is its DMA address
9288c2ecf20Sopenharmony_ci *
9298c2ecf20Sopenharmony_ci * This driver manages the dma address unless message->is_dma_mapped.
9308c2ecf20Sopenharmony_ci */
9318c2ecf20Sopenharmony_cistatic int
9328c2ecf20Sopenharmony_ciatmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
9338c2ecf20Sopenharmony_ci{
9348c2ecf20Sopenharmony_ci	struct device	*dev = &as->pdev->dev;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
9378c2ecf20Sopenharmony_ci	if (xfer->tx_buf) {
9388c2ecf20Sopenharmony_ci		/* tx_buf is a const void* where we need a void * for the dma
9398c2ecf20Sopenharmony_ci		 * mapping */
9408c2ecf20Sopenharmony_ci		void *nonconst_tx = (void *)xfer->tx_buf;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci		xfer->tx_dma = dma_map_single(dev,
9438c2ecf20Sopenharmony_ci				nonconst_tx, xfer->len,
9448c2ecf20Sopenharmony_ci				DMA_TO_DEVICE);
9458c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, xfer->tx_dma))
9468c2ecf20Sopenharmony_ci			return -ENOMEM;
9478c2ecf20Sopenharmony_ci	}
9488c2ecf20Sopenharmony_ci	if (xfer->rx_buf) {
9498c2ecf20Sopenharmony_ci		xfer->rx_dma = dma_map_single(dev,
9508c2ecf20Sopenharmony_ci				xfer->rx_buf, xfer->len,
9518c2ecf20Sopenharmony_ci				DMA_FROM_DEVICE);
9528c2ecf20Sopenharmony_ci		if (dma_mapping_error(dev, xfer->rx_dma)) {
9538c2ecf20Sopenharmony_ci			if (xfer->tx_buf)
9548c2ecf20Sopenharmony_ci				dma_unmap_single(dev,
9558c2ecf20Sopenharmony_ci						xfer->tx_dma, xfer->len,
9568c2ecf20Sopenharmony_ci						DMA_TO_DEVICE);
9578c2ecf20Sopenharmony_ci			return -ENOMEM;
9588c2ecf20Sopenharmony_ci		}
9598c2ecf20Sopenharmony_ci	}
9608c2ecf20Sopenharmony_ci	return 0;
9618c2ecf20Sopenharmony_ci}
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_cistatic void atmel_spi_dma_unmap_xfer(struct spi_master *master,
9648c2ecf20Sopenharmony_ci				     struct spi_transfer *xfer)
9658c2ecf20Sopenharmony_ci{
9668c2ecf20Sopenharmony_ci	if (xfer->tx_dma != INVALID_DMA_ADDRESS)
9678c2ecf20Sopenharmony_ci		dma_unmap_single(master->dev.parent, xfer->tx_dma,
9688c2ecf20Sopenharmony_ci				 xfer->len, DMA_TO_DEVICE);
9698c2ecf20Sopenharmony_ci	if (xfer->rx_dma != INVALID_DMA_ADDRESS)
9708c2ecf20Sopenharmony_ci		dma_unmap_single(master->dev.parent, xfer->rx_dma,
9718c2ecf20Sopenharmony_ci				 xfer->len, DMA_FROM_DEVICE);
9728c2ecf20Sopenharmony_ci}
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_cistatic void atmel_spi_disable_pdc_transfer(struct atmel_spi *as)
9758c2ecf20Sopenharmony_ci{
9768c2ecf20Sopenharmony_ci	spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
9778c2ecf20Sopenharmony_ci}
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_cistatic void
9808c2ecf20Sopenharmony_ciatmel_spi_pump_single_data(struct atmel_spi *as, struct spi_transfer *xfer)
9818c2ecf20Sopenharmony_ci{
9828c2ecf20Sopenharmony_ci	u8		*rxp;
9838c2ecf20Sopenharmony_ci	u16		*rxp16;
9848c2ecf20Sopenharmony_ci	unsigned long	xfer_pos = xfer->len - as->current_remaining_bytes;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8) {
9878c2ecf20Sopenharmony_ci		rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos);
9888c2ecf20Sopenharmony_ci		*rxp16 = spi_readl(as, RDR);
9898c2ecf20Sopenharmony_ci	} else {
9908c2ecf20Sopenharmony_ci		rxp = ((u8 *)xfer->rx_buf) + xfer_pos;
9918c2ecf20Sopenharmony_ci		*rxp = spi_readl(as, RDR);
9928c2ecf20Sopenharmony_ci	}
9938c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8) {
9948c2ecf20Sopenharmony_ci		if (as->current_remaining_bytes > 2)
9958c2ecf20Sopenharmony_ci			as->current_remaining_bytes -= 2;
9968c2ecf20Sopenharmony_ci		else
9978c2ecf20Sopenharmony_ci			as->current_remaining_bytes = 0;
9988c2ecf20Sopenharmony_ci	} else {
9998c2ecf20Sopenharmony_ci		as->current_remaining_bytes--;
10008c2ecf20Sopenharmony_ci	}
10018c2ecf20Sopenharmony_ci}
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_cistatic void
10048c2ecf20Sopenharmony_ciatmel_spi_pump_fifo_data(struct atmel_spi *as, struct spi_transfer *xfer)
10058c2ecf20Sopenharmony_ci{
10068c2ecf20Sopenharmony_ci	u32 fifolr = spi_readl(as, FLR);
10078c2ecf20Sopenharmony_ci	u32 num_bytes, num_data = SPI_BFEXT(RXFL, fifolr);
10088c2ecf20Sopenharmony_ci	u32 offset = xfer->len - as->current_remaining_bytes;
10098c2ecf20Sopenharmony_ci	u16 *words = (u16 *)((u8 *)xfer->rx_buf + offset);
10108c2ecf20Sopenharmony_ci	u8  *bytes = (u8  *)((u8 *)xfer->rx_buf + offset);
10118c2ecf20Sopenharmony_ci	u16 rd; /* RD field is the lowest 16 bits of RDR */
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	/* Update the number of remaining bytes to transfer */
10148c2ecf20Sopenharmony_ci	num_bytes = ((xfer->bits_per_word > 8) ?
10158c2ecf20Sopenharmony_ci		     (num_data << 1) :
10168c2ecf20Sopenharmony_ci		     num_data);
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	if (as->current_remaining_bytes > num_bytes)
10198c2ecf20Sopenharmony_ci		as->current_remaining_bytes -= num_bytes;
10208c2ecf20Sopenharmony_ci	else
10218c2ecf20Sopenharmony_ci		as->current_remaining_bytes = 0;
10228c2ecf20Sopenharmony_ci
10238c2ecf20Sopenharmony_ci	/* Handle odd number of bytes when data are more than 8bit width */
10248c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8)
10258c2ecf20Sopenharmony_ci		as->current_remaining_bytes &= ~0x1;
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	/* Read data */
10288c2ecf20Sopenharmony_ci	while (num_data) {
10298c2ecf20Sopenharmony_ci		rd = spi_readl(as, RDR);
10308c2ecf20Sopenharmony_ci		if (xfer->bits_per_word > 8)
10318c2ecf20Sopenharmony_ci			*words++ = rd;
10328c2ecf20Sopenharmony_ci		else
10338c2ecf20Sopenharmony_ci			*bytes++ = rd;
10348c2ecf20Sopenharmony_ci		num_data--;
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci}
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci/* Called from IRQ
10398c2ecf20Sopenharmony_ci *
10408c2ecf20Sopenharmony_ci * Must update "current_remaining_bytes" to keep track of data
10418c2ecf20Sopenharmony_ci * to transfer.
10428c2ecf20Sopenharmony_ci */
10438c2ecf20Sopenharmony_cistatic void
10448c2ecf20Sopenharmony_ciatmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer)
10458c2ecf20Sopenharmony_ci{
10468c2ecf20Sopenharmony_ci	if (as->fifo_size)
10478c2ecf20Sopenharmony_ci		atmel_spi_pump_fifo_data(as, xfer);
10488c2ecf20Sopenharmony_ci	else
10498c2ecf20Sopenharmony_ci		atmel_spi_pump_single_data(as, xfer);
10508c2ecf20Sopenharmony_ci}
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci/* Interrupt
10538c2ecf20Sopenharmony_ci *
10548c2ecf20Sopenharmony_ci * No need for locking in this Interrupt handler: done_status is the
10558c2ecf20Sopenharmony_ci * only information modified.
10568c2ecf20Sopenharmony_ci */
10578c2ecf20Sopenharmony_cistatic irqreturn_t
10588c2ecf20Sopenharmony_ciatmel_spi_pio_interrupt(int irq, void *dev_id)
10598c2ecf20Sopenharmony_ci{
10608c2ecf20Sopenharmony_ci	struct spi_master	*master = dev_id;
10618c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
10628c2ecf20Sopenharmony_ci	u32			status, pending, imr;
10638c2ecf20Sopenharmony_ci	struct spi_transfer	*xfer;
10648c2ecf20Sopenharmony_ci	int			ret = IRQ_NONE;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	imr = spi_readl(as, IMR);
10678c2ecf20Sopenharmony_ci	status = spi_readl(as, SR);
10688c2ecf20Sopenharmony_ci	pending = status & imr;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	if (pending & SPI_BIT(OVRES)) {
10718c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
10728c2ecf20Sopenharmony_ci		spi_writel(as, IDR, SPI_BIT(OVRES));
10738c2ecf20Sopenharmony_ci		dev_warn(master->dev.parent, "overrun\n");
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci		/*
10768c2ecf20Sopenharmony_ci		 * When we get an overrun, we disregard the current
10778c2ecf20Sopenharmony_ci		 * transfer. Data will not be copied back from any
10788c2ecf20Sopenharmony_ci		 * bounce buffer and msg->actual_len will not be
10798c2ecf20Sopenharmony_ci		 * updated with the last xfer.
10808c2ecf20Sopenharmony_ci		 *
10818c2ecf20Sopenharmony_ci		 * We will also not process any remaning transfers in
10828c2ecf20Sopenharmony_ci		 * the message.
10838c2ecf20Sopenharmony_ci		 */
10848c2ecf20Sopenharmony_ci		as->done_status = -EIO;
10858c2ecf20Sopenharmony_ci		smp_wmb();
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci		/* Clear any overrun happening while cleaning up */
10888c2ecf20Sopenharmony_ci		spi_readl(as, SR);
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci		complete(&as->xfer_completion);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	} else if (pending & (SPI_BIT(RDRF) | SPI_BIT(RXFTHF))) {
10938c2ecf20Sopenharmony_ci		atmel_spi_lock(as);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci		if (as->current_remaining_bytes) {
10968c2ecf20Sopenharmony_ci			ret = IRQ_HANDLED;
10978c2ecf20Sopenharmony_ci			xfer = as->current_transfer;
10988c2ecf20Sopenharmony_ci			atmel_spi_pump_pio_data(as, xfer);
10998c2ecf20Sopenharmony_ci			if (!as->current_remaining_bytes)
11008c2ecf20Sopenharmony_ci				spi_writel(as, IDR, pending);
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci			complete(&as->xfer_completion);
11038c2ecf20Sopenharmony_ci		}
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		atmel_spi_unlock(as);
11068c2ecf20Sopenharmony_ci	} else {
11078c2ecf20Sopenharmony_ci		WARN_ONCE(pending, "IRQ not handled, pending = %x\n", pending);
11088c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
11098c2ecf20Sopenharmony_ci		spi_writel(as, IDR, pending);
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci
11128c2ecf20Sopenharmony_ci	return ret;
11138c2ecf20Sopenharmony_ci}
11148c2ecf20Sopenharmony_ci
11158c2ecf20Sopenharmony_cistatic irqreturn_t
11168c2ecf20Sopenharmony_ciatmel_spi_pdc_interrupt(int irq, void *dev_id)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	struct spi_master	*master = dev_id;
11198c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
11208c2ecf20Sopenharmony_ci	u32			status, pending, imr;
11218c2ecf20Sopenharmony_ci	int			ret = IRQ_NONE;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	imr = spi_readl(as, IMR);
11248c2ecf20Sopenharmony_ci	status = spi_readl(as, SR);
11258c2ecf20Sopenharmony_ci	pending = status & imr;
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci	if (pending & SPI_BIT(OVRES)) {
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci		spi_writel(as, IDR, (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX)
11328c2ecf20Sopenharmony_ci				     | SPI_BIT(OVRES)));
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci		/* Clear any overrun happening while cleaning up */
11358c2ecf20Sopenharmony_ci		spi_readl(as, SR);
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci		as->done_status = -EIO;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci		complete(&as->xfer_completion);
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	} else if (pending & (SPI_BIT(RXBUFF) | SPI_BIT(ENDRX))) {
11428c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci		spi_writel(as, IDR, pending);
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci		complete(&as->xfer_completion);
11478c2ecf20Sopenharmony_ci	}
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	return ret;
11508c2ecf20Sopenharmony_ci}
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_cistatic int atmel_word_delay_csr(struct spi_device *spi, struct atmel_spi *as)
11538c2ecf20Sopenharmony_ci{
11548c2ecf20Sopenharmony_ci	struct spi_delay *delay = &spi->word_delay;
11558c2ecf20Sopenharmony_ci	u32 value = delay->value;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	switch (delay->unit) {
11588c2ecf20Sopenharmony_ci	case SPI_DELAY_UNIT_NSECS:
11598c2ecf20Sopenharmony_ci		value /= 1000;
11608c2ecf20Sopenharmony_ci		break;
11618c2ecf20Sopenharmony_ci	case SPI_DELAY_UNIT_USECS:
11628c2ecf20Sopenharmony_ci		break;
11638c2ecf20Sopenharmony_ci	default:
11648c2ecf20Sopenharmony_ci		return -EINVAL;
11658c2ecf20Sopenharmony_ci	}
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	return (as->spi_clk / 1000000 * value) >> 5;
11688c2ecf20Sopenharmony_ci}
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_cistatic void initialize_native_cs_for_gpio(struct atmel_spi *as)
11718c2ecf20Sopenharmony_ci{
11728c2ecf20Sopenharmony_ci	int i;
11738c2ecf20Sopenharmony_ci	struct spi_master *master = platform_get_drvdata(as->pdev);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	if (!as->native_cs_free)
11768c2ecf20Sopenharmony_ci		return; /* already initialized */
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	if (!master->cs_gpiods)
11798c2ecf20Sopenharmony_ci		return; /* No CS GPIO */
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	/*
11828c2ecf20Sopenharmony_ci	 * On the first version of the controller (AT91RM9200), CS0
11838c2ecf20Sopenharmony_ci	 * can't be used associated with GPIO
11848c2ecf20Sopenharmony_ci	 */
11858c2ecf20Sopenharmony_ci	if (atmel_spi_is_v2(as))
11868c2ecf20Sopenharmony_ci		i = 0;
11878c2ecf20Sopenharmony_ci	else
11888c2ecf20Sopenharmony_ci		i = 1;
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	for (; i < 4; i++)
11918c2ecf20Sopenharmony_ci		if (master->cs_gpiods[i])
11928c2ecf20Sopenharmony_ci			as->native_cs_free |= BIT(i);
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	if (as->native_cs_free)
11958c2ecf20Sopenharmony_ci		as->native_cs_for_gpio = ffs(as->native_cs_free);
11968c2ecf20Sopenharmony_ci}
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_cistatic int atmel_spi_setup(struct spi_device *spi)
11998c2ecf20Sopenharmony_ci{
12008c2ecf20Sopenharmony_ci	struct atmel_spi	*as;
12018c2ecf20Sopenharmony_ci	struct atmel_spi_device	*asd;
12028c2ecf20Sopenharmony_ci	u32			csr;
12038c2ecf20Sopenharmony_ci	unsigned int		bits = spi->bits_per_word;
12048c2ecf20Sopenharmony_ci	int chip_select;
12058c2ecf20Sopenharmony_ci	int			word_delay_csr;
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	as = spi_master_get_devdata(spi->master);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	/* see notes above re chipselect */
12108c2ecf20Sopenharmony_ci	if (!spi->cs_gpiod && (spi->mode & SPI_CS_HIGH)) {
12118c2ecf20Sopenharmony_ci		dev_warn(&spi->dev, "setup: non GPIO CS can't be active-high\n");
12128c2ecf20Sopenharmony_ci		return -EINVAL;
12138c2ecf20Sopenharmony_ci	}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	/* Setup() is called during spi_register_controller(aka
12168c2ecf20Sopenharmony_ci	 * spi_register_master) but after all membmers of the cs_gpiod
12178c2ecf20Sopenharmony_ci	 * array have been filled, so we can looked for which native
12188c2ecf20Sopenharmony_ci	 * CS will be free for using with GPIO
12198c2ecf20Sopenharmony_ci	 */
12208c2ecf20Sopenharmony_ci	initialize_native_cs_for_gpio(as);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	if (spi->cs_gpiod && as->native_cs_free) {
12238c2ecf20Sopenharmony_ci		dev_err(&spi->dev,
12248c2ecf20Sopenharmony_ci			"No native CS available to support this GPIO CS\n");
12258c2ecf20Sopenharmony_ci		return -EBUSY;
12268c2ecf20Sopenharmony_ci	}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	if (spi->cs_gpiod)
12298c2ecf20Sopenharmony_ci		chip_select = as->native_cs_for_gpio;
12308c2ecf20Sopenharmony_ci	else
12318c2ecf20Sopenharmony_ci		chip_select = spi->chip_select;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	csr = SPI_BF(BITS, bits - 8);
12348c2ecf20Sopenharmony_ci	if (spi->mode & SPI_CPOL)
12358c2ecf20Sopenharmony_ci		csr |= SPI_BIT(CPOL);
12368c2ecf20Sopenharmony_ci	if (!(spi->mode & SPI_CPHA))
12378c2ecf20Sopenharmony_ci		csr |= SPI_BIT(NCPHA);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	if (!spi->cs_gpiod)
12408c2ecf20Sopenharmony_ci		csr |= SPI_BIT(CSAAT);
12418c2ecf20Sopenharmony_ci	csr |= SPI_BF(DLYBS, 0);
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	word_delay_csr = atmel_word_delay_csr(spi, as);
12448c2ecf20Sopenharmony_ci	if (word_delay_csr < 0)
12458c2ecf20Sopenharmony_ci		return word_delay_csr;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	/* DLYBCT adds delays between words.  This is useful for slow devices
12488c2ecf20Sopenharmony_ci	 * that need a bit of time to setup the next transfer.
12498c2ecf20Sopenharmony_ci	 */
12508c2ecf20Sopenharmony_ci	csr |= SPI_BF(DLYBCT, word_delay_csr);
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	asd = spi->controller_state;
12538c2ecf20Sopenharmony_ci	if (!asd) {
12548c2ecf20Sopenharmony_ci		asd = kzalloc(sizeof(struct atmel_spi_device), GFP_KERNEL);
12558c2ecf20Sopenharmony_ci		if (!asd)
12568c2ecf20Sopenharmony_ci			return -ENOMEM;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci		spi->controller_state = asd;
12598c2ecf20Sopenharmony_ci	}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_ci	asd->csr = csr;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	dev_dbg(&spi->dev,
12648c2ecf20Sopenharmony_ci		"setup: bpw %u mode 0x%x -> csr%d %08x\n",
12658c2ecf20Sopenharmony_ci		bits, spi->mode, spi->chip_select, csr);
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if (!atmel_spi_is_v2(as))
12688c2ecf20Sopenharmony_ci		spi_writel(as, CSR0 + 4 * chip_select, csr);
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	return 0;
12718c2ecf20Sopenharmony_ci}
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_cistatic void atmel_spi_set_cs(struct spi_device *spi, bool enable)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(spi->master);
12768c2ecf20Sopenharmony_ci	/* the core doesn't really pass us enable/disable, but CS HIGH vs CS LOW
12778c2ecf20Sopenharmony_ci	 * since we already have routines for activate/deactivate translate
12788c2ecf20Sopenharmony_ci	 * high/low to active/inactive
12798c2ecf20Sopenharmony_ci	 */
12808c2ecf20Sopenharmony_ci	enable = (!!(spi->mode & SPI_CS_HIGH) == enable);
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	if (enable) {
12838c2ecf20Sopenharmony_ci		cs_activate(as, spi);
12848c2ecf20Sopenharmony_ci	} else {
12858c2ecf20Sopenharmony_ci		cs_deactivate(as, spi);
12868c2ecf20Sopenharmony_ci	}
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci}
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_cistatic int atmel_spi_one_transfer(struct spi_master *master,
12918c2ecf20Sopenharmony_ci					struct spi_device *spi,
12928c2ecf20Sopenharmony_ci					struct spi_transfer *xfer)
12938c2ecf20Sopenharmony_ci{
12948c2ecf20Sopenharmony_ci	struct atmel_spi	*as;
12958c2ecf20Sopenharmony_ci	u8			bits;
12968c2ecf20Sopenharmony_ci	u32			len;
12978c2ecf20Sopenharmony_ci	struct atmel_spi_device	*asd;
12988c2ecf20Sopenharmony_ci	int			timeout;
12998c2ecf20Sopenharmony_ci	int			ret;
13008c2ecf20Sopenharmony_ci	unsigned long		dma_timeout;
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	as = spi_master_get_devdata(master);
13038c2ecf20Sopenharmony_ci	/* This lock was orignally taken in atmel_spi_trasfer_one_message */
13048c2ecf20Sopenharmony_ci	atmel_spi_lock(as);
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	asd = spi->controller_state;
13078c2ecf20Sopenharmony_ci	bits = (asd->csr >> 4) & 0xf;
13088c2ecf20Sopenharmony_ci	if (bits != xfer->bits_per_word - 8) {
13098c2ecf20Sopenharmony_ci		dev_dbg(&spi->dev,
13108c2ecf20Sopenharmony_ci			"you can't yet change bits_per_word in transfers\n");
13118c2ecf20Sopenharmony_ci		return -ENOPROTOOPT;
13128c2ecf20Sopenharmony_ci	}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_ci	/*
13158c2ecf20Sopenharmony_ci	 * DMA map early, for performance (empties dcache ASAP) and
13168c2ecf20Sopenharmony_ci	 * better fault reporting.
13178c2ecf20Sopenharmony_ci	 */
13188c2ecf20Sopenharmony_ci	if ((!master->cur_msg->is_dma_mapped)
13198c2ecf20Sopenharmony_ci		&& as->use_pdc) {
13208c2ecf20Sopenharmony_ci		if (atmel_spi_dma_map_xfer(as, xfer) < 0)
13218c2ecf20Sopenharmony_ci			return -ENOMEM;
13228c2ecf20Sopenharmony_ci	}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	atmel_spi_set_xfer_speed(as, spi, xfer);
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	as->done_status = 0;
13278c2ecf20Sopenharmony_ci	as->current_transfer = xfer;
13288c2ecf20Sopenharmony_ci	as->current_remaining_bytes = xfer->len;
13298c2ecf20Sopenharmony_ci	while (as->current_remaining_bytes) {
13308c2ecf20Sopenharmony_ci		reinit_completion(&as->xfer_completion);
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci		if (as->use_pdc) {
13338c2ecf20Sopenharmony_ci			atmel_spi_pdc_next_xfer(master, xfer);
13348c2ecf20Sopenharmony_ci		} else if (atmel_spi_use_dma(as, xfer)) {
13358c2ecf20Sopenharmony_ci			len = as->current_remaining_bytes;
13368c2ecf20Sopenharmony_ci			ret = atmel_spi_next_xfer_dma_submit(master,
13378c2ecf20Sopenharmony_ci								xfer, &len);
13388c2ecf20Sopenharmony_ci			if (ret) {
13398c2ecf20Sopenharmony_ci				dev_err(&spi->dev,
13408c2ecf20Sopenharmony_ci					"unable to use DMA, fallback to PIO\n");
13418c2ecf20Sopenharmony_ci				as->done_status = ret;
13428c2ecf20Sopenharmony_ci				break;
13438c2ecf20Sopenharmony_ci			} else {
13448c2ecf20Sopenharmony_ci				as->current_remaining_bytes -= len;
13458c2ecf20Sopenharmony_ci				if (as->current_remaining_bytes < 0)
13468c2ecf20Sopenharmony_ci					as->current_remaining_bytes = 0;
13478c2ecf20Sopenharmony_ci			}
13488c2ecf20Sopenharmony_ci		} else {
13498c2ecf20Sopenharmony_ci			atmel_spi_next_xfer_pio(master, xfer);
13508c2ecf20Sopenharmony_ci		}
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci		/* interrupts are disabled, so free the lock for schedule */
13538c2ecf20Sopenharmony_ci		atmel_spi_unlock(as);
13548c2ecf20Sopenharmony_ci		dma_timeout = wait_for_completion_timeout(&as->xfer_completion,
13558c2ecf20Sopenharmony_ci							  SPI_DMA_TIMEOUT);
13568c2ecf20Sopenharmony_ci		atmel_spi_lock(as);
13578c2ecf20Sopenharmony_ci		if (WARN_ON(dma_timeout == 0)) {
13588c2ecf20Sopenharmony_ci			dev_err(&spi->dev, "spi transfer timeout\n");
13598c2ecf20Sopenharmony_ci			as->done_status = -EIO;
13608c2ecf20Sopenharmony_ci		}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci		if (as->done_status)
13638c2ecf20Sopenharmony_ci			break;
13648c2ecf20Sopenharmony_ci	}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	if (as->done_status) {
13678c2ecf20Sopenharmony_ci		if (as->use_pdc) {
13688c2ecf20Sopenharmony_ci			dev_warn(master->dev.parent,
13698c2ecf20Sopenharmony_ci				"overrun (%u/%u remaining)\n",
13708c2ecf20Sopenharmony_ci				spi_readl(as, TCR), spi_readl(as, RCR));
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci			/*
13738c2ecf20Sopenharmony_ci			 * Clean up DMA registers and make sure the data
13748c2ecf20Sopenharmony_ci			 * registers are empty.
13758c2ecf20Sopenharmony_ci			 */
13768c2ecf20Sopenharmony_ci			spi_writel(as, RNCR, 0);
13778c2ecf20Sopenharmony_ci			spi_writel(as, TNCR, 0);
13788c2ecf20Sopenharmony_ci			spi_writel(as, RCR, 0);
13798c2ecf20Sopenharmony_ci			spi_writel(as, TCR, 0);
13808c2ecf20Sopenharmony_ci			for (timeout = 1000; timeout; timeout--)
13818c2ecf20Sopenharmony_ci				if (spi_readl(as, SR) & SPI_BIT(TXEMPTY))
13828c2ecf20Sopenharmony_ci					break;
13838c2ecf20Sopenharmony_ci			if (!timeout)
13848c2ecf20Sopenharmony_ci				dev_warn(master->dev.parent,
13858c2ecf20Sopenharmony_ci					 "timeout waiting for TXEMPTY");
13868c2ecf20Sopenharmony_ci			while (spi_readl(as, SR) & SPI_BIT(RDRF))
13878c2ecf20Sopenharmony_ci				spi_readl(as, RDR);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci			/* Clear any overrun happening while cleaning up */
13908c2ecf20Sopenharmony_ci			spi_readl(as, SR);
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci		} else if (atmel_spi_use_dma(as, xfer)) {
13938c2ecf20Sopenharmony_ci			atmel_spi_stop_dma(master);
13948c2ecf20Sopenharmony_ci		}
13958c2ecf20Sopenharmony_ci	}
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci	if (!master->cur_msg->is_dma_mapped
13988c2ecf20Sopenharmony_ci		&& as->use_pdc)
13998c2ecf20Sopenharmony_ci		atmel_spi_dma_unmap_xfer(master, xfer);
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	if (as->use_pdc)
14028c2ecf20Sopenharmony_ci		atmel_spi_disable_pdc_transfer(as);
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	atmel_spi_unlock(as);
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_ci	return as->done_status;
14078c2ecf20Sopenharmony_ci}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_cistatic void atmel_spi_cleanup(struct spi_device *spi)
14108c2ecf20Sopenharmony_ci{
14118c2ecf20Sopenharmony_ci	struct atmel_spi_device	*asd = spi->controller_state;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	if (!asd)
14148c2ecf20Sopenharmony_ci		return;
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	spi->controller_state = NULL;
14178c2ecf20Sopenharmony_ci	kfree(asd);
14188c2ecf20Sopenharmony_ci}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_cistatic inline unsigned int atmel_get_version(struct atmel_spi *as)
14218c2ecf20Sopenharmony_ci{
14228c2ecf20Sopenharmony_ci	return spi_readl(as, VERSION) & 0x00000fff;
14238c2ecf20Sopenharmony_ci}
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_cistatic void atmel_get_caps(struct atmel_spi *as)
14268c2ecf20Sopenharmony_ci{
14278c2ecf20Sopenharmony_ci	unsigned int version;
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	version = atmel_get_version(as);
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	as->caps.is_spi2 = version > 0x121;
14328c2ecf20Sopenharmony_ci	as->caps.has_wdrbt = version >= 0x210;
14338c2ecf20Sopenharmony_ci	as->caps.has_dma_support = version >= 0x212;
14348c2ecf20Sopenharmony_ci	as->caps.has_pdc_support = version < 0x212;
14358c2ecf20Sopenharmony_ci}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_cistatic void atmel_spi_init(struct atmel_spi *as)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST));
14408c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	/* It is recommended to enable FIFOs first thing after reset */
14438c2ecf20Sopenharmony_ci	if (as->fifo_size)
14448c2ecf20Sopenharmony_ci		spi_writel(as, CR, SPI_BIT(FIFOEN));
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci	if (as->caps.has_wdrbt) {
14478c2ecf20Sopenharmony_ci		spi_writel(as, MR, SPI_BIT(WDRBT) | SPI_BIT(MODFDIS)
14488c2ecf20Sopenharmony_ci				| SPI_BIT(MSTR));
14498c2ecf20Sopenharmony_ci	} else {
14508c2ecf20Sopenharmony_ci		spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS));
14518c2ecf20Sopenharmony_ci	}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	if (as->use_pdc)
14548c2ecf20Sopenharmony_ci		spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS));
14558c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SPIEN));
14568c2ecf20Sopenharmony_ci}
14578c2ecf20Sopenharmony_ci
14588c2ecf20Sopenharmony_cistatic int atmel_spi_probe(struct platform_device *pdev)
14598c2ecf20Sopenharmony_ci{
14608c2ecf20Sopenharmony_ci	struct resource		*regs;
14618c2ecf20Sopenharmony_ci	int			irq;
14628c2ecf20Sopenharmony_ci	struct clk		*clk;
14638c2ecf20Sopenharmony_ci	int			ret;
14648c2ecf20Sopenharmony_ci	struct spi_master	*master;
14658c2ecf20Sopenharmony_ci	struct atmel_spi	*as;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	/* Select default pin state */
14688c2ecf20Sopenharmony_ci	pinctrl_pm_select_default_state(&pdev->dev);
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
14718c2ecf20Sopenharmony_ci	if (!regs)
14728c2ecf20Sopenharmony_ci		return -ENXIO;
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
14758c2ecf20Sopenharmony_ci	if (irq < 0)
14768c2ecf20Sopenharmony_ci		return irq;
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	clk = devm_clk_get(&pdev->dev, "spi_clk");
14798c2ecf20Sopenharmony_ci	if (IS_ERR(clk))
14808c2ecf20Sopenharmony_ci		return PTR_ERR(clk);
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	/* setup spi core then atmel-specific driver state */
14838c2ecf20Sopenharmony_ci	master = spi_alloc_master(&pdev->dev, sizeof(*as));
14848c2ecf20Sopenharmony_ci	if (!master)
14858c2ecf20Sopenharmony_ci		return -ENOMEM;
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	/* the spi->mode bits understood by this driver: */
14888c2ecf20Sopenharmony_ci	master->use_gpio_descriptors = true;
14898c2ecf20Sopenharmony_ci	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
14908c2ecf20Sopenharmony_ci	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16);
14918c2ecf20Sopenharmony_ci	master->dev.of_node = pdev->dev.of_node;
14928c2ecf20Sopenharmony_ci	master->bus_num = pdev->id;
14938c2ecf20Sopenharmony_ci	master->num_chipselect = 4;
14948c2ecf20Sopenharmony_ci	master->setup = atmel_spi_setup;
14958c2ecf20Sopenharmony_ci	master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX |
14968c2ecf20Sopenharmony_ci			SPI_MASTER_GPIO_SS);
14978c2ecf20Sopenharmony_ci	master->transfer_one = atmel_spi_one_transfer;
14988c2ecf20Sopenharmony_ci	master->set_cs = atmel_spi_set_cs;
14998c2ecf20Sopenharmony_ci	master->cleanup = atmel_spi_cleanup;
15008c2ecf20Sopenharmony_ci	master->auto_runtime_pm = true;
15018c2ecf20Sopenharmony_ci	master->max_dma_len = SPI_MAX_DMA_XFER;
15028c2ecf20Sopenharmony_ci	master->can_dma = atmel_spi_can_dma;
15038c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, master);
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci	as = spi_master_get_devdata(master);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	spin_lock_init(&as->lock);
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	as->pdev = pdev;
15108c2ecf20Sopenharmony_ci	as->regs = devm_ioremap_resource(&pdev->dev, regs);
15118c2ecf20Sopenharmony_ci	if (IS_ERR(as->regs)) {
15128c2ecf20Sopenharmony_ci		ret = PTR_ERR(as->regs);
15138c2ecf20Sopenharmony_ci		goto out_unmap_regs;
15148c2ecf20Sopenharmony_ci	}
15158c2ecf20Sopenharmony_ci	as->phybase = regs->start;
15168c2ecf20Sopenharmony_ci	as->irq = irq;
15178c2ecf20Sopenharmony_ci	as->clk = clk;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	init_completion(&as->xfer_completion);
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	atmel_get_caps(as);
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	as->use_dma = false;
15248c2ecf20Sopenharmony_ci	as->use_pdc = false;
15258c2ecf20Sopenharmony_ci	if (as->caps.has_dma_support) {
15268c2ecf20Sopenharmony_ci		ret = atmel_spi_configure_dma(master, as);
15278c2ecf20Sopenharmony_ci		if (ret == 0) {
15288c2ecf20Sopenharmony_ci			as->use_dma = true;
15298c2ecf20Sopenharmony_ci		} else if (ret == -EPROBE_DEFER) {
15308c2ecf20Sopenharmony_ci			goto out_unmap_regs;
15318c2ecf20Sopenharmony_ci		}
15328c2ecf20Sopenharmony_ci	} else if (as->caps.has_pdc_support) {
15338c2ecf20Sopenharmony_ci		as->use_pdc = true;
15348c2ecf20Sopenharmony_ci	}
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
15378c2ecf20Sopenharmony_ci		as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev,
15388c2ecf20Sopenharmony_ci						      SPI_MAX_DMA_XFER,
15398c2ecf20Sopenharmony_ci						      &as->dma_addr_rx_bbuf,
15408c2ecf20Sopenharmony_ci						      GFP_KERNEL | GFP_DMA);
15418c2ecf20Sopenharmony_ci		if (!as->addr_rx_bbuf) {
15428c2ecf20Sopenharmony_ci			as->use_dma = false;
15438c2ecf20Sopenharmony_ci		} else {
15448c2ecf20Sopenharmony_ci			as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev,
15458c2ecf20Sopenharmony_ci					SPI_MAX_DMA_XFER,
15468c2ecf20Sopenharmony_ci					&as->dma_addr_tx_bbuf,
15478c2ecf20Sopenharmony_ci					GFP_KERNEL | GFP_DMA);
15488c2ecf20Sopenharmony_ci			if (!as->addr_tx_bbuf) {
15498c2ecf20Sopenharmony_ci				as->use_dma = false;
15508c2ecf20Sopenharmony_ci				dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
15518c2ecf20Sopenharmony_ci						  as->addr_rx_bbuf,
15528c2ecf20Sopenharmony_ci						  as->dma_addr_rx_bbuf);
15538c2ecf20Sopenharmony_ci			}
15548c2ecf20Sopenharmony_ci		}
15558c2ecf20Sopenharmony_ci		if (!as->use_dma)
15568c2ecf20Sopenharmony_ci			dev_info(master->dev.parent,
15578c2ecf20Sopenharmony_ci				 "  can not allocate dma coherent memory\n");
15588c2ecf20Sopenharmony_ci	}
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	if (as->caps.has_dma_support && !as->use_dma)
15618c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n");
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	if (as->use_pdc) {
15648c2ecf20Sopenharmony_ci		ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pdc_interrupt,
15658c2ecf20Sopenharmony_ci					0, dev_name(&pdev->dev), master);
15668c2ecf20Sopenharmony_ci	} else {
15678c2ecf20Sopenharmony_ci		ret = devm_request_irq(&pdev->dev, irq, atmel_spi_pio_interrupt,
15688c2ecf20Sopenharmony_ci					0, dev_name(&pdev->dev), master);
15698c2ecf20Sopenharmony_ci	}
15708c2ecf20Sopenharmony_ci	if (ret)
15718c2ecf20Sopenharmony_ci		goto out_unmap_regs;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	/* Initialize the hardware */
15748c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(clk);
15758c2ecf20Sopenharmony_ci	if (ret)
15768c2ecf20Sopenharmony_ci		goto out_free_irq;
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	as->spi_clk = clk_get_rate(clk);
15798c2ecf20Sopenharmony_ci
15808c2ecf20Sopenharmony_ci	as->fifo_size = 0;
15818c2ecf20Sopenharmony_ci	if (!of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size",
15828c2ecf20Sopenharmony_ci				  &as->fifo_size)) {
15838c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "Using FIFO (%u data)\n", as->fifo_size);
15848c2ecf20Sopenharmony_ci	}
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	atmel_spi_init(as);
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci	pm_runtime_set_autosuspend_delay(&pdev->dev, AUTOSUSPEND_TIMEOUT);
15898c2ecf20Sopenharmony_ci	pm_runtime_use_autosuspend(&pdev->dev);
15908c2ecf20Sopenharmony_ci	pm_runtime_set_active(&pdev->dev);
15918c2ecf20Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	ret = devm_spi_register_master(&pdev->dev, master);
15948c2ecf20Sopenharmony_ci	if (ret)
15958c2ecf20Sopenharmony_ci		goto out_free_dma;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	/* go! */
15988c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "Atmel SPI Controller version 0x%x at 0x%08lx (irq %d)\n",
15998c2ecf20Sopenharmony_ci			atmel_get_version(as), (unsigned long)regs->start,
16008c2ecf20Sopenharmony_ci			irq);
16018c2ecf20Sopenharmony_ci
16028c2ecf20Sopenharmony_ci	return 0;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ciout_free_dma:
16058c2ecf20Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
16068c2ecf20Sopenharmony_ci	pm_runtime_set_suspended(&pdev->dev);
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	if (as->use_dma)
16098c2ecf20Sopenharmony_ci		atmel_spi_release_dma(master);
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST));
16128c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
16138c2ecf20Sopenharmony_ci	clk_disable_unprepare(clk);
16148c2ecf20Sopenharmony_ciout_free_irq:
16158c2ecf20Sopenharmony_ciout_unmap_regs:
16168c2ecf20Sopenharmony_ci	spi_master_put(master);
16178c2ecf20Sopenharmony_ci	return ret;
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cistatic int atmel_spi_remove(struct platform_device *pdev)
16218c2ecf20Sopenharmony_ci{
16228c2ecf20Sopenharmony_ci	struct spi_master	*master = platform_get_drvdata(pdev);
16238c2ecf20Sopenharmony_ci	struct atmel_spi	*as = spi_master_get_devdata(master);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	/* reset the hardware and block queue progress */
16288c2ecf20Sopenharmony_ci	if (as->use_dma) {
16298c2ecf20Sopenharmony_ci		atmel_spi_stop_dma(master);
16308c2ecf20Sopenharmony_ci		atmel_spi_release_dma(master);
16318c2ecf20Sopenharmony_ci		if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) {
16328c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
16338c2ecf20Sopenharmony_ci					  as->addr_tx_bbuf,
16348c2ecf20Sopenharmony_ci					  as->dma_addr_tx_bbuf);
16358c2ecf20Sopenharmony_ci			dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER,
16368c2ecf20Sopenharmony_ci					  as->addr_rx_bbuf,
16378c2ecf20Sopenharmony_ci					  as->dma_addr_rx_bbuf);
16388c2ecf20Sopenharmony_ci		}
16398c2ecf20Sopenharmony_ci	}
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	spin_lock_irq(&as->lock);
16428c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST));
16438c2ecf20Sopenharmony_ci	spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */
16448c2ecf20Sopenharmony_ci	spi_readl(as, SR);
16458c2ecf20Sopenharmony_ci	spin_unlock_irq(&as->lock);
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci	clk_disable_unprepare(as->clk);
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
16508c2ecf20Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	return 0;
16538c2ecf20Sopenharmony_ci}
16548c2ecf20Sopenharmony_ci
16558c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
16568c2ecf20Sopenharmony_cistatic int atmel_spi_runtime_suspend(struct device *dev)
16578c2ecf20Sopenharmony_ci{
16588c2ecf20Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
16598c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	clk_disable_unprepare(as->clk);
16628c2ecf20Sopenharmony_ci	pinctrl_pm_select_sleep_state(dev);
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	return 0;
16658c2ecf20Sopenharmony_ci}
16668c2ecf20Sopenharmony_ci
16678c2ecf20Sopenharmony_cistatic int atmel_spi_runtime_resume(struct device *dev)
16688c2ecf20Sopenharmony_ci{
16698c2ecf20Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
16708c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	pinctrl_pm_select_default_state(dev);
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	return clk_prepare_enable(as->clk);
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
16788c2ecf20Sopenharmony_cistatic int atmel_spi_suspend(struct device *dev)
16798c2ecf20Sopenharmony_ci{
16808c2ecf20Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
16818c2ecf20Sopenharmony_ci	int ret;
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	/* Stop the queue running */
16848c2ecf20Sopenharmony_ci	ret = spi_master_suspend(master);
16858c2ecf20Sopenharmony_ci	if (ret)
16868c2ecf20Sopenharmony_ci		return ret;
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci	if (!pm_runtime_suspended(dev))
16898c2ecf20Sopenharmony_ci		atmel_spi_runtime_suspend(dev);
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	return 0;
16928c2ecf20Sopenharmony_ci}
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_cistatic int atmel_spi_resume(struct device *dev)
16958c2ecf20Sopenharmony_ci{
16968c2ecf20Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
16978c2ecf20Sopenharmony_ci	struct atmel_spi *as = spi_master_get_devdata(master);
16988c2ecf20Sopenharmony_ci	int ret;
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(as->clk);
17018c2ecf20Sopenharmony_ci	if (ret)
17028c2ecf20Sopenharmony_ci		return ret;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	atmel_spi_init(as);
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	clk_disable_unprepare(as->clk);
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_ci	if (!pm_runtime_suspended(dev)) {
17098c2ecf20Sopenharmony_ci		ret = atmel_spi_runtime_resume(dev);
17108c2ecf20Sopenharmony_ci		if (ret)
17118c2ecf20Sopenharmony_ci			return ret;
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	/* Start the queue running */
17158c2ecf20Sopenharmony_ci	return spi_master_resume(master);
17168c2ecf20Sopenharmony_ci}
17178c2ecf20Sopenharmony_ci#endif
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_cistatic const struct dev_pm_ops atmel_spi_pm_ops = {
17208c2ecf20Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(atmel_spi_suspend, atmel_spi_resume)
17218c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(atmel_spi_runtime_suspend,
17228c2ecf20Sopenharmony_ci			   atmel_spi_runtime_resume, NULL)
17238c2ecf20Sopenharmony_ci};
17248c2ecf20Sopenharmony_ci#define ATMEL_SPI_PM_OPS	(&atmel_spi_pm_ops)
17258c2ecf20Sopenharmony_ci#else
17268c2ecf20Sopenharmony_ci#define ATMEL_SPI_PM_OPS	NULL
17278c2ecf20Sopenharmony_ci#endif
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_cistatic const struct of_device_id atmel_spi_dt_ids[] = {
17308c2ecf20Sopenharmony_ci	{ .compatible = "atmel,at91rm9200-spi" },
17318c2ecf20Sopenharmony_ci	{ /* sentinel */ }
17328c2ecf20Sopenharmony_ci};
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, atmel_spi_dt_ids);
17358c2ecf20Sopenharmony_ci
17368c2ecf20Sopenharmony_cistatic struct platform_driver atmel_spi_driver = {
17378c2ecf20Sopenharmony_ci	.driver		= {
17388c2ecf20Sopenharmony_ci		.name	= "atmel_spi",
17398c2ecf20Sopenharmony_ci		.pm	= ATMEL_SPI_PM_OPS,
17408c2ecf20Sopenharmony_ci		.of_match_table	= atmel_spi_dt_ids,
17418c2ecf20Sopenharmony_ci	},
17428c2ecf20Sopenharmony_ci	.probe		= atmel_spi_probe,
17438c2ecf20Sopenharmony_ci	.remove		= atmel_spi_remove,
17448c2ecf20Sopenharmony_ci};
17458c2ecf20Sopenharmony_cimodule_platform_driver(atmel_spi_driver);
17468c2ecf20Sopenharmony_ci
17478c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Atmel AT32/AT91 SPI Controller driver");
17488c2ecf20Sopenharmony_ciMODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
17498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
17508c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:atmel_spi");
1751