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