blob: 3912526ead6641067e189a825c9df8ebf8faabfc [file] [log] [blame]
addy ke64e36822014-07-01 09:03:59 +08001/*
2 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
Addy Ke5dcc44e2014-07-11 10:07:56 +08003 * Author: Addy Ke <addy.ke@rock-chips.com>
addy ke64e36822014-07-01 09:03:59 +08004 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
addy ke64e36822014-07-01 09:03:59 +080016#include <linux/clk.h>
addy ke64e36822014-07-01 09:03:59 +080017#include <linux/dmaengine.h>
Shawn Linec5c5d82016-03-10 14:51:48 +080018#include <linux/module.h>
19#include <linux/of.h>
Brian Norris23e291c2016-12-16 16:59:16 -080020#include <linux/pinctrl/consumer.h>
Shawn Linec5c5d82016-03-10 14:51:48 +080021#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <linux/pm_runtime.h>
24#include <linux/scatterlist.h>
addy ke64e36822014-07-01 09:03:59 +080025
26#define DRIVER_NAME "rockchip-spi"
27
Jeffy Chenaa099382017-06-28 12:38:43 +080028#define ROCKCHIP_SPI_CLR_BITS(reg, bits) \
29 writel_relaxed(readl_relaxed(reg) & ~(bits), reg)
30#define ROCKCHIP_SPI_SET_BITS(reg, bits) \
31 writel_relaxed(readl_relaxed(reg) | (bits), reg)
32
addy ke64e36822014-07-01 09:03:59 +080033/* SPI register offsets */
34#define ROCKCHIP_SPI_CTRLR0 0x0000
35#define ROCKCHIP_SPI_CTRLR1 0x0004
36#define ROCKCHIP_SPI_SSIENR 0x0008
37#define ROCKCHIP_SPI_SER 0x000c
38#define ROCKCHIP_SPI_BAUDR 0x0010
39#define ROCKCHIP_SPI_TXFTLR 0x0014
40#define ROCKCHIP_SPI_RXFTLR 0x0018
41#define ROCKCHIP_SPI_TXFLR 0x001c
42#define ROCKCHIP_SPI_RXFLR 0x0020
43#define ROCKCHIP_SPI_SR 0x0024
44#define ROCKCHIP_SPI_IPR 0x0028
45#define ROCKCHIP_SPI_IMR 0x002c
46#define ROCKCHIP_SPI_ISR 0x0030
47#define ROCKCHIP_SPI_RISR 0x0034
48#define ROCKCHIP_SPI_ICR 0x0038
49#define ROCKCHIP_SPI_DMACR 0x003c
50#define ROCKCHIP_SPI_DMATDLR 0x0040
51#define ROCKCHIP_SPI_DMARDLR 0x0044
52#define ROCKCHIP_SPI_TXDR 0x0400
53#define ROCKCHIP_SPI_RXDR 0x0800
54
55/* Bit fields in CTRLR0 */
56#define CR0_DFS_OFFSET 0
Emil Renner Berthing65498c62018-10-31 11:57:10 +010057#define CR0_DFS_4BIT 0x0
58#define CR0_DFS_8BIT 0x1
59#define CR0_DFS_16BIT 0x2
addy ke64e36822014-07-01 09:03:59 +080060
61#define CR0_CFS_OFFSET 2
62
63#define CR0_SCPH_OFFSET 6
64
65#define CR0_SCPOL_OFFSET 7
66
67#define CR0_CSM_OFFSET 8
68#define CR0_CSM_KEEP 0x0
69/* ss_n be high for half sclk_out cycles */
70#define CR0_CSM_HALF 0X1
71/* ss_n be high for one sclk_out cycle */
72#define CR0_CSM_ONE 0x2
73
74/* ss_n to sclk_out delay */
75#define CR0_SSD_OFFSET 10
76/*
77 * The period between ss_n active and
78 * sclk_out active is half sclk_out cycles
79 */
80#define CR0_SSD_HALF 0x0
81/*
82 * The period between ss_n active and
83 * sclk_out active is one sclk_out cycle
84 */
85#define CR0_SSD_ONE 0x1
86
87#define CR0_EM_OFFSET 11
88#define CR0_EM_LITTLE 0x0
89#define CR0_EM_BIG 0x1
90
91#define CR0_FBM_OFFSET 12
92#define CR0_FBM_MSB 0x0
93#define CR0_FBM_LSB 0x1
94
95#define CR0_BHT_OFFSET 13
96#define CR0_BHT_16BIT 0x0
97#define CR0_BHT_8BIT 0x1
98
99#define CR0_RSD_OFFSET 14
Emil Renner Berthing74b7efa2018-10-31 11:57:08 +0100100#define CR0_RSD_MAX 0x3
addy ke64e36822014-07-01 09:03:59 +0800101
102#define CR0_FRF_OFFSET 16
103#define CR0_FRF_SPI 0x0
104#define CR0_FRF_SSP 0x1
105#define CR0_FRF_MICROWIRE 0x2
106
107#define CR0_XFM_OFFSET 18
108#define CR0_XFM_MASK (0x03 << SPI_XFM_OFFSET)
109#define CR0_XFM_TR 0x0
110#define CR0_XFM_TO 0x1
111#define CR0_XFM_RO 0x2
112
113#define CR0_OPM_OFFSET 20
114#define CR0_OPM_MASTER 0x0
115#define CR0_OPM_SLAVE 0x1
116
117#define CR0_MTM_OFFSET 0x21
118
119/* Bit fields in SER, 2bit */
120#define SER_MASK 0x3
121
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100122/* Bit fields in BAUDR */
123#define BAUDR_SCKDV_MIN 2
124#define BAUDR_SCKDV_MAX 65534
125
addy ke64e36822014-07-01 09:03:59 +0800126/* Bit fields in SR, 5bit */
127#define SR_MASK 0x1f
128#define SR_BUSY (1 << 0)
129#define SR_TF_FULL (1 << 1)
130#define SR_TF_EMPTY (1 << 2)
131#define SR_RF_EMPTY (1 << 3)
132#define SR_RF_FULL (1 << 4)
133
134/* Bit fields in ISR, IMR, ISR, RISR, 5bit */
135#define INT_MASK 0x1f
136#define INT_TF_EMPTY (1 << 0)
137#define INT_TF_OVERFLOW (1 << 1)
138#define INT_RF_UNDERFLOW (1 << 2)
139#define INT_RF_OVERFLOW (1 << 3)
140#define INT_RF_FULL (1 << 4)
141
142/* Bit fields in ICR, 4bit */
143#define ICR_MASK 0x0f
144#define ICR_ALL (1 << 0)
145#define ICR_RF_UNDERFLOW (1 << 1)
146#define ICR_RF_OVERFLOW (1 << 2)
147#define ICR_TF_OVERFLOW (1 << 3)
148
149/* Bit fields in DMACR */
150#define RF_DMA_EN (1 << 0)
151#define TF_DMA_EN (1 << 1)
152
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100153/* Driver state flags */
154#define RXDMA (1 << 0)
155#define TXDMA (1 << 1)
addy ke64e36822014-07-01 09:03:59 +0800156
Addy Kef9cfd522014-10-15 19:25:49 +0800157/* sclk_out: spi master internal logic in rk3x can support 50Mhz */
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100158#define MAX_SCLK_OUT 50000000U
Addy Kef9cfd522014-10-15 19:25:49 +0800159
Brian Norris5185a812016-07-14 18:30:59 -0700160/*
161 * SPI_CTRLR1 is 16-bits, so we should support lengths of 0xffff + 1. However,
162 * the controller seems to hang when given 0x10000, so stick with this for now.
163 */
164#define ROCKCHIP_SPI_MAX_TRANLEN 0xffff
165
Jeffy Chenaa099382017-06-28 12:38:43 +0800166#define ROCKCHIP_SPI_MAX_CS_NUM 2
167
addy ke64e36822014-07-01 09:03:59 +0800168struct rockchip_spi {
169 struct device *dev;
addy ke64e36822014-07-01 09:03:59 +0800170
171 struct clk *spiclk;
172 struct clk *apb_pclk;
173
174 void __iomem *regs;
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100175 dma_addr_t dma_addr_rx;
176 dma_addr_t dma_addr_tx;
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100177
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100178 const void *tx;
179 void *rx;
180 unsigned int tx_left;
181 unsigned int rx_left;
182
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100183 atomic_t state;
184
addy ke64e36822014-07-01 09:03:59 +0800185 /*depth of the FIFO buffer */
186 u32 fifo_len;
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100187 /* frequency of spiclk */
188 u32 freq;
addy ke64e36822014-07-01 09:03:59 +0800189
addy ke64e36822014-07-01 09:03:59 +0800190 u8 n_bytes;
Emil Renner Berthing74b7efa2018-10-31 11:57:08 +0100191 u8 rsd;
addy ke64e36822014-07-01 09:03:59 +0800192
Jeffy Chenaa099382017-06-28 12:38:43 +0800193 bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
addy ke64e36822014-07-01 09:03:59 +0800194};
195
Emil Renner Berthing30688e42018-10-31 11:56:58 +0100196static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
addy ke64e36822014-07-01 09:03:59 +0800197{
Emil Renner Berthing30688e42018-10-31 11:56:58 +0100198 writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR);
addy ke64e36822014-07-01 09:03:59 +0800199}
200
Addy Ke2df08e72014-07-11 10:08:24 +0800201static inline void wait_for_idle(struct rockchip_spi *rs)
202{
203 unsigned long timeout = jiffies + msecs_to_jiffies(5);
204
205 do {
206 if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))
207 return;
Doug Anderson64bc0112014-09-03 13:44:25 -0700208 } while (!time_after(jiffies, timeout));
Addy Ke2df08e72014-07-11 10:08:24 +0800209
210 dev_warn(rs->dev, "spi controller is in busy state!\n");
211}
212
addy ke64e36822014-07-01 09:03:59 +0800213static u32 get_fifo_len(struct rockchip_spi *rs)
214{
215 u32 fifo;
216
217 for (fifo = 2; fifo < 32; fifo++) {
218 writel_relaxed(fifo, rs->regs + ROCKCHIP_SPI_TXFTLR);
219 if (fifo != readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFTLR))
220 break;
221 }
222
223 writel_relaxed(0, rs->regs + ROCKCHIP_SPI_TXFTLR);
224
225 return (fifo == 31) ? 0 : fifo;
226}
227
addy ke64e36822014-07-01 09:03:59 +0800228static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
229{
Huibin Hongb920cc32016-02-24 18:00:04 +0800230 struct spi_master *master = spi->master;
231 struct rockchip_spi *rs = spi_master_get_devdata(master);
Jeffy Chenaa099382017-06-28 12:38:43 +0800232 bool cs_asserted = !enable;
Huibin Hongb920cc32016-02-24 18:00:04 +0800233
Jeffy Chenaa099382017-06-28 12:38:43 +0800234 /* Return immediately for no-op */
235 if (cs_asserted == rs->cs_asserted[spi->chip_select])
236 return;
addy ke64e36822014-07-01 09:03:59 +0800237
Jeffy Chenaa099382017-06-28 12:38:43 +0800238 if (cs_asserted) {
239 /* Keep things powered as long as CS is asserted */
240 pm_runtime_get_sync(rs->dev);
addy ke64e36822014-07-01 09:03:59 +0800241
Jeffy Chenaa099382017-06-28 12:38:43 +0800242 ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER,
243 BIT(spi->chip_select));
244 } else {
245 ROCKCHIP_SPI_CLR_BITS(rs->regs + ROCKCHIP_SPI_SER,
246 BIT(spi->chip_select));
addy ke64e36822014-07-01 09:03:59 +0800247
Jeffy Chenaa099382017-06-28 12:38:43 +0800248 /* Drop reference from when we first asserted CS */
249 pm_runtime_put(rs->dev);
250 }
Huibin Hongb920cc32016-02-24 18:00:04 +0800251
Jeffy Chenaa099382017-06-28 12:38:43 +0800252 rs->cs_asserted[spi->chip_select] = cs_asserted;
addy ke64e36822014-07-01 09:03:59 +0800253}
254
Andy Shevchenko22917932015-02-27 17:34:16 +0200255static void rockchip_spi_handle_err(struct spi_master *master,
256 struct spi_message *msg)
addy ke64e36822014-07-01 09:03:59 +0800257{
addy ke64e36822014-07-01 09:03:59 +0800258 struct rockchip_spi *rs = spi_master_get_devdata(master);
259
Emil Renner Berthingce386102018-10-31 11:57:02 +0100260 /* stop running spi transfer
261 * this also flushes both rx and tx fifos
Addy Ke5dcc44e2014-07-11 10:07:56 +0800262 */
Emil Renner Berthingce386102018-10-31 11:57:02 +0100263 spi_enable_chip(rs, false);
264
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100265 /* make sure all interrupts are masked */
266 writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
267
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100268 if (atomic_read(&rs->state) & TXDMA)
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100269 dmaengine_terminate_async(master->dma_tx);
addy ke64e36822014-07-01 09:03:59 +0800270
Emil Renner Berthingce386102018-10-31 11:57:02 +0100271 if (atomic_read(&rs->state) & RXDMA)
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100272 dmaengine_terminate_async(master->dma_rx);
addy ke64e36822014-07-01 09:03:59 +0800273}
274
275static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
276{
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100277 u32 tx_free = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
278 u32 words = min(rs->tx_left, tx_free);
addy ke64e36822014-07-01 09:03:59 +0800279
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100280 rs->tx_left -= words;
281 for (; words; words--) {
282 u32 txw;
283
addy ke64e36822014-07-01 09:03:59 +0800284 if (rs->n_bytes == 1)
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100285 txw = *(u8 *)rs->tx;
addy ke64e36822014-07-01 09:03:59 +0800286 else
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100287 txw = *(u16 *)rs->tx;
addy ke64e36822014-07-01 09:03:59 +0800288
289 writel_relaxed(txw, rs->regs + ROCKCHIP_SPI_TXDR);
290 rs->tx += rs->n_bytes;
291 }
292}
293
294static void rockchip_spi_pio_reader(struct rockchip_spi *rs)
295{
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100296 u32 words = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
297 u32 rx_left = rs->rx_left - words;
addy ke64e36822014-07-01 09:03:59 +0800298
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100299 /* the hardware doesn't allow us to change fifo threshold
300 * level while spi is enabled, so instead make sure to leave
301 * enough words in the rx fifo to get the last interrupt
302 * exactly when all words have been received
303 */
304 if (rx_left) {
305 u32 ftl = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFTLR) + 1;
306
307 if (rx_left < ftl) {
308 rx_left = ftl;
309 words = rs->rx_left - rx_left;
310 }
311 }
312
313 rs->rx_left = rx_left;
314 for (; words; words--) {
315 u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
316
317 if (!rs->rx)
318 continue;
319
addy ke64e36822014-07-01 09:03:59 +0800320 if (rs->n_bytes == 1)
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100321 *(u8 *)rs->rx = (u8)rxw;
addy ke64e36822014-07-01 09:03:59 +0800322 else
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100323 *(u16 *)rs->rx = (u16)rxw;
addy ke64e36822014-07-01 09:03:59 +0800324 rs->rx += rs->n_bytes;
Addy Ke5dcc44e2014-07-11 10:07:56 +0800325 }
addy ke64e36822014-07-01 09:03:59 +0800326}
327
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100328static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)
addy ke64e36822014-07-01 09:03:59 +0800329{
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100330 struct spi_master *master = dev_id;
331 struct rockchip_spi *rs = spi_master_get_devdata(master);
addy ke64e36822014-07-01 09:03:59 +0800332
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100333 if (rs->tx_left)
334 rockchip_spi_pio_writer(rs);
335
336 rockchip_spi_pio_reader(rs);
337 if (!rs->rx_left) {
338 spi_enable_chip(rs, false);
339 writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
340 spi_finalize_current_transfer(master);
341 }
342
343 return IRQ_HANDLED;
344}
345
346static int rockchip_spi_prepare_irq(struct rockchip_spi *rs,
347 struct spi_transfer *xfer)
348{
349 rs->tx = xfer->tx_buf;
350 rs->rx = xfer->rx_buf;
351 rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;
352 rs->rx_left = xfer->len / rs->n_bytes;
353
354 writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);
Emil Renner Berthing30688e42018-10-31 11:56:58 +0100355 spi_enable_chip(rs, true);
Emil Renner Berthinga3c17402018-10-10 11:00:38 +0200356
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100357 if (rs->tx_left)
358 rockchip_spi_pio_writer(rs);
addy ke64e36822014-07-01 09:03:59 +0800359
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100360 /* 1 means the transfer is in progress */
361 return 1;
addy ke64e36822014-07-01 09:03:59 +0800362}
363
364static void rockchip_spi_dma_rxcb(void *data)
365{
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100366 struct spi_master *master = data;
367 struct rockchip_spi *rs = spi_master_get_devdata(master);
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100368 int state = atomic_fetch_andnot(RXDMA, &rs->state);
addy ke64e36822014-07-01 09:03:59 +0800369
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100370 if (state & TXDMA)
371 return;
addy ke64e36822014-07-01 09:03:59 +0800372
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100373 spi_enable_chip(rs, false);
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100374 spi_finalize_current_transfer(master);
addy ke64e36822014-07-01 09:03:59 +0800375}
376
377static void rockchip_spi_dma_txcb(void *data)
378{
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100379 struct spi_master *master = data;
380 struct rockchip_spi *rs = spi_master_get_devdata(master);
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100381 int state = atomic_fetch_andnot(TXDMA, &rs->state);
382
383 if (state & RXDMA)
384 return;
addy ke64e36822014-07-01 09:03:59 +0800385
Addy Ke2df08e72014-07-11 10:08:24 +0800386 /* Wait until the FIFO data completely. */
387 wait_for_idle(rs);
388
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100389 spi_enable_chip(rs, false);
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100390 spi_finalize_current_transfer(master);
addy ke64e36822014-07-01 09:03:59 +0800391}
392
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100393static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100394 struct spi_master *master, struct spi_transfer *xfer)
addy ke64e36822014-07-01 09:03:59 +0800395{
addy ke64e36822014-07-01 09:03:59 +0800396 struct dma_async_tx_descriptor *rxdesc, *txdesc;
397
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100398 atomic_set(&rs->state, 0);
addy ke64e36822014-07-01 09:03:59 +0800399
Arnd Bergmann97cf5662015-01-28 14:25:10 +0100400 rxdesc = NULL;
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100401 if (xfer->rx_buf) {
Emil Renner Berthing31bcb572018-10-31 11:56:59 +0100402 struct dma_slave_config rxconf = {
403 .direction = DMA_DEV_TO_MEM,
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100404 .src_addr = rs->dma_addr_rx,
Emil Renner Berthing31bcb572018-10-31 11:56:59 +0100405 .src_addr_width = rs->n_bytes,
406 .src_maxburst = 1,
407 };
408
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100409 dmaengine_slave_config(master->dma_rx, &rxconf);
addy ke64e36822014-07-01 09:03:59 +0800410
Addy Ke5dcc44e2014-07-11 10:07:56 +0800411 rxdesc = dmaengine_prep_slave_sg(
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100412 master->dma_rx,
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100413 xfer->rx_sg.sgl, xfer->rx_sg.nents,
Emil Renner Berthingd9071b72018-10-10 11:00:37 +0200414 DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
Shawn Linea984912016-03-09 16:11:15 +0800415 if (!rxdesc)
416 return -EINVAL;
addy ke64e36822014-07-01 09:03:59 +0800417
418 rxdesc->callback = rockchip_spi_dma_rxcb;
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100419 rxdesc->callback_param = master;
addy ke64e36822014-07-01 09:03:59 +0800420 }
421
Arnd Bergmann97cf5662015-01-28 14:25:10 +0100422 txdesc = NULL;
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100423 if (xfer->tx_buf) {
Emil Renner Berthing31bcb572018-10-31 11:56:59 +0100424 struct dma_slave_config txconf = {
425 .direction = DMA_MEM_TO_DEV,
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100426 .dst_addr = rs->dma_addr_tx,
Emil Renner Berthing31bcb572018-10-31 11:56:59 +0100427 .dst_addr_width = rs->n_bytes,
428 .dst_maxburst = rs->fifo_len / 2,
429 };
430
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100431 dmaengine_slave_config(master->dma_tx, &txconf);
addy ke64e36822014-07-01 09:03:59 +0800432
Addy Ke5dcc44e2014-07-11 10:07:56 +0800433 txdesc = dmaengine_prep_slave_sg(
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100434 master->dma_tx,
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100435 xfer->tx_sg.sgl, xfer->tx_sg.nents,
Emil Renner Berthingd9071b72018-10-10 11:00:37 +0200436 DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
Shawn Linea984912016-03-09 16:11:15 +0800437 if (!txdesc) {
438 if (rxdesc)
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100439 dmaengine_terminate_sync(master->dma_rx);
Shawn Linea984912016-03-09 16:11:15 +0800440 return -EINVAL;
441 }
addy ke64e36822014-07-01 09:03:59 +0800442
443 txdesc->callback = rockchip_spi_dma_txcb;
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100444 txdesc->callback_param = master;
addy ke64e36822014-07-01 09:03:59 +0800445 }
446
447 /* rx must be started before tx due to spi instinct */
Arnd Bergmann97cf5662015-01-28 14:25:10 +0100448 if (rxdesc) {
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100449 atomic_or(RXDMA, &rs->state);
addy ke64e36822014-07-01 09:03:59 +0800450 dmaengine_submit(rxdesc);
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100451 dma_async_issue_pending(master->dma_rx);
addy ke64e36822014-07-01 09:03:59 +0800452 }
453
Emil Renner Berthing30688e42018-10-31 11:56:58 +0100454 spi_enable_chip(rs, true);
Emil Renner Berthinga3c17402018-10-10 11:00:38 +0200455
Arnd Bergmann97cf5662015-01-28 14:25:10 +0100456 if (txdesc) {
Emil Renner Berthingfab3e482018-10-31 11:57:01 +0100457 atomic_or(TXDMA, &rs->state);
addy ke64e36822014-07-01 09:03:59 +0800458 dmaengine_submit(txdesc);
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100459 dma_async_issue_pending(master->dma_tx);
addy ke64e36822014-07-01 09:03:59 +0800460 }
Shawn Linea984912016-03-09 16:11:15 +0800461
Emil Renner Berthinga3c17402018-10-10 11:00:38 +0200462 /* 1 means the transfer is in progress */
463 return 1;
addy ke64e36822014-07-01 09:03:59 +0800464}
465
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100466static void rockchip_spi_config(struct rockchip_spi *rs,
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100467 struct spi_device *spi, struct spi_transfer *xfer,
468 bool use_dma)
addy ke64e36822014-07-01 09:03:59 +0800469{
Emil Renner Berthing2410d6a2018-10-31 11:57:00 +0100470 u32 cr0 = CR0_FRF_SPI << CR0_FRF_OFFSET
471 | CR0_BHT_8BIT << CR0_BHT_OFFSET
472 | CR0_SSD_ONE << CR0_SSD_OFFSET
473 | CR0_EM_BIG << CR0_EM_OFFSET;
Emil Renner Berthing65498c62018-10-31 11:57:10 +0100474 u32 cr1;
475 u32 dmacr = 0;
addy ke64e36822014-07-01 09:03:59 +0800476
Emil Renner Berthing74b7efa2018-10-31 11:57:08 +0100477 cr0 |= rs->rsd << CR0_RSD_OFFSET;
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100478 cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
Emil Renner Berthing04290192018-10-31 11:57:11 +0100479 if (spi->mode & SPI_LSB_FIRST)
480 cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100481
482 if (xfer->rx_buf && xfer->tx_buf)
483 cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
484 else if (xfer->rx_buf)
485 cr0 |= CR0_XFM_RO << CR0_XFM_OFFSET;
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100486 else if (use_dma)
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100487 cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
addy ke64e36822014-07-01 09:03:59 +0800488
Emil Renner Berthing65498c62018-10-31 11:57:10 +0100489 switch (xfer->bits_per_word) {
490 case 4:
491 cr0 |= CR0_DFS_4BIT << CR0_DFS_OFFSET;
492 cr1 = xfer->len - 1;
493 break;
494 case 8:
495 cr0 |= CR0_DFS_8BIT << CR0_DFS_OFFSET;
496 cr1 = xfer->len - 1;
497 break;
498 case 16:
499 cr0 |= CR0_DFS_16BIT << CR0_DFS_OFFSET;
500 cr1 = xfer->len / 2 - 1;
501 break;
502 default:
503 /* we only whitelist 4, 8 and 16 bit words in
504 * master->bits_per_word_mask, so this shouldn't
505 * happen
506 */
507 unreachable();
508 }
509
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100510 if (use_dma) {
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100511 if (xfer->tx_buf)
addy ke64e36822014-07-01 09:03:59 +0800512 dmacr |= TF_DMA_EN;
Emil Renner Berthingfc1ad8e2018-10-31 11:57:03 +0100513 if (xfer->rx_buf)
addy ke64e36822014-07-01 09:03:59 +0800514 dmacr |= RF_DMA_EN;
515 }
516
addy ke64e36822014-07-01 09:03:59 +0800517 writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
Emil Renner Berthing65498c62018-10-31 11:57:10 +0100518 writel_relaxed(cr1, rs->regs + ROCKCHIP_SPI_CTRLR1);
Huibin Hong04b37d22017-08-16 10:12:02 +0800519
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100520 /* unfortunately setting the fifo threshold level to generate an
521 * interrupt exactly when the fifo is full doesn't seem to work,
522 * so we need the strict inequality here
523 */
524 if (xfer->len < rs->fifo_len)
525 writel_relaxed(xfer->len - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
526 else
527 writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
addy ke64e36822014-07-01 09:03:59 +0800528
Huibin Hongdcfc8612018-10-10 11:00:33 +0200529 writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);
addy ke64e36822014-07-01 09:03:59 +0800530 writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
531 writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
532
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100533 /* the hardware only supports an even clock divisor, so
534 * round divisor = spiclk / speed up to nearest even number
535 * so that the resulting speed is <= the requested speed
536 */
537 writel_relaxed(2 * DIV_ROUND_UP(rs->freq, 2 * xfer->speed_hz),
538 rs->regs + ROCKCHIP_SPI_BAUDR);
addy ke64e36822014-07-01 09:03:59 +0800539}
540
Brian Norris5185a812016-07-14 18:30:59 -0700541static size_t rockchip_spi_max_transfer_size(struct spi_device *spi)
542{
543 return ROCKCHIP_SPI_MAX_TRANLEN;
544}
545
Addy Ke5dcc44e2014-07-11 10:07:56 +0800546static int rockchip_spi_transfer_one(
547 struct spi_master *master,
addy ke64e36822014-07-01 09:03:59 +0800548 struct spi_device *spi,
549 struct spi_transfer *xfer)
550{
addy ke64e36822014-07-01 09:03:59 +0800551 struct rockchip_spi *rs = spi_master_get_devdata(master);
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100552 bool use_dma;
addy ke64e36822014-07-01 09:03:59 +0800553
Doug Anderson62946172014-09-03 13:44:26 -0700554 WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
555 (readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY));
addy ke64e36822014-07-01 09:03:59 +0800556
557 if (!xfer->tx_buf && !xfer->rx_buf) {
558 dev_err(rs->dev, "No buffer for transfer\n");
559 return -EINVAL;
560 }
561
Brian Norris5185a812016-07-14 18:30:59 -0700562 if (xfer->len > ROCKCHIP_SPI_MAX_TRANLEN) {
563 dev_err(rs->dev, "Transfer is too long (%d)\n", xfer->len);
564 return -EINVAL;
565 }
566
Emil Renner Berthing65498c62018-10-31 11:57:10 +0100567 rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2;
addy ke64e36822014-07-01 09:03:59 +0800568
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100569 use_dma = master->can_dma ? master->can_dma(master, spi, xfer) : false;
addy ke64e36822014-07-01 09:03:59 +0800570
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100571 rockchip_spi_config(rs, spi, xfer, use_dma);
addy ke64e36822014-07-01 09:03:59 +0800572
Emil Renner Berthingeff02752018-10-31 11:57:06 +0100573 if (use_dma)
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100574 return rockchip_spi_prepare_dma(rs, master, xfer);
addy ke64e36822014-07-01 09:03:59 +0800575
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100576 return rockchip_spi_prepare_irq(rs, xfer);
addy ke64e36822014-07-01 09:03:59 +0800577}
578
579static bool rockchip_spi_can_dma(struct spi_master *master,
Addy Ke5dcc44e2014-07-11 10:07:56 +0800580 struct spi_device *spi,
581 struct spi_transfer *xfer)
addy ke64e36822014-07-01 09:03:59 +0800582{
583 struct rockchip_spi *rs = spi_master_get_devdata(master);
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100584 unsigned int bytes_per_word = xfer->bits_per_word <= 8 ? 1 : 2;
addy ke64e36822014-07-01 09:03:59 +0800585
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100586 /* if the numbor of spi words to transfer is less than the fifo
587 * length we can just fill the fifo and wait for a single irq,
588 * so don't bother setting up dma
589 */
590 return xfer->len / bytes_per_word >= rs->fifo_len;
addy ke64e36822014-07-01 09:03:59 +0800591}
592
593static int rockchip_spi_probe(struct platform_device *pdev)
594{
Jeffy Chen43de9792017-08-07 20:40:18 +0800595 int ret;
addy ke64e36822014-07-01 09:03:59 +0800596 struct rockchip_spi *rs;
597 struct spi_master *master;
598 struct resource *mem;
Julius Werner76b17e62015-03-26 16:30:25 -0700599 u32 rsd_nsecs;
addy ke64e36822014-07-01 09:03:59 +0800600
601 master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi));
Addy Ke5dcc44e2014-07-11 10:07:56 +0800602 if (!master)
addy ke64e36822014-07-01 09:03:59 +0800603 return -ENOMEM;
Addy Ke5dcc44e2014-07-11 10:07:56 +0800604
addy ke64e36822014-07-01 09:03:59 +0800605 platform_set_drvdata(pdev, master);
606
607 rs = spi_master_get_devdata(master);
addy ke64e36822014-07-01 09:03:59 +0800608
609 /* Get basic io resource and map it */
610 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
611 rs->regs = devm_ioremap_resource(&pdev->dev, mem);
612 if (IS_ERR(rs->regs)) {
addy ke64e36822014-07-01 09:03:59 +0800613 ret = PTR_ERR(rs->regs);
Jeffy Chenc3515872017-06-13 13:25:40 +0800614 goto err_put_master;
addy ke64e36822014-07-01 09:03:59 +0800615 }
616
617 rs->apb_pclk = devm_clk_get(&pdev->dev, "apb_pclk");
618 if (IS_ERR(rs->apb_pclk)) {
619 dev_err(&pdev->dev, "Failed to get apb_pclk\n");
620 ret = PTR_ERR(rs->apb_pclk);
Jeffy Chenc3515872017-06-13 13:25:40 +0800621 goto err_put_master;
addy ke64e36822014-07-01 09:03:59 +0800622 }
623
624 rs->spiclk = devm_clk_get(&pdev->dev, "spiclk");
625 if (IS_ERR(rs->spiclk)) {
626 dev_err(&pdev->dev, "Failed to get spi_pclk\n");
627 ret = PTR_ERR(rs->spiclk);
Jeffy Chenc3515872017-06-13 13:25:40 +0800628 goto err_put_master;
addy ke64e36822014-07-01 09:03:59 +0800629 }
630
631 ret = clk_prepare_enable(rs->apb_pclk);
Jeffy Chen43de9792017-08-07 20:40:18 +0800632 if (ret < 0) {
addy ke64e36822014-07-01 09:03:59 +0800633 dev_err(&pdev->dev, "Failed to enable apb_pclk\n");
Jeffy Chenc3515872017-06-13 13:25:40 +0800634 goto err_put_master;
addy ke64e36822014-07-01 09:03:59 +0800635 }
636
637 ret = clk_prepare_enable(rs->spiclk);
Jeffy Chen43de9792017-08-07 20:40:18 +0800638 if (ret < 0) {
addy ke64e36822014-07-01 09:03:59 +0800639 dev_err(&pdev->dev, "Failed to enable spi_clk\n");
Jeffy Chenc3515872017-06-13 13:25:40 +0800640 goto err_disable_apbclk;
addy ke64e36822014-07-01 09:03:59 +0800641 }
642
Emil Renner Berthing30688e42018-10-31 11:56:58 +0100643 spi_enable_chip(rs, false);
addy ke64e36822014-07-01 09:03:59 +0800644
Emil Renner Berthing01b59ce2018-10-31 11:57:09 +0100645 ret = platform_get_irq(pdev, 0);
646 if (ret < 0)
647 goto err_disable_spiclk;
648
649 ret = devm_request_threaded_irq(&pdev->dev, ret, rockchip_spi_isr, NULL,
650 IRQF_ONESHOT, dev_name(&pdev->dev), master);
651 if (ret)
652 goto err_disable_spiclk;
653
addy ke64e36822014-07-01 09:03:59 +0800654 rs->dev = &pdev->dev;
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100655 rs->freq = clk_get_rate(rs->spiclk);
addy ke64e36822014-07-01 09:03:59 +0800656
Julius Werner76b17e62015-03-26 16:30:25 -0700657 if (!of_property_read_u32(pdev->dev.of_node, "rx-sample-delay-ns",
Emil Renner Berthing74b7efa2018-10-31 11:57:08 +0100658 &rsd_nsecs)) {
659 /* rx sample delay is expressed in parent clock cycles (max 3) */
660 u32 rsd = DIV_ROUND_CLOSEST(rsd_nsecs * (rs->freq >> 8),
661 1000000000 >> 8);
662 if (!rsd) {
663 dev_warn(rs->dev, "%u Hz are too slow to express %u ns delay\n",
664 rs->freq, rsd_nsecs);
665 } else if (rsd > CR0_RSD_MAX) {
666 rsd = CR0_RSD_MAX;
667 dev_warn(rs->dev, "%u Hz are too fast to express %u ns delay, clamping at %u ns\n",
668 rs->freq, rsd_nsecs,
669 CR0_RSD_MAX * 1000000000U / rs->freq);
670 }
671 rs->rsd = rsd;
672 }
Julius Werner76b17e62015-03-26 16:30:25 -0700673
addy ke64e36822014-07-01 09:03:59 +0800674 rs->fifo_len = get_fifo_len(rs);
675 if (!rs->fifo_len) {
676 dev_err(&pdev->dev, "Failed to get fifo length\n");
Wei Yongjundb7e8d92014-07-20 22:02:04 +0800677 ret = -EINVAL;
Jeffy Chenc3515872017-06-13 13:25:40 +0800678 goto err_disable_spiclk;
addy ke64e36822014-07-01 09:03:59 +0800679 }
680
addy ke64e36822014-07-01 09:03:59 +0800681 pm_runtime_set_active(&pdev->dev);
682 pm_runtime_enable(&pdev->dev);
683
684 master->auto_runtime_pm = true;
685 master->bus_num = pdev->id;
Emil Renner Berthing04290192018-10-31 11:57:11 +0100686 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST;
Jeffy Chenaa099382017-06-28 12:38:43 +0800687 master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
addy ke64e36822014-07-01 09:03:59 +0800688 master->dev.of_node = pdev->dev.of_node;
Emil Renner Berthing65498c62018-10-31 11:57:10 +0100689 master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8) | SPI_BPW_MASK(4);
Emil Renner Berthing420b82f2018-10-31 11:57:07 +0100690 master->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;
691 master->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT);
addy ke64e36822014-07-01 09:03:59 +0800692
693 master->set_cs = rockchip_spi_set_cs;
addy ke64e36822014-07-01 09:03:59 +0800694 master->transfer_one = rockchip_spi_transfer_one;
Brian Norris5185a812016-07-14 18:30:59 -0700695 master->max_transfer_size = rockchip_spi_max_transfer_size;
Andy Shevchenko22917932015-02-27 17:34:16 +0200696 master->handle_err = rockchip_spi_handle_err;
Jeffy Chenc8637952017-06-28 12:38:42 +0800697 master->flags = SPI_MASTER_GPIO_SS;
addy ke64e36822014-07-01 09:03:59 +0800698
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100699 master->dma_tx = dma_request_chan(rs->dev, "tx");
700 if (IS_ERR(master->dma_tx)) {
Shawn Lin61cadcf2016-03-09 16:11:32 +0800701 /* Check tx to see if we need defer probing driver */
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100702 if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) {
Shawn Lin61cadcf2016-03-09 16:11:32 +0800703 ret = -EPROBE_DEFER;
Jeffy Chenc3515872017-06-13 13:25:40 +0800704 goto err_disable_pm_runtime;
Shawn Lin61cadcf2016-03-09 16:11:32 +0800705 }
addy ke64e36822014-07-01 09:03:59 +0800706 dev_warn(rs->dev, "Failed to request TX DMA channel\n");
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100707 master->dma_tx = NULL;
Shawn Lin61cadcf2016-03-09 16:11:32 +0800708 }
addy ke64e36822014-07-01 09:03:59 +0800709
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100710 master->dma_rx = dma_request_chan(rs->dev, "rx");
711 if (IS_ERR(master->dma_rx)) {
712 if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) {
Shawn Line4c0e062016-03-31 11:11:41 +0800713 ret = -EPROBE_DEFER;
Dan Carpenter5de7ed02016-05-04 09:25:46 +0300714 goto err_free_dma_tx;
addy ke64e36822014-07-01 09:03:59 +0800715 }
716 dev_warn(rs->dev, "Failed to request RX DMA channel\n");
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100717 master->dma_rx = NULL;
addy ke64e36822014-07-01 09:03:59 +0800718 }
719
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100720 if (master->dma_tx && master->dma_rx) {
721 rs->dma_addr_tx = mem->start + ROCKCHIP_SPI_TXDR;
722 rs->dma_addr_rx = mem->start + ROCKCHIP_SPI_RXDR;
addy ke64e36822014-07-01 09:03:59 +0800723 master->can_dma = rockchip_spi_can_dma;
addy ke64e36822014-07-01 09:03:59 +0800724 }
725
726 ret = devm_spi_register_master(&pdev->dev, master);
Jeffy Chen43de9792017-08-07 20:40:18 +0800727 if (ret < 0) {
addy ke64e36822014-07-01 09:03:59 +0800728 dev_err(&pdev->dev, "Failed to register master\n");
Jeffy Chenc3515872017-06-13 13:25:40 +0800729 goto err_free_dma_rx;
addy ke64e36822014-07-01 09:03:59 +0800730 }
731
addy ke64e36822014-07-01 09:03:59 +0800732 return 0;
733
Jeffy Chenc3515872017-06-13 13:25:40 +0800734err_free_dma_rx:
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100735 if (master->dma_rx)
736 dma_release_channel(master->dma_rx);
Dan Carpenter5de7ed02016-05-04 09:25:46 +0300737err_free_dma_tx:
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100738 if (master->dma_tx)
739 dma_release_channel(master->dma_tx);
Jeffy Chenc3515872017-06-13 13:25:40 +0800740err_disable_pm_runtime:
741 pm_runtime_disable(&pdev->dev);
742err_disable_spiclk:
addy ke64e36822014-07-01 09:03:59 +0800743 clk_disable_unprepare(rs->spiclk);
Jeffy Chenc3515872017-06-13 13:25:40 +0800744err_disable_apbclk:
addy ke64e36822014-07-01 09:03:59 +0800745 clk_disable_unprepare(rs->apb_pclk);
Jeffy Chenc3515872017-06-13 13:25:40 +0800746err_put_master:
addy ke64e36822014-07-01 09:03:59 +0800747 spi_master_put(master);
748
749 return ret;
750}
751
752static int rockchip_spi_remove(struct platform_device *pdev)
753{
754 struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
755 struct rockchip_spi *rs = spi_master_get_devdata(master);
756
Jeffy Chen6a06e892017-08-07 20:40:19 +0800757 pm_runtime_get_sync(&pdev->dev);
addy ke64e36822014-07-01 09:03:59 +0800758
759 clk_disable_unprepare(rs->spiclk);
760 clk_disable_unprepare(rs->apb_pclk);
761
Jeffy Chen6a06e892017-08-07 20:40:19 +0800762 pm_runtime_put_noidle(&pdev->dev);
763 pm_runtime_disable(&pdev->dev);
764 pm_runtime_set_suspended(&pdev->dev);
765
Emil Renner Berthingeee06a92018-10-31 11:57:04 +0100766 if (master->dma_tx)
767 dma_release_channel(master->dma_tx);
768 if (master->dma_rx)
769 dma_release_channel(master->dma_rx);
addy ke64e36822014-07-01 09:03:59 +0800770
Shawn Lin844c9f42016-02-15 16:28:12 +0800771 spi_master_put(master);
772
addy ke64e36822014-07-01 09:03:59 +0800773 return 0;
774}
775
776#ifdef CONFIG_PM_SLEEP
777static int rockchip_spi_suspend(struct device *dev)
778{
Jeffy Chen43de9792017-08-07 20:40:18 +0800779 int ret;
addy ke64e36822014-07-01 09:03:59 +0800780 struct spi_master *master = dev_get_drvdata(dev);
addy ke64e36822014-07-01 09:03:59 +0800781
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100782 ret = spi_master_suspend(master);
Jeffy Chen43de9792017-08-07 20:40:18 +0800783 if (ret < 0)
addy ke64e36822014-07-01 09:03:59 +0800784 return ret;
785
Jeffy Chend38c4ae12017-08-07 20:40:20 +0800786 ret = pm_runtime_force_suspend(dev);
787 if (ret < 0)
788 return ret;
addy ke64e36822014-07-01 09:03:59 +0800789
Brian Norris23e291c2016-12-16 16:59:16 -0800790 pinctrl_pm_select_sleep_state(dev);
791
Jeffy Chen43de9792017-08-07 20:40:18 +0800792 return 0;
addy ke64e36822014-07-01 09:03:59 +0800793}
794
795static int rockchip_spi_resume(struct device *dev)
796{
Jeffy Chen43de9792017-08-07 20:40:18 +0800797 int ret;
addy ke64e36822014-07-01 09:03:59 +0800798 struct spi_master *master = dev_get_drvdata(dev);
799 struct rockchip_spi *rs = spi_master_get_devdata(master);
800
Brian Norris23e291c2016-12-16 16:59:16 -0800801 pinctrl_pm_select_default_state(dev);
802
Jeffy Chend38c4ae12017-08-07 20:40:20 +0800803 ret = pm_runtime_force_resume(dev);
804 if (ret < 0)
805 return ret;
addy ke64e36822014-07-01 09:03:59 +0800806
Emil Renner Berthingd790c342018-10-31 11:57:05 +0100807 ret = spi_master_resume(master);
addy ke64e36822014-07-01 09:03:59 +0800808 if (ret < 0) {
809 clk_disable_unprepare(rs->spiclk);
810 clk_disable_unprepare(rs->apb_pclk);
811 }
812
Jeffy Chen43de9792017-08-07 20:40:18 +0800813 return 0;
addy ke64e36822014-07-01 09:03:59 +0800814}
815#endif /* CONFIG_PM_SLEEP */
816
Rafael J. Wysockiec833052014-12-13 00:41:15 +0100817#ifdef CONFIG_PM
addy ke64e36822014-07-01 09:03:59 +0800818static int rockchip_spi_runtime_suspend(struct device *dev)
819{
820 struct spi_master *master = dev_get_drvdata(dev);
821 struct rockchip_spi *rs = spi_master_get_devdata(master);
822
823 clk_disable_unprepare(rs->spiclk);
824 clk_disable_unprepare(rs->apb_pclk);
825
826 return 0;
827}
828
829static int rockchip_spi_runtime_resume(struct device *dev)
830{
831 int ret;
832 struct spi_master *master = dev_get_drvdata(dev);
833 struct rockchip_spi *rs = spi_master_get_devdata(master);
834
835 ret = clk_prepare_enable(rs->apb_pclk);
Jeffy Chen43de9792017-08-07 20:40:18 +0800836 if (ret < 0)
addy ke64e36822014-07-01 09:03:59 +0800837 return ret;
838
839 ret = clk_prepare_enable(rs->spiclk);
Jeffy Chen43de9792017-08-07 20:40:18 +0800840 if (ret < 0)
addy ke64e36822014-07-01 09:03:59 +0800841 clk_disable_unprepare(rs->apb_pclk);
842
Jeffy Chen43de9792017-08-07 20:40:18 +0800843 return 0;
addy ke64e36822014-07-01 09:03:59 +0800844}
Rafael J. Wysockiec833052014-12-13 00:41:15 +0100845#endif /* CONFIG_PM */
addy ke64e36822014-07-01 09:03:59 +0800846
847static const struct dev_pm_ops rockchip_spi_pm = {
848 SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)
849 SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,
850 rockchip_spi_runtime_resume, NULL)
851};
852
853static const struct of_device_id rockchip_spi_dt_match[] = {
Andy Yan6b860e62017-08-14 16:34:22 +0800854 { .compatible = "rockchip,rv1108-spi", },
Caesar Wangaa29ea32016-05-20 07:56:21 +0800855 { .compatible = "rockchip,rk3036-spi", },
addy ke64e36822014-07-01 09:03:59 +0800856 { .compatible = "rockchip,rk3066-spi", },
Addy Keb839b782014-07-11 10:09:19 +0800857 { .compatible = "rockchip,rk3188-spi", },
Caesar Wangaa29ea32016-05-20 07:56:21 +0800858 { .compatible = "rockchip,rk3228-spi", },
Addy Keb839b782014-07-11 10:09:19 +0800859 { .compatible = "rockchip,rk3288-spi", },
Caesar Wangaa29ea32016-05-20 07:56:21 +0800860 { .compatible = "rockchip,rk3368-spi", },
Xu Jianqun9b7a5622016-02-18 19:16:31 +0800861 { .compatible = "rockchip,rk3399-spi", },
addy ke64e36822014-07-01 09:03:59 +0800862 { },
863};
864MODULE_DEVICE_TABLE(of, rockchip_spi_dt_match);
865
866static struct platform_driver rockchip_spi_driver = {
867 .driver = {
868 .name = DRIVER_NAME,
addy ke64e36822014-07-01 09:03:59 +0800869 .pm = &rockchip_spi_pm,
870 .of_match_table = of_match_ptr(rockchip_spi_dt_match),
871 },
872 .probe = rockchip_spi_probe,
873 .remove = rockchip_spi_remove,
874};
875
876module_platform_driver(rockchip_spi_driver);
877
Addy Ke5dcc44e2014-07-11 10:07:56 +0800878MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>");
addy ke64e36822014-07-01 09:03:59 +0800879MODULE_DESCRIPTION("ROCKCHIP SPI Controller Driver");
880MODULE_LICENSE("GPL v2");