18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Copyright 2018 SiFive, Inc. 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// SiFive SPI controller driver (master mode only) 68c2ecf20Sopenharmony_ci// 78c2ecf20Sopenharmony_ci// Author: SiFive, Inc. 88c2ecf20Sopenharmony_ci// sifive@sifive.com 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/clk.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 158c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 168c2ecf20Sopenharmony_ci#include <linux/io.h> 178c2ecf20Sopenharmony_ci#include <linux/log2.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DRIVER_NAME "sifive_spi" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define SIFIVE_SPI_MAX_CS 32 228c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DEFAULT_DEPTH 8 238c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DEFAULT_MAX_BITS 8 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* register offsets */ 268c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_SCKDIV 0x00 /* Serial clock divisor */ 278c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_SCKMODE 0x04 /* Serial clock mode */ 288c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_CSID 0x10 /* Chip select ID */ 298c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_CSDEF 0x14 /* Chip select default */ 308c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_CSMODE 0x18 /* Chip select mode */ 318c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_DELAY0 0x28 /* Delay control 0 */ 328c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_DELAY1 0x2c /* Delay control 1 */ 338c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_FMT 0x40 /* Frame format */ 348c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_TXDATA 0x48 /* Tx FIFO data */ 358c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_RXDATA 0x4c /* Rx FIFO data */ 368c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_TXMARK 0x50 /* Tx FIFO watermark */ 378c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_RXMARK 0x54 /* Rx FIFO watermark */ 388c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_FCTRL 0x60 /* SPI flash interface control */ 398c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_FFMT 0x64 /* SPI flash instruction format */ 408c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_IE 0x70 /* Interrupt Enable Register */ 418c2ecf20Sopenharmony_ci#define SIFIVE_SPI_REG_IP 0x74 /* Interrupt Pendings Register */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* sckdiv bits */ 448c2ecf20Sopenharmony_ci#define SIFIVE_SPI_SCKDIV_DIV_MASK 0xfffU 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/* sckmode bits */ 478c2ecf20Sopenharmony_ci#define SIFIVE_SPI_SCKMODE_PHA BIT(0) 488c2ecf20Sopenharmony_ci#define SIFIVE_SPI_SCKMODE_POL BIT(1) 498c2ecf20Sopenharmony_ci#define SIFIVE_SPI_SCKMODE_MODE_MASK (SIFIVE_SPI_SCKMODE_PHA | \ 508c2ecf20Sopenharmony_ci SIFIVE_SPI_SCKMODE_POL) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* csmode bits */ 538c2ecf20Sopenharmony_ci#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U 548c2ecf20Sopenharmony_ci#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U 558c2ecf20Sopenharmony_ci#define SIFIVE_SPI_CSMODE_MODE_OFF 3U 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* delay0 bits */ 588c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY0_CSSCK(x) ((u32)(x)) 598c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU 608c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY0_SCKCS(x) ((u32)(x) << 16) 618c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* delay1 bits */ 648c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY1_INTERCS(x) ((u32)(x)) 658c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU 668c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((u32)(x) << 16) 678c2ecf20Sopenharmony_ci#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* fmt bits */ 708c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_PROTO_SINGLE 0U 718c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_PROTO_DUAL 1U 728c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_PROTO_QUAD 2U 738c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_PROTO_MASK 3U 748c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_ENDIAN BIT(2) 758c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_DIR BIT(3) 768c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_LEN(x) ((u32)(x) << 16) 778c2ecf20Sopenharmony_ci#define SIFIVE_SPI_FMT_LEN_MASK (0xfU << 16) 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/* txdata bits */ 808c2ecf20Sopenharmony_ci#define SIFIVE_SPI_TXDATA_DATA_MASK 0xffU 818c2ecf20Sopenharmony_ci#define SIFIVE_SPI_TXDATA_FULL BIT(31) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* rxdata bits */ 848c2ecf20Sopenharmony_ci#define SIFIVE_SPI_RXDATA_DATA_MASK 0xffU 858c2ecf20Sopenharmony_ci#define SIFIVE_SPI_RXDATA_EMPTY BIT(31) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* ie and ip bits */ 888c2ecf20Sopenharmony_ci#define SIFIVE_SPI_IP_TXWM BIT(0) 898c2ecf20Sopenharmony_ci#define SIFIVE_SPI_IP_RXWM BIT(1) 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct sifive_spi { 928c2ecf20Sopenharmony_ci void __iomem *regs; /* virt. address of control registers */ 938c2ecf20Sopenharmony_ci struct clk *clk; /* bus clock */ 948c2ecf20Sopenharmony_ci unsigned int fifo_depth; /* fifo depth in words */ 958c2ecf20Sopenharmony_ci u32 cs_inactive; /* level of the CS pins when inactive */ 968c2ecf20Sopenharmony_ci struct completion done; /* wake-up from interrupt */ 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void sifive_spi_write(struct sifive_spi *spi, int offset, u32 value) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci iowrite32(value, spi->regs + offset); 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic u32 sifive_spi_read(struct sifive_spi *spi, int offset) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci return ioread32(spi->regs + offset); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void sifive_spi_init(struct sifive_spi *spi) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci /* Watermark interrupts are disabled by default */ 1128c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Default watermark FIFO threshold values */ 1158c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_TXMARK, 1); 1168c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK, 0); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Set CS/SCK Delays and Inactive Time to defaults */ 1198c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY0, 1208c2ecf20Sopenharmony_ci SIFIVE_SPI_DELAY0_CSSCK(1) | 1218c2ecf20Sopenharmony_ci SIFIVE_SPI_DELAY0_SCKCS(1)); 1228c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_DELAY1, 1238c2ecf20Sopenharmony_ci SIFIVE_SPI_DELAY1_INTERCS(1) | 1248c2ecf20Sopenharmony_ci SIFIVE_SPI_DELAY1_INTERXFR(0)); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Exit specialized memory-mapped SPI flash mode */ 1278c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_FCTRL, 0); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic int 1318c2ecf20Sopenharmony_cisifive_spi_prepare_message(struct spi_master *master, struct spi_message *msg) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct sifive_spi *spi = spi_master_get_devdata(master); 1348c2ecf20Sopenharmony_ci struct spi_device *device = msg->spi; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Update the chip select polarity */ 1378c2ecf20Sopenharmony_ci if (device->mode & SPI_CS_HIGH) 1388c2ecf20Sopenharmony_ci spi->cs_inactive &= ~BIT(device->chip_select); 1398c2ecf20Sopenharmony_ci else 1408c2ecf20Sopenharmony_ci spi->cs_inactive |= BIT(device->chip_select); 1418c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci /* Select the correct device */ 1448c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_CSID, device->chip_select); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci /* Set clock mode */ 1478c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_SCKMODE, 1488c2ecf20Sopenharmony_ci device->mode & SIFIVE_SPI_SCKMODE_MODE_MASK); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return 0; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic void sifive_spi_set_cs(struct spi_device *device, bool is_high) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct sifive_spi *spi = spi_master_get_devdata(device->master); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */ 1588c2ecf20Sopenharmony_ci if (device->mode & SPI_CS_HIGH) 1598c2ecf20Sopenharmony_ci is_high = !is_high; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_CSMODE, is_high ? 1628c2ecf20Sopenharmony_ci SIFIVE_SPI_CSMODE_MODE_AUTO : 1638c2ecf20Sopenharmony_ci SIFIVE_SPI_CSMODE_MODE_HOLD); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic int 1678c2ecf20Sopenharmony_cisifive_spi_prep_transfer(struct sifive_spi *spi, struct spi_device *device, 1688c2ecf20Sopenharmony_ci struct spi_transfer *t) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci u32 cr; 1718c2ecf20Sopenharmony_ci unsigned int mode; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* Calculate and program the clock rate */ 1748c2ecf20Sopenharmony_ci cr = DIV_ROUND_UP(clk_get_rate(spi->clk) >> 1, t->speed_hz) - 1; 1758c2ecf20Sopenharmony_ci cr &= SIFIVE_SPI_SCKDIV_DIV_MASK; 1768c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_SCKDIV, cr); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci mode = max_t(unsigned int, t->rx_nbits, t->tx_nbits); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Set frame format */ 1818c2ecf20Sopenharmony_ci cr = SIFIVE_SPI_FMT_LEN(t->bits_per_word); 1828c2ecf20Sopenharmony_ci switch (mode) { 1838c2ecf20Sopenharmony_ci case SPI_NBITS_QUAD: 1848c2ecf20Sopenharmony_ci cr |= SIFIVE_SPI_FMT_PROTO_QUAD; 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci case SPI_NBITS_DUAL: 1878c2ecf20Sopenharmony_ci cr |= SIFIVE_SPI_FMT_PROTO_DUAL; 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci default: 1908c2ecf20Sopenharmony_ci cr |= SIFIVE_SPI_FMT_PROTO_SINGLE; 1918c2ecf20Sopenharmony_ci break; 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci if (device->mode & SPI_LSB_FIRST) 1948c2ecf20Sopenharmony_ci cr |= SIFIVE_SPI_FMT_ENDIAN; 1958c2ecf20Sopenharmony_ci if (!t->rx_buf) 1968c2ecf20Sopenharmony_ci cr |= SIFIVE_SPI_FMT_DIR; 1978c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_FMT, cr); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* We will want to poll if the time we need to wait is 2008c2ecf20Sopenharmony_ci * less than the context switching time. 2018c2ecf20Sopenharmony_ci * Let's call that threshold 5us. The operation will take: 2028c2ecf20Sopenharmony_ci * (8/mode) * fifo_depth / hz <= 5 * 10^-6 2038c2ecf20Sopenharmony_ci * 1600000 * fifo_depth <= hz * mode 2048c2ecf20Sopenharmony_ci */ 2058c2ecf20Sopenharmony_ci return 1600000 * spi->fifo_depth <= t->speed_hz * mode; 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistatic irqreturn_t sifive_spi_irq(int irq, void *dev_id) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci struct sifive_spi *spi = dev_id; 2118c2ecf20Sopenharmony_ci u32 ip = sifive_spi_read(spi, SIFIVE_SPI_REG_IP); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (ip & (SIFIVE_SPI_IP_TXWM | SIFIVE_SPI_IP_RXWM)) { 2148c2ecf20Sopenharmony_ci /* Disable interrupts until next transfer */ 2158c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); 2168c2ecf20Sopenharmony_ci complete(&spi->done); 2178c2ecf20Sopenharmony_ci return IRQ_HANDLED; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci return IRQ_NONE; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic void sifive_spi_wait(struct sifive_spi *spi, u32 bit, int poll) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci if (poll) { 2268c2ecf20Sopenharmony_ci u32 cr; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci do { 2298c2ecf20Sopenharmony_ci cr = sifive_spi_read(spi, SIFIVE_SPI_REG_IP); 2308c2ecf20Sopenharmony_ci } while (!(cr & bit)); 2318c2ecf20Sopenharmony_ci } else { 2328c2ecf20Sopenharmony_ci reinit_completion(&spi->done); 2338c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_IE, bit); 2348c2ecf20Sopenharmony_ci wait_for_completion(&spi->done); 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic void sifive_spi_tx(struct sifive_spi *spi, const u8 *tx_ptr) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci WARN_ON_ONCE((sifive_spi_read(spi, SIFIVE_SPI_REG_TXDATA) 2418c2ecf20Sopenharmony_ci & SIFIVE_SPI_TXDATA_FULL) != 0); 2428c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_TXDATA, 2438c2ecf20Sopenharmony_ci *tx_ptr & SIFIVE_SPI_TXDATA_DATA_MASK); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void sifive_spi_rx(struct sifive_spi *spi, u8 *rx_ptr) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci u32 data = sifive_spi_read(spi, SIFIVE_SPI_REG_RXDATA); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci WARN_ON_ONCE((data & SIFIVE_SPI_RXDATA_EMPTY) != 0); 2518c2ecf20Sopenharmony_ci *rx_ptr = data & SIFIVE_SPI_RXDATA_DATA_MASK; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int 2558c2ecf20Sopenharmony_cisifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, 2568c2ecf20Sopenharmony_ci struct spi_transfer *t) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci struct sifive_spi *spi = spi_master_get_devdata(master); 2598c2ecf20Sopenharmony_ci int poll = sifive_spi_prep_transfer(spi, device, t); 2608c2ecf20Sopenharmony_ci const u8 *tx_ptr = t->tx_buf; 2618c2ecf20Sopenharmony_ci u8 *rx_ptr = t->rx_buf; 2628c2ecf20Sopenharmony_ci unsigned int remaining_words = t->len; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci while (remaining_words) { 2658c2ecf20Sopenharmony_ci unsigned int n_words = min(remaining_words, spi->fifo_depth); 2668c2ecf20Sopenharmony_ci unsigned int i; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Enqueue n_words for transmission */ 2698c2ecf20Sopenharmony_ci for (i = 0; i < n_words; i++) 2708c2ecf20Sopenharmony_ci sifive_spi_tx(spi, tx_ptr++); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (rx_ptr) { 2738c2ecf20Sopenharmony_ci /* Wait for transmission + reception to complete */ 2748c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_RXMARK, 2758c2ecf20Sopenharmony_ci n_words - 1); 2768c2ecf20Sopenharmony_ci sifive_spi_wait(spi, SIFIVE_SPI_IP_RXWM, poll); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* Read out all the data from the RX FIFO */ 2798c2ecf20Sopenharmony_ci for (i = 0; i < n_words; i++) 2808c2ecf20Sopenharmony_ci sifive_spi_rx(spi, rx_ptr++); 2818c2ecf20Sopenharmony_ci } else { 2828c2ecf20Sopenharmony_ci /* Wait for transmission to complete */ 2838c2ecf20Sopenharmony_ci sifive_spi_wait(spi, SIFIVE_SPI_IP_TXWM, poll); 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci remaining_words -= n_words; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic int sifive_spi_probe(struct platform_device *pdev) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct sifive_spi *spi; 2958c2ecf20Sopenharmony_ci int ret, irq, num_cs; 2968c2ecf20Sopenharmony_ci u32 cs_bits, max_bits_per_word; 2978c2ecf20Sopenharmony_ci struct spi_master *master; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci master = spi_alloc_master(&pdev->dev, sizeof(struct sifive_spi)); 3008c2ecf20Sopenharmony_ci if (!master) { 3018c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "out of memory\n"); 3028c2ecf20Sopenharmony_ci return -ENOMEM; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci spi = spi_master_get_devdata(master); 3068c2ecf20Sopenharmony_ci init_completion(&spi->done); 3078c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, master); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci spi->regs = devm_platform_ioremap_resource(pdev, 0); 3108c2ecf20Sopenharmony_ci if (IS_ERR(spi->regs)) { 3118c2ecf20Sopenharmony_ci ret = PTR_ERR(spi->regs); 3128c2ecf20Sopenharmony_ci goto put_master; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci spi->clk = devm_clk_get(&pdev->dev, NULL); 3168c2ecf20Sopenharmony_ci if (IS_ERR(spi->clk)) { 3178c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to find bus clock\n"); 3188c2ecf20Sopenharmony_ci ret = PTR_ERR(spi->clk); 3198c2ecf20Sopenharmony_ci goto put_master; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 3238c2ecf20Sopenharmony_ci if (irq < 0) { 3248c2ecf20Sopenharmony_ci ret = irq; 3258c2ecf20Sopenharmony_ci goto put_master; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* Optional parameters */ 3298c2ecf20Sopenharmony_ci ret = 3308c2ecf20Sopenharmony_ci of_property_read_u32(pdev->dev.of_node, "sifive,fifo-depth", 3318c2ecf20Sopenharmony_ci &spi->fifo_depth); 3328c2ecf20Sopenharmony_ci if (ret < 0) 3338c2ecf20Sopenharmony_ci spi->fifo_depth = SIFIVE_SPI_DEFAULT_DEPTH; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci ret = 3368c2ecf20Sopenharmony_ci of_property_read_u32(pdev->dev.of_node, "sifive,max-bits-per-word", 3378c2ecf20Sopenharmony_ci &max_bits_per_word); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (!ret && max_bits_per_word < 8) { 3408c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Only 8bit SPI words supported by the driver\n"); 3418c2ecf20Sopenharmony_ci ret = -EINVAL; 3428c2ecf20Sopenharmony_ci goto put_master; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* Spin up the bus clock before hitting registers */ 3468c2ecf20Sopenharmony_ci ret = clk_prepare_enable(spi->clk); 3478c2ecf20Sopenharmony_ci if (ret) { 3488c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to enable bus clock\n"); 3498c2ecf20Sopenharmony_ci goto put_master; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* probe the number of CS lines */ 3538c2ecf20Sopenharmony_ci spi->cs_inactive = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); 3548c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, 0xffffffffU); 3558c2ecf20Sopenharmony_ci cs_bits = sifive_spi_read(spi, SIFIVE_SPI_REG_CSDEF); 3568c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_CSDEF, spi->cs_inactive); 3578c2ecf20Sopenharmony_ci if (!cs_bits) { 3588c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Could not auto probe CS lines\n"); 3598c2ecf20Sopenharmony_ci ret = -EINVAL; 3608c2ecf20Sopenharmony_ci goto disable_clk; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci num_cs = ilog2(cs_bits) + 1; 3648c2ecf20Sopenharmony_ci if (num_cs > SIFIVE_SPI_MAX_CS) { 3658c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Invalid number of spi slaves\n"); 3668c2ecf20Sopenharmony_ci ret = -EINVAL; 3678c2ecf20Sopenharmony_ci goto disable_clk; 3688c2ecf20Sopenharmony_ci } 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* Define our master */ 3718c2ecf20Sopenharmony_ci master->dev.of_node = pdev->dev.of_node; 3728c2ecf20Sopenharmony_ci master->bus_num = pdev->id; 3738c2ecf20Sopenharmony_ci master->num_chipselect = num_cs; 3748c2ecf20Sopenharmony_ci master->mode_bits = SPI_CPHA | SPI_CPOL 3758c2ecf20Sopenharmony_ci | SPI_CS_HIGH | SPI_LSB_FIRST 3768c2ecf20Sopenharmony_ci | SPI_TX_DUAL | SPI_TX_QUAD 3778c2ecf20Sopenharmony_ci | SPI_RX_DUAL | SPI_RX_QUAD; 3788c2ecf20Sopenharmony_ci /* TODO: add driver support for bits_per_word < 8 3798c2ecf20Sopenharmony_ci * we need to "left-align" the bits (unless SPI_LSB_FIRST) 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ci master->bits_per_word_mask = SPI_BPW_MASK(8); 3828c2ecf20Sopenharmony_ci master->flags = SPI_CONTROLLER_MUST_TX | SPI_MASTER_GPIO_SS; 3838c2ecf20Sopenharmony_ci master->prepare_message = sifive_spi_prepare_message; 3848c2ecf20Sopenharmony_ci master->set_cs = sifive_spi_set_cs; 3858c2ecf20Sopenharmony_ci master->transfer_one = sifive_spi_transfer_one; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci pdev->dev.dma_mask = NULL; 3888c2ecf20Sopenharmony_ci /* Configure the SPI master hardware */ 3898c2ecf20Sopenharmony_ci sifive_spi_init(spi); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* Register for SPI Interrupt */ 3928c2ecf20Sopenharmony_ci ret = devm_request_irq(&pdev->dev, irq, sifive_spi_irq, 0, 3938c2ecf20Sopenharmony_ci dev_name(&pdev->dev), spi); 3948c2ecf20Sopenharmony_ci if (ret) { 3958c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Unable to bind to interrupt\n"); 3968c2ecf20Sopenharmony_ci goto disable_clk; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", 4008c2ecf20Sopenharmony_ci irq, master->num_chipselect); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci ret = devm_spi_register_master(&pdev->dev, master); 4038c2ecf20Sopenharmony_ci if (ret < 0) { 4048c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "spi_register_master failed\n"); 4058c2ecf20Sopenharmony_ci goto disable_clk; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci return 0; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cidisable_clk: 4118c2ecf20Sopenharmony_ci clk_disable_unprepare(spi->clk); 4128c2ecf20Sopenharmony_ciput_master: 4138c2ecf20Sopenharmony_ci spi_master_put(master); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci return ret; 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic int sifive_spi_remove(struct platform_device *pdev) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci struct spi_master *master = platform_get_drvdata(pdev); 4218c2ecf20Sopenharmony_ci struct sifive_spi *spi = spi_master_get_devdata(master); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci /* Disable all the interrupts just in case */ 4248c2ecf20Sopenharmony_ci sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); 4258c2ecf20Sopenharmony_ci clk_disable_unprepare(spi->clk); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return 0; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic const struct of_device_id sifive_spi_of_match[] = { 4318c2ecf20Sopenharmony_ci { .compatible = "sifive,spi0", }, 4328c2ecf20Sopenharmony_ci {} 4338c2ecf20Sopenharmony_ci}; 4348c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sifive_spi_of_match); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistatic struct platform_driver sifive_spi_driver = { 4378c2ecf20Sopenharmony_ci .probe = sifive_spi_probe, 4388c2ecf20Sopenharmony_ci .remove = sifive_spi_remove, 4398c2ecf20Sopenharmony_ci .driver = { 4408c2ecf20Sopenharmony_ci .name = SIFIVE_SPI_DRIVER_NAME, 4418c2ecf20Sopenharmony_ci .of_match_table = sifive_spi_of_match, 4428c2ecf20Sopenharmony_ci }, 4438c2ecf20Sopenharmony_ci}; 4448c2ecf20Sopenharmony_cimodule_platform_driver(sifive_spi_driver); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ciMODULE_AUTHOR("SiFive, Inc. <sifive@sifive.com>"); 4478c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SiFive SPI driver"); 4488c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 449