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