1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Renesas RZ/V2M Clocked Serial Interface (CSI) driver |
4 | * |
5 | * Copyright (C) 2023 Renesas Electronics Corporation |
6 | */ |
7 | |
8 | #include <linux/bits.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/count_zeros.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/iopoll.h> |
13 | #include <linux/log2.h> |
14 | #include <linux/of.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/property.h> |
17 | #include <linux/reset.h> |
18 | #include <linux/spi/spi.h> |
19 | #include <linux/units.h> |
20 | |
21 | /* Registers */ |
22 | #define CSI_MODE 0x00 /* CSI mode control */ |
23 | #define CSI_CLKSEL 0x04 /* CSI clock select */ |
24 | #define CSI_CNT 0x08 /* CSI control */ |
25 | #define CSI_INT 0x0C /* CSI interrupt status */ |
26 | #define CSI_IFIFOL 0x10 /* CSI receive FIFO level display */ |
27 | #define CSI_OFIFOL 0x14 /* CSI transmit FIFO level display */ |
28 | #define CSI_IFIFO 0x18 /* CSI receive window */ |
29 | #define CSI_OFIFO 0x1C /* CSI transmit window */ |
30 | #define CSI_FIFOTRG 0x20 /* CSI FIFO trigger level */ |
31 | |
32 | /* CSI_MODE */ |
33 | #define CSI_MODE_CSIE BIT(7) |
34 | #define CSI_MODE_TRMD BIT(6) |
35 | #define CSI_MODE_CCL BIT(5) |
36 | #define CSI_MODE_DIR BIT(4) |
37 | #define CSI_MODE_CSOT BIT(0) |
38 | |
39 | #define CSI_MODE_SETUP 0x00000040 |
40 | |
41 | /* CSI_CLKSEL */ |
42 | #define CSI_CLKSEL_SS_ENA BIT(19) |
43 | #define CSI_CLKSEL_SS_POL BIT(18) |
44 | #define CSI_CLKSEL_SS (CSI_CLKSEL_SS_ENA | CSI_CLKSEL_SS_POL) |
45 | #define CSI_CLKSEL_CKP BIT(17) |
46 | #define CSI_CLKSEL_DAP BIT(16) |
47 | #define CSI_CLKSEL_MODE (CSI_CLKSEL_CKP|CSI_CLKSEL_DAP) |
48 | #define CSI_CLKSEL_SLAVE BIT(15) |
49 | #define CSI_CLKSEL_CKS GENMASK(14, 1) |
50 | |
51 | /* CSI_CNT */ |
52 | #define CSI_CNT_CSIRST BIT(28) |
53 | #define CSI_CNT_R_TRGEN BIT(19) |
54 | #define CSI_CNT_UNDER_E BIT(13) |
55 | #define CSI_CNT_OVERF_E BIT(12) |
56 | #define CSI_CNT_TREND_E BIT(9) |
57 | #define CSI_CNT_CSIEND_E BIT(8) |
58 | #define CSI_CNT_T_TRGR_E BIT(4) |
59 | #define CSI_CNT_R_TRGR_E BIT(0) |
60 | |
61 | /* CSI_INT */ |
62 | #define CSI_INT_UNDER BIT(13) |
63 | #define CSI_INT_OVERF BIT(12) |
64 | #define CSI_INT_TREND BIT(9) |
65 | #define CSI_INT_CSIEND BIT(8) |
66 | #define CSI_INT_T_TRGR BIT(4) |
67 | #define CSI_INT_R_TRGR BIT(0) |
68 | |
69 | /* CSI_FIFOTRG */ |
70 | #define CSI_FIFOTRG_R_TRG GENMASK(2, 0) |
71 | |
72 | #define CSI_FIFO_SIZE_BYTES 32U |
73 | #define CSI_FIFO_HALF_SIZE 16U |
74 | #define CSI_EN_DIS_TIMEOUT_US 100 |
75 | /* |
76 | * Clock "csiclk" gets divided by 2 * CSI_CLKSEL_CKS in order to generate the |
77 | * serial clock (output from master), with CSI_CLKSEL_CKS ranging from 0x1 (that |
78 | * means "csiclk" is divided by 2) to 0x3FFF ("csiclk" is divided by 32766). |
79 | */ |
80 | #define CSI_CKS_MAX GENMASK(13, 0) |
81 | |
82 | #define UNDERRUN_ERROR BIT(0) |
83 | #define OVERFLOW_ERROR BIT(1) |
84 | #define TX_TIMEOUT_ERROR BIT(2) |
85 | #define RX_TIMEOUT_ERROR BIT(3) |
86 | |
87 | #define CSI_MAX_SPI_SCKO (8 * HZ_PER_MHZ) |
88 | |
89 | #define CSI_CLKSEL_SS_DISABLED 0 |
90 | #define CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW BIT(1) |
91 | #define CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH GENMASK(1, 0) |
92 | |
93 | struct rzv2m_csi_priv { |
94 | void __iomem *base; |
95 | struct clk *csiclk; |
96 | struct clk *pclk; |
97 | struct device *dev; |
98 | struct spi_controller *controller; |
99 | const void *txbuf; |
100 | void *rxbuf; |
101 | unsigned int buffer_len; |
102 | unsigned int bytes_sent; |
103 | unsigned int bytes_received; |
104 | unsigned int bytes_to_transfer; |
105 | unsigned int words_to_transfer; |
106 | unsigned int bytes_per_word; |
107 | wait_queue_head_t wait; |
108 | u32 errors; |
109 | u32 status; |
110 | bool target_aborted; |
111 | bool use_ss_pin; |
112 | }; |
113 | |
114 | static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi, |
115 | int reg_offs, int bit_mask, u32 value) |
116 | { |
117 | int nr_zeros; |
118 | u32 tmp; |
119 | |
120 | nr_zeros = count_trailing_zeros(x: bit_mask); |
121 | value <<= nr_zeros; |
122 | |
123 | tmp = (readl(addr: csi->base + reg_offs) & ~bit_mask) | value; |
124 | writel(val: tmp, addr: csi->base + reg_offs); |
125 | } |
126 | |
127 | static int rzv2m_csi_sw_reset(struct rzv2m_csi_priv *csi, int assert) |
128 | { |
129 | u32 reg; |
130 | |
131 | rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_CSIRST, value: assert); |
132 | |
133 | if (!assert) |
134 | return 0; |
135 | |
136 | return readl_poll_timeout(csi->base + CSI_MODE, reg, |
137 | !(reg & CSI_MODE_CSOT), 0, |
138 | CSI_EN_DIS_TIMEOUT_US); |
139 | } |
140 | |
141 | static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi, |
142 | int enable, bool wait) |
143 | { |
144 | u32 reg; |
145 | |
146 | rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CSIE, value: enable); |
147 | |
148 | if (enable || !wait) |
149 | return 0; |
150 | |
151 | return readl_poll_timeout(csi->base + CSI_MODE, reg, |
152 | !(reg & CSI_MODE_CSOT), 0, |
153 | CSI_EN_DIS_TIMEOUT_US); |
154 | } |
155 | |
156 | static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi) |
157 | { |
158 | unsigned int i; |
159 | |
160 | if (readl(addr: csi->base + CSI_OFIFOL)) |
161 | return -EIO; |
162 | |
163 | if (csi->bytes_per_word == 2) { |
164 | const u16 *buf = csi->txbuf; |
165 | |
166 | for (i = 0; i < csi->words_to_transfer; i++) |
167 | writel(val: buf[i], addr: csi->base + CSI_OFIFO); |
168 | } else { |
169 | const u8 *buf = csi->txbuf; |
170 | |
171 | for (i = 0; i < csi->words_to_transfer; i++) |
172 | writel(val: buf[i], addr: csi->base + CSI_OFIFO); |
173 | } |
174 | |
175 | csi->txbuf += csi->bytes_to_transfer; |
176 | csi->bytes_sent += csi->bytes_to_transfer; |
177 | |
178 | return 0; |
179 | } |
180 | |
181 | static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi) |
182 | { |
183 | unsigned int i; |
184 | |
185 | if (readl(addr: csi->base + CSI_IFIFOL) != csi->bytes_to_transfer) |
186 | return -EIO; |
187 | |
188 | if (csi->bytes_per_word == 2) { |
189 | u16 *buf = csi->rxbuf; |
190 | |
191 | for (i = 0; i < csi->words_to_transfer; i++) |
192 | buf[i] = (u16)readl(addr: csi->base + CSI_IFIFO); |
193 | } else { |
194 | u8 *buf = csi->rxbuf; |
195 | |
196 | for (i = 0; i < csi->words_to_transfer; i++) |
197 | buf[i] = (u8)readl(addr: csi->base + CSI_IFIFO); |
198 | } |
199 | |
200 | csi->rxbuf += csi->bytes_to_transfer; |
201 | csi->bytes_received += csi->bytes_to_transfer; |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | static inline void rzv2m_csi_empty_rxfifo(struct rzv2m_csi_priv *csi) |
207 | { |
208 | unsigned int i; |
209 | |
210 | for (i = 0; i < csi->words_to_transfer; i++) |
211 | readl(addr: csi->base + CSI_IFIFO); |
212 | } |
213 | |
214 | static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) |
215 | { |
216 | unsigned int bytes_transferred = max(csi->bytes_received, csi->bytes_sent); |
217 | unsigned int bytes_remaining = csi->buffer_len - bytes_transferred; |
218 | unsigned int to_transfer; |
219 | |
220 | if (csi->txbuf) |
221 | /* |
222 | * Leaving a little bit of headroom in the FIFOs makes it very |
223 | * hard to raise an overflow error (which is only possible |
224 | * when IP transmits and receives at the same time). |
225 | */ |
226 | to_transfer = min(CSI_FIFO_HALF_SIZE, bytes_remaining); |
227 | else |
228 | to_transfer = min(CSI_FIFO_SIZE_BYTES, bytes_remaining); |
229 | |
230 | if (csi->bytes_per_word == 2) |
231 | to_transfer >>= 1; |
232 | |
233 | /* |
234 | * We can only choose a trigger level from a predefined set of values. |
235 | * This will pick a value that is the greatest possible integer that's |
236 | * less than or equal to the number of bytes we need to transfer. |
237 | * This may result in multiple smaller transfers. |
238 | */ |
239 | csi->words_to_transfer = rounddown_pow_of_two(to_transfer); |
240 | |
241 | if (csi->bytes_per_word == 2) |
242 | csi->bytes_to_transfer = csi->words_to_transfer << 1; |
243 | else |
244 | csi->bytes_to_transfer = csi->words_to_transfer; |
245 | } |
246 | |
247 | static inline void rzv2m_csi_set_rx_fifo_trigger_level(struct rzv2m_csi_priv *csi) |
248 | { |
249 | rzv2m_csi_reg_write_bit(csi, CSI_FIFOTRG, CSI_FIFOTRG_R_TRG, |
250 | ilog2(csi->words_to_transfer)); |
251 | } |
252 | |
253 | static inline void rzv2m_csi_enable_rx_trigger(struct rzv2m_csi_priv *csi, |
254 | bool enable) |
255 | { |
256 | rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_R_TRGEN, value: enable); |
257 | } |
258 | |
259 | static void rzv2m_csi_disable_irqs(const struct rzv2m_csi_priv *csi, |
260 | u32 enable_bits) |
261 | { |
262 | u32 cnt = readl(addr: csi->base + CSI_CNT); |
263 | |
264 | writel(val: cnt & ~enable_bits, addr: csi->base + CSI_CNT); |
265 | } |
266 | |
267 | static void rzv2m_csi_disable_all_irqs(struct rzv2m_csi_priv *csi) |
268 | { |
269 | rzv2m_csi_disable_irqs(csi, CSI_CNT_R_TRGR_E | CSI_CNT_T_TRGR_E | |
270 | CSI_CNT_CSIEND_E | CSI_CNT_TREND_E | |
271 | CSI_CNT_OVERF_E | CSI_CNT_UNDER_E); |
272 | } |
273 | |
274 | static inline void rzv2m_csi_clear_irqs(struct rzv2m_csi_priv *csi, u32 irqs) |
275 | { |
276 | writel(val: irqs, addr: csi->base + CSI_INT); |
277 | } |
278 | |
279 | static void rzv2m_csi_clear_all_irqs(struct rzv2m_csi_priv *csi) |
280 | { |
281 | rzv2m_csi_clear_irqs(csi, CSI_INT_UNDER | CSI_INT_OVERF | |
282 | CSI_INT_TREND | CSI_INT_CSIEND | CSI_INT_T_TRGR | |
283 | CSI_INT_R_TRGR); |
284 | } |
285 | |
286 | static void rzv2m_csi_enable_irqs(struct rzv2m_csi_priv *csi, u32 enable_bits) |
287 | { |
288 | u32 cnt = readl(addr: csi->base + CSI_CNT); |
289 | |
290 | writel(val: cnt | enable_bits, addr: csi->base + CSI_CNT); |
291 | } |
292 | |
293 | static int rzv2m_csi_wait_for_interrupt(struct rzv2m_csi_priv *csi, |
294 | u32 wait_mask, u32 enable_bits) |
295 | { |
296 | int ret; |
297 | |
298 | rzv2m_csi_enable_irqs(csi, enable_bits); |
299 | |
300 | if (spi_controller_is_target(ctlr: csi->controller)) { |
301 | ret = wait_event_interruptible(csi->wait, |
302 | ((csi->status & wait_mask) == wait_mask) || |
303 | csi->errors || csi->target_aborted); |
304 | if (ret || csi->target_aborted) |
305 | ret = -EINTR; |
306 | } else { |
307 | ret = wait_event_timeout(csi->wait, |
308 | ((csi->status & wait_mask) == wait_mask) || |
309 | csi->errors, HZ) == 0 ? -ETIMEDOUT : 0; |
310 | } |
311 | |
312 | rzv2m_csi_disable_irqs(csi, enable_bits); |
313 | |
314 | if (csi->errors) |
315 | return -EIO; |
316 | |
317 | return ret; |
318 | } |
319 | |
320 | static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi) |
321 | { |
322 | int ret; |
323 | |
324 | if (readl(addr: csi->base + CSI_IFIFOL) >= csi->bytes_to_transfer) |
325 | return 0; |
326 | |
327 | ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR, |
328 | CSI_CNT_R_TRGR_E); |
329 | if (ret == -ETIMEDOUT) |
330 | csi->errors |= RX_TIMEOUT_ERROR; |
331 | |
332 | return ret; |
333 | } |
334 | |
335 | static irqreturn_t rzv2m_csi_irq_handler(int irq, void *data) |
336 | { |
337 | struct rzv2m_csi_priv *csi = data; |
338 | |
339 | csi->status = readl(addr: csi->base + CSI_INT); |
340 | rzv2m_csi_disable_irqs(csi, enable_bits: csi->status); |
341 | |
342 | if (csi->status & CSI_INT_OVERF) |
343 | csi->errors |= OVERFLOW_ERROR; |
344 | if (csi->status & CSI_INT_UNDER) |
345 | csi->errors |= UNDERRUN_ERROR; |
346 | |
347 | wake_up(&csi->wait); |
348 | |
349 | return IRQ_HANDLED; |
350 | } |
351 | |
352 | static void rzv2m_csi_setup_clock(struct rzv2m_csi_priv *csi, u32 spi_hz) |
353 | { |
354 | unsigned long csiclk_rate = clk_get_rate(clk: csi->csiclk); |
355 | unsigned long pclk_rate = clk_get_rate(clk: csi->pclk); |
356 | unsigned long csiclk_rate_limit = pclk_rate >> 1; |
357 | u32 cks; |
358 | |
359 | /* |
360 | * There is a restriction on the frequency of CSICLK, it has to be <= |
361 | * PCLK / 2. |
362 | */ |
363 | if (csiclk_rate > csiclk_rate_limit) { |
364 | clk_set_rate(clk: csi->csiclk, rate: csiclk_rate >> 1); |
365 | csiclk_rate = clk_get_rate(clk: csi->csiclk); |
366 | } else if ((csiclk_rate << 1) <= csiclk_rate_limit) { |
367 | clk_set_rate(clk: csi->csiclk, rate: csiclk_rate << 1); |
368 | csiclk_rate = clk_get_rate(clk: csi->csiclk); |
369 | } |
370 | |
371 | spi_hz = spi_hz > CSI_MAX_SPI_SCKO ? CSI_MAX_SPI_SCKO : spi_hz; |
372 | |
373 | cks = DIV_ROUND_UP(csiclk_rate, spi_hz << 1); |
374 | if (cks > CSI_CKS_MAX) |
375 | cks = CSI_CKS_MAX; |
376 | |
377 | dev_dbg(csi->dev, "SPI clk rate is %ldHz\n" , csiclk_rate / (cks << 1)); |
378 | |
379 | rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKS, value: cks); |
380 | } |
381 | |
382 | static void rzv2m_csi_setup_operating_mode(struct rzv2m_csi_priv *csi, |
383 | struct spi_transfer *t) |
384 | { |
385 | if (t->rx_buf && !t->tx_buf) |
386 | /* Reception-only mode */ |
387 | rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, value: 0); |
388 | else |
389 | /* Send and receive mode */ |
390 | rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_TRMD, value: 1); |
391 | |
392 | csi->bytes_per_word = t->bits_per_word / 8; |
393 | rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CCL, |
394 | value: csi->bytes_per_word == 2); |
395 | } |
396 | |
397 | static int rzv2m_csi_setup(struct spi_device *spi) |
398 | { |
399 | struct rzv2m_csi_priv *csi = spi_controller_get_devdata(ctlr: spi->controller); |
400 | u32 slave_selection = CSI_CLKSEL_SS_DISABLED; |
401 | int ret; |
402 | |
403 | rzv2m_csi_sw_reset(csi, assert: 0); |
404 | |
405 | writel(CSI_MODE_SETUP, addr: csi->base + CSI_MODE); |
406 | |
407 | /* Setup clock polarity and phase timing */ |
408 | rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_MODE, |
409 | value: ~spi->mode & SPI_MODE_X_MASK); |
410 | |
411 | /* Setup serial data order */ |
412 | rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR, |
413 | value: !!(spi->mode & SPI_LSB_FIRST)); |
414 | |
415 | /* Set the role, 1 for target and 0 for host */ |
416 | rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SLAVE, |
417 | value: !!spi_controller_is_target(ctlr: csi->controller)); |
418 | |
419 | if (csi->use_ss_pin) |
420 | slave_selection = spi->mode & SPI_CS_HIGH ? |
421 | CSI_CLKSEL_SS_ENABLED_ACTIVE_HIGH : |
422 | CSI_CLKSEL_SS_ENABLED_ACTIVE_LOW; |
423 | |
424 | /* Configure the slave selection (SS) pin */ |
425 | rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_SS, value: slave_selection); |
426 | |
427 | /* Give the IP a SW reset */ |
428 | ret = rzv2m_csi_sw_reset(csi, assert: 1); |
429 | if (ret) |
430 | return ret; |
431 | rzv2m_csi_sw_reset(csi, assert: 0); |
432 | |
433 | /* |
434 | * We need to enable the communication so that the clock will settle |
435 | * for the right polarity before enabling the CS. |
436 | */ |
437 | rzv2m_csi_start_stop_operation(csi, enable: 1, wait: false); |
438 | udelay(10); |
439 | rzv2m_csi_start_stop_operation(csi, enable: 0, wait: false); |
440 | |
441 | return 0; |
442 | } |
443 | |
444 | static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) |
445 | { |
446 | bool tx_completed = !csi->txbuf; |
447 | bool rx_completed = !csi->rxbuf; |
448 | int ret = 0; |
449 | |
450 | /* Make sure the TX FIFO is empty */ |
451 | writel(val: 0, addr: csi->base + CSI_OFIFOL); |
452 | |
453 | /* Make sure the RX FIFO is empty */ |
454 | writel(val: 0, addr: csi->base + CSI_IFIFOL); |
455 | |
456 | csi->bytes_sent = 0; |
457 | csi->bytes_received = 0; |
458 | csi->errors = 0; |
459 | csi->target_aborted = false; |
460 | |
461 | rzv2m_csi_disable_all_irqs(csi); |
462 | rzv2m_csi_clear_all_irqs(csi); |
463 | rzv2m_csi_enable_rx_trigger(csi, enable: true); |
464 | |
465 | while (!tx_completed || !rx_completed) { |
466 | /* |
467 | * Decide how many words we are going to transfer during |
468 | * this cycle (for both TX and RX), then set the RX FIFO trigger |
469 | * level accordingly. No need to set a trigger level for the |
470 | * TX FIFO, as this IP comes with an interrupt that fires when |
471 | * the TX FIFO is empty. |
472 | */ |
473 | rzv2m_csi_calc_current_transfer(csi); |
474 | rzv2m_csi_set_rx_fifo_trigger_level(csi); |
475 | |
476 | rzv2m_csi_enable_irqs(csi, CSI_INT_OVERF | CSI_INT_UNDER); |
477 | |
478 | writel(readl(addr: csi->base + CSI_INT), addr: csi->base + CSI_INT); |
479 | csi->status = 0; |
480 | |
481 | /* TX */ |
482 | if (csi->txbuf) { |
483 | ret = rzv2m_csi_fill_txfifo(csi); |
484 | if (ret) |
485 | break; |
486 | |
487 | if (csi->bytes_sent == csi->buffer_len) |
488 | tx_completed = true; |
489 | } |
490 | |
491 | rzv2m_csi_start_stop_operation(csi, enable: 1, wait: false); |
492 | |
493 | /* |
494 | * Make sure the RX FIFO contains the desired number of words. |
495 | * We then either flush its content, or we copy it onto |
496 | * csi->rxbuf. |
497 | */ |
498 | ret = rzv2m_csi_wait_for_rx_ready(csi); |
499 | if (ret) |
500 | break; |
501 | |
502 | if (!spi_controller_is_target(ctlr: csi->controller)) |
503 | rzv2m_csi_start_stop_operation(csi, enable: 0, wait: false); |
504 | |
505 | /* RX */ |
506 | if (csi->rxbuf) { |
507 | ret = rzv2m_csi_read_rxfifo(csi); |
508 | if (ret) |
509 | break; |
510 | |
511 | if (csi->bytes_received == csi->buffer_len) |
512 | rx_completed = true; |
513 | } else { |
514 | rzv2m_csi_empty_rxfifo(csi); |
515 | } |
516 | |
517 | if (csi->errors) { |
518 | ret = -EIO; |
519 | break; |
520 | } |
521 | } |
522 | |
523 | rzv2m_csi_start_stop_operation(csi, enable: 0, wait: true); |
524 | rzv2m_csi_disable_all_irqs(csi); |
525 | rzv2m_csi_enable_rx_trigger(csi, enable: false); |
526 | rzv2m_csi_clear_all_irqs(csi); |
527 | |
528 | return ret; |
529 | } |
530 | |
531 | static int rzv2m_csi_transfer_one(struct spi_controller *controller, |
532 | struct spi_device *spi, |
533 | struct spi_transfer *transfer) |
534 | { |
535 | struct rzv2m_csi_priv *csi = spi_controller_get_devdata(ctlr: controller); |
536 | struct device *dev = csi->dev; |
537 | int ret; |
538 | |
539 | csi->txbuf = transfer->tx_buf; |
540 | csi->rxbuf = transfer->rx_buf; |
541 | csi->buffer_len = transfer->len; |
542 | |
543 | rzv2m_csi_setup_operating_mode(csi, t: transfer); |
544 | |
545 | if (!spi_controller_is_target(ctlr: csi->controller)) |
546 | rzv2m_csi_setup_clock(csi, spi_hz: transfer->speed_hz); |
547 | |
548 | ret = rzv2m_csi_pio_transfer(csi); |
549 | if (ret) { |
550 | if (csi->errors & UNDERRUN_ERROR) |
551 | dev_err(dev, "Underrun error\n" ); |
552 | if (csi->errors & OVERFLOW_ERROR) |
553 | dev_err(dev, "Overflow error\n" ); |
554 | if (csi->errors & TX_TIMEOUT_ERROR) |
555 | dev_err(dev, "TX timeout error\n" ); |
556 | if (csi->errors & RX_TIMEOUT_ERROR) |
557 | dev_err(dev, "RX timeout error\n" ); |
558 | } |
559 | |
560 | return ret; |
561 | } |
562 | |
563 | static int rzv2m_csi_target_abort(struct spi_controller *ctlr) |
564 | { |
565 | struct rzv2m_csi_priv *csi = spi_controller_get_devdata(ctlr); |
566 | |
567 | csi->target_aborted = true; |
568 | wake_up(&csi->wait); |
569 | |
570 | return 0; |
571 | } |
572 | |
573 | static int rzv2m_csi_probe(struct platform_device *pdev) |
574 | { |
575 | struct device_node *np = pdev->dev.of_node; |
576 | struct spi_controller *controller; |
577 | struct device *dev = &pdev->dev; |
578 | struct rzv2m_csi_priv *csi; |
579 | struct reset_control *rstc; |
580 | bool target_mode; |
581 | int irq; |
582 | int ret; |
583 | |
584 | target_mode = of_property_read_bool(np, propname: "spi-slave" ); |
585 | |
586 | if (target_mode) |
587 | controller = devm_spi_alloc_target(dev, size: sizeof(*csi)); |
588 | else |
589 | controller = devm_spi_alloc_host(dev, size: sizeof(*csi)); |
590 | |
591 | if (!controller) |
592 | return -ENOMEM; |
593 | |
594 | csi = spi_controller_get_devdata(ctlr: controller); |
595 | platform_set_drvdata(pdev, data: csi); |
596 | |
597 | csi->use_ss_pin = false; |
598 | if (spi_controller_is_target(ctlr: controller) && |
599 | !of_property_read_bool(np, propname: "renesas,csi-no-ss" )) |
600 | csi->use_ss_pin = true; |
601 | |
602 | csi->dev = dev; |
603 | csi->controller = controller; |
604 | csi->target_aborted = false; |
605 | |
606 | csi->base = devm_platform_ioremap_resource(pdev, index: 0); |
607 | if (IS_ERR(ptr: csi->base)) |
608 | return PTR_ERR(ptr: csi->base); |
609 | |
610 | irq = platform_get_irq(pdev, 0); |
611 | if (irq < 0) |
612 | return irq; |
613 | |
614 | csi->csiclk = devm_clk_get(dev, id: "csiclk" ); |
615 | if (IS_ERR(ptr: csi->csiclk)) |
616 | return dev_err_probe(dev, err: PTR_ERR(ptr: csi->csiclk), |
617 | fmt: "could not get csiclk\n" ); |
618 | |
619 | csi->pclk = devm_clk_get(dev, id: "pclk" ); |
620 | if (IS_ERR(ptr: csi->pclk)) |
621 | return dev_err_probe(dev, err: PTR_ERR(ptr: csi->pclk), |
622 | fmt: "could not get pclk\n" ); |
623 | |
624 | rstc = devm_reset_control_get_shared(dev, NULL); |
625 | if (IS_ERR(ptr: rstc)) |
626 | return dev_err_probe(dev, err: PTR_ERR(ptr: rstc), fmt: "Missing reset ctrl\n" ); |
627 | |
628 | init_waitqueue_head(&csi->wait); |
629 | |
630 | controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH; |
631 | controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); |
632 | controller->setup = rzv2m_csi_setup; |
633 | controller->transfer_one = rzv2m_csi_transfer_one; |
634 | controller->use_gpio_descriptors = true; |
635 | controller->target_abort = rzv2m_csi_target_abort; |
636 | |
637 | device_set_node(dev: &controller->dev, dev_fwnode(dev)); |
638 | |
639 | ret = devm_request_irq(dev, irq, handler: rzv2m_csi_irq_handler, irqflags: 0, |
640 | devname: dev_name(dev), dev_id: csi); |
641 | if (ret) |
642 | return dev_err_probe(dev, err: ret, fmt: "cannot request IRQ\n" ); |
643 | |
644 | /* |
645 | * The reset also affects other HW that is not under the control |
646 | * of Linux. Therefore, all we can do is make sure the reset is |
647 | * deasserted. |
648 | */ |
649 | reset_control_deassert(rstc); |
650 | |
651 | /* Make sure the IP is in SW reset state */ |
652 | ret = rzv2m_csi_sw_reset(csi, assert: 1); |
653 | if (ret) |
654 | return ret; |
655 | |
656 | ret = clk_prepare_enable(clk: csi->csiclk); |
657 | if (ret) |
658 | return dev_err_probe(dev, err: ret, fmt: "could not enable csiclk\n" ); |
659 | |
660 | ret = spi_register_controller(ctlr: controller); |
661 | if (ret) { |
662 | clk_disable_unprepare(clk: csi->csiclk); |
663 | return dev_err_probe(dev, err: ret, fmt: "register controller failed\n" ); |
664 | } |
665 | |
666 | return 0; |
667 | } |
668 | |
669 | static void rzv2m_csi_remove(struct platform_device *pdev) |
670 | { |
671 | struct rzv2m_csi_priv *csi = platform_get_drvdata(pdev); |
672 | |
673 | spi_unregister_controller(ctlr: csi->controller); |
674 | rzv2m_csi_sw_reset(csi, assert: 1); |
675 | clk_disable_unprepare(clk: csi->csiclk); |
676 | } |
677 | |
678 | static const struct of_device_id rzv2m_csi_match[] = { |
679 | { .compatible = "renesas,rzv2m-csi" }, |
680 | { /* sentinel */ } |
681 | }; |
682 | MODULE_DEVICE_TABLE(of, rzv2m_csi_match); |
683 | |
684 | static struct platform_driver rzv2m_csi_drv = { |
685 | .probe = rzv2m_csi_probe, |
686 | .remove_new = rzv2m_csi_remove, |
687 | .driver = { |
688 | .name = "rzv2m_csi" , |
689 | .of_match_table = rzv2m_csi_match, |
690 | }, |
691 | }; |
692 | module_platform_driver(rzv2m_csi_drv); |
693 | |
694 | MODULE_LICENSE("GPL" ); |
695 | MODULE_AUTHOR("Fabrizio Castro <castro.fabrizio.jz@renesas.com>" ); |
696 | MODULE_DESCRIPTION("Clocked Serial Interface Driver" ); |
697 | |