18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for Cirrus Logic EP93xx SPI controller.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Mika Westerberg
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Explicit FIFO handling code was inspired by amba-pl022 driver.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Chip select support using other than built-in GPIOs by H. Hartley Sweeten.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * For more information about the SPI controller see documentation on Cirrus
128c2ecf20Sopenharmony_ci * Logic web site:
138c2ecf20Sopenharmony_ci *     https://www.cirrus.com/en/pubs/manual/EP93xx_Users_Guide_UM1.pdf
148c2ecf20Sopenharmony_ci */
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci#include <linux/clk.h>
188c2ecf20Sopenharmony_ci#include <linux/err.h>
198c2ecf20Sopenharmony_ci#include <linux/delay.h>
208c2ecf20Sopenharmony_ci#include <linux/device.h>
218c2ecf20Sopenharmony_ci#include <linux/dmaengine.h>
228c2ecf20Sopenharmony_ci#include <linux/bitops.h>
238c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
248c2ecf20Sopenharmony_ci#include <linux/module.h>
258c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
268c2ecf20Sopenharmony_ci#include <linux/sched.h>
278c2ecf20Sopenharmony_ci#include <linux/scatterlist.h>
288c2ecf20Sopenharmony_ci#include <linux/spi/spi.h>
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include <linux/platform_data/dma-ep93xx.h>
318c2ecf20Sopenharmony_ci#include <linux/platform_data/spi-ep93xx.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define SSPCR0			0x0000
348c2ecf20Sopenharmony_ci#define SSPCR0_SPO		BIT(6)
358c2ecf20Sopenharmony_ci#define SSPCR0_SPH		BIT(7)
368c2ecf20Sopenharmony_ci#define SSPCR0_SCR_SHIFT	8
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define SSPCR1			0x0004
398c2ecf20Sopenharmony_ci#define SSPCR1_RIE		BIT(0)
408c2ecf20Sopenharmony_ci#define SSPCR1_TIE		BIT(1)
418c2ecf20Sopenharmony_ci#define SSPCR1_RORIE		BIT(2)
428c2ecf20Sopenharmony_ci#define SSPCR1_LBM		BIT(3)
438c2ecf20Sopenharmony_ci#define SSPCR1_SSE		BIT(4)
448c2ecf20Sopenharmony_ci#define SSPCR1_MS		BIT(5)
458c2ecf20Sopenharmony_ci#define SSPCR1_SOD		BIT(6)
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define SSPDR			0x0008
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#define SSPSR			0x000c
508c2ecf20Sopenharmony_ci#define SSPSR_TFE		BIT(0)
518c2ecf20Sopenharmony_ci#define SSPSR_TNF		BIT(1)
528c2ecf20Sopenharmony_ci#define SSPSR_RNE		BIT(2)
538c2ecf20Sopenharmony_ci#define SSPSR_RFF		BIT(3)
548c2ecf20Sopenharmony_ci#define SSPSR_BSY		BIT(4)
558c2ecf20Sopenharmony_ci#define SSPCPSR			0x0010
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define SSPIIR			0x0014
588c2ecf20Sopenharmony_ci#define SSPIIR_RIS		BIT(0)
598c2ecf20Sopenharmony_ci#define SSPIIR_TIS		BIT(1)
608c2ecf20Sopenharmony_ci#define SSPIIR_RORIS		BIT(2)
618c2ecf20Sopenharmony_ci#define SSPICR			SSPIIR
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* timeout in milliseconds */
648c2ecf20Sopenharmony_ci#define SPI_TIMEOUT		5
658c2ecf20Sopenharmony_ci/* maximum depth of RX/TX FIFO */
668c2ecf20Sopenharmony_ci#define SPI_FIFO_SIZE		8
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci/**
698c2ecf20Sopenharmony_ci * struct ep93xx_spi - EP93xx SPI controller structure
708c2ecf20Sopenharmony_ci * @clk: clock for the controller
718c2ecf20Sopenharmony_ci * @mmio: pointer to ioremap()'d registers
728c2ecf20Sopenharmony_ci * @sspdr_phys: physical address of the SSPDR register
738c2ecf20Sopenharmony_ci * @tx: current byte in transfer to transmit
748c2ecf20Sopenharmony_ci * @rx: current byte in transfer to receive
758c2ecf20Sopenharmony_ci * @fifo_level: how full is FIFO (%0..%SPI_FIFO_SIZE - %1). Receiving one
768c2ecf20Sopenharmony_ci *              frame decreases this level and sending one frame increases it.
778c2ecf20Sopenharmony_ci * @dma_rx: RX DMA channel
788c2ecf20Sopenharmony_ci * @dma_tx: TX DMA channel
798c2ecf20Sopenharmony_ci * @dma_rx_data: RX parameters passed to the DMA engine
808c2ecf20Sopenharmony_ci * @dma_tx_data: TX parameters passed to the DMA engine
818c2ecf20Sopenharmony_ci * @rx_sgt: sg table for RX transfers
828c2ecf20Sopenharmony_ci * @tx_sgt: sg table for TX transfers
838c2ecf20Sopenharmony_ci * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by
848c2ecf20Sopenharmony_ci *            the client
858c2ecf20Sopenharmony_ci */
868c2ecf20Sopenharmony_cistruct ep93xx_spi {
878c2ecf20Sopenharmony_ci	struct clk			*clk;
888c2ecf20Sopenharmony_ci	void __iomem			*mmio;
898c2ecf20Sopenharmony_ci	unsigned long			sspdr_phys;
908c2ecf20Sopenharmony_ci	size_t				tx;
918c2ecf20Sopenharmony_ci	size_t				rx;
928c2ecf20Sopenharmony_ci	size_t				fifo_level;
938c2ecf20Sopenharmony_ci	struct dma_chan			*dma_rx;
948c2ecf20Sopenharmony_ci	struct dma_chan			*dma_tx;
958c2ecf20Sopenharmony_ci	struct ep93xx_dma_data		dma_rx_data;
968c2ecf20Sopenharmony_ci	struct ep93xx_dma_data		dma_tx_data;
978c2ecf20Sopenharmony_ci	struct sg_table			rx_sgt;
988c2ecf20Sopenharmony_ci	struct sg_table			tx_sgt;
998c2ecf20Sopenharmony_ci	void				*zeropage;
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci/* converts bits per word to CR0.DSS value */
1038c2ecf20Sopenharmony_ci#define bits_per_word_to_dss(bpw)	((bpw) - 1)
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci/**
1068c2ecf20Sopenharmony_ci * ep93xx_spi_calc_divisors() - calculates SPI clock divisors
1078c2ecf20Sopenharmony_ci * @master: SPI master
1088c2ecf20Sopenharmony_ci * @rate: desired SPI output clock rate
1098c2ecf20Sopenharmony_ci * @div_cpsr: pointer to return the cpsr (pre-scaler) divider
1108c2ecf20Sopenharmony_ci * @div_scr: pointer to return the scr divider
1118c2ecf20Sopenharmony_ci */
1128c2ecf20Sopenharmony_cistatic int ep93xx_spi_calc_divisors(struct spi_master *master,
1138c2ecf20Sopenharmony_ci				    u32 rate, u8 *div_cpsr, u8 *div_scr)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
1168c2ecf20Sopenharmony_ci	unsigned long spi_clk_rate = clk_get_rate(espi->clk);
1178c2ecf20Sopenharmony_ci	int cpsr, scr;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	/*
1208c2ecf20Sopenharmony_ci	 * Make sure that max value is between values supported by the
1218c2ecf20Sopenharmony_ci	 * controller.
1228c2ecf20Sopenharmony_ci	 */
1238c2ecf20Sopenharmony_ci	rate = clamp(rate, master->min_speed_hz, master->max_speed_hz);
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	/*
1268c2ecf20Sopenharmony_ci	 * Calculate divisors so that we can get speed according the
1278c2ecf20Sopenharmony_ci	 * following formula:
1288c2ecf20Sopenharmony_ci	 *	rate = spi_clock_rate / (cpsr * (1 + scr))
1298c2ecf20Sopenharmony_ci	 *
1308c2ecf20Sopenharmony_ci	 * cpsr must be even number and starts from 2, scr can be any number
1318c2ecf20Sopenharmony_ci	 * between 0 and 255.
1328c2ecf20Sopenharmony_ci	 */
1338c2ecf20Sopenharmony_ci	for (cpsr = 2; cpsr <= 254; cpsr += 2) {
1348c2ecf20Sopenharmony_ci		for (scr = 0; scr <= 255; scr++) {
1358c2ecf20Sopenharmony_ci			if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) {
1368c2ecf20Sopenharmony_ci				*div_scr = (u8)scr;
1378c2ecf20Sopenharmony_ci				*div_cpsr = (u8)cpsr;
1388c2ecf20Sopenharmony_ci				return 0;
1398c2ecf20Sopenharmony_ci			}
1408c2ecf20Sopenharmony_ci		}
1418c2ecf20Sopenharmony_ci	}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return -EINVAL;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic int ep93xx_spi_chip_setup(struct spi_master *master,
1478c2ecf20Sopenharmony_ci				 struct spi_device *spi,
1488c2ecf20Sopenharmony_ci				 struct spi_transfer *xfer)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
1518c2ecf20Sopenharmony_ci	u8 dss = bits_per_word_to_dss(xfer->bits_per_word);
1528c2ecf20Sopenharmony_ci	u8 div_cpsr = 0;
1538c2ecf20Sopenharmony_ci	u8 div_scr = 0;
1548c2ecf20Sopenharmony_ci	u16 cr0;
1558c2ecf20Sopenharmony_ci	int err;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	err = ep93xx_spi_calc_divisors(master, xfer->speed_hz,
1588c2ecf20Sopenharmony_ci				       &div_cpsr, &div_scr);
1598c2ecf20Sopenharmony_ci	if (err)
1608c2ecf20Sopenharmony_ci		return err;
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	cr0 = div_scr << SSPCR0_SCR_SHIFT;
1638c2ecf20Sopenharmony_ci	if (spi->mode & SPI_CPOL)
1648c2ecf20Sopenharmony_ci		cr0 |= SSPCR0_SPO;
1658c2ecf20Sopenharmony_ci	if (spi->mode & SPI_CPHA)
1668c2ecf20Sopenharmony_ci		cr0 |= SSPCR0_SPH;
1678c2ecf20Sopenharmony_ci	cr0 |= dss;
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	dev_dbg(&master->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n",
1708c2ecf20Sopenharmony_ci		spi->mode, div_cpsr, div_scr, dss);
1718c2ecf20Sopenharmony_ci	dev_dbg(&master->dev, "setup: cr0 %#x\n", cr0);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	writel(div_cpsr, espi->mmio + SSPCPSR);
1748c2ecf20Sopenharmony_ci	writel(cr0, espi->mmio + SSPCR0);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	return 0;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic void ep93xx_do_write(struct spi_master *master)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
1828c2ecf20Sopenharmony_ci	struct spi_transfer *xfer = master->cur_msg->state;
1838c2ecf20Sopenharmony_ci	u32 val = 0;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8) {
1868c2ecf20Sopenharmony_ci		if (xfer->tx_buf)
1878c2ecf20Sopenharmony_ci			val = ((u16 *)xfer->tx_buf)[espi->tx];
1888c2ecf20Sopenharmony_ci		espi->tx += 2;
1898c2ecf20Sopenharmony_ci	} else {
1908c2ecf20Sopenharmony_ci		if (xfer->tx_buf)
1918c2ecf20Sopenharmony_ci			val = ((u8 *)xfer->tx_buf)[espi->tx];
1928c2ecf20Sopenharmony_ci		espi->tx += 1;
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci	writel(val, espi->mmio + SSPDR);
1958c2ecf20Sopenharmony_ci}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_cistatic void ep93xx_do_read(struct spi_master *master)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
2008c2ecf20Sopenharmony_ci	struct spi_transfer *xfer = master->cur_msg->state;
2018c2ecf20Sopenharmony_ci	u32 val;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	val = readl(espi->mmio + SSPDR);
2048c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8) {
2058c2ecf20Sopenharmony_ci		if (xfer->rx_buf)
2068c2ecf20Sopenharmony_ci			((u16 *)xfer->rx_buf)[espi->rx] = val;
2078c2ecf20Sopenharmony_ci		espi->rx += 2;
2088c2ecf20Sopenharmony_ci	} else {
2098c2ecf20Sopenharmony_ci		if (xfer->rx_buf)
2108c2ecf20Sopenharmony_ci			((u8 *)xfer->rx_buf)[espi->rx] = val;
2118c2ecf20Sopenharmony_ci		espi->rx += 1;
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci/**
2168c2ecf20Sopenharmony_ci * ep93xx_spi_read_write() - perform next RX/TX transfer
2178c2ecf20Sopenharmony_ci * @master: SPI master
2188c2ecf20Sopenharmony_ci *
2198c2ecf20Sopenharmony_ci * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If
2208c2ecf20Sopenharmony_ci * called several times, the whole transfer will be completed. Returns
2218c2ecf20Sopenharmony_ci * %-EINPROGRESS when current transfer was not yet completed otherwise %0.
2228c2ecf20Sopenharmony_ci *
2238c2ecf20Sopenharmony_ci * When this function is finished, RX FIFO should be empty and TX FIFO should be
2248c2ecf20Sopenharmony_ci * full.
2258c2ecf20Sopenharmony_ci */
2268c2ecf20Sopenharmony_cistatic int ep93xx_spi_read_write(struct spi_master *master)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
2298c2ecf20Sopenharmony_ci	struct spi_transfer *xfer = master->cur_msg->state;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/* read as long as RX FIFO has frames in it */
2328c2ecf20Sopenharmony_ci	while ((readl(espi->mmio + SSPSR) & SSPSR_RNE)) {
2338c2ecf20Sopenharmony_ci		ep93xx_do_read(master);
2348c2ecf20Sopenharmony_ci		espi->fifo_level--;
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	/* write as long as TX FIFO has room */
2388c2ecf20Sopenharmony_ci	while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < xfer->len) {
2398c2ecf20Sopenharmony_ci		ep93xx_do_write(master);
2408c2ecf20Sopenharmony_ci		espi->fifo_level++;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (espi->rx == xfer->len)
2448c2ecf20Sopenharmony_ci		return 0;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci	return -EINPROGRESS;
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic enum dma_transfer_direction
2508c2ecf20Sopenharmony_ciep93xx_dma_data_to_trans_dir(enum dma_data_direction dir)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	switch (dir) {
2538c2ecf20Sopenharmony_ci	case DMA_TO_DEVICE:
2548c2ecf20Sopenharmony_ci		return DMA_MEM_TO_DEV;
2558c2ecf20Sopenharmony_ci	case DMA_FROM_DEVICE:
2568c2ecf20Sopenharmony_ci		return DMA_DEV_TO_MEM;
2578c2ecf20Sopenharmony_ci	default:
2588c2ecf20Sopenharmony_ci		return DMA_TRANS_NONE;
2598c2ecf20Sopenharmony_ci	}
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci/**
2638c2ecf20Sopenharmony_ci * ep93xx_spi_dma_prepare() - prepares a DMA transfer
2648c2ecf20Sopenharmony_ci * @master: SPI master
2658c2ecf20Sopenharmony_ci * @dir: DMA transfer direction
2668c2ecf20Sopenharmony_ci *
2678c2ecf20Sopenharmony_ci * Function configures the DMA, maps the buffer and prepares the DMA
2688c2ecf20Sopenharmony_ci * descriptor. Returns a valid DMA descriptor in case of success and ERR_PTR
2698c2ecf20Sopenharmony_ci * in case of failure.
2708c2ecf20Sopenharmony_ci */
2718c2ecf20Sopenharmony_cistatic struct dma_async_tx_descriptor *
2728c2ecf20Sopenharmony_ciep93xx_spi_dma_prepare(struct spi_master *master,
2738c2ecf20Sopenharmony_ci		       enum dma_data_direction dir)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
2768c2ecf20Sopenharmony_ci	struct spi_transfer *xfer = master->cur_msg->state;
2778c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *txd;
2788c2ecf20Sopenharmony_ci	enum dma_slave_buswidth buswidth;
2798c2ecf20Sopenharmony_ci	struct dma_slave_config conf;
2808c2ecf20Sopenharmony_ci	struct scatterlist *sg;
2818c2ecf20Sopenharmony_ci	struct sg_table *sgt;
2828c2ecf20Sopenharmony_ci	struct dma_chan *chan;
2838c2ecf20Sopenharmony_ci	const void *buf, *pbuf;
2848c2ecf20Sopenharmony_ci	size_t len = xfer->len;
2858c2ecf20Sopenharmony_ci	int i, ret, nents;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	if (xfer->bits_per_word > 8)
2888c2ecf20Sopenharmony_ci		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
2898c2ecf20Sopenharmony_ci	else
2908c2ecf20Sopenharmony_ci		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	memset(&conf, 0, sizeof(conf));
2938c2ecf20Sopenharmony_ci	conf.direction = ep93xx_dma_data_to_trans_dir(dir);
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (dir == DMA_FROM_DEVICE) {
2968c2ecf20Sopenharmony_ci		chan = espi->dma_rx;
2978c2ecf20Sopenharmony_ci		buf = xfer->rx_buf;
2988c2ecf20Sopenharmony_ci		sgt = &espi->rx_sgt;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci		conf.src_addr = espi->sspdr_phys;
3018c2ecf20Sopenharmony_ci		conf.src_addr_width = buswidth;
3028c2ecf20Sopenharmony_ci	} else {
3038c2ecf20Sopenharmony_ci		chan = espi->dma_tx;
3048c2ecf20Sopenharmony_ci		buf = xfer->tx_buf;
3058c2ecf20Sopenharmony_ci		sgt = &espi->tx_sgt;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci		conf.dst_addr = espi->sspdr_phys;
3088c2ecf20Sopenharmony_ci		conf.dst_addr_width = buswidth;
3098c2ecf20Sopenharmony_ci	}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	ret = dmaengine_slave_config(chan, &conf);
3128c2ecf20Sopenharmony_ci	if (ret)
3138c2ecf20Sopenharmony_ci		return ERR_PTR(ret);
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_ci	/*
3168c2ecf20Sopenharmony_ci	 * We need to split the transfer into PAGE_SIZE'd chunks. This is
3178c2ecf20Sopenharmony_ci	 * because we are using @espi->zeropage to provide a zero RX buffer
3188c2ecf20Sopenharmony_ci	 * for the TX transfers and we have only allocated one page for that.
3198c2ecf20Sopenharmony_ci	 *
3208c2ecf20Sopenharmony_ci	 * For performance reasons we allocate a new sg_table only when
3218c2ecf20Sopenharmony_ci	 * needed. Otherwise we will re-use the current one. Eventually the
3228c2ecf20Sopenharmony_ci	 * last sg_table is released in ep93xx_spi_release_dma().
3238c2ecf20Sopenharmony_ci	 */
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	nents = DIV_ROUND_UP(len, PAGE_SIZE);
3268c2ecf20Sopenharmony_ci	if (nents != sgt->nents) {
3278c2ecf20Sopenharmony_ci		sg_free_table(sgt);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci		ret = sg_alloc_table(sgt, nents, GFP_KERNEL);
3308c2ecf20Sopenharmony_ci		if (ret)
3318c2ecf20Sopenharmony_ci			return ERR_PTR(ret);
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	pbuf = buf;
3358c2ecf20Sopenharmony_ci	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
3368c2ecf20Sopenharmony_ci		size_t bytes = min_t(size_t, len, PAGE_SIZE);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci		if (buf) {
3398c2ecf20Sopenharmony_ci			sg_set_page(sg, virt_to_page(pbuf), bytes,
3408c2ecf20Sopenharmony_ci				    offset_in_page(pbuf));
3418c2ecf20Sopenharmony_ci		} else {
3428c2ecf20Sopenharmony_ci			sg_set_page(sg, virt_to_page(espi->zeropage),
3438c2ecf20Sopenharmony_ci				    bytes, 0);
3448c2ecf20Sopenharmony_ci		}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci		pbuf += bytes;
3478c2ecf20Sopenharmony_ci		len -= bytes;
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	if (WARN_ON(len)) {
3518c2ecf20Sopenharmony_ci		dev_warn(&master->dev, "len = %zu expected 0!\n", len);
3528c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
3568c2ecf20Sopenharmony_ci	if (!nents)
3578c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, conf.direction,
3608c2ecf20Sopenharmony_ci				      DMA_CTRL_ACK);
3618c2ecf20Sopenharmony_ci	if (!txd) {
3628c2ecf20Sopenharmony_ci		dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
3638c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci	return txd;
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci/**
3698c2ecf20Sopenharmony_ci * ep93xx_spi_dma_finish() - finishes with a DMA transfer
3708c2ecf20Sopenharmony_ci * @master: SPI master
3718c2ecf20Sopenharmony_ci * @dir: DMA transfer direction
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * Function finishes with the DMA transfer. After this, the DMA buffer is
3748c2ecf20Sopenharmony_ci * unmapped.
3758c2ecf20Sopenharmony_ci */
3768c2ecf20Sopenharmony_cistatic void ep93xx_spi_dma_finish(struct spi_master *master,
3778c2ecf20Sopenharmony_ci				  enum dma_data_direction dir)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
3808c2ecf20Sopenharmony_ci	struct dma_chan *chan;
3818c2ecf20Sopenharmony_ci	struct sg_table *sgt;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	if (dir == DMA_FROM_DEVICE) {
3848c2ecf20Sopenharmony_ci		chan = espi->dma_rx;
3858c2ecf20Sopenharmony_ci		sgt = &espi->rx_sgt;
3868c2ecf20Sopenharmony_ci	} else {
3878c2ecf20Sopenharmony_ci		chan = espi->dma_tx;
3888c2ecf20Sopenharmony_ci		sgt = &espi->tx_sgt;
3898c2ecf20Sopenharmony_ci	}
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci	dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
3928c2ecf20Sopenharmony_ci}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_cistatic void ep93xx_spi_dma_callback(void *callback_param)
3958c2ecf20Sopenharmony_ci{
3968c2ecf20Sopenharmony_ci	struct spi_master *master = callback_param;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	ep93xx_spi_dma_finish(master, DMA_TO_DEVICE);
3998c2ecf20Sopenharmony_ci	ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	spi_finalize_current_transfer(master);
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic int ep93xx_spi_dma_transfer(struct spi_master *master)
4058c2ecf20Sopenharmony_ci{
4068c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
4078c2ecf20Sopenharmony_ci	struct dma_async_tx_descriptor *rxd, *txd;
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	rxd = ep93xx_spi_dma_prepare(master, DMA_FROM_DEVICE);
4108c2ecf20Sopenharmony_ci	if (IS_ERR(rxd)) {
4118c2ecf20Sopenharmony_ci		dev_err(&master->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
4128c2ecf20Sopenharmony_ci		return PTR_ERR(rxd);
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	txd = ep93xx_spi_dma_prepare(master, DMA_TO_DEVICE);
4168c2ecf20Sopenharmony_ci	if (IS_ERR(txd)) {
4178c2ecf20Sopenharmony_ci		ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE);
4188c2ecf20Sopenharmony_ci		dev_err(&master->dev, "DMA TX failed: %ld\n", PTR_ERR(txd));
4198c2ecf20Sopenharmony_ci		return PTR_ERR(txd);
4208c2ecf20Sopenharmony_ci	}
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	/* We are ready when RX is done */
4238c2ecf20Sopenharmony_ci	rxd->callback = ep93xx_spi_dma_callback;
4248c2ecf20Sopenharmony_ci	rxd->callback_param = master;
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	/* Now submit both descriptors and start DMA */
4278c2ecf20Sopenharmony_ci	dmaengine_submit(rxd);
4288c2ecf20Sopenharmony_ci	dmaengine_submit(txd);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	dma_async_issue_pending(espi->dma_rx);
4318c2ecf20Sopenharmony_ci	dma_async_issue_pending(espi->dma_tx);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	/* signal that we need to wait for completion */
4348c2ecf20Sopenharmony_ci	return 1;
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	struct spi_master *master = dev_id;
4408c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
4418c2ecf20Sopenharmony_ci	u32 val;
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	/*
4448c2ecf20Sopenharmony_ci	 * If we got ROR (receive overrun) interrupt we know that something is
4458c2ecf20Sopenharmony_ci	 * wrong. Just abort the message.
4468c2ecf20Sopenharmony_ci	 */
4478c2ecf20Sopenharmony_ci	if (readl(espi->mmio + SSPIIR) & SSPIIR_RORIS) {
4488c2ecf20Sopenharmony_ci		/* clear the overrun interrupt */
4498c2ecf20Sopenharmony_ci		writel(0, espi->mmio + SSPICR);
4508c2ecf20Sopenharmony_ci		dev_warn(&master->dev,
4518c2ecf20Sopenharmony_ci			 "receive overrun, aborting the message\n");
4528c2ecf20Sopenharmony_ci		master->cur_msg->status = -EIO;
4538c2ecf20Sopenharmony_ci	} else {
4548c2ecf20Sopenharmony_ci		/*
4558c2ecf20Sopenharmony_ci		 * Interrupt is either RX (RIS) or TX (TIS). For both cases we
4568c2ecf20Sopenharmony_ci		 * simply execute next data transfer.
4578c2ecf20Sopenharmony_ci		 */
4588c2ecf20Sopenharmony_ci		if (ep93xx_spi_read_write(master)) {
4598c2ecf20Sopenharmony_ci			/*
4608c2ecf20Sopenharmony_ci			 * In normal case, there still is some processing left
4618c2ecf20Sopenharmony_ci			 * for current transfer. Let's wait for the next
4628c2ecf20Sopenharmony_ci			 * interrupt then.
4638c2ecf20Sopenharmony_ci			 */
4648c2ecf20Sopenharmony_ci			return IRQ_HANDLED;
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	/*
4698c2ecf20Sopenharmony_ci	 * Current transfer is finished, either with error or with success. In
4708c2ecf20Sopenharmony_ci	 * any case we disable interrupts and notify the worker to handle
4718c2ecf20Sopenharmony_ci	 * any post-processing of the message.
4728c2ecf20Sopenharmony_ci	 */
4738c2ecf20Sopenharmony_ci	val = readl(espi->mmio + SSPCR1);
4748c2ecf20Sopenharmony_ci	val &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
4758c2ecf20Sopenharmony_ci	writel(val, espi->mmio + SSPCR1);
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	spi_finalize_current_transfer(master);
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
4808c2ecf20Sopenharmony_ci}
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cistatic int ep93xx_spi_transfer_one(struct spi_master *master,
4838c2ecf20Sopenharmony_ci				   struct spi_device *spi,
4848c2ecf20Sopenharmony_ci				   struct spi_transfer *xfer)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
4878c2ecf20Sopenharmony_ci	u32 val;
4888c2ecf20Sopenharmony_ci	int ret;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	ret = ep93xx_spi_chip_setup(master, spi, xfer);
4918c2ecf20Sopenharmony_ci	if (ret) {
4928c2ecf20Sopenharmony_ci		dev_err(&master->dev, "failed to setup chip for transfer\n");
4938c2ecf20Sopenharmony_ci		return ret;
4948c2ecf20Sopenharmony_ci	}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	master->cur_msg->state = xfer;
4978c2ecf20Sopenharmony_ci	espi->rx = 0;
4988c2ecf20Sopenharmony_ci	espi->tx = 0;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	/*
5018c2ecf20Sopenharmony_ci	 * There is no point of setting up DMA for the transfers which will
5028c2ecf20Sopenharmony_ci	 * fit into the FIFO and can be transferred with a single interrupt.
5038c2ecf20Sopenharmony_ci	 * So in these cases we will be using PIO and don't bother for DMA.
5048c2ecf20Sopenharmony_ci	 */
5058c2ecf20Sopenharmony_ci	if (espi->dma_rx && xfer->len > SPI_FIFO_SIZE)
5068c2ecf20Sopenharmony_ci		return ep93xx_spi_dma_transfer(master);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* Using PIO so prime the TX FIFO and enable interrupts */
5098c2ecf20Sopenharmony_ci	ep93xx_spi_read_write(master);
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	val = readl(espi->mmio + SSPCR1);
5128c2ecf20Sopenharmony_ci	val |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE);
5138c2ecf20Sopenharmony_ci	writel(val, espi->mmio + SSPCR1);
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/* signal that we need to wait for completion */
5168c2ecf20Sopenharmony_ci	return 1;
5178c2ecf20Sopenharmony_ci}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_cistatic int ep93xx_spi_prepare_message(struct spi_master *master,
5208c2ecf20Sopenharmony_ci				      struct spi_message *msg)
5218c2ecf20Sopenharmony_ci{
5228c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
5238c2ecf20Sopenharmony_ci	unsigned long timeout;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	/*
5268c2ecf20Sopenharmony_ci	 * Just to be sure: flush any data from RX FIFO.
5278c2ecf20Sopenharmony_ci	 */
5288c2ecf20Sopenharmony_ci	timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT);
5298c2ecf20Sopenharmony_ci	while (readl(espi->mmio + SSPSR) & SSPSR_RNE) {
5308c2ecf20Sopenharmony_ci		if (time_after(jiffies, timeout)) {
5318c2ecf20Sopenharmony_ci			dev_warn(&master->dev,
5328c2ecf20Sopenharmony_ci				 "timeout while flushing RX FIFO\n");
5338c2ecf20Sopenharmony_ci			return -ETIMEDOUT;
5348c2ecf20Sopenharmony_ci		}
5358c2ecf20Sopenharmony_ci		readl(espi->mmio + SSPDR);
5368c2ecf20Sopenharmony_ci	}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	/*
5398c2ecf20Sopenharmony_ci	 * We explicitly handle FIFO level. This way we don't have to check TX
5408c2ecf20Sopenharmony_ci	 * FIFO status using %SSPSR_TNF bit which may cause RX FIFO overruns.
5418c2ecf20Sopenharmony_ci	 */
5428c2ecf20Sopenharmony_ci	espi->fifo_level = 0;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	return 0;
5458c2ecf20Sopenharmony_ci}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_cistatic int ep93xx_spi_prepare_hardware(struct spi_master *master)
5488c2ecf20Sopenharmony_ci{
5498c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
5508c2ecf20Sopenharmony_ci	u32 val;
5518c2ecf20Sopenharmony_ci	int ret;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ret = clk_enable(espi->clk);
5548c2ecf20Sopenharmony_ci	if (ret)
5558c2ecf20Sopenharmony_ci		return ret;
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	val = readl(espi->mmio + SSPCR1);
5588c2ecf20Sopenharmony_ci	val |= SSPCR1_SSE;
5598c2ecf20Sopenharmony_ci	writel(val, espi->mmio + SSPCR1);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci	return 0;
5628c2ecf20Sopenharmony_ci}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_cistatic int ep93xx_spi_unprepare_hardware(struct spi_master *master)
5658c2ecf20Sopenharmony_ci{
5668c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
5678c2ecf20Sopenharmony_ci	u32 val;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	val = readl(espi->mmio + SSPCR1);
5708c2ecf20Sopenharmony_ci	val &= ~SSPCR1_SSE;
5718c2ecf20Sopenharmony_ci	writel(val, espi->mmio + SSPCR1);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	clk_disable(espi->clk);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	return 0;
5768c2ecf20Sopenharmony_ci}
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_cistatic bool ep93xx_spi_dma_filter(struct dma_chan *chan, void *filter_param)
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	if (ep93xx_dma_chan_is_m2p(chan))
5818c2ecf20Sopenharmony_ci		return false;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	chan->private = filter_param;
5848c2ecf20Sopenharmony_ci	return true;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic int ep93xx_spi_setup_dma(struct ep93xx_spi *espi)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	dma_cap_mask_t mask;
5908c2ecf20Sopenharmony_ci	int ret;
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	espi->zeropage = (void *)get_zeroed_page(GFP_KERNEL);
5938c2ecf20Sopenharmony_ci	if (!espi->zeropage)
5948c2ecf20Sopenharmony_ci		return -ENOMEM;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	dma_cap_zero(mask);
5978c2ecf20Sopenharmony_ci	dma_cap_set(DMA_SLAVE, mask);
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	espi->dma_rx_data.port = EP93XX_DMA_SSP;
6008c2ecf20Sopenharmony_ci	espi->dma_rx_data.direction = DMA_DEV_TO_MEM;
6018c2ecf20Sopenharmony_ci	espi->dma_rx_data.name = "ep93xx-spi-rx";
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	espi->dma_rx = dma_request_channel(mask, ep93xx_spi_dma_filter,
6048c2ecf20Sopenharmony_ci					   &espi->dma_rx_data);
6058c2ecf20Sopenharmony_ci	if (!espi->dma_rx) {
6068c2ecf20Sopenharmony_ci		ret = -ENODEV;
6078c2ecf20Sopenharmony_ci		goto fail_free_page;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	espi->dma_tx_data.port = EP93XX_DMA_SSP;
6118c2ecf20Sopenharmony_ci	espi->dma_tx_data.direction = DMA_MEM_TO_DEV;
6128c2ecf20Sopenharmony_ci	espi->dma_tx_data.name = "ep93xx-spi-tx";
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	espi->dma_tx = dma_request_channel(mask, ep93xx_spi_dma_filter,
6158c2ecf20Sopenharmony_ci					   &espi->dma_tx_data);
6168c2ecf20Sopenharmony_ci	if (!espi->dma_tx) {
6178c2ecf20Sopenharmony_ci		ret = -ENODEV;
6188c2ecf20Sopenharmony_ci		goto fail_release_rx;
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	return 0;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cifail_release_rx:
6248c2ecf20Sopenharmony_ci	dma_release_channel(espi->dma_rx);
6258c2ecf20Sopenharmony_ci	espi->dma_rx = NULL;
6268c2ecf20Sopenharmony_cifail_free_page:
6278c2ecf20Sopenharmony_ci	free_page((unsigned long)espi->zeropage);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	return ret;
6308c2ecf20Sopenharmony_ci}
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_cistatic void ep93xx_spi_release_dma(struct ep93xx_spi *espi)
6338c2ecf20Sopenharmony_ci{
6348c2ecf20Sopenharmony_ci	if (espi->dma_rx) {
6358c2ecf20Sopenharmony_ci		dma_release_channel(espi->dma_rx);
6368c2ecf20Sopenharmony_ci		sg_free_table(&espi->rx_sgt);
6378c2ecf20Sopenharmony_ci	}
6388c2ecf20Sopenharmony_ci	if (espi->dma_tx) {
6398c2ecf20Sopenharmony_ci		dma_release_channel(espi->dma_tx);
6408c2ecf20Sopenharmony_ci		sg_free_table(&espi->tx_sgt);
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	if (espi->zeropage)
6448c2ecf20Sopenharmony_ci		free_page((unsigned long)espi->zeropage);
6458c2ecf20Sopenharmony_ci}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_cistatic int ep93xx_spi_probe(struct platform_device *pdev)
6488c2ecf20Sopenharmony_ci{
6498c2ecf20Sopenharmony_ci	struct spi_master *master;
6508c2ecf20Sopenharmony_ci	struct ep93xx_spi_info *info;
6518c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi;
6528c2ecf20Sopenharmony_ci	struct resource *res;
6538c2ecf20Sopenharmony_ci	int irq;
6548c2ecf20Sopenharmony_ci	int error;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	info = dev_get_platdata(&pdev->dev);
6578c2ecf20Sopenharmony_ci	if (!info) {
6588c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "missing platform data\n");
6598c2ecf20Sopenharmony_ci		return -EINVAL;
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
6638c2ecf20Sopenharmony_ci	if (irq < 0)
6648c2ecf20Sopenharmony_ci		return -EBUSY;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
6678c2ecf20Sopenharmony_ci	if (!res) {
6688c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "unable to get iomem resource\n");
6698c2ecf20Sopenharmony_ci		return -ENODEV;
6708c2ecf20Sopenharmony_ci	}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci	master = spi_alloc_master(&pdev->dev, sizeof(*espi));
6738c2ecf20Sopenharmony_ci	if (!master)
6748c2ecf20Sopenharmony_ci		return -ENOMEM;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	master->use_gpio_descriptors = true;
6778c2ecf20Sopenharmony_ci	master->prepare_transfer_hardware = ep93xx_spi_prepare_hardware;
6788c2ecf20Sopenharmony_ci	master->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware;
6798c2ecf20Sopenharmony_ci	master->prepare_message = ep93xx_spi_prepare_message;
6808c2ecf20Sopenharmony_ci	master->transfer_one = ep93xx_spi_transfer_one;
6818c2ecf20Sopenharmony_ci	master->bus_num = pdev->id;
6828c2ecf20Sopenharmony_ci	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
6838c2ecf20Sopenharmony_ci	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
6848c2ecf20Sopenharmony_ci	/*
6858c2ecf20Sopenharmony_ci	 * The SPI core will count the number of GPIO descriptors to figure
6868c2ecf20Sopenharmony_ci	 * out the number of chip selects available on the platform.
6878c2ecf20Sopenharmony_ci	 */
6888c2ecf20Sopenharmony_ci	master->num_chipselect = 0;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, master);
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	espi = spi_master_get_devdata(master);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	espi->clk = devm_clk_get(&pdev->dev, NULL);
6958c2ecf20Sopenharmony_ci	if (IS_ERR(espi->clk)) {
6968c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "unable to get spi clock\n");
6978c2ecf20Sopenharmony_ci		error = PTR_ERR(espi->clk);
6988c2ecf20Sopenharmony_ci		goto fail_release_master;
6998c2ecf20Sopenharmony_ci	}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	/*
7028c2ecf20Sopenharmony_ci	 * Calculate maximum and minimum supported clock rates
7038c2ecf20Sopenharmony_ci	 * for the controller.
7048c2ecf20Sopenharmony_ci	 */
7058c2ecf20Sopenharmony_ci	master->max_speed_hz = clk_get_rate(espi->clk) / 2;
7068c2ecf20Sopenharmony_ci	master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256);
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	espi->sspdr_phys = res->start + SSPDR;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	espi->mmio = devm_ioremap_resource(&pdev->dev, res);
7118c2ecf20Sopenharmony_ci	if (IS_ERR(espi->mmio)) {
7128c2ecf20Sopenharmony_ci		error = PTR_ERR(espi->mmio);
7138c2ecf20Sopenharmony_ci		goto fail_release_master;
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt,
7178c2ecf20Sopenharmony_ci				0, "ep93xx-spi", master);
7188c2ecf20Sopenharmony_ci	if (error) {
7198c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to request irq\n");
7208c2ecf20Sopenharmony_ci		goto fail_release_master;
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (info->use_dma && ep93xx_spi_setup_dma(espi))
7248c2ecf20Sopenharmony_ci		dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n");
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/* make sure that the hardware is disabled */
7278c2ecf20Sopenharmony_ci	writel(0, espi->mmio + SSPCR1);
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	error = devm_spi_register_master(&pdev->dev, master);
7308c2ecf20Sopenharmony_ci	if (error) {
7318c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to register SPI master\n");
7328c2ecf20Sopenharmony_ci		goto fail_free_dma;
7338c2ecf20Sopenharmony_ci	}
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n",
7368c2ecf20Sopenharmony_ci		 (unsigned long)res->start, irq);
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	return 0;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cifail_free_dma:
7418c2ecf20Sopenharmony_ci	ep93xx_spi_release_dma(espi);
7428c2ecf20Sopenharmony_cifail_release_master:
7438c2ecf20Sopenharmony_ci	spi_master_put(master);
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	return error;
7468c2ecf20Sopenharmony_ci}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_cistatic int ep93xx_spi_remove(struct platform_device *pdev)
7498c2ecf20Sopenharmony_ci{
7508c2ecf20Sopenharmony_ci	struct spi_master *master = platform_get_drvdata(pdev);
7518c2ecf20Sopenharmony_ci	struct ep93xx_spi *espi = spi_master_get_devdata(master);
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	ep93xx_spi_release_dma(espi);
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	return 0;
7568c2ecf20Sopenharmony_ci}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic struct platform_driver ep93xx_spi_driver = {
7598c2ecf20Sopenharmony_ci	.driver		= {
7608c2ecf20Sopenharmony_ci		.name	= "ep93xx-spi",
7618c2ecf20Sopenharmony_ci	},
7628c2ecf20Sopenharmony_ci	.probe		= ep93xx_spi_probe,
7638c2ecf20Sopenharmony_ci	.remove		= ep93xx_spi_remove,
7648c2ecf20Sopenharmony_ci};
7658c2ecf20Sopenharmony_cimodule_platform_driver(ep93xx_spi_driver);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("EP93xx SPI Controller driver");
7688c2ecf20Sopenharmony_ciMODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
7698c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
7708c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:ep93xx-spi");
771