Commit | Line | Data |
---|---|---|
f62ca4e2 LK |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // Copyright (c) 2021 Sunplus Inc. | |
3 | // Author: Li-hao Kuo <lhjeff911@gmail.com> | |
4 | ||
5 | #include <linux/bitfield.h> | |
6 | #include <linux/clk.h> | |
7 | #include <linux/delay.h> | |
8 | #include <linux/dma-mapping.h> | |
9 | #include <linux/interrupt.h> | |
10 | #include <linux/module.h> | |
11 | #include <linux/of.h> | |
12 | #include <linux/platform_device.h> | |
13 | #include <linux/pm_runtime.h> | |
14 | #include <linux/reset.h> | |
15 | #include <linux/spi/spi.h> | |
16 | ||
17 | #define SP7021_DATA_RDY_REG 0x0044 | |
18 | #define SP7021_SLAVE_DMA_CTRL_REG 0x0048 | |
19 | #define SP7021_SLAVE_DMA_LENGTH_REG 0x004c | |
20 | #define SP7021_SLAVE_DMA_ADDR_REG 0x004c | |
21 | ||
22 | #define SP7021_SLAVE_DATA_RDY BIT(0) | |
23 | #define SP7021_SLAVE_SW_RST BIT(1) | |
24 | #define SP7021_SLA_DMA_W_INT BIT(8) | |
25 | #define SP7021_SLAVE_CLR_INT BIT(8) | |
26 | #define SP7021_SLAVE_DMA_EN BIT(0) | |
27 | #define SP7021_SLAVE_DMA_RW BIT(6) | |
28 | #define SP7021_SLAVE_DMA_CMD GENMASK(3, 2) | |
29 | ||
30 | #define SP7021_FIFO_REG 0x0034 | |
31 | #define SP7021_SPI_STATUS_REG 0x0038 | |
32 | #define SP7021_SPI_CONFIG_REG 0x003c | |
33 | #define SP7021_INT_BUSY_REG 0x004c | |
34 | #define SP7021_DMA_CTRL_REG 0x0050 | |
35 | ||
36 | #define SP7021_SPI_START_FD BIT(0) | |
37 | #define SP7021_FD_SW_RST BIT(1) | |
38 | #define SP7021_TX_EMP_FLAG BIT(2) | |
39 | #define SP7021_RX_EMP_FLAG BIT(4) | |
40 | #define SP7021_RX_FULL_FLAG BIT(5) | |
41 | #define SP7021_FINISH_FLAG BIT(6) | |
42 | ||
43 | #define SP7021_TX_CNT_MASK GENMASK(11, 8) | |
44 | #define SP7021_RX_CNT_MASK GENMASK(15, 12) | |
45 | #define SP7021_TX_LEN_MASK GENMASK(23, 16) | |
46 | #define SP7021_GET_LEN_MASK GENMASK(31, 24) | |
47 | #define SP7021_SET_TX_LEN GENMASK(23, 16) | |
48 | #define SP7021_SET_XFER_LEN GENMASK(31, 24) | |
49 | ||
50 | #define SP7021_CPOL_FD BIT(0) | |
51 | #define SP7021_CPHA_R BIT(1) | |
52 | #define SP7021_CPHA_W BIT(2) | |
53 | #define SP7021_LSB_SEL BIT(4) | |
54 | #define SP7021_CS_POR BIT(5) | |
55 | #define SP7021_FD_SEL BIT(6) | |
56 | ||
57 | #define SP7021_RX_UNIT GENMASK(8, 7) | |
58 | #define SP7021_TX_UNIT GENMASK(10, 9) | |
59 | #define SP7021_TX_EMP_FLAG_MASK BIT(11) | |
60 | #define SP7021_RX_FULL_FLAG_MASK BIT(14) | |
61 | #define SP7021_FINISH_FLAG_MASK BIT(15) | |
62 | #define SP7021_CLEAN_RW_BYTE GENMASK(10, 7) | |
63 | #define SP7021_CLEAN_FLUG_MASK GENMASK(15, 11) | |
64 | #define SP7021_CLK_MASK GENMASK(31, 16) | |
65 | ||
66 | #define SP7021_INT_BYPASS BIT(3) | |
67 | #define SP7021_CLR_MASTER_INT BIT(6) | |
68 | ||
69 | #define SP7021_SPI_DATA_SIZE (255) | |
70 | #define SP7021_FIFO_DATA_LEN (16) | |
71 | ||
f62ca4e2 LK |
72 | enum { |
73 | SP7021_MASTER_MODE = 0, | |
74 | SP7021_SLAVE_MODE = 1, | |
75 | }; | |
76 | ||
77 | struct sp7021_spi_ctlr { | |
78 | struct device *dev; | |
79 | struct spi_controller *ctlr; | |
80 | void __iomem *m_base; | |
81 | void __iomem *s_base; | |
82 | u32 xfer_conf; | |
83 | int mode; | |
84 | int m_irq; | |
85 | int s_irq; | |
86 | struct clk *spi_clk; | |
87 | struct reset_control *rstc; | |
88 | // irq spin lock | |
89 | spinlock_t lock; | |
90 | // data xfer lock | |
91 | struct mutex buf_lock; | |
92 | struct completion isr_done; | |
93 | struct completion slave_isr; | |
94 | unsigned int rx_cur_len; | |
95 | unsigned int tx_cur_len; | |
96 | unsigned int data_unit; | |
97 | const u8 *tx_buf; | |
98 | u8 *rx_buf; | |
99 | }; | |
100 | ||
101 | static irqreturn_t sp7021_spi_slave_irq(int irq, void *dev) | |
102 | { | |
103 | struct sp7021_spi_ctlr *pspim = dev; | |
104 | unsigned int data_status; | |
105 | ||
106 | data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG); | |
47e8fe57 LK |
107 | data_status |= SP7021_SLAVE_CLR_INT; |
108 | writel(data_status , pspim->s_base + SP7021_DATA_RDY_REG); | |
f62ca4e2 LK |
109 | complete(&pspim->slave_isr); |
110 | return IRQ_HANDLED; | |
111 | } | |
112 | ||
113 | static int sp7021_spi_slave_abort(struct spi_controller *ctlr) | |
114 | { | |
115 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
116 | ||
117 | complete(&pspim->slave_isr); | |
118 | complete(&pspim->isr_done); | |
119 | return 0; | |
120 | } | |
121 | ||
6938e02f | 122 | static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer) |
f62ca4e2 LK |
123 | { |
124 | struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); | |
47e8fe57 | 125 | u32 value; |
f62ca4e2 LK |
126 | |
127 | reinit_completion(&pspim->slave_isr); | |
47e8fe57 LK |
128 | value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); |
129 | writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); | |
f62ca4e2 LK |
130 | writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); |
131 | writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); | |
47e8fe57 LK |
132 | value = readl(pspim->s_base + SP7021_DATA_RDY_REG); |
133 | value |= SP7021_SLAVE_DATA_RDY; | |
134 | writel(value, pspim->s_base + SP7021_DATA_RDY_REG); | |
f62ca4e2 LK |
135 | if (wait_for_completion_interruptible(&pspim->isr_done)) { |
136 | dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); | |
137 | return -EINTR; | |
138 | } | |
139 | return 0; | |
140 | } | |
141 | ||
6938e02f | 142 | static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer) |
f62ca4e2 LK |
143 | { |
144 | struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); | |
47e8fe57 | 145 | u32 value; |
f62ca4e2 LK |
146 | |
147 | reinit_completion(&pspim->isr_done); | |
47e8fe57 LK |
148 | value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); |
149 | writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); | |
f62ca4e2 LK |
150 | writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); |
151 | writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); | |
152 | if (wait_for_completion_interruptible(&pspim->isr_done)) { | |
153 | dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); | |
154 | return -EINTR; | |
155 | } | |
156 | writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); | |
47e8fe57 | 157 | return 0; |
f62ca4e2 LK |
158 | } |
159 | ||
6938e02f | 160 | static void sp7021_spi_master_rb(struct sp7021_spi_ctlr *pspim, unsigned int len) |
f62ca4e2 LK |
161 | { |
162 | int i; | |
163 | ||
164 | for (i = 0; i < len; i++) { | |
165 | pspim->rx_buf[pspim->rx_cur_len] = | |
166 | readl(pspim->m_base + SP7021_FIFO_REG); | |
167 | pspim->rx_cur_len++; | |
168 | } | |
169 | } | |
170 | ||
6938e02f | 171 | static void sp7021_spi_master_wb(struct sp7021_spi_ctlr *pspim, unsigned int len) |
f62ca4e2 LK |
172 | { |
173 | int i; | |
174 | ||
175 | for (i = 0; i < len; i++) { | |
176 | writel(pspim->tx_buf[pspim->tx_cur_len], | |
177 | pspim->m_base + SP7021_FIFO_REG); | |
178 | pspim->tx_cur_len++; | |
179 | } | |
180 | } | |
181 | ||
182 | static irqreturn_t sp7021_spi_master_irq(int irq, void *dev) | |
183 | { | |
184 | struct sp7021_spi_ctlr *pspim = dev; | |
185 | unsigned int tx_cnt, total_len; | |
186 | unsigned int tx_len, rx_cnt; | |
187 | unsigned int fd_status; | |
f62ca4e2 LK |
188 | bool isrdone = false; |
189 | u32 value; | |
190 | ||
191 | fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); | |
192 | tx_cnt = FIELD_GET(SP7021_TX_CNT_MASK, fd_status); | |
193 | tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); | |
194 | total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); | |
195 | ||
196 | if ((fd_status & SP7021_TX_EMP_FLAG) && (fd_status & SP7021_RX_EMP_FLAG) && total_len == 0) | |
197 | return IRQ_NONE; | |
198 | ||
199 | if (tx_len == 0 && total_len == 0) | |
200 | return IRQ_NONE; | |
201 | ||
47e8fe57 | 202 | spin_lock_irq(&pspim->lock); |
f62ca4e2 LK |
203 | |
204 | rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); | |
205 | if (fd_status & SP7021_RX_FULL_FLAG) | |
206 | rx_cnt = pspim->data_unit; | |
207 | ||
208 | tx_cnt = min(tx_len - pspim->tx_cur_len, pspim->data_unit - tx_cnt); | |
209 | dev_dbg(pspim->dev, "fd_st=0x%x rx_c:%d tx_c:%d tx_l:%d", | |
210 | fd_status, rx_cnt, tx_cnt, tx_len); | |
211 | ||
212 | if (rx_cnt > 0) | |
213 | sp7021_spi_master_rb(pspim, rx_cnt); | |
214 | if (tx_cnt > 0) | |
215 | sp7021_spi_master_wb(pspim, tx_cnt); | |
216 | ||
217 | fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); | |
218 | tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); | |
219 | total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); | |
220 | ||
221 | if (fd_status & SP7021_FINISH_FLAG || tx_len == pspim->tx_cur_len) { | |
222 | while (total_len != pspim->rx_cur_len) { | |
223 | fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); | |
224 | total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); | |
225 | if (fd_status & SP7021_RX_FULL_FLAG) | |
226 | rx_cnt = pspim->data_unit; | |
227 | else | |
228 | rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); | |
229 | ||
230 | if (rx_cnt > 0) | |
231 | sp7021_spi_master_rb(pspim, rx_cnt); | |
232 | } | |
233 | value = readl(pspim->m_base + SP7021_INT_BUSY_REG); | |
234 | value |= SP7021_CLR_MASTER_INT; | |
235 | writel(value, pspim->m_base + SP7021_INT_BUSY_REG); | |
236 | writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); | |
237 | isrdone = true; | |
238 | } | |
239 | ||
240 | if (isrdone) | |
241 | complete(&pspim->isr_done); | |
47e8fe57 | 242 | spin_unlock_irq(&pspim->lock); |
f62ca4e2 LK |
243 | return IRQ_HANDLED; |
244 | } | |
245 | ||
246 | static void sp7021_prep_transfer(struct spi_controller *ctlr, struct spi_device *spi) | |
247 | { | |
248 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
249 | ||
250 | pspim->tx_cur_len = 0; | |
251 | pspim->rx_cur_len = 0; | |
252 | pspim->data_unit = SP7021_FIFO_DATA_LEN; | |
253 | } | |
254 | ||
255 | // preliminary set CS, CPOL, CPHA and LSB | |
256 | static int sp7021_spi_controller_prepare_message(struct spi_controller *ctlr, | |
257 | struct spi_message *msg) | |
258 | { | |
259 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
260 | struct spi_device *s = msg->spi; | |
261 | u32 valus, rs = 0; | |
262 | ||
263 | valus = readl(pspim->m_base + SP7021_SPI_STATUS_REG); | |
264 | valus |= SP7021_FD_SW_RST; | |
265 | writel(valus, pspim->m_base + SP7021_SPI_STATUS_REG); | |
266 | rs |= SP7021_FD_SEL; | |
267 | if (s->mode & SPI_CPOL) | |
268 | rs |= SP7021_CPOL_FD; | |
269 | ||
270 | if (s->mode & SPI_LSB_FIRST) | |
271 | rs |= SP7021_LSB_SEL; | |
272 | ||
273 | if (s->mode & SPI_CS_HIGH) | |
274 | rs |= SP7021_CS_POR; | |
275 | ||
276 | if (s->mode & SPI_CPHA) | |
277 | rs |= SP7021_CPHA_R; | |
278 | else | |
279 | rs |= SP7021_CPHA_W; | |
280 | ||
281 | rs |= FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); | |
282 | pspim->xfer_conf = rs; | |
283 | if (pspim->xfer_conf & SP7021_CPOL_FD) | |
284 | writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); | |
285 | ||
286 | return 0; | |
287 | } | |
288 | ||
289 | static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfer *xfer) | |
290 | { | |
291 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
292 | u32 clk_rate, clk_sel, div; | |
293 | ||
294 | clk_rate = clk_get_rate(pspim->spi_clk); | |
47e8fe57 LK |
295 | div = max(2U, clk_rate / xfer->speed_hz); |
296 | ||
f62ca4e2 | 297 | clk_sel = (div / 2) - 1; |
47e8fe57 | 298 | pspim->xfer_conf &= ~SP7021_CLK_MASK; |
f62ca4e2 LK |
299 | pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel); |
300 | writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); | |
301 | } | |
302 | ||
303 | static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, | |
304 | struct spi_transfer *xfer) | |
305 | { | |
306 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
307 | unsigned long timeout = msecs_to_jiffies(1000); | |
308 | unsigned int xfer_cnt, xfer_len, last_len; | |
309 | unsigned int i, len_temp; | |
310 | u32 reg_temp; | |
f62ca4e2 LK |
311 | |
312 | xfer_cnt = xfer->len / SP7021_SPI_DATA_SIZE; | |
313 | last_len = xfer->len % SP7021_SPI_DATA_SIZE; | |
314 | ||
315 | for (i = 0; i <= xfer_cnt; i++) { | |
316 | mutex_lock(&pspim->buf_lock); | |
317 | sp7021_prep_transfer(ctlr, spi); | |
318 | sp7021_spi_setup_clk(ctlr, xfer); | |
319 | reinit_completion(&pspim->isr_done); | |
320 | ||
321 | if (i == xfer_cnt) | |
322 | xfer_len = last_len; | |
323 | else | |
324 | xfer_len = SP7021_SPI_DATA_SIZE; | |
325 | ||
326 | pspim->tx_buf = xfer->tx_buf + i * SP7021_SPI_DATA_SIZE; | |
327 | pspim->rx_buf = xfer->rx_buf + i * SP7021_SPI_DATA_SIZE; | |
328 | ||
329 | if (pspim->tx_cur_len < xfer_len) { | |
330 | len_temp = min(pspim->data_unit, xfer_len); | |
331 | sp7021_spi_master_wb(pspim, len_temp); | |
332 | } | |
333 | reg_temp = readl(pspim->m_base + SP7021_SPI_CONFIG_REG); | |
334 | reg_temp &= ~SP7021_CLEAN_RW_BYTE; | |
335 | reg_temp &= ~SP7021_CLEAN_FLUG_MASK; | |
336 | reg_temp |= SP7021_FD_SEL | SP7021_FINISH_FLAG_MASK | | |
337 | SP7021_TX_EMP_FLAG_MASK | SP7021_RX_FULL_FLAG_MASK | | |
338 | FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); | |
339 | writel(reg_temp, pspim->m_base + SP7021_SPI_CONFIG_REG); | |
340 | ||
341 | reg_temp = FIELD_PREP(SP7021_SET_TX_LEN, xfer_len) | | |
342 | FIELD_PREP(SP7021_SET_XFER_LEN, xfer_len) | | |
343 | SP7021_SPI_START_FD; | |
344 | writel(reg_temp, pspim->m_base + SP7021_SPI_STATUS_REG); | |
345 | ||
346 | if (!wait_for_completion_interruptible_timeout(&pspim->isr_done, timeout)) { | |
347 | dev_err(&spi->dev, "wait_for_completion err\n"); | |
20dc69ca | 348 | mutex_unlock(&pspim->buf_lock); |
f62ca4e2 LK |
349 | return -ETIMEDOUT; |
350 | } | |
351 | ||
352 | reg_temp = readl(pspim->m_base + SP7021_SPI_STATUS_REG); | |
353 | if (reg_temp & SP7021_FINISH_FLAG) { | |
354 | writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); | |
355 | writel(readl(pspim->m_base + SP7021_SPI_CONFIG_REG) & | |
356 | SP7021_CLEAN_FLUG_MASK, pspim->m_base + SP7021_SPI_CONFIG_REG); | |
357 | } | |
358 | ||
359 | if (pspim->xfer_conf & SP7021_CPOL_FD) | |
360 | writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); | |
361 | ||
362 | mutex_unlock(&pspim->buf_lock); | |
f62ca4e2 | 363 | } |
47e8fe57 | 364 | return 0; |
f62ca4e2 LK |
365 | } |
366 | ||
367 | static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, | |
368 | struct spi_transfer *xfer) | |
369 | { | |
370 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
371 | struct device *dev = pspim->dev; | |
5790597d | 372 | int ret; |
f62ca4e2 | 373 | |
5790597d | 374 | if (xfer->tx_buf && !xfer->rx_buf) { |
f62ca4e2 LK |
375 | xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf, |
376 | xfer->len, DMA_TO_DEVICE); | |
377 | if (dma_mapping_error(dev, xfer->tx_dma)) | |
378 | return -ENOMEM; | |
07025cea YL |
379 | ret = sp7021_spi_slave_tx(spi, xfer); |
380 | dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); | |
5790597d | 381 | } else if (xfer->rx_buf && !xfer->tx_buf) { |
f62ca4e2 LK |
382 | xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, xfer->len, |
383 | DMA_FROM_DEVICE); | |
384 | if (dma_mapping_error(dev, xfer->rx_dma)) | |
385 | return -ENOMEM; | |
f62ca4e2 | 386 | ret = sp7021_spi_slave_rx(spi, xfer); |
f62ca4e2 | 387 | dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); |
5790597d LK |
388 | } else { |
389 | dev_dbg(&ctlr->dev, "%s() wrong command\n", __func__); | |
390 | return -EINVAL; | |
391 | } | |
f62ca4e2 LK |
392 | |
393 | spi_finalize_current_transfer(ctlr); | |
394 | return ret; | |
395 | } | |
396 | ||
397 | static void sp7021_spi_disable_unprepare(void *data) | |
398 | { | |
399 | clk_disable_unprepare(data); | |
400 | } | |
401 | ||
402 | static void sp7021_spi_reset_control_assert(void *data) | |
403 | { | |
404 | reset_control_assert(data); | |
405 | } | |
406 | ||
407 | static int sp7021_spi_controller_probe(struct platform_device *pdev) | |
408 | { | |
409 | struct device *dev = &pdev->dev; | |
410 | struct sp7021_spi_ctlr *pspim; | |
411 | struct spi_controller *ctlr; | |
412 | int mode, ret; | |
413 | ||
414 | pdev->id = of_alias_get_id(pdev->dev.of_node, "sp_spi"); | |
415 | ||
416 | if (device_property_read_bool(dev, "spi-slave")) | |
417 | mode = SP7021_SLAVE_MODE; | |
418 | else | |
419 | mode = SP7021_MASTER_MODE; | |
420 | ||
421 | if (mode == SP7021_SLAVE_MODE) | |
422 | ctlr = devm_spi_alloc_slave(dev, sizeof(*pspim)); | |
423 | else | |
424 | ctlr = devm_spi_alloc_master(dev, sizeof(*pspim)); | |
425 | if (!ctlr) | |
426 | return -ENOMEM; | |
47e8fe57 | 427 | device_set_node(&ctlr->dev, dev_fwnode(dev)); |
f62ca4e2 LK |
428 | ctlr->bus_num = pdev->id; |
429 | ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; | |
430 | ctlr->auto_runtime_pm = true; | |
431 | ctlr->prepare_message = sp7021_spi_controller_prepare_message; | |
432 | if (mode == SP7021_SLAVE_MODE) { | |
433 | ctlr->transfer_one = sp7021_spi_slave_transfer_one; | |
434 | ctlr->slave_abort = sp7021_spi_slave_abort; | |
435 | ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; | |
436 | } else { | |
437 | ctlr->bits_per_word_mask = SPI_BPW_MASK(8); | |
438 | ctlr->min_speed_hz = 40000; | |
439 | ctlr->max_speed_hz = 25000000; | |
440 | ctlr->use_gpio_descriptors = true; | |
441 | ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; | |
442 | ctlr->transfer_one = sp7021_spi_master_transfer_one; | |
443 | } | |
444 | platform_set_drvdata(pdev, ctlr); | |
445 | pspim = spi_controller_get_devdata(ctlr); | |
446 | pspim->mode = mode; | |
447 | pspim->ctlr = ctlr; | |
448 | pspim->dev = dev; | |
449 | spin_lock_init(&pspim->lock); | |
450 | mutex_init(&pspim->buf_lock); | |
451 | init_completion(&pspim->isr_done); | |
452 | init_completion(&pspim->slave_isr); | |
453 | ||
454 | pspim->m_base = devm_platform_ioremap_resource_byname(pdev, "master"); | |
455 | if (IS_ERR(pspim->m_base)) | |
456 | return dev_err_probe(dev, PTR_ERR(pspim->m_base), "m_base get fail\n"); | |
457 | ||
458 | pspim->s_base = devm_platform_ioremap_resource_byname(pdev, "slave"); | |
459 | if (IS_ERR(pspim->s_base)) | |
460 | return dev_err_probe(dev, PTR_ERR(pspim->s_base), "s_base get fail\n"); | |
461 | ||
462 | pspim->m_irq = platform_get_irq_byname(pdev, "master_risc"); | |
463 | if (pspim->m_irq < 0) | |
464 | return pspim->m_irq; | |
465 | ||
466 | pspim->s_irq = platform_get_irq_byname(pdev, "slave_risc"); | |
467 | if (pspim->s_irq < 0) | |
468 | return pspim->s_irq; | |
469 | ||
f62ca4e2 LK |
470 | pspim->spi_clk = devm_clk_get(dev, NULL); |
471 | if (IS_ERR(pspim->spi_clk)) | |
472 | return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n"); | |
473 | ||
474 | pspim->rstc = devm_reset_control_get_exclusive(dev, NULL); | |
475 | if (IS_ERR(pspim->rstc)) | |
476 | return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n"); | |
477 | ||
478 | ret = clk_prepare_enable(pspim->spi_clk); | |
479 | if (ret) | |
480 | return dev_err_probe(dev, ret, "failed to enable clk\n"); | |
481 | ||
482 | ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk); | |
483 | if (ret) | |
484 | return ret; | |
485 | ||
486 | ret = reset_control_deassert(pspim->rstc); | |
487 | if (ret) | |
488 | return dev_err_probe(dev, ret, "failed to deassert reset\n"); | |
489 | ||
490 | ret = devm_add_action_or_reset(dev, sp7021_spi_reset_control_assert, pspim->rstc); | |
491 | if (ret) | |
492 | return ret; | |
493 | ||
47e8fe57 LK |
494 | ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq, |
495 | IRQF_TRIGGER_RISING, pdev->name, pspim); | |
496 | if (ret) | |
497 | return ret; | |
498 | ||
499 | ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq, | |
500 | IRQF_TRIGGER_RISING, pdev->name, pspim); | |
501 | if (ret) | |
502 | return ret; | |
503 | ||
f62ca4e2 LK |
504 | pm_runtime_enable(dev); |
505 | ret = spi_register_controller(ctlr); | |
506 | if (ret) { | |
507 | pm_runtime_disable(dev); | |
508 | return dev_err_probe(dev, ret, "spi_register_master fail\n"); | |
509 | } | |
510 | return 0; | |
511 | } | |
512 | ||
513 | static int sp7021_spi_controller_remove(struct platform_device *pdev) | |
514 | { | |
515 | struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); | |
516 | ||
517 | spi_unregister_controller(ctlr); | |
518 | pm_runtime_disable(&pdev->dev); | |
519 | pm_runtime_set_suspended(&pdev->dev); | |
520 | return 0; | |
521 | } | |
522 | ||
523 | static int __maybe_unused sp7021_spi_controller_suspend(struct device *dev) | |
524 | { | |
525 | struct spi_controller *ctlr = dev_get_drvdata(dev); | |
526 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
527 | ||
528 | return reset_control_assert(pspim->rstc); | |
529 | } | |
530 | ||
531 | static int __maybe_unused sp7021_spi_controller_resume(struct device *dev) | |
532 | { | |
533 | struct spi_controller *ctlr = dev_get_drvdata(dev); | |
534 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
535 | ||
536 | reset_control_deassert(pspim->rstc); | |
537 | return clk_prepare_enable(pspim->spi_clk); | |
538 | } | |
539 | ||
6938e02f | 540 | #ifdef CONFIG_PM |
f62ca4e2 LK |
541 | static int sp7021_spi_runtime_suspend(struct device *dev) |
542 | { | |
543 | struct spi_controller *ctlr = dev_get_drvdata(dev); | |
544 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
545 | ||
546 | return reset_control_assert(pspim->rstc); | |
547 | } | |
548 | ||
549 | static int sp7021_spi_runtime_resume(struct device *dev) | |
550 | { | |
551 | struct spi_controller *ctlr = dev_get_drvdata(dev); | |
552 | struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); | |
553 | ||
554 | return reset_control_deassert(pspim->rstc); | |
555 | } | |
6938e02f | 556 | #endif |
f62ca4e2 LK |
557 | |
558 | static const struct dev_pm_ops sp7021_spi_pm_ops = { | |
559 | SET_RUNTIME_PM_OPS(sp7021_spi_runtime_suspend, | |
560 | sp7021_spi_runtime_resume, NULL) | |
561 | SET_SYSTEM_SLEEP_PM_OPS(sp7021_spi_controller_suspend, | |
562 | sp7021_spi_controller_resume) | |
563 | }; | |
564 | ||
565 | static const struct of_device_id sp7021_spi_controller_ids[] = { | |
566 | { .compatible = "sunplus,sp7021-spi" }, | |
567 | {} | |
568 | }; | |
569 | MODULE_DEVICE_TABLE(of, sp7021_spi_controller_ids); | |
570 | ||
571 | static struct platform_driver sp7021_spi_controller_driver = { | |
572 | .probe = sp7021_spi_controller_probe, | |
573 | .remove = sp7021_spi_controller_remove, | |
574 | .driver = { | |
575 | .name = "sunplus,sp7021-spi-controller", | |
576 | .of_match_table = sp7021_spi_controller_ids, | |
577 | .pm = &sp7021_spi_pm_ops, | |
578 | }, | |
579 | }; | |
580 | module_platform_driver(sp7021_spi_controller_driver); | |
581 | ||
582 | MODULE_AUTHOR("Li-hao Kuo <lhjeff911@gmail.com>"); | |
583 | MODULE_DESCRIPTION("Sunplus SPI controller driver"); | |
584 | MODULE_LICENSE("GPL"); |