18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for Broadcom BCM2835 SPI Controllers 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Chris Boot 68c2ecf20Sopenharmony_ci * Copyright (C) 2013 Stephen Warren 78c2ecf20Sopenharmony_ci * Copyright (C) 2015 Martin Sperl 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This driver is inspired by: 108c2ecf20Sopenharmony_ci * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> 118c2ecf20Sopenharmony_ci * spi-atmel.c, Copyright (C) 2006 Atmel Corporation 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <linux/completion.h> 168c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 198c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 208c2ecf20Sopenharmony_ci#include <linux/err.h> 218c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 228c2ecf20Sopenharmony_ci#include <linux/io.h> 238c2ecf20Sopenharmony_ci#include <linux/kernel.h> 248c2ecf20Sopenharmony_ci#include <linux/module.h> 258c2ecf20Sopenharmony_ci#include <linux/of.h> 268c2ecf20Sopenharmony_ci#include <linux/of_address.h> 278c2ecf20Sopenharmony_ci#include <linux/of_device.h> 288c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 298c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> /* FIXME: using chip internals */ 308c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> /* FIXME: using chip internals */ 318c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 328c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* SPI register offsets */ 358c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS 0x00 368c2ecf20Sopenharmony_ci#define BCM2835_SPI_FIFO 0x04 378c2ecf20Sopenharmony_ci#define BCM2835_SPI_CLK 0x08 388c2ecf20Sopenharmony_ci#define BCM2835_SPI_DLEN 0x0c 398c2ecf20Sopenharmony_ci#define BCM2835_SPI_LTOH 0x10 408c2ecf20Sopenharmony_ci#define BCM2835_SPI_DC 0x14 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* Bitfields in CS */ 438c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_LEN_LONG 0x02000000 448c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_DMA_LEN 0x01000000 458c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CSPOL2 0x00800000 468c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CSPOL1 0x00400000 478c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CSPOL0 0x00200000 488c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_RXF 0x00100000 498c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_RXR 0x00080000 508c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_TXD 0x00040000 518c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_RXD 0x00020000 528c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_DONE 0x00010000 538c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_LEN 0x00002000 548c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_REN 0x00001000 558c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_ADCS 0x00000800 568c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_INTR 0x00000400 578c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_INTD 0x00000200 588c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_DMAEN 0x00000100 598c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_TA 0x00000080 608c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CSPOL 0x00000040 618c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CLEAR_RX 0x00000020 628c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CLEAR_TX 0x00000010 638c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CPOL 0x00000008 648c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CPHA 0x00000004 658c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CS_10 0x00000002 668c2ecf20Sopenharmony_ci#define BCM2835_SPI_CS_CS_01 0x00000001 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define BCM2835_SPI_FIFO_SIZE 64 698c2ecf20Sopenharmony_ci#define BCM2835_SPI_FIFO_SIZE_3_4 48 708c2ecf20Sopenharmony_ci#define BCM2835_SPI_DMA_MIN_LENGTH 96 718c2ecf20Sopenharmony_ci#define BCM2835_SPI_NUM_CS 24 /* raise as necessary */ 728c2ecf20Sopenharmony_ci#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ 738c2ecf20Sopenharmony_ci | SPI_NO_CS | SPI_3WIRE) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define DRV_NAME "spi-bcm2835" 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci/* define polling limits */ 788c2ecf20Sopenharmony_cistatic unsigned int polling_limit_us = 30; 798c2ecf20Sopenharmony_cimodule_param(polling_limit_us, uint, 0664); 808c2ecf20Sopenharmony_ciMODULE_PARM_DESC(polling_limit_us, 818c2ecf20Sopenharmony_ci "time in us to run a transfer in polling mode\n"); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/** 848c2ecf20Sopenharmony_ci * struct bcm2835_spi - BCM2835 SPI controller 858c2ecf20Sopenharmony_ci * @regs: base address of register map 868c2ecf20Sopenharmony_ci * @clk: core clock, divided to calculate serial clock 878c2ecf20Sopenharmony_ci * @clk_hz: core clock cached speed 888c2ecf20Sopenharmony_ci * @irq: interrupt, signals TX FIFO empty or RX FIFO ¾ full 898c2ecf20Sopenharmony_ci * @tfr: SPI transfer currently processed 908c2ecf20Sopenharmony_ci * @ctlr: SPI controller reverse lookup 918c2ecf20Sopenharmony_ci * @tx_buf: pointer whence next transmitted byte is read 928c2ecf20Sopenharmony_ci * @rx_buf: pointer where next received byte is written 938c2ecf20Sopenharmony_ci * @tx_len: remaining bytes to transmit 948c2ecf20Sopenharmony_ci * @rx_len: remaining bytes to receive 958c2ecf20Sopenharmony_ci * @tx_prologue: bytes transmitted without DMA if first TX sglist entry's 968c2ecf20Sopenharmony_ci * length is not a multiple of 4 (to overcome hardware limitation) 978c2ecf20Sopenharmony_ci * @rx_prologue: bytes received without DMA if first RX sglist entry's 988c2ecf20Sopenharmony_ci * length is not a multiple of 4 (to overcome hardware limitation) 998c2ecf20Sopenharmony_ci * @tx_spillover: whether @tx_prologue spills over to second TX sglist entry 1008c2ecf20Sopenharmony_ci * @prepare_cs: precalculated CS register value for ->prepare_message() 1018c2ecf20Sopenharmony_ci * (uses slave-specific clock polarity and phase settings) 1028c2ecf20Sopenharmony_ci * @debugfs_dir: the debugfs directory - neede to remove debugfs when 1038c2ecf20Sopenharmony_ci * unloading the module 1048c2ecf20Sopenharmony_ci * @count_transfer_polling: count of how often polling mode is used 1058c2ecf20Sopenharmony_ci * @count_transfer_irq: count of how often interrupt mode is used 1068c2ecf20Sopenharmony_ci * @count_transfer_irq_after_polling: count of how often we fall back to 1078c2ecf20Sopenharmony_ci * interrupt mode after starting in polling mode. 1088c2ecf20Sopenharmony_ci * These are counted as well in @count_transfer_polling and 1098c2ecf20Sopenharmony_ci * @count_transfer_irq 1108c2ecf20Sopenharmony_ci * @count_transfer_dma: count how often dma mode is used 1118c2ecf20Sopenharmony_ci * @chip_select: SPI slave currently selected 1128c2ecf20Sopenharmony_ci * (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs) 1138c2ecf20Sopenharmony_ci * @tx_dma_active: whether a TX DMA descriptor is in progress 1148c2ecf20Sopenharmony_ci * @rx_dma_active: whether a RX DMA descriptor is in progress 1158c2ecf20Sopenharmony_ci * (used by bcm2835_spi_dma_tx_done() to handle a race) 1168c2ecf20Sopenharmony_ci * @fill_tx_desc: preallocated TX DMA descriptor used for RX-only transfers 1178c2ecf20Sopenharmony_ci * (cyclically copies from zero page to TX FIFO) 1188c2ecf20Sopenharmony_ci * @fill_tx_addr: bus address of zero page 1198c2ecf20Sopenharmony_ci * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers 1208c2ecf20Sopenharmony_ci * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register) 1218c2ecf20Sopenharmony_ci * @clear_rx_addr: bus address of @clear_rx_cs 1228c2ecf20Sopenharmony_ci * @clear_rx_cs: precalculated CS register value to clear RX FIFO 1238c2ecf20Sopenharmony_ci * (uses slave-specific clock polarity and phase settings) 1248c2ecf20Sopenharmony_ci */ 1258c2ecf20Sopenharmony_cistruct bcm2835_spi { 1268c2ecf20Sopenharmony_ci void __iomem *regs; 1278c2ecf20Sopenharmony_ci struct clk *clk; 1288c2ecf20Sopenharmony_ci unsigned long clk_hz; 1298c2ecf20Sopenharmony_ci int irq; 1308c2ecf20Sopenharmony_ci struct spi_transfer *tfr; 1318c2ecf20Sopenharmony_ci struct spi_controller *ctlr; 1328c2ecf20Sopenharmony_ci const u8 *tx_buf; 1338c2ecf20Sopenharmony_ci u8 *rx_buf; 1348c2ecf20Sopenharmony_ci int tx_len; 1358c2ecf20Sopenharmony_ci int rx_len; 1368c2ecf20Sopenharmony_ci int tx_prologue; 1378c2ecf20Sopenharmony_ci int rx_prologue; 1388c2ecf20Sopenharmony_ci unsigned int tx_spillover; 1398c2ecf20Sopenharmony_ci u32 prepare_cs[BCM2835_SPI_NUM_CS]; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci struct dentry *debugfs_dir; 1428c2ecf20Sopenharmony_ci u64 count_transfer_polling; 1438c2ecf20Sopenharmony_ci u64 count_transfer_irq; 1448c2ecf20Sopenharmony_ci u64 count_transfer_irq_after_polling; 1458c2ecf20Sopenharmony_ci u64 count_transfer_dma; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci u8 chip_select; 1488c2ecf20Sopenharmony_ci unsigned int tx_dma_active; 1498c2ecf20Sopenharmony_ci unsigned int rx_dma_active; 1508c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *fill_tx_desc; 1518c2ecf20Sopenharmony_ci dma_addr_t fill_tx_addr; 1528c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *clear_rx_desc[BCM2835_SPI_NUM_CS]; 1538c2ecf20Sopenharmony_ci dma_addr_t clear_rx_addr; 1548c2ecf20Sopenharmony_ci u32 clear_rx_cs[BCM2835_SPI_NUM_CS] ____cacheline_aligned; 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 1588c2ecf20Sopenharmony_cistatic void bcm2835_debugfs_create(struct bcm2835_spi *bs, 1598c2ecf20Sopenharmony_ci const char *dname) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci char name[64]; 1628c2ecf20Sopenharmony_ci struct dentry *dir; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* get full name */ 1658c2ecf20Sopenharmony_ci snprintf(name, sizeof(name), "spi-bcm2835-%s", dname); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* the base directory */ 1688c2ecf20Sopenharmony_ci dir = debugfs_create_dir(name, NULL); 1698c2ecf20Sopenharmony_ci bs->debugfs_dir = dir; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* the counters */ 1728c2ecf20Sopenharmony_ci debugfs_create_u64("count_transfer_polling", 0444, dir, 1738c2ecf20Sopenharmony_ci &bs->count_transfer_polling); 1748c2ecf20Sopenharmony_ci debugfs_create_u64("count_transfer_irq", 0444, dir, 1758c2ecf20Sopenharmony_ci &bs->count_transfer_irq); 1768c2ecf20Sopenharmony_ci debugfs_create_u64("count_transfer_irq_after_polling", 0444, dir, 1778c2ecf20Sopenharmony_ci &bs->count_transfer_irq_after_polling); 1788c2ecf20Sopenharmony_ci debugfs_create_u64("count_transfer_dma", 0444, dir, 1798c2ecf20Sopenharmony_ci &bs->count_transfer_dma); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void bcm2835_debugfs_remove(struct bcm2835_spi *bs) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci debugfs_remove_recursive(bs->debugfs_dir); 1858c2ecf20Sopenharmony_ci bs->debugfs_dir = NULL; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci#else 1888c2ecf20Sopenharmony_cistatic void bcm2835_debugfs_create(struct bcm2835_spi *bs, 1898c2ecf20Sopenharmony_ci const char *dname) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic void bcm2835_debugfs_remove(struct bcm2835_spi *bs) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */ 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic inline u32 bcm2835_rd(struct bcm2835_spi *bs, unsigned int reg) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci return readl(bs->regs + reg); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic inline void bcm2835_wr(struct bcm2835_spi *bs, unsigned int reg, u32 val) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci writel(val, bs->regs + reg); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic inline void bcm2835_rd_fifo(struct bcm2835_spi *bs) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci u8 byte; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci while ((bs->rx_len) && 2138c2ecf20Sopenharmony_ci (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_RXD)) { 2148c2ecf20Sopenharmony_ci byte = bcm2835_rd(bs, BCM2835_SPI_FIFO); 2158c2ecf20Sopenharmony_ci if (bs->rx_buf) 2168c2ecf20Sopenharmony_ci *bs->rx_buf++ = byte; 2178c2ecf20Sopenharmony_ci bs->rx_len--; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic inline void bcm2835_wr_fifo(struct bcm2835_spi *bs) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci u8 byte; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci while ((bs->tx_len) && 2268c2ecf20Sopenharmony_ci (bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_TXD)) { 2278c2ecf20Sopenharmony_ci byte = bs->tx_buf ? *bs->tx_buf++ : 0; 2288c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_FIFO, byte); 2298c2ecf20Sopenharmony_ci bs->tx_len--; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci/** 2348c2ecf20Sopenharmony_ci * bcm2835_rd_fifo_count() - blindly read exactly @count bytes from RX FIFO 2358c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 2368c2ecf20Sopenharmony_ci * @count: bytes to read from RX FIFO 2378c2ecf20Sopenharmony_ci * 2388c2ecf20Sopenharmony_ci * The caller must ensure that @bs->rx_len is greater than or equal to @count, 2398c2ecf20Sopenharmony_ci * that the RX FIFO contains at least @count bytes and that the DMA Enable flag 2408c2ecf20Sopenharmony_ci * in the CS register is set (such that a read from the FIFO register receives 2418c2ecf20Sopenharmony_ci * 32-bit instead of just 8-bit). Moreover @bs->rx_buf must not be %NULL. 2428c2ecf20Sopenharmony_ci */ 2438c2ecf20Sopenharmony_cistatic inline void bcm2835_rd_fifo_count(struct bcm2835_spi *bs, int count) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci u32 val; 2468c2ecf20Sopenharmony_ci int len; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci bs->rx_len -= count; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci do { 2518c2ecf20Sopenharmony_ci val = bcm2835_rd(bs, BCM2835_SPI_FIFO); 2528c2ecf20Sopenharmony_ci len = min(count, 4); 2538c2ecf20Sopenharmony_ci memcpy(bs->rx_buf, &val, len); 2548c2ecf20Sopenharmony_ci bs->rx_buf += len; 2558c2ecf20Sopenharmony_ci count -= 4; 2568c2ecf20Sopenharmony_ci } while (count > 0); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci/** 2608c2ecf20Sopenharmony_ci * bcm2835_wr_fifo_count() - blindly write exactly @count bytes to TX FIFO 2618c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 2628c2ecf20Sopenharmony_ci * @count: bytes to write to TX FIFO 2638c2ecf20Sopenharmony_ci * 2648c2ecf20Sopenharmony_ci * The caller must ensure that @bs->tx_len is greater than or equal to @count, 2658c2ecf20Sopenharmony_ci * that the TX FIFO can accommodate @count bytes and that the DMA Enable flag 2668c2ecf20Sopenharmony_ci * in the CS register is set (such that a write to the FIFO register transmits 2678c2ecf20Sopenharmony_ci * 32-bit instead of just 8-bit). 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_cistatic inline void bcm2835_wr_fifo_count(struct bcm2835_spi *bs, int count) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci u32 val; 2728c2ecf20Sopenharmony_ci int len; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci bs->tx_len -= count; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci do { 2778c2ecf20Sopenharmony_ci if (bs->tx_buf) { 2788c2ecf20Sopenharmony_ci len = min(count, 4); 2798c2ecf20Sopenharmony_ci memcpy(&val, bs->tx_buf, len); 2808c2ecf20Sopenharmony_ci bs->tx_buf += len; 2818c2ecf20Sopenharmony_ci } else { 2828c2ecf20Sopenharmony_ci val = 0; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_FIFO, val); 2858c2ecf20Sopenharmony_ci count -= 4; 2868c2ecf20Sopenharmony_ci } while (count > 0); 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/** 2908c2ecf20Sopenharmony_ci * bcm2835_wait_tx_fifo_empty() - busy-wait for TX FIFO to empty 2918c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * The caller must ensure that the RX FIFO can accommodate as many bytes 2948c2ecf20Sopenharmony_ci * as have been written to the TX FIFO: Transmission is halted once the 2958c2ecf20Sopenharmony_ci * RX FIFO is full, causing this function to spin forever. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_cistatic inline void bcm2835_wait_tx_fifo_empty(struct bcm2835_spi *bs) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) 3008c2ecf20Sopenharmony_ci cpu_relax(); 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/** 3048c2ecf20Sopenharmony_ci * bcm2835_rd_fifo_blind() - blindly read up to @count bytes from RX FIFO 3058c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 3068c2ecf20Sopenharmony_ci * @count: bytes available for reading in RX FIFO 3078c2ecf20Sopenharmony_ci */ 3088c2ecf20Sopenharmony_cistatic inline void bcm2835_rd_fifo_blind(struct bcm2835_spi *bs, int count) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci u8 val; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci count = min(count, bs->rx_len); 3138c2ecf20Sopenharmony_ci bs->rx_len -= count; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci do { 3168c2ecf20Sopenharmony_ci val = bcm2835_rd(bs, BCM2835_SPI_FIFO); 3178c2ecf20Sopenharmony_ci if (bs->rx_buf) 3188c2ecf20Sopenharmony_ci *bs->rx_buf++ = val; 3198c2ecf20Sopenharmony_ci } while (--count); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/** 3238c2ecf20Sopenharmony_ci * bcm2835_wr_fifo_blind() - blindly write up to @count bytes to TX FIFO 3248c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 3258c2ecf20Sopenharmony_ci * @count: bytes available for writing in TX FIFO 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_cistatic inline void bcm2835_wr_fifo_blind(struct bcm2835_spi *bs, int count) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci u8 val; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci count = min(count, bs->tx_len); 3328c2ecf20Sopenharmony_ci bs->tx_len -= count; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci do { 3358c2ecf20Sopenharmony_ci val = bs->tx_buf ? *bs->tx_buf++ : 0; 3368c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_FIFO, val); 3378c2ecf20Sopenharmony_ci } while (--count); 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_cistatic void bcm2835_spi_reset_hw(struct bcm2835_spi *bs) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* Disable SPI interrupts and transfer */ 3458c2ecf20Sopenharmony_ci cs &= ~(BCM2835_SPI_CS_INTR | 3468c2ecf20Sopenharmony_ci BCM2835_SPI_CS_INTD | 3478c2ecf20Sopenharmony_ci BCM2835_SPI_CS_DMAEN | 3488c2ecf20Sopenharmony_ci BCM2835_SPI_CS_TA); 3498c2ecf20Sopenharmony_ci /* 3508c2ecf20Sopenharmony_ci * Transmission sometimes breaks unless the DONE bit is written at the 3518c2ecf20Sopenharmony_ci * end of every transfer. The spec says it's a RO bit. Either the 3528c2ecf20Sopenharmony_ci * spec is wrong and the bit is actually of type RW1C, or it's a 3538c2ecf20Sopenharmony_ci * hardware erratum. 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_DONE; 3568c2ecf20Sopenharmony_ci /* and reset RX/TX FIFOS */ 3578c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* and reset the SPI_HW */ 3608c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs); 3618c2ecf20Sopenharmony_ci /* as well as DLEN */ 3628c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_DLEN, 0); 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic irqreturn_t bcm2835_spi_interrupt(int irq, void *dev_id) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = dev_id; 3688c2ecf20Sopenharmony_ci u32 cs = bcm2835_rd(bs, BCM2835_SPI_CS); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* 3718c2ecf20Sopenharmony_ci * An interrupt is signaled either if DONE is set (TX FIFO empty) 3728c2ecf20Sopenharmony_ci * or if RXR is set (RX FIFO >= ¾ full). 3738c2ecf20Sopenharmony_ci */ 3748c2ecf20Sopenharmony_ci if (cs & BCM2835_SPI_CS_RXF) 3758c2ecf20Sopenharmony_ci bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); 3768c2ecf20Sopenharmony_ci else if (cs & BCM2835_SPI_CS_RXR) 3778c2ecf20Sopenharmony_ci bcm2835_rd_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE_3_4); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (bs->tx_len && cs & BCM2835_SPI_CS_DONE) 3808c2ecf20Sopenharmony_ci bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* Read as many bytes as possible from FIFO */ 3838c2ecf20Sopenharmony_ci bcm2835_rd_fifo(bs); 3848c2ecf20Sopenharmony_ci /* Write as many bytes as possible to FIFO */ 3858c2ecf20Sopenharmony_ci bcm2835_wr_fifo(bs); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (!bs->rx_len) { 3888c2ecf20Sopenharmony_ci /* Transfer complete - reset SPI HW */ 3898c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 3908c2ecf20Sopenharmony_ci /* wake up the framework */ 3918c2ecf20Sopenharmony_ci complete(&bs->ctlr->xfer_completion); 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic int bcm2835_spi_transfer_one_irq(struct spi_controller *ctlr, 3988c2ecf20Sopenharmony_ci struct spi_device *spi, 3998c2ecf20Sopenharmony_ci struct spi_transfer *tfr, 4008c2ecf20Sopenharmony_ci u32 cs, bool fifo_empty) 4018c2ecf20Sopenharmony_ci{ 4028c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* update usage statistics */ 4058c2ecf20Sopenharmony_ci bs->count_transfer_irq++; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /* 4088c2ecf20Sopenharmony_ci * Enable HW block, but with interrupts still disabled. 4098c2ecf20Sopenharmony_ci * Otherwise the empty TX FIFO would immediately trigger an interrupt. 4108c2ecf20Sopenharmony_ci */ 4118c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* fill TX FIFO as much as possible */ 4148c2ecf20Sopenharmony_ci if (fifo_empty) 4158c2ecf20Sopenharmony_ci bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); 4168c2ecf20Sopenharmony_ci bcm2835_wr_fifo(bs); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci /* enable interrupts */ 4198c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_INTR | BCM2835_SPI_CS_INTD | BCM2835_SPI_CS_TA; 4208c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* signal that we need to wait for completion */ 4238c2ecf20Sopenharmony_ci return 1; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/** 4278c2ecf20Sopenharmony_ci * bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA 4288c2ecf20Sopenharmony_ci * @ctlr: SPI master controller 4298c2ecf20Sopenharmony_ci * @tfr: SPI transfer 4308c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 4318c2ecf20Sopenharmony_ci * @cs: CS register 4328c2ecf20Sopenharmony_ci * 4338c2ecf20Sopenharmony_ci * A limitation in DMA mode is that the FIFO must be accessed in 4 byte chunks. 4348c2ecf20Sopenharmony_ci * Only the final write access is permitted to transmit less than 4 bytes, the 4358c2ecf20Sopenharmony_ci * SPI controller deduces its intended size from the DLEN register. 4368c2ecf20Sopenharmony_ci * 4378c2ecf20Sopenharmony_ci * If a TX or RX sglist contains multiple entries, one per page, and the first 4388c2ecf20Sopenharmony_ci * entry starts in the middle of a page, that first entry's length may not be 4398c2ecf20Sopenharmony_ci * a multiple of 4. Subsequent entries are fine because they span an entire 4408c2ecf20Sopenharmony_ci * page, hence do have a length that's a multiple of 4. 4418c2ecf20Sopenharmony_ci * 4428c2ecf20Sopenharmony_ci * This cannot happen with kmalloc'ed buffers (which is what most clients use) 4438c2ecf20Sopenharmony_ci * because they are contiguous in physical memory and therefore not split on 4448c2ecf20Sopenharmony_ci * page boundaries by spi_map_buf(). But it *can* happen with vmalloc'ed 4458c2ecf20Sopenharmony_ci * buffers. 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * The DMA engine is incapable of combining sglist entries into a continuous 4488c2ecf20Sopenharmony_ci * stream of 4 byte chunks, it treats every entry separately: A TX entry is 4498c2ecf20Sopenharmony_ci * rounded up a to a multiple of 4 bytes by transmitting surplus bytes, an RX 4508c2ecf20Sopenharmony_ci * entry is rounded up by throwing away received bytes. 4518c2ecf20Sopenharmony_ci * 4528c2ecf20Sopenharmony_ci * Overcome this limitation by transferring the first few bytes without DMA: 4538c2ecf20Sopenharmony_ci * E.g. if the first TX sglist entry's length is 23 and the first RX's is 42, 4548c2ecf20Sopenharmony_ci * write 3 bytes to the TX FIFO but read only 2 bytes from the RX FIFO. 4558c2ecf20Sopenharmony_ci * The residue of 1 byte in the RX FIFO is picked up by DMA. Together with 4568c2ecf20Sopenharmony_ci * the rest of the first RX sglist entry it makes up a multiple of 4 bytes. 4578c2ecf20Sopenharmony_ci * 4588c2ecf20Sopenharmony_ci * Should the RX prologue be larger, say, 3 vis-à-vis a TX prologue of 1, 4598c2ecf20Sopenharmony_ci * write 1 + 4 = 5 bytes to the TX FIFO and read 3 bytes from the RX FIFO. 4608c2ecf20Sopenharmony_ci * Caution, the additional 4 bytes spill over to the second TX sglist entry 4618c2ecf20Sopenharmony_ci * if the length of the first is *exactly* 1. 4628c2ecf20Sopenharmony_ci * 4638c2ecf20Sopenharmony_ci * At most 6 bytes are written and at most 3 bytes read. Do we know the 4648c2ecf20Sopenharmony_ci * transfer has this many bytes? Yes, see BCM2835_SPI_DMA_MIN_LENGTH. 4658c2ecf20Sopenharmony_ci * 4668c2ecf20Sopenharmony_ci * The FIFO is normally accessed with 8-bit width by the CPU and 32-bit width 4678c2ecf20Sopenharmony_ci * by the DMA engine. Toggling the DMA Enable flag in the CS register switches 4688c2ecf20Sopenharmony_ci * the width but also garbles the FIFO's contents. The prologue must therefore 4698c2ecf20Sopenharmony_ci * be transmitted in 32-bit width to ensure that the following DMA transfer can 4708c2ecf20Sopenharmony_ci * pick up the residue in the RX FIFO in ungarbled form. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_cistatic void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr, 4738c2ecf20Sopenharmony_ci struct spi_transfer *tfr, 4748c2ecf20Sopenharmony_ci struct bcm2835_spi *bs, 4758c2ecf20Sopenharmony_ci u32 cs) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci int tx_remaining; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci bs->tfr = tfr; 4808c2ecf20Sopenharmony_ci bs->tx_prologue = 0; 4818c2ecf20Sopenharmony_ci bs->rx_prologue = 0; 4828c2ecf20Sopenharmony_ci bs->tx_spillover = false; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (bs->tx_buf && !sg_is_last(&tfr->tx_sg.sgl[0])) 4858c2ecf20Sopenharmony_ci bs->tx_prologue = sg_dma_len(&tfr->tx_sg.sgl[0]) & 3; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (bs->rx_buf && !sg_is_last(&tfr->rx_sg.sgl[0])) { 4888c2ecf20Sopenharmony_ci bs->rx_prologue = sg_dma_len(&tfr->rx_sg.sgl[0]) & 3; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (bs->rx_prologue > bs->tx_prologue) { 4918c2ecf20Sopenharmony_ci if (!bs->tx_buf || sg_is_last(&tfr->tx_sg.sgl[0])) { 4928c2ecf20Sopenharmony_ci bs->tx_prologue = bs->rx_prologue; 4938c2ecf20Sopenharmony_ci } else { 4948c2ecf20Sopenharmony_ci bs->tx_prologue += 4; 4958c2ecf20Sopenharmony_ci bs->tx_spillover = 4968c2ecf20Sopenharmony_ci !(sg_dma_len(&tfr->tx_sg.sgl[0]) & ~3); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci } 4998c2ecf20Sopenharmony_ci } 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci /* rx_prologue > 0 implies tx_prologue > 0, so check only the latter */ 5028c2ecf20Sopenharmony_ci if (!bs->tx_prologue) 5038c2ecf20Sopenharmony_ci return; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* Write and read RX prologue. Adjust first entry in RX sglist. */ 5068c2ecf20Sopenharmony_ci if (bs->rx_prologue) { 5078c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->rx_prologue); 5088c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA 5098c2ecf20Sopenharmony_ci | BCM2835_SPI_CS_DMAEN); 5108c2ecf20Sopenharmony_ci bcm2835_wr_fifo_count(bs, bs->rx_prologue); 5118c2ecf20Sopenharmony_ci bcm2835_wait_tx_fifo_empty(bs); 5128c2ecf20Sopenharmony_ci bcm2835_rd_fifo_count(bs, bs->rx_prologue); 5138c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_RX 5148c2ecf20Sopenharmony_ci | BCM2835_SPI_CS_CLEAR_TX 5158c2ecf20Sopenharmony_ci | BCM2835_SPI_CS_DONE); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci dma_sync_single_for_device(ctlr->dma_rx->device->dev, 5188c2ecf20Sopenharmony_ci sg_dma_address(&tfr->rx_sg.sgl[0]), 5198c2ecf20Sopenharmony_ci bs->rx_prologue, DMA_FROM_DEVICE); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci sg_dma_address(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; 5228c2ecf20Sopenharmony_ci sg_dma_len(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci if (!bs->tx_buf) 5268c2ecf20Sopenharmony_ci return; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci /* 5298c2ecf20Sopenharmony_ci * Write remaining TX prologue. Adjust first entry in TX sglist. 5308c2ecf20Sopenharmony_ci * Also adjust second entry if prologue spills over to it. 5318c2ecf20Sopenharmony_ci */ 5328c2ecf20Sopenharmony_ci tx_remaining = bs->tx_prologue - bs->rx_prologue; 5338c2ecf20Sopenharmony_ci if (tx_remaining) { 5348c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_DLEN, tx_remaining); 5358c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA 5368c2ecf20Sopenharmony_ci | BCM2835_SPI_CS_DMAEN); 5378c2ecf20Sopenharmony_ci bcm2835_wr_fifo_count(bs, tx_remaining); 5388c2ecf20Sopenharmony_ci bcm2835_wait_tx_fifo_empty(bs); 5398c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_CLEAR_TX 5408c2ecf20Sopenharmony_ci | BCM2835_SPI_CS_DONE); 5418c2ecf20Sopenharmony_ci } 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci if (likely(!bs->tx_spillover)) { 5448c2ecf20Sopenharmony_ci sg_dma_address(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; 5458c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; 5468c2ecf20Sopenharmony_ci } else { 5478c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[0]) = 0; 5488c2ecf20Sopenharmony_ci sg_dma_address(&tfr->tx_sg.sgl[1]) += 4; 5498c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[1]) -= 4; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci/** 5548c2ecf20Sopenharmony_ci * bcm2835_spi_undo_prologue() - reconstruct original sglist state 5558c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 5568c2ecf20Sopenharmony_ci * 5578c2ecf20Sopenharmony_ci * Undo changes which were made to an SPI transfer's sglist when transmitting 5588c2ecf20Sopenharmony_ci * the prologue. This is necessary to ensure the same memory ranges are 5598c2ecf20Sopenharmony_ci * unmapped that were originally mapped. 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_cistatic void bcm2835_spi_undo_prologue(struct bcm2835_spi *bs) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct spi_transfer *tfr = bs->tfr; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci if (!bs->tx_prologue) 5668c2ecf20Sopenharmony_ci return; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci if (bs->rx_prologue) { 5698c2ecf20Sopenharmony_ci sg_dma_address(&tfr->rx_sg.sgl[0]) -= bs->rx_prologue; 5708c2ecf20Sopenharmony_ci sg_dma_len(&tfr->rx_sg.sgl[0]) += bs->rx_prologue; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci if (!bs->tx_buf) 5748c2ecf20Sopenharmony_ci goto out; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (likely(!bs->tx_spillover)) { 5778c2ecf20Sopenharmony_ci sg_dma_address(&tfr->tx_sg.sgl[0]) -= bs->tx_prologue; 5788c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[0]) += bs->tx_prologue; 5798c2ecf20Sopenharmony_ci } else { 5808c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[0]) = bs->tx_prologue - 4; 5818c2ecf20Sopenharmony_ci sg_dma_address(&tfr->tx_sg.sgl[1]) -= 4; 5828c2ecf20Sopenharmony_ci sg_dma_len(&tfr->tx_sg.sgl[1]) += 4; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ciout: 5858c2ecf20Sopenharmony_ci bs->tx_prologue = 0; 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci/** 5898c2ecf20Sopenharmony_ci * bcm2835_spi_dma_rx_done() - callback for DMA RX channel 5908c2ecf20Sopenharmony_ci * @data: SPI master controller 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * Used for bidirectional and RX-only transfers. 5938c2ecf20Sopenharmony_ci */ 5948c2ecf20Sopenharmony_cistatic void bcm2835_spi_dma_rx_done(void *data) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci struct spi_controller *ctlr = data; 5978c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci /* terminate tx-dma as we do not have an irq for it 6008c2ecf20Sopenharmony_ci * because when the rx dma will terminate and this callback 6018c2ecf20Sopenharmony_ci * is called the tx-dma must have finished - can't get to this 6028c2ecf20Sopenharmony_ci * situation otherwise... 6038c2ecf20Sopenharmony_ci */ 6048c2ecf20Sopenharmony_ci dmaengine_terminate_async(ctlr->dma_tx); 6058c2ecf20Sopenharmony_ci bs->tx_dma_active = false; 6068c2ecf20Sopenharmony_ci bs->rx_dma_active = false; 6078c2ecf20Sopenharmony_ci bcm2835_spi_undo_prologue(bs); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci /* reset fifo and HW */ 6108c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci /* and mark as completed */; 6138c2ecf20Sopenharmony_ci complete(&ctlr->xfer_completion); 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci/** 6178c2ecf20Sopenharmony_ci * bcm2835_spi_dma_tx_done() - callback for DMA TX channel 6188c2ecf20Sopenharmony_ci * @data: SPI master controller 6198c2ecf20Sopenharmony_ci * 6208c2ecf20Sopenharmony_ci * Used for TX-only transfers. 6218c2ecf20Sopenharmony_ci */ 6228c2ecf20Sopenharmony_cistatic void bcm2835_spi_dma_tx_done(void *data) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct spi_controller *ctlr = data; 6258c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci /* busy-wait for TX FIFO to empty */ 6288c2ecf20Sopenharmony_ci while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) 6298c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, 6308c2ecf20Sopenharmony_ci bs->clear_rx_cs[bs->chip_select]); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci bs->tx_dma_active = false; 6338c2ecf20Sopenharmony_ci smp_wmb(); 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* 6368c2ecf20Sopenharmony_ci * In case of a very short transfer, RX DMA may not have been 6378c2ecf20Sopenharmony_ci * issued yet. The onus is then on bcm2835_spi_transfer_one_dma() 6388c2ecf20Sopenharmony_ci * to terminate it immediately after issuing. 6398c2ecf20Sopenharmony_ci */ 6408c2ecf20Sopenharmony_ci if (cmpxchg(&bs->rx_dma_active, true, false)) 6418c2ecf20Sopenharmony_ci dmaengine_terminate_async(ctlr->dma_rx); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci bcm2835_spi_undo_prologue(bs); 6448c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 6458c2ecf20Sopenharmony_ci complete(&ctlr->xfer_completion); 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci/** 6498c2ecf20Sopenharmony_ci * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist 6508c2ecf20Sopenharmony_ci * @ctlr: SPI master controller 6518c2ecf20Sopenharmony_ci * @spi: SPI slave 6528c2ecf20Sopenharmony_ci * @tfr: SPI transfer 6538c2ecf20Sopenharmony_ci * @bs: BCM2835 SPI controller 6548c2ecf20Sopenharmony_ci * @is_tx: whether to submit DMA descriptor for TX or RX sglist 6558c2ecf20Sopenharmony_ci * 6568c2ecf20Sopenharmony_ci * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr. 6578c2ecf20Sopenharmony_ci * Return 0 on success or a negative error number. 6588c2ecf20Sopenharmony_ci */ 6598c2ecf20Sopenharmony_cistatic int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, 6608c2ecf20Sopenharmony_ci struct spi_device *spi, 6618c2ecf20Sopenharmony_ci struct spi_transfer *tfr, 6628c2ecf20Sopenharmony_ci struct bcm2835_spi *bs, 6638c2ecf20Sopenharmony_ci bool is_tx) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci struct dma_chan *chan; 6668c2ecf20Sopenharmony_ci struct scatterlist *sgl; 6678c2ecf20Sopenharmony_ci unsigned int nents; 6688c2ecf20Sopenharmony_ci enum dma_transfer_direction dir; 6698c2ecf20Sopenharmony_ci unsigned long flags; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *desc; 6728c2ecf20Sopenharmony_ci dma_cookie_t cookie; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (is_tx) { 6758c2ecf20Sopenharmony_ci dir = DMA_MEM_TO_DEV; 6768c2ecf20Sopenharmony_ci chan = ctlr->dma_tx; 6778c2ecf20Sopenharmony_ci nents = tfr->tx_sg.nents; 6788c2ecf20Sopenharmony_ci sgl = tfr->tx_sg.sgl; 6798c2ecf20Sopenharmony_ci flags = tfr->rx_buf ? 0 : DMA_PREP_INTERRUPT; 6808c2ecf20Sopenharmony_ci } else { 6818c2ecf20Sopenharmony_ci dir = DMA_DEV_TO_MEM; 6828c2ecf20Sopenharmony_ci chan = ctlr->dma_rx; 6838c2ecf20Sopenharmony_ci nents = tfr->rx_sg.nents; 6848c2ecf20Sopenharmony_ci sgl = tfr->rx_sg.sgl; 6858c2ecf20Sopenharmony_ci flags = DMA_PREP_INTERRUPT; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci /* prepare the channel */ 6888c2ecf20Sopenharmony_ci desc = dmaengine_prep_slave_sg(chan, sgl, nents, dir, flags); 6898c2ecf20Sopenharmony_ci if (!desc) 6908c2ecf20Sopenharmony_ci return -EINVAL; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci /* 6938c2ecf20Sopenharmony_ci * Completion is signaled by the RX channel for bidirectional and 6948c2ecf20Sopenharmony_ci * RX-only transfers; else by the TX channel for TX-only transfers. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_ci if (!is_tx) { 6978c2ecf20Sopenharmony_ci desc->callback = bcm2835_spi_dma_rx_done; 6988c2ecf20Sopenharmony_ci desc->callback_param = ctlr; 6998c2ecf20Sopenharmony_ci } else if (!tfr->rx_buf) { 7008c2ecf20Sopenharmony_ci desc->callback = bcm2835_spi_dma_tx_done; 7018c2ecf20Sopenharmony_ci desc->callback_param = ctlr; 7028c2ecf20Sopenharmony_ci bs->chip_select = spi->chip_select; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* submit it to DMA-engine */ 7068c2ecf20Sopenharmony_ci cookie = dmaengine_submit(desc); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci return dma_submit_error(cookie); 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci/** 7128c2ecf20Sopenharmony_ci * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine 7138c2ecf20Sopenharmony_ci * @ctlr: SPI master controller 7148c2ecf20Sopenharmony_ci * @spi: SPI slave 7158c2ecf20Sopenharmony_ci * @tfr: SPI transfer 7168c2ecf20Sopenharmony_ci * @cs: CS register 7178c2ecf20Sopenharmony_ci * 7188c2ecf20Sopenharmony_ci * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up 7198c2ecf20Sopenharmony_ci * the TX and RX DMA channel to copy between memory and FIFO register. 7208c2ecf20Sopenharmony_ci * 7218c2ecf20Sopenharmony_ci * For *TX-only* transfers (rx_buf is %NULL), copying the RX FIFO's contents to 7228c2ecf20Sopenharmony_ci * memory is pointless. However not reading the RX FIFO isn't an option either 7238c2ecf20Sopenharmony_ci * because transmission is halted once it's full. As a workaround, cyclically 7248c2ecf20Sopenharmony_ci * clear the RX FIFO by setting the CLEAR_RX bit in the CS register. 7258c2ecf20Sopenharmony_ci * 7268c2ecf20Sopenharmony_ci * The CS register value is precalculated in bcm2835_spi_setup(). Normally 7278c2ecf20Sopenharmony_ci * this is called only once, on slave registration. A DMA descriptor to write 7288c2ecf20Sopenharmony_ci * this value is preallocated in bcm2835_dma_init(). All that's left to do 7298c2ecf20Sopenharmony_ci * when performing a TX-only transfer is to submit this descriptor to the RX 7308c2ecf20Sopenharmony_ci * DMA channel. Latency is thereby minimized. The descriptor does not 7318c2ecf20Sopenharmony_ci * generate any interrupts while running. It must be terminated once the 7328c2ecf20Sopenharmony_ci * TX DMA channel is done. 7338c2ecf20Sopenharmony_ci * 7348c2ecf20Sopenharmony_ci * Clearing the RX FIFO is paced by the DREQ signal. The signal is asserted 7358c2ecf20Sopenharmony_ci * when the RX FIFO becomes half full, i.e. 32 bytes. (Tuneable with the DC 7368c2ecf20Sopenharmony_ci * register.) Reading 32 bytes from the RX FIFO would normally require 8 bus 7378c2ecf20Sopenharmony_ci * accesses, whereas clearing it requires only 1 bus access. So an 8-fold 7388c2ecf20Sopenharmony_ci * reduction in bus traffic and thus energy consumption is achieved. 7398c2ecf20Sopenharmony_ci * 7408c2ecf20Sopenharmony_ci * For *RX-only* transfers (tx_buf is %NULL), fill the TX FIFO by cyclically 7418c2ecf20Sopenharmony_ci * copying from the zero page. The DMA descriptor to do this is preallocated 7428c2ecf20Sopenharmony_ci * in bcm2835_dma_init(). It must be terminated once the RX DMA channel is 7438c2ecf20Sopenharmony_ci * done and can then be reused. 7448c2ecf20Sopenharmony_ci * 7458c2ecf20Sopenharmony_ci * The BCM2835 DMA driver autodetects when a transaction copies from the zero 7468c2ecf20Sopenharmony_ci * page and utilizes the DMA controller's ability to synthesize zeroes instead 7478c2ecf20Sopenharmony_ci * of copying them from memory. This reduces traffic on the memory bus. The 7488c2ecf20Sopenharmony_ci * feature is not available on so-called "lite" channels, but normally TX DMA 7498c2ecf20Sopenharmony_ci * is backed by a full-featured channel. 7508c2ecf20Sopenharmony_ci * 7518c2ecf20Sopenharmony_ci * Zero-filling the TX FIFO is paced by the DREQ signal. Unfortunately the 7528c2ecf20Sopenharmony_ci * BCM2835 SPI controller continues to assert DREQ even after the DLEN register 7538c2ecf20Sopenharmony_ci * has been counted down to zero (hardware erratum). Thus, when the transfer 7548c2ecf20Sopenharmony_ci * has finished, the DMA engine zero-fills the TX FIFO until it is half full. 7558c2ecf20Sopenharmony_ci * (Tuneable with the DC register.) So up to 9 gratuitous bus accesses are 7568c2ecf20Sopenharmony_ci * performed at the end of an RX-only transfer. 7578c2ecf20Sopenharmony_ci */ 7588c2ecf20Sopenharmony_cistatic int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, 7598c2ecf20Sopenharmony_ci struct spi_device *spi, 7608c2ecf20Sopenharmony_ci struct spi_transfer *tfr, 7618c2ecf20Sopenharmony_ci u32 cs) 7628c2ecf20Sopenharmony_ci{ 7638c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 7648c2ecf20Sopenharmony_ci dma_cookie_t cookie; 7658c2ecf20Sopenharmony_ci int ret; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci /* update usage statistics */ 7688c2ecf20Sopenharmony_ci bs->count_transfer_dma++; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /* 7718c2ecf20Sopenharmony_ci * Transfer first few bytes without DMA if length of first TX or RX 7728c2ecf20Sopenharmony_ci * sglist entry is not a multiple of 4 bytes (hardware limitation). 7738c2ecf20Sopenharmony_ci */ 7748c2ecf20Sopenharmony_ci bcm2835_spi_transfer_prologue(ctlr, tfr, bs, cs); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci /* setup tx-DMA */ 7778c2ecf20Sopenharmony_ci if (bs->tx_buf) { 7788c2ecf20Sopenharmony_ci ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, true); 7798c2ecf20Sopenharmony_ci } else { 7808c2ecf20Sopenharmony_ci cookie = dmaengine_submit(bs->fill_tx_desc); 7818c2ecf20Sopenharmony_ci ret = dma_submit_error(cookie); 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci if (ret) 7848c2ecf20Sopenharmony_ci goto err_reset_hw; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci /* set the DMA length */ 7878c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_DLEN, bs->tx_len); 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci /* start the HW */ 7908c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, 7918c2ecf20Sopenharmony_ci cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci bs->tx_dma_active = true; 7948c2ecf20Sopenharmony_ci smp_wmb(); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci /* start TX early */ 7978c2ecf20Sopenharmony_ci dma_async_issue_pending(ctlr->dma_tx); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* setup rx-DMA late - to run transfers while 8008c2ecf20Sopenharmony_ci * mapping of the rx buffers still takes place 8018c2ecf20Sopenharmony_ci * this saves 10us or more. 8028c2ecf20Sopenharmony_ci */ 8038c2ecf20Sopenharmony_ci if (bs->rx_buf) { 8048c2ecf20Sopenharmony_ci ret = bcm2835_spi_prepare_sg(ctlr, spi, tfr, bs, false); 8058c2ecf20Sopenharmony_ci } else { 8068c2ecf20Sopenharmony_ci cookie = dmaengine_submit(bs->clear_rx_desc[spi->chip_select]); 8078c2ecf20Sopenharmony_ci ret = dma_submit_error(cookie); 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci if (ret) { 8108c2ecf20Sopenharmony_ci /* need to reset on errors */ 8118c2ecf20Sopenharmony_ci dmaengine_terminate_sync(ctlr->dma_tx); 8128c2ecf20Sopenharmony_ci bs->tx_dma_active = false; 8138c2ecf20Sopenharmony_ci goto err_reset_hw; 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* start rx dma late */ 8178c2ecf20Sopenharmony_ci dma_async_issue_pending(ctlr->dma_rx); 8188c2ecf20Sopenharmony_ci bs->rx_dma_active = true; 8198c2ecf20Sopenharmony_ci smp_mb(); 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci /* 8228c2ecf20Sopenharmony_ci * In case of a very short TX-only transfer, bcm2835_spi_dma_tx_done() 8238c2ecf20Sopenharmony_ci * may run before RX DMA is issued. Terminate RX DMA if so. 8248c2ecf20Sopenharmony_ci */ 8258c2ecf20Sopenharmony_ci if (!bs->rx_buf && !bs->tx_dma_active && 8268c2ecf20Sopenharmony_ci cmpxchg(&bs->rx_dma_active, true, false)) { 8278c2ecf20Sopenharmony_ci dmaengine_terminate_async(ctlr->dma_rx); 8288c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci /* wait for wakeup in framework */ 8328c2ecf20Sopenharmony_ci return 1; 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cierr_reset_hw: 8358c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 8368c2ecf20Sopenharmony_ci bcm2835_spi_undo_prologue(bs); 8378c2ecf20Sopenharmony_ci return ret; 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_cistatic bool bcm2835_spi_can_dma(struct spi_controller *ctlr, 8418c2ecf20Sopenharmony_ci struct spi_device *spi, 8428c2ecf20Sopenharmony_ci struct spi_transfer *tfr) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci /* we start DMA efforts only on bigger transfers */ 8458c2ecf20Sopenharmony_ci if (tfr->len < BCM2835_SPI_DMA_MIN_LENGTH) 8468c2ecf20Sopenharmony_ci return false; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* return OK */ 8498c2ecf20Sopenharmony_ci return true; 8508c2ecf20Sopenharmony_ci} 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_cistatic void bcm2835_dma_release(struct spi_controller *ctlr, 8538c2ecf20Sopenharmony_ci struct bcm2835_spi *bs) 8548c2ecf20Sopenharmony_ci{ 8558c2ecf20Sopenharmony_ci int i; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci if (ctlr->dma_tx) { 8588c2ecf20Sopenharmony_ci dmaengine_terminate_sync(ctlr->dma_tx); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (bs->fill_tx_desc) 8618c2ecf20Sopenharmony_ci dmaengine_desc_free(bs->fill_tx_desc); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci if (bs->fill_tx_addr) 8648c2ecf20Sopenharmony_ci dma_unmap_page_attrs(ctlr->dma_tx->device->dev, 8658c2ecf20Sopenharmony_ci bs->fill_tx_addr, sizeof(u32), 8668c2ecf20Sopenharmony_ci DMA_TO_DEVICE, 8678c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci dma_release_channel(ctlr->dma_tx); 8708c2ecf20Sopenharmony_ci ctlr->dma_tx = NULL; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (ctlr->dma_rx) { 8748c2ecf20Sopenharmony_ci dmaengine_terminate_sync(ctlr->dma_rx); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci for (i = 0; i < BCM2835_SPI_NUM_CS; i++) 8778c2ecf20Sopenharmony_ci if (bs->clear_rx_desc[i]) 8788c2ecf20Sopenharmony_ci dmaengine_desc_free(bs->clear_rx_desc[i]); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci if (bs->clear_rx_addr) 8818c2ecf20Sopenharmony_ci dma_unmap_single(ctlr->dma_rx->device->dev, 8828c2ecf20Sopenharmony_ci bs->clear_rx_addr, 8838c2ecf20Sopenharmony_ci sizeof(bs->clear_rx_cs), 8848c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci dma_release_channel(ctlr->dma_rx); 8878c2ecf20Sopenharmony_ci ctlr->dma_rx = NULL; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, 8928c2ecf20Sopenharmony_ci struct bcm2835_spi *bs) 8938c2ecf20Sopenharmony_ci{ 8948c2ecf20Sopenharmony_ci struct dma_slave_config slave_config; 8958c2ecf20Sopenharmony_ci const __be32 *addr; 8968c2ecf20Sopenharmony_ci dma_addr_t dma_reg_base; 8978c2ecf20Sopenharmony_ci int ret, i; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci /* base address in dma-space */ 9008c2ecf20Sopenharmony_ci addr = of_get_address(ctlr->dev.of_node, 0, NULL, NULL); 9018c2ecf20Sopenharmony_ci if (!addr) { 9028c2ecf20Sopenharmony_ci dev_err(dev, "could not get DMA-register address - not using dma mode\n"); 9038c2ecf20Sopenharmony_ci /* Fall back to interrupt mode */ 9048c2ecf20Sopenharmony_ci return 0; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci dma_reg_base = be32_to_cpup(addr); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* get tx/rx dma */ 9098c2ecf20Sopenharmony_ci ctlr->dma_tx = dma_request_chan(dev, "tx"); 9108c2ecf20Sopenharmony_ci if (IS_ERR(ctlr->dma_tx)) { 9118c2ecf20Sopenharmony_ci dev_err(dev, "no tx-dma configuration found - not using dma mode\n"); 9128c2ecf20Sopenharmony_ci ret = PTR_ERR(ctlr->dma_tx); 9138c2ecf20Sopenharmony_ci ctlr->dma_tx = NULL; 9148c2ecf20Sopenharmony_ci goto err; 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci ctlr->dma_rx = dma_request_chan(dev, "rx"); 9178c2ecf20Sopenharmony_ci if (IS_ERR(ctlr->dma_rx)) { 9188c2ecf20Sopenharmony_ci dev_err(dev, "no rx-dma configuration found - not using dma mode\n"); 9198c2ecf20Sopenharmony_ci ret = PTR_ERR(ctlr->dma_rx); 9208c2ecf20Sopenharmony_ci ctlr->dma_rx = NULL; 9218c2ecf20Sopenharmony_ci goto err_release; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci /* 9258c2ecf20Sopenharmony_ci * The TX DMA channel either copies a transfer's TX buffer to the FIFO 9268c2ecf20Sopenharmony_ci * or, in case of an RX-only transfer, cyclically copies from the zero 9278c2ecf20Sopenharmony_ci * page to the FIFO using a preallocated, reusable descriptor. 9288c2ecf20Sopenharmony_ci */ 9298c2ecf20Sopenharmony_ci slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); 9308c2ecf20Sopenharmony_ci slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(ctlr->dma_tx, &slave_config); 9338c2ecf20Sopenharmony_ci if (ret) 9348c2ecf20Sopenharmony_ci goto err_config; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev, 9378c2ecf20Sopenharmony_ci ZERO_PAGE(0), 0, sizeof(u32), 9388c2ecf20Sopenharmony_ci DMA_TO_DEVICE, 9398c2ecf20Sopenharmony_ci DMA_ATTR_SKIP_CPU_SYNC); 9408c2ecf20Sopenharmony_ci if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) { 9418c2ecf20Sopenharmony_ci dev_err(dev, "cannot map zero page - not using DMA mode\n"); 9428c2ecf20Sopenharmony_ci bs->fill_tx_addr = 0; 9438c2ecf20Sopenharmony_ci ret = -ENOMEM; 9448c2ecf20Sopenharmony_ci goto err_release; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci bs->fill_tx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_tx, 9488c2ecf20Sopenharmony_ci bs->fill_tx_addr, 9498c2ecf20Sopenharmony_ci sizeof(u32), 0, 9508c2ecf20Sopenharmony_ci DMA_MEM_TO_DEV, 0); 9518c2ecf20Sopenharmony_ci if (!bs->fill_tx_desc) { 9528c2ecf20Sopenharmony_ci dev_err(dev, "cannot prepare fill_tx_desc - not using DMA mode\n"); 9538c2ecf20Sopenharmony_ci ret = -ENOMEM; 9548c2ecf20Sopenharmony_ci goto err_release; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci ret = dmaengine_desc_set_reuse(bs->fill_tx_desc); 9588c2ecf20Sopenharmony_ci if (ret) { 9598c2ecf20Sopenharmony_ci dev_err(dev, "cannot reuse fill_tx_desc - not using DMA mode\n"); 9608c2ecf20Sopenharmony_ci goto err_release; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci /* 9648c2ecf20Sopenharmony_ci * The RX DMA channel is used bidirectionally: It either reads the 9658c2ecf20Sopenharmony_ci * RX FIFO or, in case of a TX-only transfer, cyclically writes a 9668c2ecf20Sopenharmony_ci * precalculated value to the CS register to clear the RX FIFO. 9678c2ecf20Sopenharmony_ci */ 9688c2ecf20Sopenharmony_ci slave_config.src_addr = (u32)(dma_reg_base + BCM2835_SPI_FIFO); 9698c2ecf20Sopenharmony_ci slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 9708c2ecf20Sopenharmony_ci slave_config.dst_addr = (u32)(dma_reg_base + BCM2835_SPI_CS); 9718c2ecf20Sopenharmony_ci slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(ctlr->dma_rx, &slave_config); 9748c2ecf20Sopenharmony_ci if (ret) 9758c2ecf20Sopenharmony_ci goto err_config; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci bs->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev, 9788c2ecf20Sopenharmony_ci bs->clear_rx_cs, 9798c2ecf20Sopenharmony_ci sizeof(bs->clear_rx_cs), 9808c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 9818c2ecf20Sopenharmony_ci if (dma_mapping_error(ctlr->dma_rx->device->dev, bs->clear_rx_addr)) { 9828c2ecf20Sopenharmony_ci dev_err(dev, "cannot map clear_rx_cs - not using DMA mode\n"); 9838c2ecf20Sopenharmony_ci bs->clear_rx_addr = 0; 9848c2ecf20Sopenharmony_ci ret = -ENOMEM; 9858c2ecf20Sopenharmony_ci goto err_release; 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci for (i = 0; i < BCM2835_SPI_NUM_CS; i++) { 9898c2ecf20Sopenharmony_ci bs->clear_rx_desc[i] = dmaengine_prep_dma_cyclic(ctlr->dma_rx, 9908c2ecf20Sopenharmony_ci bs->clear_rx_addr + i * sizeof(u32), 9918c2ecf20Sopenharmony_ci sizeof(u32), 0, 9928c2ecf20Sopenharmony_ci DMA_MEM_TO_DEV, 0); 9938c2ecf20Sopenharmony_ci if (!bs->clear_rx_desc[i]) { 9948c2ecf20Sopenharmony_ci dev_err(dev, "cannot prepare clear_rx_desc - not using DMA mode\n"); 9958c2ecf20Sopenharmony_ci ret = -ENOMEM; 9968c2ecf20Sopenharmony_ci goto err_release; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci ret = dmaengine_desc_set_reuse(bs->clear_rx_desc[i]); 10008c2ecf20Sopenharmony_ci if (ret) { 10018c2ecf20Sopenharmony_ci dev_err(dev, "cannot reuse clear_rx_desc - not using DMA mode\n"); 10028c2ecf20Sopenharmony_ci goto err_release; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci /* all went well, so set can_dma */ 10078c2ecf20Sopenharmony_ci ctlr->can_dma = bcm2835_spi_can_dma; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci return 0; 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_cierr_config: 10128c2ecf20Sopenharmony_ci dev_err(dev, "issue configuring dma: %d - not using DMA mode\n", 10138c2ecf20Sopenharmony_ci ret); 10148c2ecf20Sopenharmony_cierr_release: 10158c2ecf20Sopenharmony_ci bcm2835_dma_release(ctlr, bs); 10168c2ecf20Sopenharmony_cierr: 10178c2ecf20Sopenharmony_ci /* 10188c2ecf20Sopenharmony_ci * Only report error for deferred probing, otherwise fall back to 10198c2ecf20Sopenharmony_ci * interrupt mode 10208c2ecf20Sopenharmony_ci */ 10218c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 10228c2ecf20Sopenharmony_ci ret = 0; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci return ret; 10258c2ecf20Sopenharmony_ci} 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_cistatic int bcm2835_spi_transfer_one_poll(struct spi_controller *ctlr, 10288c2ecf20Sopenharmony_ci struct spi_device *spi, 10298c2ecf20Sopenharmony_ci struct spi_transfer *tfr, 10308c2ecf20Sopenharmony_ci u32 cs) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 10338c2ecf20Sopenharmony_ci unsigned long timeout; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci /* update usage statistics */ 10368c2ecf20Sopenharmony_ci bs->count_transfer_polling++; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* enable HW block without interrupts */ 10398c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA); 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci /* fill in the fifo before timeout calculations 10428c2ecf20Sopenharmony_ci * if we are interrupted here, then the data is 10438c2ecf20Sopenharmony_ci * getting transferred by the HW while we are interrupted 10448c2ecf20Sopenharmony_ci */ 10458c2ecf20Sopenharmony_ci bcm2835_wr_fifo_blind(bs, BCM2835_SPI_FIFO_SIZE); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* set the timeout to at least 2 jiffies */ 10488c2ecf20Sopenharmony_ci timeout = jiffies + 2 + HZ * polling_limit_us / 1000000; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* loop until finished the transfer */ 10518c2ecf20Sopenharmony_ci while (bs->rx_len) { 10528c2ecf20Sopenharmony_ci /* fill in tx fifo with remaining data */ 10538c2ecf20Sopenharmony_ci bcm2835_wr_fifo(bs); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci /* read from fifo as much as possible */ 10568c2ecf20Sopenharmony_ci bcm2835_rd_fifo(bs); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci /* if there is still data pending to read 10598c2ecf20Sopenharmony_ci * then check the timeout 10608c2ecf20Sopenharmony_ci */ 10618c2ecf20Sopenharmony_ci if (bs->rx_len && time_after(jiffies, timeout)) { 10628c2ecf20Sopenharmony_ci dev_dbg_ratelimited(&spi->dev, 10638c2ecf20Sopenharmony_ci "timeout period reached: jiffies: %lu remaining tx/rx: %d/%d - falling back to interrupt mode\n", 10648c2ecf20Sopenharmony_ci jiffies - timeout, 10658c2ecf20Sopenharmony_ci bs->tx_len, bs->rx_len); 10668c2ecf20Sopenharmony_ci /* fall back to interrupt mode */ 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci /* update usage statistics */ 10698c2ecf20Sopenharmony_ci bs->count_transfer_irq_after_polling++; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci return bcm2835_spi_transfer_one_irq(ctlr, spi, 10728c2ecf20Sopenharmony_ci tfr, cs, false); 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci /* Transfer complete - reset SPI HW */ 10778c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 10788c2ecf20Sopenharmony_ci /* and return without waiting for completion */ 10798c2ecf20Sopenharmony_ci return 0; 10808c2ecf20Sopenharmony_ci} 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_cistatic int bcm2835_spi_transfer_one(struct spi_controller *ctlr, 10838c2ecf20Sopenharmony_ci struct spi_device *spi, 10848c2ecf20Sopenharmony_ci struct spi_transfer *tfr) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 10878c2ecf20Sopenharmony_ci unsigned long spi_hz, cdiv; 10888c2ecf20Sopenharmony_ci unsigned long hz_per_byte, byte_limit; 10898c2ecf20Sopenharmony_ci u32 cs = bs->prepare_cs[spi->chip_select]; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci /* set clock */ 10928c2ecf20Sopenharmony_ci spi_hz = tfr->speed_hz; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci if (spi_hz >= bs->clk_hz / 2) { 10958c2ecf20Sopenharmony_ci cdiv = 2; /* clk_hz/2 is the fastest we can go */ 10968c2ecf20Sopenharmony_ci } else if (spi_hz) { 10978c2ecf20Sopenharmony_ci /* CDIV must be a multiple of two */ 10988c2ecf20Sopenharmony_ci cdiv = DIV_ROUND_UP(bs->clk_hz, spi_hz); 10998c2ecf20Sopenharmony_ci cdiv += (cdiv % 2); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (cdiv >= 65536) 11028c2ecf20Sopenharmony_ci cdiv = 0; /* 0 is the slowest we can go */ 11038c2ecf20Sopenharmony_ci } else { 11048c2ecf20Sopenharmony_ci cdiv = 0; /* 0 is the slowest we can go */ 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci tfr->effective_speed_hz = cdiv ? (bs->clk_hz / cdiv) : (bs->clk_hz / 65536); 11078c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CLK, cdiv); 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci /* handle all the 3-wire mode */ 11108c2ecf20Sopenharmony_ci if (spi->mode & SPI_3WIRE && tfr->rx_buf) 11118c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_REN; 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci /* set transmit buffers and length */ 11148c2ecf20Sopenharmony_ci bs->tx_buf = tfr->tx_buf; 11158c2ecf20Sopenharmony_ci bs->rx_buf = tfr->rx_buf; 11168c2ecf20Sopenharmony_ci bs->tx_len = tfr->len; 11178c2ecf20Sopenharmony_ci bs->rx_len = tfr->len; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci /* Calculate the estimated time in us the transfer runs. Note that 11208c2ecf20Sopenharmony_ci * there is 1 idle clocks cycles after each byte getting transferred 11218c2ecf20Sopenharmony_ci * so we have 9 cycles/byte. This is used to find the number of Hz 11228c2ecf20Sopenharmony_ci * per byte per polling limit. E.g., we can transfer 1 byte in 30 us 11238c2ecf20Sopenharmony_ci * per 300,000 Hz of bus clock. 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_ci hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0; 11268c2ecf20Sopenharmony_ci byte_limit = hz_per_byte ? tfr->effective_speed_hz / hz_per_byte : 1; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* run in polling mode for short transfers */ 11298c2ecf20Sopenharmony_ci if (tfr->len < byte_limit) 11308c2ecf20Sopenharmony_ci return bcm2835_spi_transfer_one_poll(ctlr, spi, tfr, cs); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci /* run in dma mode if conditions are right 11338c2ecf20Sopenharmony_ci * Note that unlike poll or interrupt mode DMA mode does not have 11348c2ecf20Sopenharmony_ci * this 1 idle clock cycle pattern but runs the spi clock without gaps 11358c2ecf20Sopenharmony_ci */ 11368c2ecf20Sopenharmony_ci if (ctlr->can_dma && bcm2835_spi_can_dma(ctlr, spi, tfr)) 11378c2ecf20Sopenharmony_ci return bcm2835_spi_transfer_one_dma(ctlr, spi, tfr, cs); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci /* run in interrupt-mode */ 11408c2ecf20Sopenharmony_ci return bcm2835_spi_transfer_one_irq(ctlr, spi, tfr, cs, true); 11418c2ecf20Sopenharmony_ci} 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_cistatic int bcm2835_spi_prepare_message(struct spi_controller *ctlr, 11448c2ecf20Sopenharmony_ci struct spi_message *msg) 11458c2ecf20Sopenharmony_ci{ 11468c2ecf20Sopenharmony_ci struct spi_device *spi = msg->spi; 11478c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 11488c2ecf20Sopenharmony_ci int ret; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci if (ctlr->can_dma) { 11518c2ecf20Sopenharmony_ci /* 11528c2ecf20Sopenharmony_ci * DMA transfers are limited to 16 bit (0 to 65535 bytes) by 11538c2ecf20Sopenharmony_ci * the SPI HW due to DLEN. Split up transfers (32-bit FIFO 11548c2ecf20Sopenharmony_ci * aligned) if the limit is exceeded. 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_ci ret = spi_split_transfers_maxsize(ctlr, msg, 65532, 11578c2ecf20Sopenharmony_ci GFP_KERNEL | GFP_DMA); 11588c2ecf20Sopenharmony_ci if (ret) 11598c2ecf20Sopenharmony_ci return ret; 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci /* 11638c2ecf20Sopenharmony_ci * Set up clock polarity before spi_transfer_one_message() asserts 11648c2ecf20Sopenharmony_ci * chip select to avoid a gratuitous clock signal edge. 11658c2ecf20Sopenharmony_ci */ 11668c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, bs->prepare_cs[spi->chip_select]); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci return 0; 11698c2ecf20Sopenharmony_ci} 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_cistatic void bcm2835_spi_handle_err(struct spi_controller *ctlr, 11728c2ecf20Sopenharmony_ci struct spi_message *msg) 11738c2ecf20Sopenharmony_ci{ 11748c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 11758c2ecf20Sopenharmony_ci 11768c2ecf20Sopenharmony_ci /* if an error occurred and we have an active dma, then terminate */ 11778c2ecf20Sopenharmony_ci if (ctlr->dma_tx) { 11788c2ecf20Sopenharmony_ci dmaengine_terminate_sync(ctlr->dma_tx); 11798c2ecf20Sopenharmony_ci bs->tx_dma_active = false; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci if (ctlr->dma_rx) { 11828c2ecf20Sopenharmony_ci dmaengine_terminate_sync(ctlr->dma_rx); 11838c2ecf20Sopenharmony_ci bs->rx_dma_active = false; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci bcm2835_spi_undo_prologue(bs); 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci /* and reset */ 11888c2ecf20Sopenharmony_ci bcm2835_spi_reset_hw(bs); 11898c2ecf20Sopenharmony_ci} 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_cistatic int chip_match_name(struct gpio_chip *chip, void *data) 11928c2ecf20Sopenharmony_ci{ 11938c2ecf20Sopenharmony_ci return !strcmp(chip->label, data); 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_cistatic int bcm2835_spi_setup(struct spi_device *spi) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci struct spi_controller *ctlr = spi->controller; 11998c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 12008c2ecf20Sopenharmony_ci struct gpio_chip *chip; 12018c2ecf20Sopenharmony_ci u32 cs; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (spi->chip_select >= BCM2835_SPI_NUM_CS) { 12048c2ecf20Sopenharmony_ci dev_err(&spi->dev, "only %d chip-selects supported\n", 12058c2ecf20Sopenharmony_ci BCM2835_SPI_NUM_CS - 1); 12068c2ecf20Sopenharmony_ci return -EINVAL; 12078c2ecf20Sopenharmony_ci } 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci /* 12108c2ecf20Sopenharmony_ci * Precalculate SPI slave's CS register value for ->prepare_message(): 12118c2ecf20Sopenharmony_ci * The driver always uses software-controlled GPIO chip select, hence 12128c2ecf20Sopenharmony_ci * set the hardware-controlled native chip select to an invalid value 12138c2ecf20Sopenharmony_ci * to prevent it from interfering. 12148c2ecf20Sopenharmony_ci */ 12158c2ecf20Sopenharmony_ci cs = BCM2835_SPI_CS_CS_10 | BCM2835_SPI_CS_CS_01; 12168c2ecf20Sopenharmony_ci if (spi->mode & SPI_CPOL) 12178c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_CPOL; 12188c2ecf20Sopenharmony_ci if (spi->mode & SPI_CPHA) 12198c2ecf20Sopenharmony_ci cs |= BCM2835_SPI_CS_CPHA; 12208c2ecf20Sopenharmony_ci bs->prepare_cs[spi->chip_select] = cs; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci /* 12238c2ecf20Sopenharmony_ci * Precalculate SPI slave's CS register value to clear RX FIFO 12248c2ecf20Sopenharmony_ci * in case of a TX-only DMA transfer. 12258c2ecf20Sopenharmony_ci */ 12268c2ecf20Sopenharmony_ci if (ctlr->dma_rx) { 12278c2ecf20Sopenharmony_ci bs->clear_rx_cs[spi->chip_select] = cs | 12288c2ecf20Sopenharmony_ci BCM2835_SPI_CS_TA | 12298c2ecf20Sopenharmony_ci BCM2835_SPI_CS_DMAEN | 12308c2ecf20Sopenharmony_ci BCM2835_SPI_CS_CLEAR_RX; 12318c2ecf20Sopenharmony_ci dma_sync_single_for_device(ctlr->dma_rx->device->dev, 12328c2ecf20Sopenharmony_ci bs->clear_rx_addr, 12338c2ecf20Sopenharmony_ci sizeof(bs->clear_rx_cs), 12348c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* 12388c2ecf20Sopenharmony_ci * sanity checking the native-chipselects 12398c2ecf20Sopenharmony_ci */ 12408c2ecf20Sopenharmony_ci if (spi->mode & SPI_NO_CS) 12418c2ecf20Sopenharmony_ci return 0; 12428c2ecf20Sopenharmony_ci /* 12438c2ecf20Sopenharmony_ci * The SPI core has successfully requested the CS GPIO line from the 12448c2ecf20Sopenharmony_ci * device tree, so we are done. 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci if (spi->cs_gpiod) 12478c2ecf20Sopenharmony_ci return 0; 12488c2ecf20Sopenharmony_ci if (spi->chip_select > 1) { 12498c2ecf20Sopenharmony_ci /* error in the case of native CS requested with CS > 1 12508c2ecf20Sopenharmony_ci * officially there is a CS2, but it is not documented 12518c2ecf20Sopenharmony_ci * which GPIO is connected with that... 12528c2ecf20Sopenharmony_ci */ 12538c2ecf20Sopenharmony_ci dev_err(&spi->dev, 12548c2ecf20Sopenharmony_ci "setup: only two native chip-selects are supported\n"); 12558c2ecf20Sopenharmony_ci return -EINVAL; 12568c2ecf20Sopenharmony_ci } 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci /* 12598c2ecf20Sopenharmony_ci * Translate native CS to GPIO 12608c2ecf20Sopenharmony_ci * 12618c2ecf20Sopenharmony_ci * FIXME: poking around in the gpiolib internals like this is 12628c2ecf20Sopenharmony_ci * not very good practice. Find a way to locate the real problem 12638c2ecf20Sopenharmony_ci * and fix it. Why is the GPIO descriptor in spi->cs_gpiod 12648c2ecf20Sopenharmony_ci * sometimes not assigned correctly? Erroneous device trees? 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci /* get the gpio chip for the base */ 12688c2ecf20Sopenharmony_ci chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); 12698c2ecf20Sopenharmony_ci if (!chip) 12708c2ecf20Sopenharmony_ci return 0; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci spi->cs_gpiod = gpiochip_request_own_desc(chip, 8 - spi->chip_select, 12738c2ecf20Sopenharmony_ci DRV_NAME, 12748c2ecf20Sopenharmony_ci GPIO_LOOKUP_FLAGS_DEFAULT, 12758c2ecf20Sopenharmony_ci GPIOD_OUT_LOW); 12768c2ecf20Sopenharmony_ci if (IS_ERR(spi->cs_gpiod)) 12778c2ecf20Sopenharmony_ci return PTR_ERR(spi->cs_gpiod); 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci /* and set up the "mode" and level */ 12808c2ecf20Sopenharmony_ci dev_info(&spi->dev, "setting up native-CS%i to use GPIO\n", 12818c2ecf20Sopenharmony_ci spi->chip_select); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci return 0; 12848c2ecf20Sopenharmony_ci} 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_cistatic int bcm2835_spi_probe(struct platform_device *pdev) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci struct spi_controller *ctlr; 12898c2ecf20Sopenharmony_ci struct bcm2835_spi *bs; 12908c2ecf20Sopenharmony_ci int err; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci ctlr = devm_spi_alloc_master(&pdev->dev, ALIGN(sizeof(*bs), 12938c2ecf20Sopenharmony_ci dma_get_cache_alignment())); 12948c2ecf20Sopenharmony_ci if (!ctlr) 12958c2ecf20Sopenharmony_ci return -ENOMEM; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, ctlr); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci ctlr->use_gpio_descriptors = true; 13008c2ecf20Sopenharmony_ci ctlr->mode_bits = BCM2835_SPI_MODE_BITS; 13018c2ecf20Sopenharmony_ci ctlr->bits_per_word_mask = SPI_BPW_MASK(8); 13028c2ecf20Sopenharmony_ci ctlr->num_chipselect = 3; 13038c2ecf20Sopenharmony_ci ctlr->setup = bcm2835_spi_setup; 13048c2ecf20Sopenharmony_ci ctlr->transfer_one = bcm2835_spi_transfer_one; 13058c2ecf20Sopenharmony_ci ctlr->handle_err = bcm2835_spi_handle_err; 13068c2ecf20Sopenharmony_ci ctlr->prepare_message = bcm2835_spi_prepare_message; 13078c2ecf20Sopenharmony_ci ctlr->dev.of_node = pdev->dev.of_node; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci bs = spi_controller_get_devdata(ctlr); 13108c2ecf20Sopenharmony_ci bs->ctlr = ctlr; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci bs->regs = devm_platform_ioremap_resource(pdev, 0); 13138c2ecf20Sopenharmony_ci if (IS_ERR(bs->regs)) 13148c2ecf20Sopenharmony_ci return PTR_ERR(bs->regs); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci bs->clk = devm_clk_get(&pdev->dev, NULL); 13178c2ecf20Sopenharmony_ci if (IS_ERR(bs->clk)) 13188c2ecf20Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(bs->clk), 13198c2ecf20Sopenharmony_ci "could not get clk\n"); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci bs->irq = platform_get_irq(pdev, 0); 13228c2ecf20Sopenharmony_ci if (bs->irq <= 0) 13238c2ecf20Sopenharmony_ci return bs->irq ? bs->irq : -ENODEV; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci clk_prepare_enable(bs->clk); 13268c2ecf20Sopenharmony_ci bs->clk_hz = clk_get_rate(bs->clk); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci err = bcm2835_dma_init(ctlr, &pdev->dev, bs); 13298c2ecf20Sopenharmony_ci if (err) 13308c2ecf20Sopenharmony_ci goto out_clk_disable; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci /* initialise the hardware with the default polarities */ 13338c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, 13348c2ecf20Sopenharmony_ci BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0, 13378c2ecf20Sopenharmony_ci dev_name(&pdev->dev), bs); 13388c2ecf20Sopenharmony_ci if (err) { 13398c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "could not request IRQ: %d\n", err); 13408c2ecf20Sopenharmony_ci goto out_dma_release; 13418c2ecf20Sopenharmony_ci } 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci err = spi_register_controller(ctlr); 13448c2ecf20Sopenharmony_ci if (err) { 13458c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "could not register SPI controller: %d\n", 13468c2ecf20Sopenharmony_ci err); 13478c2ecf20Sopenharmony_ci goto out_dma_release; 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci bcm2835_debugfs_create(bs, dev_name(&pdev->dev)); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci return 0; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ciout_dma_release: 13558c2ecf20Sopenharmony_ci bcm2835_dma_release(ctlr, bs); 13568c2ecf20Sopenharmony_ciout_clk_disable: 13578c2ecf20Sopenharmony_ci clk_disable_unprepare(bs->clk); 13588c2ecf20Sopenharmony_ci return err; 13598c2ecf20Sopenharmony_ci} 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_cistatic int bcm2835_spi_remove(struct platform_device *pdev) 13628c2ecf20Sopenharmony_ci{ 13638c2ecf20Sopenharmony_ci struct spi_controller *ctlr = platform_get_drvdata(pdev); 13648c2ecf20Sopenharmony_ci struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci bcm2835_debugfs_remove(bs); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci spi_unregister_controller(ctlr); 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci bcm2835_dma_release(ctlr, bs); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* Clear FIFOs, and disable the HW block */ 13738c2ecf20Sopenharmony_ci bcm2835_wr(bs, BCM2835_SPI_CS, 13748c2ecf20Sopenharmony_ci BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci clk_disable_unprepare(bs->clk); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci return 0; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistatic void bcm2835_spi_shutdown(struct platform_device *pdev) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci int ret; 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci ret = bcm2835_spi_remove(pdev); 13868c2ecf20Sopenharmony_ci if (ret) 13878c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to shutdown\n"); 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_cistatic const struct of_device_id bcm2835_spi_match[] = { 13918c2ecf20Sopenharmony_ci { .compatible = "brcm,bcm2835-spi", }, 13928c2ecf20Sopenharmony_ci {} 13938c2ecf20Sopenharmony_ci}; 13948c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, bcm2835_spi_match); 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_cistatic struct platform_driver bcm2835_spi_driver = { 13978c2ecf20Sopenharmony_ci .driver = { 13988c2ecf20Sopenharmony_ci .name = DRV_NAME, 13998c2ecf20Sopenharmony_ci .of_match_table = bcm2835_spi_match, 14008c2ecf20Sopenharmony_ci }, 14018c2ecf20Sopenharmony_ci .probe = bcm2835_spi_probe, 14028c2ecf20Sopenharmony_ci .remove = bcm2835_spi_remove, 14038c2ecf20Sopenharmony_ci .shutdown = bcm2835_spi_shutdown, 14048c2ecf20Sopenharmony_ci}; 14058c2ecf20Sopenharmony_cimodule_platform_driver(bcm2835_spi_driver); 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835"); 14088c2ecf20Sopenharmony_ciMODULE_AUTHOR("Chris Boot <bootc@bootc.net>"); 14098c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1410