xref: /linux/drivers/spi/spi-st-ssc4.c (revision 09355402325819675027eda25aba7026a325390c)
19e862375SLee Jones /*
29e862375SLee Jones  *  Copyright (c) 2008-2014 STMicroelectronics Limited
39e862375SLee Jones  *
49e862375SLee Jones  *  Author: Angus Clark <Angus.Clark@st.com>
59e862375SLee Jones  *          Patrice Chotard <patrice.chotard@st.com>
69e862375SLee Jones  *          Lee Jones <lee.jones@linaro.org>
79e862375SLee Jones  *
89e862375SLee Jones  *  SPI master mode controller driver, used in STMicroelectronics devices.
99e862375SLee Jones  *
109e862375SLee Jones  *  May be copied or modified under the terms of the GNU General Public
119e862375SLee Jones  *  License Version 2.0 only.  See linux/COPYING for more information.
129e862375SLee Jones  */
139e862375SLee Jones 
149e862375SLee Jones #include <linux/clk.h>
159e862375SLee Jones #include <linux/delay.h>
169e862375SLee Jones #include <linux/interrupt.h>
179e862375SLee Jones #include <linux/io.h>
189e862375SLee Jones #include <linux/module.h>
199e862375SLee Jones #include <linux/pinctrl/consumer.h>
209e862375SLee Jones #include <linux/platform_device.h>
219e862375SLee Jones #include <linux/of.h>
229e862375SLee Jones #include <linux/of_gpio.h>
239e862375SLee Jones #include <linux/of_irq.h>
249e862375SLee Jones #include <linux/pm_runtime.h>
259e862375SLee Jones #include <linux/spi/spi.h>
269e862375SLee Jones #include <linux/spi/spi_bitbang.h>
279e862375SLee Jones 
289e862375SLee Jones /* SSC registers */
299e862375SLee Jones #define SSC_BRG				0x000
309e862375SLee Jones #define SSC_TBUF			0x004
319e862375SLee Jones #define SSC_RBUF			0x008
329e862375SLee Jones #define SSC_CTL				0x00C
339e862375SLee Jones #define SSC_IEN				0x010
349e862375SLee Jones #define SSC_I2C				0x018
359e862375SLee Jones 
369e862375SLee Jones /* SSC Control */
379e862375SLee Jones #define SSC_CTL_DATA_WIDTH_9		0x8
389e862375SLee Jones #define SSC_CTL_DATA_WIDTH_MSK		0xf
399e862375SLee Jones #define SSC_CTL_BM			0xf
409e862375SLee Jones #define SSC_CTL_HB			BIT(4)
419e862375SLee Jones #define SSC_CTL_PH			BIT(5)
429e862375SLee Jones #define SSC_CTL_PO			BIT(6)
439e862375SLee Jones #define SSC_CTL_SR			BIT(7)
449e862375SLee Jones #define SSC_CTL_MS			BIT(8)
459e862375SLee Jones #define SSC_CTL_EN			BIT(9)
469e862375SLee Jones #define SSC_CTL_LPB			BIT(10)
479e862375SLee Jones #define SSC_CTL_EN_TX_FIFO		BIT(11)
489e862375SLee Jones #define SSC_CTL_EN_RX_FIFO		BIT(12)
499e862375SLee Jones #define SSC_CTL_EN_CLST_RX		BIT(13)
509e862375SLee Jones 
519e862375SLee Jones /* SSC Interrupt Enable */
529e862375SLee Jones #define SSC_IEN_TEEN			BIT(2)
539e862375SLee Jones 
549e862375SLee Jones #define FIFO_SIZE			8
559e862375SLee Jones 
569e862375SLee Jones struct spi_st {
579e862375SLee Jones 	/* SSC SPI Controller */
589e862375SLee Jones 	void __iomem		*base;
599e862375SLee Jones 	struct clk		*clk;
609e862375SLee Jones 	struct device		*dev;
619e862375SLee Jones 
629e862375SLee Jones 	/* SSC SPI current transaction */
639e862375SLee Jones 	const u8		*tx_ptr;
649e862375SLee Jones 	u8			*rx_ptr;
659e862375SLee Jones 	u16			bytes_per_word;
669e862375SLee Jones 	unsigned int		words_remaining;
679e862375SLee Jones 	unsigned int		baud;
689e862375SLee Jones 	struct completion	done;
699e862375SLee Jones };
709e862375SLee Jones 
719e862375SLee Jones static int spi_st_clk_enable(struct spi_st *spi_st)
729e862375SLee Jones {
739e862375SLee Jones 	/*
749e862375SLee Jones 	 * Current platforms use one of the core clocks for SPI and I2C.
759e862375SLee Jones 	 * If we attempt to disable the clock, the system will hang.
769e862375SLee Jones 	 *
779e862375SLee Jones 	 * TODO: Remove this when platform supports power domains.
789e862375SLee Jones 	 */
799e862375SLee Jones 	return 0;
809e862375SLee Jones 
819e862375SLee Jones 	return clk_prepare_enable(spi_st->clk);
829e862375SLee Jones }
839e862375SLee Jones 
849e862375SLee Jones static void spi_st_clk_disable(struct spi_st *spi_st)
859e862375SLee Jones {
869e862375SLee Jones 	/*
879e862375SLee Jones 	 * Current platforms use one of the core clocks for SPI and I2C.
889e862375SLee Jones 	 * If we attempt to disable the clock, the system will hang.
899e862375SLee Jones 	 *
909e862375SLee Jones 	 * TODO: Remove this when platform supports power domains.
919e862375SLee Jones 	 */
929e862375SLee Jones 	return;
939e862375SLee Jones 
949e862375SLee Jones 	clk_disable_unprepare(spi_st->clk);
959e862375SLee Jones }
969e862375SLee Jones 
979e862375SLee Jones /* Load the TX FIFO */
989e862375SLee Jones static void ssc_write_tx_fifo(struct spi_st *spi_st)
999e862375SLee Jones {
1009e862375SLee Jones 	unsigned int count, i;
1019e862375SLee Jones 	uint32_t word = 0;
1029e862375SLee Jones 
1039e862375SLee Jones 	if (spi_st->words_remaining > FIFO_SIZE)
1049e862375SLee Jones 		count = FIFO_SIZE;
1059e862375SLee Jones 	else
1069e862375SLee Jones 		count = spi_st->words_remaining;
1079e862375SLee Jones 
1089e862375SLee Jones 	for (i = 0; i < count; i++) {
1099e862375SLee Jones 		if (spi_st->tx_ptr) {
1109e862375SLee Jones 			if (spi_st->bytes_per_word == 1) {
1119e862375SLee Jones 				word = *spi_st->tx_ptr++;
1129e862375SLee Jones 			} else {
1139e862375SLee Jones 				word = *spi_st->tx_ptr++;
1149e862375SLee Jones 				word = *spi_st->tx_ptr++ | (word << 8);
1159e862375SLee Jones 			}
1169e862375SLee Jones 		}
1179e862375SLee Jones 		writel_relaxed(word, spi_st->base + SSC_TBUF);
1189e862375SLee Jones 	}
1199e862375SLee Jones }
1209e862375SLee Jones 
1219e862375SLee Jones /* Read the RX FIFO */
1229e862375SLee Jones static void ssc_read_rx_fifo(struct spi_st *spi_st)
1239e862375SLee Jones {
1249e862375SLee Jones 	unsigned int count, i;
1259e862375SLee Jones 	uint32_t word = 0;
1269e862375SLee Jones 
1279e862375SLee Jones 	if (spi_st->words_remaining > FIFO_SIZE)
1289e862375SLee Jones 		count = FIFO_SIZE;
1299e862375SLee Jones 	else
1309e862375SLee Jones 		count = spi_st->words_remaining;
1319e862375SLee Jones 
1329e862375SLee Jones 	for (i = 0; i < count; i++) {
1339e862375SLee Jones 		word = readl_relaxed(spi_st->base + SSC_RBUF);
1349e862375SLee Jones 
1359e862375SLee Jones 		if (spi_st->rx_ptr) {
1369e862375SLee Jones 			if (spi_st->bytes_per_word == 1) {
1379e862375SLee Jones 				*spi_st->rx_ptr++ = (uint8_t)word;
1389e862375SLee Jones 			} else {
1399e862375SLee Jones 				*spi_st->rx_ptr++ = (word >> 8);
1409e862375SLee Jones 				*spi_st->rx_ptr++ = word & 0xff;
1419e862375SLee Jones 			}
1429e862375SLee Jones 		}
1439e862375SLee Jones 	}
1449e862375SLee Jones 	spi_st->words_remaining -= count;
1459e862375SLee Jones }
1469e862375SLee Jones 
1479e862375SLee Jones static int spi_st_transfer_one(struct spi_master *master,
1489e862375SLee Jones 			       struct spi_device *spi, struct spi_transfer *t)
1499e862375SLee Jones {
1509e862375SLee Jones 	struct spi_st *spi_st = spi_master_get_devdata(master);
1519e862375SLee Jones 	uint32_t ctl = 0;
1529e862375SLee Jones 
1539e862375SLee Jones 	/* Setup transfer */
1549e862375SLee Jones 	spi_st->tx_ptr = t->tx_buf;
1559e862375SLee Jones 	spi_st->rx_ptr = t->rx_buf;
1569e862375SLee Jones 
1579e862375SLee Jones 	if (spi->bits_per_word > 8) {
1589e862375SLee Jones 		/*
1599e862375SLee Jones 		 * Anything greater than 8 bits-per-word requires 2
1609e862375SLee Jones 		 * bytes-per-word in the RX/TX buffers
1619e862375SLee Jones 		 */
1629e862375SLee Jones 		spi_st->bytes_per_word = 2;
1639e862375SLee Jones 		spi_st->words_remaining = t->len / 2;
1649e862375SLee Jones 
1659e862375SLee Jones 	} else if (spi->bits_per_word == 8 && !(t->len & 0x1)) {
1669e862375SLee Jones 		/*
1679e862375SLee Jones 		 * If transfer is even-length, and 8 bits-per-word, then
1689e862375SLee Jones 		 * implement as half-length 16 bits-per-word transfer
1699e862375SLee Jones 		 */
1709e862375SLee Jones 		spi_st->bytes_per_word = 2;
1719e862375SLee Jones 		spi_st->words_remaining = t->len / 2;
1729e862375SLee Jones 
1739e862375SLee Jones 		/* Set SSC_CTL to 16 bits-per-word */
1749e862375SLee Jones 		ctl = readl_relaxed(spi_st->base + SSC_CTL);
1759e862375SLee Jones 		writel_relaxed((ctl | 0xf), spi_st->base + SSC_CTL);
1769e862375SLee Jones 
1779e862375SLee Jones 		readl_relaxed(spi_st->base + SSC_RBUF);
1789e862375SLee Jones 
1799e862375SLee Jones 	} else {
1809e862375SLee Jones 		spi_st->bytes_per_word = 1;
1819e862375SLee Jones 		spi_st->words_remaining = t->len;
1829e862375SLee Jones 	}
1839e862375SLee Jones 
1849e862375SLee Jones 	reinit_completion(&spi_st->done);
1859e862375SLee Jones 
1869e862375SLee Jones 	/* Start transfer by writing to the TX FIFO */
1879e862375SLee Jones 	ssc_write_tx_fifo(spi_st);
1889e862375SLee Jones 	writel_relaxed(SSC_IEN_TEEN, spi_st->base + SSC_IEN);
1899e862375SLee Jones 
1909e862375SLee Jones 	/* Wait for transfer to complete */
1919e862375SLee Jones 	wait_for_completion(&spi_st->done);
1929e862375SLee Jones 
1939e862375SLee Jones 	/* Restore SSC_CTL if necessary */
1949e862375SLee Jones 	if (ctl)
1959e862375SLee Jones 		writel_relaxed(ctl, spi_st->base + SSC_CTL);
1969e862375SLee Jones 
1979e862375SLee Jones 	spi_finalize_current_transfer(spi->master);
1989e862375SLee Jones 
1999e862375SLee Jones 	return t->len;
2009e862375SLee Jones }
2019e862375SLee Jones 
2029e862375SLee Jones static void spi_st_cleanup(struct spi_device *spi)
2039e862375SLee Jones {
2049e862375SLee Jones 	int cs = spi->cs_gpio;
2059e862375SLee Jones 
2069e862375SLee Jones 	if (gpio_is_valid(cs))
2079e862375SLee Jones 		devm_gpio_free(&spi->dev, cs);
2089e862375SLee Jones }
2099e862375SLee Jones 
2109e862375SLee Jones /* the spi->mode bits understood by this driver: */
2119e862375SLee Jones #define MODEBITS  (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH)
2129e862375SLee Jones static int spi_st_setup(struct spi_device *spi)
2139e862375SLee Jones {
2149e862375SLee Jones 	struct spi_st *spi_st = spi_master_get_devdata(spi->master);
2159e862375SLee Jones 	u32 spi_st_clk, sscbrg, var;
2169e862375SLee Jones 	u32 hz = spi->max_speed_hz;
2179e862375SLee Jones 	int cs = spi->cs_gpio;
2189e862375SLee Jones 	int ret;
2199e862375SLee Jones 
2209e862375SLee Jones 	if (!hz)  {
2219e862375SLee Jones 		dev_err(&spi->dev, "max_speed_hz unspecified\n");
2229e862375SLee Jones 		return -EINVAL;
2239e862375SLee Jones 	}
2249e862375SLee Jones 
2259e862375SLee Jones 	if (!gpio_is_valid(cs)) {
2269e862375SLee Jones 		dev_err(&spi->dev, "%d is not a valid gpio\n", cs);
2279e862375SLee Jones 		return -EINVAL;
2289e862375SLee Jones 	}
2299e862375SLee Jones 
2309e862375SLee Jones 	if (devm_gpio_request(&spi->dev, cs, dev_name(&spi->dev))) {
2319e862375SLee Jones 		dev_err(&spi->dev, "could not request gpio:%d\n", cs);
2329e862375SLee Jones 		return -EINVAL;
2339e862375SLee Jones 	}
2349e862375SLee Jones 
2359e862375SLee Jones 	ret = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH);
2369e862375SLee Jones 	if (ret)
2379e862375SLee Jones 		return ret;
2389e862375SLee Jones 
2399e862375SLee Jones 	spi_st_clk = clk_get_rate(spi_st->clk);
2409e862375SLee Jones 
2419e862375SLee Jones 	/* Set SSC_BRF */
2429e862375SLee Jones 	sscbrg = spi_st_clk / (2 * hz);
2439e862375SLee Jones 	if (sscbrg < 0x07 || sscbrg > BIT(16)) {
2449e862375SLee Jones 		dev_err(&spi->dev,
2459e862375SLee Jones 			"baudrate %d outside valid range %d\n", sscbrg, hz);
2469e862375SLee Jones 		return -EINVAL;
2479e862375SLee Jones 	}
2489e862375SLee Jones 
2499e862375SLee Jones 	spi_st->baud = spi_st_clk / (2 * sscbrg);
2509e862375SLee Jones 	if (sscbrg == BIT(16)) /* 16-bit counter wraps */
2519e862375SLee Jones 		sscbrg = 0x0;
2529e862375SLee Jones 
2539e862375SLee Jones 	writel_relaxed(sscbrg, spi_st->base + SSC_BRG);
2549e862375SLee Jones 
2559e862375SLee Jones 	dev_dbg(&spi->dev,
2569e862375SLee Jones 		"setting baudrate:target= %u hz, actual= %u hz, sscbrg= %u\n",
2579e862375SLee Jones 		hz, spi_st->baud, sscbrg);
2589e862375SLee Jones 
2599e862375SLee Jones 	 /* Set SSC_CTL and enable SSC */
2609e862375SLee Jones 	 var = readl_relaxed(spi_st->base + SSC_CTL);
2619e862375SLee Jones 	 var |= SSC_CTL_MS;
2629e862375SLee Jones 
2639e862375SLee Jones 	 if (spi->mode & SPI_CPOL)
2649e862375SLee Jones 		var |= SSC_CTL_PO;
2659e862375SLee Jones 	 else
2669e862375SLee Jones 		var &= ~SSC_CTL_PO;
2679e862375SLee Jones 
2689e862375SLee Jones 	 if (spi->mode & SPI_CPHA)
2699e862375SLee Jones 		var |= SSC_CTL_PH;
2709e862375SLee Jones 	 else
2719e862375SLee Jones 		var &= ~SSC_CTL_PH;
2729e862375SLee Jones 
2739e862375SLee Jones 	 if ((spi->mode & SPI_LSB_FIRST) == 0)
2749e862375SLee Jones 		var |= SSC_CTL_HB;
2759e862375SLee Jones 	 else
2769e862375SLee Jones 		var &= ~SSC_CTL_HB;
2779e862375SLee Jones 
2789e862375SLee Jones 	 if (spi->mode & SPI_LOOP)
2799e862375SLee Jones 		var |= SSC_CTL_LPB;
2809e862375SLee Jones 	 else
2819e862375SLee Jones 		var &= ~SSC_CTL_LPB;
2829e862375SLee Jones 
2839e862375SLee Jones 	 var &= ~SSC_CTL_DATA_WIDTH_MSK;
2849e862375SLee Jones 	 var |= (spi->bits_per_word - 1);
2859e862375SLee Jones 
2869e862375SLee Jones 	 var |= SSC_CTL_EN_TX_FIFO | SSC_CTL_EN_RX_FIFO;
2879e862375SLee Jones 	 var |= SSC_CTL_EN;
2889e862375SLee Jones 
2899e862375SLee Jones 	 writel_relaxed(var, spi_st->base + SSC_CTL);
2909e862375SLee Jones 
2919e862375SLee Jones 	 /* Clear the status register */
2929e862375SLee Jones 	 readl_relaxed(spi_st->base + SSC_RBUF);
2939e862375SLee Jones 
2949e862375SLee Jones 	 return 0;
2959e862375SLee Jones }
2969e862375SLee Jones 
2979e862375SLee Jones /* Interrupt fired when TX shift register becomes empty */
2989e862375SLee Jones static irqreturn_t spi_st_irq(int irq, void *dev_id)
2999e862375SLee Jones {
3009e862375SLee Jones 	struct spi_st *spi_st = (struct spi_st *)dev_id;
3019e862375SLee Jones 
3029e862375SLee Jones 	/* Read RX FIFO */
3039e862375SLee Jones 	ssc_read_rx_fifo(spi_st);
3049e862375SLee Jones 
3059e862375SLee Jones 	/* Fill TX FIFO */
3069e862375SLee Jones 	if (spi_st->words_remaining) {
3079e862375SLee Jones 		ssc_write_tx_fifo(spi_st);
3089e862375SLee Jones 	} else {
3099e862375SLee Jones 		/* TX/RX complete */
3109e862375SLee Jones 		writel_relaxed(0x0, spi_st->base + SSC_IEN);
3119e862375SLee Jones 		/*
3129e862375SLee Jones 		 * read SSC_IEN to ensure that this bit is set
3139e862375SLee Jones 		 * before re-enabling interrupt
3149e862375SLee Jones 		 */
3159e862375SLee Jones 		readl(spi_st->base + SSC_IEN);
3169e862375SLee Jones 		complete(&spi_st->done);
3179e862375SLee Jones 	}
3189e862375SLee Jones 
3199e862375SLee Jones 	return IRQ_HANDLED;
3209e862375SLee Jones }
3219e862375SLee Jones 
3229e862375SLee Jones static int spi_st_probe(struct platform_device *pdev)
3239e862375SLee Jones {
3249e862375SLee Jones 	struct device_node *np = pdev->dev.of_node;
3259e862375SLee Jones 	struct spi_master *master;
3269e862375SLee Jones 	struct resource *res;
3279e862375SLee Jones 	struct spi_st *spi_st;
3289e862375SLee Jones 	int irq, ret = 0;
3299e862375SLee Jones 	u32 var;
3309e862375SLee Jones 
3319e862375SLee Jones 	master = spi_alloc_master(&pdev->dev, sizeof(*spi_st));
3329e862375SLee Jones 	if (!master)
3339e862375SLee Jones 		return -ENOMEM;
3349e862375SLee Jones 
3359e862375SLee Jones 	master->dev.of_node		= np;
3369e862375SLee Jones 	master->mode_bits		= MODEBITS;
3379e862375SLee Jones 	master->setup			= spi_st_setup;
3389e862375SLee Jones 	master->cleanup			= spi_st_cleanup;
3399e862375SLee Jones 	master->transfer_one		= spi_st_transfer_one;
3409e862375SLee Jones 	master->bits_per_word_mask	= SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
3419e862375SLee Jones 	master->auto_runtime_pm		= true;
3429e862375SLee Jones 	master->bus_num			= pdev->id;
3439e862375SLee Jones 	spi_st				= spi_master_get_devdata(master);
3449e862375SLee Jones 
3459e862375SLee Jones 	spi_st->clk = devm_clk_get(&pdev->dev, "ssc");
3469e862375SLee Jones 	if (IS_ERR(spi_st->clk)) {
3479e862375SLee Jones 		dev_err(&pdev->dev, "Unable to request clock\n");
3489e862375SLee Jones 		return PTR_ERR(spi_st->clk);
3499e862375SLee Jones 	}
3509e862375SLee Jones 
3519e862375SLee Jones 	ret = spi_st_clk_enable(spi_st);
3529e862375SLee Jones 	if (ret)
3539e862375SLee Jones 		return ret;
3549e862375SLee Jones 
3559e862375SLee Jones 	init_completion(&spi_st->done);
3569e862375SLee Jones 
3579e862375SLee Jones 	/* Get resources */
3589e862375SLee Jones 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3599e862375SLee Jones 	spi_st->base = devm_ioremap_resource(&pdev->dev, res);
3609e862375SLee Jones 	if (IS_ERR(spi_st->base)) {
3619e862375SLee Jones 		ret = PTR_ERR(spi_st->base);
3629e862375SLee Jones 		goto clk_disable;
3639e862375SLee Jones 	}
3649e862375SLee Jones 
3659e862375SLee Jones 	/* Disable I2C and Reset SSC */
3669e862375SLee Jones 	writel_relaxed(0x0, spi_st->base + SSC_I2C);
3679e862375SLee Jones 	var = readw_relaxed(spi_st->base + SSC_CTL);
3689e862375SLee Jones 	var |= SSC_CTL_SR;
3699e862375SLee Jones 	writel_relaxed(var, spi_st->base + SSC_CTL);
3709e862375SLee Jones 
3719e862375SLee Jones 	udelay(1);
3729e862375SLee Jones 	var = readl_relaxed(spi_st->base + SSC_CTL);
3739e862375SLee Jones 	var &= ~SSC_CTL_SR;
3749e862375SLee Jones 	writel_relaxed(var, spi_st->base + SSC_CTL);
3759e862375SLee Jones 
3769e862375SLee Jones 	/* Set SSC into slave mode before reconfiguring PIO pins */
3779e862375SLee Jones 	var = readl_relaxed(spi_st->base + SSC_CTL);
3789e862375SLee Jones 	var &= ~SSC_CTL_MS;
3799e862375SLee Jones 	writel_relaxed(var, spi_st->base + SSC_CTL);
3809e862375SLee Jones 
3819e862375SLee Jones 	irq = irq_of_parse_and_map(np, 0);
3829e862375SLee Jones 	if (!irq) {
3839e862375SLee Jones 		dev_err(&pdev->dev, "IRQ missing or invalid\n");
3849e862375SLee Jones 		ret = -EINVAL;
3859e862375SLee Jones 		goto clk_disable;
3869e862375SLee Jones 	}
3879e862375SLee Jones 
3889e862375SLee Jones 	ret = devm_request_irq(&pdev->dev, irq, spi_st_irq, 0,
3899e862375SLee Jones 			       pdev->name, spi_st);
3909e862375SLee Jones 	if (ret) {
3919e862375SLee Jones 		dev_err(&pdev->dev, "Failed to request irq %d\n", irq);
3929e862375SLee Jones 		goto clk_disable;
3939e862375SLee Jones 	}
3949e862375SLee Jones 
3959e862375SLee Jones 	/* by default the device is on */
3969e862375SLee Jones 	pm_runtime_set_active(&pdev->dev);
3979e862375SLee Jones 	pm_runtime_enable(&pdev->dev);
3989e862375SLee Jones 
3999e862375SLee Jones 	platform_set_drvdata(pdev, master);
4009e862375SLee Jones 
4019e862375SLee Jones 	ret = devm_spi_register_master(&pdev->dev, master);
4029e862375SLee Jones 	if (ret) {
4039e862375SLee Jones 		dev_err(&pdev->dev, "Failed to register master\n");
4049e862375SLee Jones 		goto clk_disable;
4059e862375SLee Jones 	}
4069e862375SLee Jones 
4079e862375SLee Jones 	return 0;
4089e862375SLee Jones 
4099e862375SLee Jones clk_disable:
4109e862375SLee Jones 	spi_st_clk_disable(spi_st);
4119e862375SLee Jones 
4129e862375SLee Jones 	return ret;
4139e862375SLee Jones }
4149e862375SLee Jones 
4159e862375SLee Jones static int spi_st_remove(struct platform_device *pdev)
4169e862375SLee Jones {
4179e862375SLee Jones 	struct spi_master *master = platform_get_drvdata(pdev);
4189e862375SLee Jones 	struct spi_st *spi_st = spi_master_get_devdata(master);
4199e862375SLee Jones 
4209e862375SLee Jones 	spi_st_clk_disable(spi_st);
4219e862375SLee Jones 
4229e862375SLee Jones 	pinctrl_pm_select_sleep_state(&pdev->dev);
4239e862375SLee Jones 
4249e862375SLee Jones 	return 0;
4259e862375SLee Jones }
4269e862375SLee Jones 
4279e862375SLee Jones #ifdef CONFIG_PM
4289e862375SLee Jones static int spi_st_runtime_suspend(struct device *dev)
4299e862375SLee Jones {
4309e862375SLee Jones 	struct spi_master *master = dev_get_drvdata(dev);
4319e862375SLee Jones 	struct spi_st *spi_st = spi_master_get_devdata(master);
4329e862375SLee Jones 
4339e862375SLee Jones 	writel_relaxed(0, spi_st->base + SSC_IEN);
4349e862375SLee Jones 	pinctrl_pm_select_sleep_state(dev);
4359e862375SLee Jones 
4369e862375SLee Jones 	spi_st_clk_disable(spi_st);
4379e862375SLee Jones 
4389e862375SLee Jones 	return 0;
4399e862375SLee Jones }
4409e862375SLee Jones 
4419e862375SLee Jones static int spi_st_runtime_resume(struct device *dev)
4429e862375SLee Jones {
4439e862375SLee Jones 	struct spi_master *master = dev_get_drvdata(dev);
4449e862375SLee Jones 	struct spi_st *spi_st = spi_master_get_devdata(master);
4459e862375SLee Jones 	int ret;
4469e862375SLee Jones 
4479e862375SLee Jones 	ret = spi_st_clk_enable(spi_st);
4489e862375SLee Jones 	pinctrl_pm_select_default_state(dev);
4499e862375SLee Jones 
4509e862375SLee Jones 	return ret;
4519e862375SLee Jones }
4529e862375SLee Jones #endif
4539e862375SLee Jones 
4549e862375SLee Jones #ifdef CONFIG_PM_SLEEP
4559e862375SLee Jones static int spi_st_suspend(struct device *dev)
4569e862375SLee Jones {
4579e862375SLee Jones 	struct spi_master *master = dev_get_drvdata(dev);
4589e862375SLee Jones 	int ret;
4599e862375SLee Jones 
4609e862375SLee Jones 	ret = spi_master_suspend(master);
4619e862375SLee Jones 	if (ret)
4629e862375SLee Jones 		return ret;
4639e862375SLee Jones 
4649e862375SLee Jones 	return pm_runtime_force_suspend(dev);
4659e862375SLee Jones }
4669e862375SLee Jones 
4679e862375SLee Jones static int spi_st_resume(struct device *dev)
4689e862375SLee Jones {
4699e862375SLee Jones 	struct spi_master *master = dev_get_drvdata(dev);
4709e862375SLee Jones 	int ret;
4719e862375SLee Jones 
4729e862375SLee Jones 	ret = spi_master_resume(master);
4739e862375SLee Jones 	if (ret)
4749e862375SLee Jones 		return ret;
4759e862375SLee Jones 
4769e862375SLee Jones 	return pm_runtime_force_resume(dev);
4779e862375SLee Jones }
4789e862375SLee Jones #endif
4799e862375SLee Jones 
4809e862375SLee Jones static const struct dev_pm_ops spi_st_pm = {
4819e862375SLee Jones 	SET_SYSTEM_SLEEP_PM_OPS(spi_st_suspend, spi_st_resume)
4829e862375SLee Jones 	SET_RUNTIME_PM_OPS(spi_st_runtime_suspend, spi_st_runtime_resume, NULL)
4839e862375SLee Jones };
4849e862375SLee Jones 
485*09355402SFabian Frederick static const struct of_device_id stm_spi_match[] = {
4869e862375SLee Jones 	{ .compatible = "st,comms-ssc4-spi", },
4879e862375SLee Jones 	{},
4889e862375SLee Jones };
4899e862375SLee Jones MODULE_DEVICE_TABLE(of, stm_spi_match);
4909e862375SLee Jones 
4919e862375SLee Jones static struct platform_driver spi_st_driver = {
4929e862375SLee Jones 	.driver = {
4939e862375SLee Jones 		.name = "spi-st",
4949e862375SLee Jones 		.pm = &spi_st_pm,
4959e862375SLee Jones 		.of_match_table = of_match_ptr(stm_spi_match),
4969e862375SLee Jones 	},
4979e862375SLee Jones 	.probe = spi_st_probe,
4989e862375SLee Jones 	.remove = spi_st_remove,
4999e862375SLee Jones };
5009e862375SLee Jones module_platform_driver(spi_st_driver);
5019e862375SLee Jones 
5029e862375SLee Jones MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>");
5039e862375SLee Jones MODULE_DESCRIPTION("STM SSC SPI driver");
5049e862375SLee Jones MODULE_LICENSE("GPL v2");
505