1f3949fd0SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29e862375SLee Jones /*
39e862375SLee Jones * Copyright (c) 2008-2014 STMicroelectronics Limited
49e862375SLee Jones *
59e862375SLee Jones * Author: Angus Clark <Angus.Clark@st.com>
69e862375SLee Jones * Patrice Chotard <patrice.chotard@st.com>
79e862375SLee Jones * Lee Jones <lee.jones@linaro.org>
89e862375SLee Jones *
9*e6b7e64cSYang Yingliang * SPI host mode controller driver, used in STMicroelectronics devices.
109e862375SLee Jones */
119e862375SLee Jones
129e862375SLee Jones #include <linux/clk.h>
139e862375SLee Jones #include <linux/delay.h>
149e862375SLee Jones #include <linux/interrupt.h>
159e862375SLee Jones #include <linux/io.h>
169e862375SLee Jones #include <linux/module.h>
179e862375SLee Jones #include <linux/pinctrl/consumer.h>
189e862375SLee Jones #include <linux/platform_device.h>
199e862375SLee Jones #include <linux/of.h>
209e862375SLee Jones #include <linux/of_irq.h>
219e862375SLee Jones #include <linux/pm_runtime.h>
229e862375SLee Jones #include <linux/spi/spi.h>
239e862375SLee Jones #include <linux/spi/spi_bitbang.h>
249e862375SLee Jones
259e862375SLee Jones /* SSC registers */
269e862375SLee Jones #define SSC_BRG 0x000
279e862375SLee Jones #define SSC_TBUF 0x004
289e862375SLee Jones #define SSC_RBUF 0x008
299e862375SLee Jones #define SSC_CTL 0x00C
309e862375SLee Jones #define SSC_IEN 0x010
319e862375SLee Jones #define SSC_I2C 0x018
329e862375SLee Jones
339e862375SLee Jones /* SSC Control */
349e862375SLee Jones #define SSC_CTL_DATA_WIDTH_9 0x8
359e862375SLee Jones #define SSC_CTL_DATA_WIDTH_MSK 0xf
369e862375SLee Jones #define SSC_CTL_BM 0xf
379e862375SLee Jones #define SSC_CTL_HB BIT(4)
389e862375SLee Jones #define SSC_CTL_PH BIT(5)
399e862375SLee Jones #define SSC_CTL_PO BIT(6)
409e862375SLee Jones #define SSC_CTL_SR BIT(7)
419e862375SLee Jones #define SSC_CTL_MS BIT(8)
429e862375SLee Jones #define SSC_CTL_EN BIT(9)
439e862375SLee Jones #define SSC_CTL_LPB BIT(10)
449e862375SLee Jones #define SSC_CTL_EN_TX_FIFO BIT(11)
459e862375SLee Jones #define SSC_CTL_EN_RX_FIFO BIT(12)
469e862375SLee Jones #define SSC_CTL_EN_CLST_RX BIT(13)
479e862375SLee Jones
489e862375SLee Jones /* SSC Interrupt Enable */
499e862375SLee Jones #define SSC_IEN_TEEN BIT(2)
509e862375SLee Jones
519e862375SLee Jones #define FIFO_SIZE 8
529e862375SLee Jones
539e862375SLee Jones struct spi_st {
549e862375SLee Jones /* SSC SPI Controller */
559e862375SLee Jones void __iomem *base;
569e862375SLee Jones struct clk *clk;
579e862375SLee Jones struct device *dev;
589e862375SLee Jones
599e862375SLee Jones /* SSC SPI current transaction */
609e862375SLee Jones const u8 *tx_ptr;
619e862375SLee Jones u8 *rx_ptr;
629e862375SLee Jones u16 bytes_per_word;
639e862375SLee Jones unsigned int words_remaining;
649e862375SLee Jones unsigned int baud;
659e862375SLee Jones struct completion done;
669e862375SLee Jones };
679e862375SLee Jones
689e862375SLee Jones /* Load the TX FIFO */
ssc_write_tx_fifo(struct spi_st * spi_st)699e862375SLee Jones static void ssc_write_tx_fifo(struct spi_st *spi_st)
709e862375SLee Jones {
719e862375SLee Jones unsigned int count, i;
729e862375SLee Jones uint32_t word = 0;
739e862375SLee Jones
749e862375SLee Jones if (spi_st->words_remaining > FIFO_SIZE)
759e862375SLee Jones count = FIFO_SIZE;
769e862375SLee Jones else
779e862375SLee Jones count = spi_st->words_remaining;
789e862375SLee Jones
799e862375SLee Jones for (i = 0; i < count; i++) {
809e862375SLee Jones if (spi_st->tx_ptr) {
819e862375SLee Jones if (spi_st->bytes_per_word == 1) {
829e862375SLee Jones word = *spi_st->tx_ptr++;
839e862375SLee Jones } else {
849e862375SLee Jones word = *spi_st->tx_ptr++;
859e862375SLee Jones word = *spi_st->tx_ptr++ | (word << 8);
869e862375SLee Jones }
879e862375SLee Jones }
889e862375SLee Jones writel_relaxed(word, spi_st->base + SSC_TBUF);
899e862375SLee Jones }
909e862375SLee Jones }
919e862375SLee Jones
929e862375SLee Jones /* Read the RX FIFO */
ssc_read_rx_fifo(struct spi_st * spi_st)939e862375SLee Jones static void ssc_read_rx_fifo(struct spi_st *spi_st)
949e862375SLee Jones {
959e862375SLee Jones unsigned int count, i;
969e862375SLee Jones uint32_t word = 0;
979e862375SLee Jones
989e862375SLee Jones if (spi_st->words_remaining > FIFO_SIZE)
999e862375SLee Jones count = FIFO_SIZE;
1009e862375SLee Jones else
1019e862375SLee Jones count = spi_st->words_remaining;
1029e862375SLee Jones
1039e862375SLee Jones for (i = 0; i < count; i++) {
1049e862375SLee Jones word = readl_relaxed(spi_st->base + SSC_RBUF);
1059e862375SLee Jones
1069e862375SLee Jones if (spi_st->rx_ptr) {
1079e862375SLee Jones if (spi_st->bytes_per_word == 1) {
1089e862375SLee Jones *spi_st->rx_ptr++ = (uint8_t)word;
1099e862375SLee Jones } else {
1109e862375SLee Jones *spi_st->rx_ptr++ = (word >> 8);
1119e862375SLee Jones *spi_st->rx_ptr++ = word & 0xff;
1129e862375SLee Jones }
1139e862375SLee Jones }
1149e862375SLee Jones }
1159e862375SLee Jones spi_st->words_remaining -= count;
1169e862375SLee Jones }
1179e862375SLee Jones
spi_st_transfer_one(struct spi_controller * host,struct spi_device * spi,struct spi_transfer * t)118*e6b7e64cSYang Yingliang static int spi_st_transfer_one(struct spi_controller *host,
1199e862375SLee Jones struct spi_device *spi, struct spi_transfer *t)
1209e862375SLee Jones {
121*e6b7e64cSYang Yingliang struct spi_st *spi_st = spi_controller_get_devdata(host);
1229e862375SLee Jones uint32_t ctl = 0;
1239e862375SLee Jones
1249e862375SLee Jones /* Setup transfer */
1259e862375SLee Jones spi_st->tx_ptr = t->tx_buf;
1269e862375SLee Jones spi_st->rx_ptr = t->rx_buf;
1279e862375SLee Jones
1289e862375SLee Jones if (spi->bits_per_word > 8) {
1299e862375SLee Jones /*
1309e862375SLee Jones * Anything greater than 8 bits-per-word requires 2
1319e862375SLee Jones * bytes-per-word in the RX/TX buffers
1329e862375SLee Jones */
1339e862375SLee Jones spi_st->bytes_per_word = 2;
1349e862375SLee Jones spi_st->words_remaining = t->len / 2;
1359e862375SLee Jones
1369e862375SLee Jones } else if (spi->bits_per_word == 8 && !(t->len & 0x1)) {
1379e862375SLee Jones /*
1389e862375SLee Jones * If transfer is even-length, and 8 bits-per-word, then
1399e862375SLee Jones * implement as half-length 16 bits-per-word transfer
1409e862375SLee Jones */
1419e862375SLee Jones spi_st->bytes_per_word = 2;
1429e862375SLee Jones spi_st->words_remaining = t->len / 2;
1439e862375SLee Jones
1449e862375SLee Jones /* Set SSC_CTL to 16 bits-per-word */
1459e862375SLee Jones ctl = readl_relaxed(spi_st->base + SSC_CTL);
1469e862375SLee Jones writel_relaxed((ctl | 0xf), spi_st->base + SSC_CTL);
1479e862375SLee Jones
1489e862375SLee Jones readl_relaxed(spi_st->base + SSC_RBUF);
1499e862375SLee Jones
1509e862375SLee Jones } else {
1519e862375SLee Jones spi_st->bytes_per_word = 1;
1529e862375SLee Jones spi_st->words_remaining = t->len;
1539e862375SLee Jones }
1549e862375SLee Jones
1559e862375SLee Jones reinit_completion(&spi_st->done);
1569e862375SLee Jones
1579e862375SLee Jones /* Start transfer by writing to the TX FIFO */
1589e862375SLee Jones ssc_write_tx_fifo(spi_st);
1599e862375SLee Jones writel_relaxed(SSC_IEN_TEEN, spi_st->base + SSC_IEN);
1609e862375SLee Jones
1619e862375SLee Jones /* Wait for transfer to complete */
1629e862375SLee Jones wait_for_completion(&spi_st->done);
1639e862375SLee Jones
1649e862375SLee Jones /* Restore SSC_CTL if necessary */
1659e862375SLee Jones if (ctl)
1669e862375SLee Jones writel_relaxed(ctl, spi_st->base + SSC_CTL);
1679e862375SLee Jones
168*e6b7e64cSYang Yingliang spi_finalize_current_transfer(spi->controller);
1699e862375SLee Jones
1709e862375SLee Jones return t->len;
1719e862375SLee Jones }
1729e862375SLee Jones
1739e862375SLee Jones /* the spi->mode bits understood by this driver: */
1749e862375SLee Jones #define MODEBITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH)
spi_st_setup(struct spi_device * spi)1759e862375SLee Jones static int spi_st_setup(struct spi_device *spi)
1769e862375SLee Jones {
177*e6b7e64cSYang Yingliang struct spi_st *spi_st = spi_controller_get_devdata(spi->controller);
1789e862375SLee Jones u32 spi_st_clk, sscbrg, var;
1799e862375SLee Jones u32 hz = spi->max_speed_hz;
1809e862375SLee Jones
1819e862375SLee Jones if (!hz) {
1829e862375SLee Jones dev_err(&spi->dev, "max_speed_hz unspecified\n");
1839e862375SLee Jones return -EINVAL;
1849e862375SLee Jones }
1859e862375SLee Jones
1869e264f3fSAmit Kumar Mahapatra via Alsa-devel if (!spi_get_csgpiod(spi, 0)) {
18732159969SLinus Walleij dev_err(&spi->dev, "no valid gpio assigned\n");
1889e862375SLee Jones return -EINVAL;
1899e862375SLee Jones }
1909e862375SLee Jones
1919e862375SLee Jones spi_st_clk = clk_get_rate(spi_st->clk);
1929e862375SLee Jones
1939e862375SLee Jones /* Set SSC_BRF */
1949e862375SLee Jones sscbrg = spi_st_clk / (2 * hz);
1959e862375SLee Jones if (sscbrg < 0x07 || sscbrg > BIT(16)) {
1969e862375SLee Jones dev_err(&spi->dev,
1979e862375SLee Jones "baudrate %d outside valid range %d\n", sscbrg, hz);
19832159969SLinus Walleij return -EINVAL;
1999e862375SLee Jones }
2009e862375SLee Jones
2019e862375SLee Jones spi_st->baud = spi_st_clk / (2 * sscbrg);
2029e862375SLee Jones if (sscbrg == BIT(16)) /* 16-bit counter wraps */
2039e862375SLee Jones sscbrg = 0x0;
2049e862375SLee Jones
2059e862375SLee Jones writel_relaxed(sscbrg, spi_st->base + SSC_BRG);
2069e862375SLee Jones
2079e862375SLee Jones dev_dbg(&spi->dev,
2089e862375SLee Jones "setting baudrate:target= %u hz, actual= %u hz, sscbrg= %u\n",
2099e862375SLee Jones hz, spi_st->baud, sscbrg);
2109e862375SLee Jones
2119e862375SLee Jones /* Set SSC_CTL and enable SSC */
2129e862375SLee Jones var = readl_relaxed(spi_st->base + SSC_CTL);
2139e862375SLee Jones var |= SSC_CTL_MS;
2149e862375SLee Jones
2159e862375SLee Jones if (spi->mode & SPI_CPOL)
2169e862375SLee Jones var |= SSC_CTL_PO;
2179e862375SLee Jones else
2189e862375SLee Jones var &= ~SSC_CTL_PO;
2199e862375SLee Jones
2209e862375SLee Jones if (spi->mode & SPI_CPHA)
2219e862375SLee Jones var |= SSC_CTL_PH;
2229e862375SLee Jones else
2239e862375SLee Jones var &= ~SSC_CTL_PH;
2249e862375SLee Jones
2259e862375SLee Jones if ((spi->mode & SPI_LSB_FIRST) == 0)
2269e862375SLee Jones var |= SSC_CTL_HB;
2279e862375SLee Jones else
2289e862375SLee Jones var &= ~SSC_CTL_HB;
2299e862375SLee Jones
2309e862375SLee Jones if (spi->mode & SPI_LOOP)
2319e862375SLee Jones var |= SSC_CTL_LPB;
2329e862375SLee Jones else
2339e862375SLee Jones var &= ~SSC_CTL_LPB;
2349e862375SLee Jones
2359e862375SLee Jones var &= ~SSC_CTL_DATA_WIDTH_MSK;
2369e862375SLee Jones var |= (spi->bits_per_word - 1);
2379e862375SLee Jones
2389e862375SLee Jones var |= SSC_CTL_EN_TX_FIFO | SSC_CTL_EN_RX_FIFO;
2399e862375SLee Jones var |= SSC_CTL_EN;
2409e862375SLee Jones
2419e862375SLee Jones writel_relaxed(var, spi_st->base + SSC_CTL);
2429e862375SLee Jones
2439e862375SLee Jones /* Clear the status register */
2449e862375SLee Jones readl_relaxed(spi_st->base + SSC_RBUF);
2459e862375SLee Jones
2469e862375SLee Jones return 0;
2479e862375SLee Jones }
2489e862375SLee Jones
2499e862375SLee Jones /* Interrupt fired when TX shift register becomes empty */
spi_st_irq(int irq,void * dev_id)2509e862375SLee Jones static irqreturn_t spi_st_irq(int irq, void *dev_id)
2519e862375SLee Jones {
2529e862375SLee Jones struct spi_st *spi_st = (struct spi_st *)dev_id;
2539e862375SLee Jones
2549e862375SLee Jones /* Read RX FIFO */
2559e862375SLee Jones ssc_read_rx_fifo(spi_st);
2569e862375SLee Jones
2579e862375SLee Jones /* Fill TX FIFO */
2589e862375SLee Jones if (spi_st->words_remaining) {
2599e862375SLee Jones ssc_write_tx_fifo(spi_st);
2609e862375SLee Jones } else {
2619e862375SLee Jones /* TX/RX complete */
2629e862375SLee Jones writel_relaxed(0x0, spi_st->base + SSC_IEN);
2639e862375SLee Jones /*
2649e862375SLee Jones * read SSC_IEN to ensure that this bit is set
2659e862375SLee Jones * before re-enabling interrupt
2669e862375SLee Jones */
2679e862375SLee Jones readl(spi_st->base + SSC_IEN);
2689e862375SLee Jones complete(&spi_st->done);
2699e862375SLee Jones }
2709e862375SLee Jones
2719e862375SLee Jones return IRQ_HANDLED;
2729e862375SLee Jones }
2739e862375SLee Jones
spi_st_probe(struct platform_device * pdev)2749e862375SLee Jones static int spi_st_probe(struct platform_device *pdev)
2759e862375SLee Jones {
2769e862375SLee Jones struct device_node *np = pdev->dev.of_node;
277*e6b7e64cSYang Yingliang struct spi_controller *host;
2789e862375SLee Jones struct spi_st *spi_st;
2799e862375SLee Jones int irq, ret = 0;
2809e862375SLee Jones u32 var;
2819e862375SLee Jones
282*e6b7e64cSYang Yingliang host = spi_alloc_host(&pdev->dev, sizeof(*spi_st));
283*e6b7e64cSYang Yingliang if (!host)
2849e862375SLee Jones return -ENOMEM;
2859e862375SLee Jones
286*e6b7e64cSYang Yingliang host->dev.of_node = np;
287*e6b7e64cSYang Yingliang host->mode_bits = MODEBITS;
288*e6b7e64cSYang Yingliang host->setup = spi_st_setup;
289*e6b7e64cSYang Yingliang host->transfer_one = spi_st_transfer_one;
290*e6b7e64cSYang Yingliang host->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
291*e6b7e64cSYang Yingliang host->auto_runtime_pm = true;
292*e6b7e64cSYang Yingliang host->bus_num = pdev->id;
293*e6b7e64cSYang Yingliang host->use_gpio_descriptors = true;
294*e6b7e64cSYang Yingliang spi_st = spi_controller_get_devdata(host);
2959e862375SLee Jones
2969e862375SLee Jones spi_st->clk = devm_clk_get(&pdev->dev, "ssc");
2979e862375SLee Jones if (IS_ERR(spi_st->clk)) {
2989e862375SLee Jones dev_err(&pdev->dev, "Unable to request clock\n");
2991051550eSAxel Lin ret = PTR_ERR(spi_st->clk);
300*e6b7e64cSYang Yingliang goto put_host;
3019e862375SLee Jones }
3029e862375SLee Jones
303cf4b5cebSLee Jones ret = clk_prepare_enable(spi_st->clk);
3049e862375SLee Jones if (ret)
305*e6b7e64cSYang Yingliang goto put_host;
3069e862375SLee Jones
3079e862375SLee Jones init_completion(&spi_st->done);
3089e862375SLee Jones
3099e862375SLee Jones /* Get resources */
310338dd352SYueHaibing spi_st->base = devm_platform_ioremap_resource(pdev, 0);
3119e862375SLee Jones if (IS_ERR(spi_st->base)) {
3129e862375SLee Jones ret = PTR_ERR(spi_st->base);
3139e862375SLee Jones goto clk_disable;
3149e862375SLee Jones }
3159e862375SLee Jones
3169e862375SLee Jones /* Disable I2C and Reset SSC */
3179e862375SLee Jones writel_relaxed(0x0, spi_st->base + SSC_I2C);
3189e862375SLee Jones var = readw_relaxed(spi_st->base + SSC_CTL);
3199e862375SLee Jones var |= SSC_CTL_SR;
3209e862375SLee Jones writel_relaxed(var, spi_st->base + SSC_CTL);
3219e862375SLee Jones
3229e862375SLee Jones udelay(1);
3239e862375SLee Jones var = readl_relaxed(spi_st->base + SSC_CTL);
3249e862375SLee Jones var &= ~SSC_CTL_SR;
3259e862375SLee Jones writel_relaxed(var, spi_st->base + SSC_CTL);
3269e862375SLee Jones
327*e6b7e64cSYang Yingliang /* Set SSC into target mode before reconfiguring PIO pins */
3289e862375SLee Jones var = readl_relaxed(spi_st->base + SSC_CTL);
3299e862375SLee Jones var &= ~SSC_CTL_MS;
3309e862375SLee Jones writel_relaxed(var, spi_st->base + SSC_CTL);
3319e862375SLee Jones
3329e862375SLee Jones irq = irq_of_parse_and_map(np, 0);
3339e862375SLee Jones if (!irq) {
3349e862375SLee Jones dev_err(&pdev->dev, "IRQ missing or invalid\n");
3359e862375SLee Jones ret = -EINVAL;
3369e862375SLee Jones goto clk_disable;
3379e862375SLee Jones }
3389e862375SLee Jones
3399e862375SLee Jones ret = devm_request_irq(&pdev->dev, irq, spi_st_irq, 0,
3409e862375SLee Jones pdev->name, spi_st);
3419e862375SLee Jones if (ret) {
3429e862375SLee Jones dev_err(&pdev->dev, "Failed to request irq %d\n", irq);
3439e862375SLee Jones goto clk_disable;
3449e862375SLee Jones }
3459e862375SLee Jones
3469e862375SLee Jones /* by default the device is on */
3479e862375SLee Jones pm_runtime_set_active(&pdev->dev);
3489e862375SLee Jones pm_runtime_enable(&pdev->dev);
3499e862375SLee Jones
350*e6b7e64cSYang Yingliang platform_set_drvdata(pdev, host);
3519e862375SLee Jones
352*e6b7e64cSYang Yingliang ret = devm_spi_register_controller(&pdev->dev, host);
3539e862375SLee Jones if (ret) {
354*e6b7e64cSYang Yingliang dev_err(&pdev->dev, "Failed to register host\n");
3555ef76dacSLukas Wunner goto rpm_disable;
3569e862375SLee Jones }
3579e862375SLee Jones
3589e862375SLee Jones return 0;
3599e862375SLee Jones
3605ef76dacSLukas Wunner rpm_disable:
361cd050abeSChuhong Yuan pm_runtime_disable(&pdev->dev);
3625ef76dacSLukas Wunner clk_disable:
363cf4b5cebSLee Jones clk_disable_unprepare(spi_st->clk);
364*e6b7e64cSYang Yingliang put_host:
365*e6b7e64cSYang Yingliang spi_controller_put(host);
3669e862375SLee Jones return ret;
3679e862375SLee Jones }
3689e862375SLee Jones
spi_st_remove(struct platform_device * pdev)3692dd42da0SUwe Kleine-König static void spi_st_remove(struct platform_device *pdev)
3709e862375SLee Jones {
371*e6b7e64cSYang Yingliang struct spi_controller *host = platform_get_drvdata(pdev);
372*e6b7e64cSYang Yingliang struct spi_st *spi_st = spi_controller_get_devdata(host);
3739e862375SLee Jones
374cd050abeSChuhong Yuan pm_runtime_disable(&pdev->dev);
375cd050abeSChuhong Yuan
376cf4b5cebSLee Jones clk_disable_unprepare(spi_st->clk);
3779e862375SLee Jones
3789e862375SLee Jones pinctrl_pm_select_sleep_state(&pdev->dev);
3799e862375SLee Jones }
3809e862375SLee Jones
3819e862375SLee Jones #ifdef CONFIG_PM
spi_st_runtime_suspend(struct device * dev)3829e862375SLee Jones static int spi_st_runtime_suspend(struct device *dev)
3839e862375SLee Jones {
384*e6b7e64cSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
385*e6b7e64cSYang Yingliang struct spi_st *spi_st = spi_controller_get_devdata(host);
3869e862375SLee Jones
3879e862375SLee Jones writel_relaxed(0, spi_st->base + SSC_IEN);
3889e862375SLee Jones pinctrl_pm_select_sleep_state(dev);
3899e862375SLee Jones
390cf4b5cebSLee Jones clk_disable_unprepare(spi_st->clk);
3919e862375SLee Jones
3929e862375SLee Jones return 0;
3939e862375SLee Jones }
3949e862375SLee Jones
spi_st_runtime_resume(struct device * dev)3959e862375SLee Jones static int spi_st_runtime_resume(struct device *dev)
3969e862375SLee Jones {
397*e6b7e64cSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
398*e6b7e64cSYang Yingliang struct spi_st *spi_st = spi_controller_get_devdata(host);
3999e862375SLee Jones int ret;
4009e862375SLee Jones
401cf4b5cebSLee Jones ret = clk_prepare_enable(spi_st->clk);
4029e862375SLee Jones pinctrl_pm_select_default_state(dev);
4039e862375SLee Jones
4049e862375SLee Jones return ret;
4059e862375SLee Jones }
4069e862375SLee Jones #endif
4079e862375SLee Jones
4089e862375SLee Jones #ifdef CONFIG_PM_SLEEP
spi_st_suspend(struct device * dev)4099e862375SLee Jones static int spi_st_suspend(struct device *dev)
4109e862375SLee Jones {
411*e6b7e64cSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
4129e862375SLee Jones int ret;
4139e862375SLee Jones
414*e6b7e64cSYang Yingliang ret = spi_controller_suspend(host);
4159e862375SLee Jones if (ret)
4169e862375SLee Jones return ret;
4179e862375SLee Jones
4189e862375SLee Jones return pm_runtime_force_suspend(dev);
4199e862375SLee Jones }
4209e862375SLee Jones
spi_st_resume(struct device * dev)4219e862375SLee Jones static int spi_st_resume(struct device *dev)
4229e862375SLee Jones {
423*e6b7e64cSYang Yingliang struct spi_controller *host = dev_get_drvdata(dev);
4249e862375SLee Jones int ret;
4259e862375SLee Jones
426*e6b7e64cSYang Yingliang ret = spi_controller_resume(host);
4279e862375SLee Jones if (ret)
4289e862375SLee Jones return ret;
4299e862375SLee Jones
4309e862375SLee Jones return pm_runtime_force_resume(dev);
4319e862375SLee Jones }
4329e862375SLee Jones #endif
4339e862375SLee Jones
4349e862375SLee Jones static const struct dev_pm_ops spi_st_pm = {
4359e862375SLee Jones SET_SYSTEM_SLEEP_PM_OPS(spi_st_suspend, spi_st_resume)
4369e862375SLee Jones SET_RUNTIME_PM_OPS(spi_st_runtime_suspend, spi_st_runtime_resume, NULL)
4379e862375SLee Jones };
4389e862375SLee Jones
43909355402SFabian Frederick static const struct of_device_id stm_spi_match[] = {
4409e862375SLee Jones { .compatible = "st,comms-ssc4-spi", },
4419e862375SLee Jones {},
4429e862375SLee Jones };
4439e862375SLee Jones MODULE_DEVICE_TABLE(of, stm_spi_match);
4449e862375SLee Jones
4459e862375SLee Jones static struct platform_driver spi_st_driver = {
4469e862375SLee Jones .driver = {
4479e862375SLee Jones .name = "spi-st",
4489e862375SLee Jones .pm = &spi_st_pm,
4499e862375SLee Jones .of_match_table = of_match_ptr(stm_spi_match),
4509e862375SLee Jones },
4519e862375SLee Jones .probe = spi_st_probe,
4522dd42da0SUwe Kleine-König .remove_new = spi_st_remove,
4539e862375SLee Jones };
4549e862375SLee Jones module_platform_driver(spi_st_driver);
4559e862375SLee Jones
4569e862375SLee Jones MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>");
4579e862375SLee Jones MODULE_DESCRIPTION("STM SSC SPI driver");
4589e862375SLee Jones MODULE_LICENSE("GPL v2");
459