]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
3558fe90 MR |
2 | /* |
3 | * Copyright (C) 2012 - 2014 Allwinner Tech | |
4 | * Pan Nan <pannan@allwinnertech.com> | |
5 | * | |
6 | * Copyright (C) 2014 Maxime Ripard | |
7 | * Maxime Ripard <maxime.ripard@free-electrons.com> | |
3558fe90 MR |
8 | */ |
9 | ||
9a3ef9df | 10 | #include <linux/bitfield.h> |
3558fe90 MR |
11 | #include <linux/clk.h> |
12 | #include <linux/delay.h> | |
13 | #include <linux/device.h> | |
14 | #include <linux/interrupt.h> | |
15 | #include <linux/io.h> | |
16 | #include <linux/module.h> | |
10565dfd | 17 | #include <linux/of_device.h> |
3558fe90 MR |
18 | #include <linux/platform_device.h> |
19 | #include <linux/pm_runtime.h> | |
20 | #include <linux/reset.h> | |
3558fe90 MR |
21 | |
22 | #include <linux/spi/spi.h> | |
23 | ||
24 | #define SUN6I_FIFO_DEPTH 128 | |
10565dfd | 25 | #define SUN8I_FIFO_DEPTH 64 |
3558fe90 MR |
26 | |
27 | #define SUN6I_GBL_CTL_REG 0x04 | |
28 | #define SUN6I_GBL_CTL_BUS_ENABLE BIT(0) | |
29 | #define SUN6I_GBL_CTL_MASTER BIT(1) | |
30 | #define SUN6I_GBL_CTL_TP BIT(7) | |
31 | #define SUN6I_GBL_CTL_RST BIT(31) | |
32 | ||
33 | #define SUN6I_TFR_CTL_REG 0x08 | |
34 | #define SUN6I_TFR_CTL_CPHA BIT(0) | |
35 | #define SUN6I_TFR_CTL_CPOL BIT(1) | |
36 | #define SUN6I_TFR_CTL_SPOL BIT(2) | |
d31ad46f AL |
37 | #define SUN6I_TFR_CTL_CS_MASK 0x30 |
38 | #define SUN6I_TFR_CTL_CS(cs) (((cs) << 4) & SUN6I_TFR_CTL_CS_MASK) | |
3558fe90 MR |
39 | #define SUN6I_TFR_CTL_CS_MANUAL BIT(6) |
40 | #define SUN6I_TFR_CTL_CS_LEVEL BIT(7) | |
41 | #define SUN6I_TFR_CTL_DHB BIT(8) | |
42 | #define SUN6I_TFR_CTL_FBS BIT(12) | |
43 | #define SUN6I_TFR_CTL_XCH BIT(31) | |
44 | ||
45 | #define SUN6I_INT_CTL_REG 0x10 | |
913f536c IZ |
46 | #define SUN6I_INT_CTL_RF_RDY BIT(0) |
47 | #define SUN6I_INT_CTL_TF_ERQ BIT(4) | |
3558fe90 MR |
48 | #define SUN6I_INT_CTL_RF_OVF BIT(8) |
49 | #define SUN6I_INT_CTL_TC BIT(12) | |
50 | ||
51 | #define SUN6I_INT_STA_REG 0x14 | |
52 | ||
53 | #define SUN6I_FIFO_CTL_REG 0x18 | |
913f536c IZ |
54 | #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_MASK 0xff |
55 | #define SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS 0 | |
3558fe90 | 56 | #define SUN6I_FIFO_CTL_RF_RST BIT(15) |
913f536c IZ |
57 | #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_MASK 0xff |
58 | #define SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS 16 | |
3558fe90 MR |
59 | #define SUN6I_FIFO_CTL_TF_RST BIT(31) |
60 | ||
61 | #define SUN6I_FIFO_STA_REG 0x1c | |
5197da03 | 62 | #define SUN6I_FIFO_STA_RF_CNT_MASK GENMASK(7, 0) |
9a3ef9df | 63 | #define SUN6I_FIFO_STA_TF_CNT_MASK GENMASK(23, 16) |
3558fe90 MR |
64 | |
65 | #define SUN6I_CLK_CTL_REG 0x24 | |
66 | #define SUN6I_CLK_CTL_CDR2_MASK 0xff | |
67 | #define SUN6I_CLK_CTL_CDR2(div) (((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0) | |
68 | #define SUN6I_CLK_CTL_CDR1_MASK 0xf | |
69 | #define SUN6I_CLK_CTL_CDR1(div) (((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8) | |
70 | #define SUN6I_CLK_CTL_DRS BIT(12) | |
71 | ||
913f536c IZ |
72 | #define SUN6I_MAX_XFER_SIZE 0xffffff |
73 | ||
3558fe90 | 74 | #define SUN6I_BURST_CNT_REG 0x30 |
3558fe90 MR |
75 | |
76 | #define SUN6I_XMIT_CNT_REG 0x34 | |
3558fe90 MR |
77 | |
78 | #define SUN6I_BURST_CTL_CNT_REG 0x38 | |
3558fe90 MR |
79 | |
80 | #define SUN6I_TXDATA_REG 0x200 | |
81 | #define SUN6I_RXDATA_REG 0x300 | |
82 | ||
83 | struct sun6i_spi { | |
84 | struct spi_master *master; | |
85 | void __iomem *base_addr; | |
86 | struct clk *hclk; | |
87 | struct clk *mclk; | |
88 | struct reset_control *rstc; | |
89 | ||
90 | struct completion done; | |
91 | ||
92 | const u8 *tx_buf; | |
93 | u8 *rx_buf; | |
94 | int len; | |
10565dfd | 95 | unsigned long fifo_depth; |
3558fe90 MR |
96 | }; |
97 | ||
98 | static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) | |
99 | { | |
100 | return readl(sspi->base_addr + reg); | |
101 | } | |
102 | ||
103 | static inline void sun6i_spi_write(struct sun6i_spi *sspi, u32 reg, u32 value) | |
104 | { | |
105 | writel(value, sspi->base_addr + reg); | |
106 | } | |
107 | ||
5197da03 MKB |
108 | static inline u32 sun6i_spi_get_rx_fifo_count(struct sun6i_spi *sspi) |
109 | { | |
110 | u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG); | |
111 | ||
112 | return FIELD_GET(SUN6I_FIFO_STA_RF_CNT_MASK, reg); | |
113 | } | |
114 | ||
913f536c IZ |
115 | static inline u32 sun6i_spi_get_tx_fifo_count(struct sun6i_spi *sspi) |
116 | { | |
117 | u32 reg = sun6i_spi_read(sspi, SUN6I_FIFO_STA_REG); | |
118 | ||
9a3ef9df | 119 | return FIELD_GET(SUN6I_FIFO_STA_TF_CNT_MASK, reg); |
913f536c IZ |
120 | } |
121 | ||
122 | static inline void sun6i_spi_enable_interrupt(struct sun6i_spi *sspi, u32 mask) | |
123 | { | |
124 | u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG); | |
125 | ||
126 | reg |= mask; | |
127 | sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg); | |
128 | } | |
129 | ||
130 | static inline void sun6i_spi_disable_interrupt(struct sun6i_spi *sspi, u32 mask) | |
131 | { | |
132 | u32 reg = sun6i_spi_read(sspi, SUN6I_INT_CTL_REG); | |
133 | ||
134 | reg &= ~mask; | |
135 | sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, reg); | |
136 | } | |
137 | ||
92a52ee8 | 138 | static inline void sun6i_spi_drain_fifo(struct sun6i_spi *sspi) |
3558fe90 | 139 | { |
92a52ee8 | 140 | u32 len; |
3558fe90 MR |
141 | u8 byte; |
142 | ||
143 | /* See how much data is available */ | |
92a52ee8 | 144 | len = sun6i_spi_get_rx_fifo_count(sspi); |
3558fe90 MR |
145 | |
146 | while (len--) { | |
147 | byte = readb(sspi->base_addr + SUN6I_RXDATA_REG); | |
148 | if (sspi->rx_buf) | |
149 | *sspi->rx_buf++ = byte; | |
150 | } | |
151 | } | |
152 | ||
e4e8ca3f | 153 | static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi) |
3558fe90 | 154 | { |
913f536c | 155 | u32 cnt; |
e4e8ca3f | 156 | int len; |
3558fe90 MR |
157 | u8 byte; |
158 | ||
913f536c IZ |
159 | /* See how much data we can fit */ |
160 | cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi); | |
161 | ||
e4e8ca3f | 162 | len = min((int)cnt, sspi->len); |
3558fe90 MR |
163 | |
164 | while (len--) { | |
165 | byte = sspi->tx_buf ? *sspi->tx_buf++ : 0; | |
166 | writeb(byte, sspi->base_addr + SUN6I_TXDATA_REG); | |
167 | sspi->len--; | |
168 | } | |
169 | } | |
170 | ||
171 | static void sun6i_spi_set_cs(struct spi_device *spi, bool enable) | |
172 | { | |
173 | struct sun6i_spi *sspi = spi_master_get_devdata(spi->master); | |
174 | u32 reg; | |
175 | ||
176 | reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); | |
177 | reg &= ~SUN6I_TFR_CTL_CS_MASK; | |
178 | reg |= SUN6I_TFR_CTL_CS(spi->chip_select); | |
179 | ||
180 | if (enable) | |
181 | reg |= SUN6I_TFR_CTL_CS_LEVEL; | |
182 | else | |
183 | reg &= ~SUN6I_TFR_CTL_CS_LEVEL; | |
184 | ||
185 | sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); | |
186 | } | |
187 | ||
794912cf MS |
188 | static size_t sun6i_spi_max_transfer_size(struct spi_device *spi) |
189 | { | |
3288d5cb | 190 | return SUN6I_MAX_XFER_SIZE - 1; |
794912cf | 191 | } |
3558fe90 MR |
192 | |
193 | static int sun6i_spi_transfer_one(struct spi_master *master, | |
194 | struct spi_device *spi, | |
195 | struct spi_transfer *tfr) | |
196 | { | |
197 | struct sun6i_spi *sspi = spi_master_get_devdata(master); | |
ed7815db | 198 | unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout; |
719bd654 | 199 | unsigned int start, end, tx_time; |
913f536c | 200 | unsigned int trig_level; |
3558fe90 MR |
201 | unsigned int tx_len = 0; |
202 | int ret = 0; | |
203 | u32 reg; | |
204 | ||
913f536c | 205 | if (tfr->len > SUN6I_MAX_XFER_SIZE) |
3558fe90 MR |
206 | return -EINVAL; |
207 | ||
208 | reinit_completion(&sspi->done); | |
209 | sspi->tx_buf = tfr->tx_buf; | |
210 | sspi->rx_buf = tfr->rx_buf; | |
211 | sspi->len = tfr->len; | |
212 | ||
213 | /* Clear pending interrupts */ | |
214 | sun6i_spi_write(sspi, SUN6I_INT_STA_REG, ~0); | |
215 | ||
216 | /* Reset FIFO */ | |
217 | sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, | |
218 | SUN6I_FIFO_CTL_RF_RST | SUN6I_FIFO_CTL_TF_RST); | |
219 | ||
913f536c IZ |
220 | /* |
221 | * Setup FIFO interrupt trigger level | |
222 | * Here we choose 3/4 of the full fifo depth, as it's the hardcoded | |
223 | * value used in old generation of Allwinner SPI controller. | |
224 | * (See spi-sun4i.c) | |
225 | */ | |
226 | trig_level = sspi->fifo_depth / 4 * 3; | |
227 | sun6i_spi_write(sspi, SUN6I_FIFO_CTL_REG, | |
228 | (trig_level << SUN6I_FIFO_CTL_RF_RDY_TRIG_LEVEL_BITS) | | |
229 | (trig_level << SUN6I_FIFO_CTL_TF_ERQ_TRIG_LEVEL_BITS)); | |
230 | ||
3558fe90 MR |
231 | /* |
232 | * Setup the transfer control register: Chip Select, | |
233 | * polarities, etc. | |
234 | */ | |
235 | reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); | |
236 | ||
237 | if (spi->mode & SPI_CPOL) | |
238 | reg |= SUN6I_TFR_CTL_CPOL; | |
239 | else | |
240 | reg &= ~SUN6I_TFR_CTL_CPOL; | |
241 | ||
242 | if (spi->mode & SPI_CPHA) | |
243 | reg |= SUN6I_TFR_CTL_CPHA; | |
244 | else | |
245 | reg &= ~SUN6I_TFR_CTL_CPHA; | |
246 | ||
247 | if (spi->mode & SPI_LSB_FIRST) | |
248 | reg |= SUN6I_TFR_CTL_FBS; | |
249 | else | |
250 | reg &= ~SUN6I_TFR_CTL_FBS; | |
251 | ||
252 | /* | |
253 | * If it's a TX only transfer, we don't want to fill the RX | |
254 | * FIFO with bogus data | |
255 | */ | |
256 | if (sspi->rx_buf) | |
257 | reg &= ~SUN6I_TFR_CTL_DHB; | |
258 | else | |
259 | reg |= SUN6I_TFR_CTL_DHB; | |
260 | ||
261 | /* We want to control the chip select manually */ | |
262 | reg |= SUN6I_TFR_CTL_CS_MANUAL; | |
263 | ||
264 | sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); | |
265 | ||
266 | /* Ensure that we have a parent clock fast enough */ | |
267 | mclk_rate = clk_get_rate(sspi->mclk); | |
47284e3e MW |
268 | if (mclk_rate < (2 * tfr->speed_hz)) { |
269 | clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); | |
3558fe90 MR |
270 | mclk_rate = clk_get_rate(sspi->mclk); |
271 | } | |
272 | ||
273 | /* | |
274 | * Setup clock divider. | |
275 | * | |
276 | * We have two choices there. Either we can use the clock | |
277 | * divide rate 1, which is calculated thanks to this formula: | |
278 | * SPI_CLK = MOD_CLK / (2 ^ cdr) | |
279 | * Or we can use CDR2, which is calculated with the formula: | |
280 | * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) | |
281 | * Wether we use the former or the latter is set through the | |
282 | * DRS bit. | |
283 | * | |
284 | * First try CDR2, and if we can't reach the expected | |
285 | * frequency, fall back to CDR1. | |
286 | */ | |
ed7815db MKB |
287 | div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); |
288 | div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); | |
289 | if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { | |
290 | reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; | |
0bc7b8a2 | 291 | tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); |
3558fe90 | 292 | } else { |
ed7815db | 293 | div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); |
3558fe90 | 294 | reg = SUN6I_CLK_CTL_CDR1(div); |
0bc7b8a2 | 295 | tfr->effective_speed_hz = mclk_rate / (1 << div); |
3558fe90 MR |
296 | } |
297 | ||
298 | sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); | |
299 | ||
300 | /* Setup the transfer now... */ | |
301 | if (sspi->tx_buf) | |
302 | tx_len = tfr->len; | |
303 | ||
304 | /* Setup the counters */ | |
2130be57 MKB |
305 | sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len); |
306 | sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len); | |
307 | sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len); | |
3558fe90 MR |
308 | |
309 | /* Fill the TX FIFO */ | |
e4e8ca3f | 310 | sun6i_spi_fill_fifo(sspi); |
3558fe90 MR |
311 | |
312 | /* Enable the interrupts */ | |
313 | sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, SUN6I_INT_CTL_TC); | |
913f536c IZ |
314 | sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TC | |
315 | SUN6I_INT_CTL_RF_RDY); | |
316 | if (tx_len > sspi->fifo_depth) | |
317 | sun6i_spi_enable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ); | |
3558fe90 MR |
318 | |
319 | /* Start the transfer */ | |
320 | reg = sun6i_spi_read(sspi, SUN6I_TFR_CTL_REG); | |
321 | sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg | SUN6I_TFR_CTL_XCH); | |
322 | ||
719bd654 MS |
323 | tx_time = max(tfr->len * 8 * 2 / (tfr->speed_hz / 1000), 100U); |
324 | start = jiffies; | |
3558fe90 | 325 | timeout = wait_for_completion_timeout(&sspi->done, |
719bd654 MS |
326 | msecs_to_jiffies(tx_time)); |
327 | end = jiffies; | |
3558fe90 | 328 | if (!timeout) { |
719bd654 MS |
329 | dev_warn(&master->dev, |
330 | "%s: timeout transferring %u bytes@%iHz for %i(%i)ms", | |
331 | dev_name(&spi->dev), tfr->len, tfr->speed_hz, | |
332 | jiffies_to_msecs(end - start), tx_time); | |
3558fe90 | 333 | ret = -ETIMEDOUT; |
3558fe90 MR |
334 | } |
335 | ||
3558fe90 MR |
336 | sun6i_spi_write(sspi, SUN6I_INT_CTL_REG, 0); |
337 | ||
338 | return ret; | |
339 | } | |
340 | ||
341 | static irqreturn_t sun6i_spi_handler(int irq, void *dev_id) | |
342 | { | |
343 | struct sun6i_spi *sspi = dev_id; | |
344 | u32 status = sun6i_spi_read(sspi, SUN6I_INT_STA_REG); | |
345 | ||
346 | /* Transfer complete */ | |
347 | if (status & SUN6I_INT_CTL_TC) { | |
348 | sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TC); | |
92a52ee8 | 349 | sun6i_spi_drain_fifo(sspi); |
3558fe90 MR |
350 | complete(&sspi->done); |
351 | return IRQ_HANDLED; | |
352 | } | |
353 | ||
913f536c IZ |
354 | /* Receive FIFO 3/4 full */ |
355 | if (status & SUN6I_INT_CTL_RF_RDY) { | |
92a52ee8 | 356 | sun6i_spi_drain_fifo(sspi); |
913f536c IZ |
357 | /* Only clear the interrupt _after_ draining the FIFO */ |
358 | sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_RF_RDY); | |
359 | return IRQ_HANDLED; | |
360 | } | |
361 | ||
362 | /* Transmit FIFO 3/4 empty */ | |
363 | if (status & SUN6I_INT_CTL_TF_ERQ) { | |
e4e8ca3f | 364 | sun6i_spi_fill_fifo(sspi); |
913f536c IZ |
365 | |
366 | if (!sspi->len) | |
367 | /* nothing left to transmit */ | |
368 | sun6i_spi_disable_interrupt(sspi, SUN6I_INT_CTL_TF_ERQ); | |
369 | ||
370 | /* Only clear the interrupt _after_ re-seeding the FIFO */ | |
371 | sun6i_spi_write(sspi, SUN6I_INT_STA_REG, SUN6I_INT_CTL_TF_ERQ); | |
372 | ||
373 | return IRQ_HANDLED; | |
374 | } | |
375 | ||
3558fe90 MR |
376 | return IRQ_NONE; |
377 | } | |
378 | ||
379 | static int sun6i_spi_runtime_resume(struct device *dev) | |
380 | { | |
381 | struct spi_master *master = dev_get_drvdata(dev); | |
382 | struct sun6i_spi *sspi = spi_master_get_devdata(master); | |
383 | int ret; | |
384 | ||
385 | ret = clk_prepare_enable(sspi->hclk); | |
386 | if (ret) { | |
387 | dev_err(dev, "Couldn't enable AHB clock\n"); | |
388 | goto out; | |
389 | } | |
390 | ||
391 | ret = clk_prepare_enable(sspi->mclk); | |
392 | if (ret) { | |
393 | dev_err(dev, "Couldn't enable module clock\n"); | |
394 | goto err; | |
395 | } | |
396 | ||
397 | ret = reset_control_deassert(sspi->rstc); | |
398 | if (ret) { | |
399 | dev_err(dev, "Couldn't deassert the device from reset\n"); | |
400 | goto err2; | |
401 | } | |
402 | ||
403 | sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, | |
404 | SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP); | |
405 | ||
406 | return 0; | |
407 | ||
408 | err2: | |
409 | clk_disable_unprepare(sspi->mclk); | |
410 | err: | |
411 | clk_disable_unprepare(sspi->hclk); | |
412 | out: | |
413 | return ret; | |
414 | } | |
415 | ||
416 | static int sun6i_spi_runtime_suspend(struct device *dev) | |
417 | { | |
418 | struct spi_master *master = dev_get_drvdata(dev); | |
419 | struct sun6i_spi *sspi = spi_master_get_devdata(master); | |
420 | ||
421 | reset_control_assert(sspi->rstc); | |
422 | clk_disable_unprepare(sspi->mclk); | |
423 | clk_disable_unprepare(sspi->hclk); | |
424 | ||
425 | return 0; | |
426 | } | |
427 | ||
428 | static int sun6i_spi_probe(struct platform_device *pdev) | |
429 | { | |
430 | struct spi_master *master; | |
431 | struct sun6i_spi *sspi; | |
3558fe90 MR |
432 | int ret = 0, irq; |
433 | ||
434 | master = spi_alloc_master(&pdev->dev, sizeof(struct sun6i_spi)); | |
435 | if (!master) { | |
436 | dev_err(&pdev->dev, "Unable to allocate SPI Master\n"); | |
437 | return -ENOMEM; | |
438 | } | |
439 | ||
440 | platform_set_drvdata(pdev, master); | |
441 | sspi = spi_master_get_devdata(master); | |
442 | ||
7c7c31f7 | 443 | sspi->base_addr = devm_platform_ioremap_resource(pdev, 0); |
3558fe90 MR |
444 | if (IS_ERR(sspi->base_addr)) { |
445 | ret = PTR_ERR(sspi->base_addr); | |
446 | goto err_free_master; | |
447 | } | |
448 | ||
449 | irq = platform_get_irq(pdev, 0); | |
450 | if (irq < 0) { | |
3558fe90 MR |
451 | ret = -ENXIO; |
452 | goto err_free_master; | |
453 | } | |
454 | ||
455 | ret = devm_request_irq(&pdev->dev, irq, sun6i_spi_handler, | |
456 | 0, "sun6i-spi", sspi); | |
457 | if (ret) { | |
458 | dev_err(&pdev->dev, "Cannot request IRQ\n"); | |
459 | goto err_free_master; | |
460 | } | |
461 | ||
462 | sspi->master = master; | |
10565dfd MK |
463 | sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev); |
464 | ||
0b06d8cf MS |
465 | master->max_speed_hz = 100 * 1000 * 1000; |
466 | master->min_speed_hz = 3 * 1000; | |
74750e06 | 467 | master->use_gpio_descriptors = true; |
3558fe90 MR |
468 | master->set_cs = sun6i_spi_set_cs; |
469 | master->transfer_one = sun6i_spi_transfer_one; | |
470 | master->num_chipselect = 4; | |
471 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; | |
743a46b8 | 472 | master->bits_per_word_mask = SPI_BPW_MASK(8); |
3558fe90 MR |
473 | master->dev.of_node = pdev->dev.of_node; |
474 | master->auto_runtime_pm = true; | |
794912cf | 475 | master->max_transfer_size = sun6i_spi_max_transfer_size; |
3558fe90 MR |
476 | |
477 | sspi->hclk = devm_clk_get(&pdev->dev, "ahb"); | |
478 | if (IS_ERR(sspi->hclk)) { | |
479 | dev_err(&pdev->dev, "Unable to acquire AHB clock\n"); | |
480 | ret = PTR_ERR(sspi->hclk); | |
481 | goto err_free_master; | |
482 | } | |
483 | ||
484 | sspi->mclk = devm_clk_get(&pdev->dev, "mod"); | |
485 | if (IS_ERR(sspi->mclk)) { | |
486 | dev_err(&pdev->dev, "Unable to acquire module clock\n"); | |
487 | ret = PTR_ERR(sspi->mclk); | |
488 | goto err_free_master; | |
489 | } | |
490 | ||
491 | init_completion(&sspi->done); | |
492 | ||
36bc7491 | 493 | sspi->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
3558fe90 MR |
494 | if (IS_ERR(sspi->rstc)) { |
495 | dev_err(&pdev->dev, "Couldn't get reset controller\n"); | |
496 | ret = PTR_ERR(sspi->rstc); | |
497 | goto err_free_master; | |
498 | } | |
499 | ||
500 | /* | |
501 | * This wake-up/shutdown pattern is to be able to have the | |
502 | * device woken up, even if runtime_pm is disabled | |
503 | */ | |
504 | ret = sun6i_spi_runtime_resume(&pdev->dev); | |
505 | if (ret) { | |
506 | dev_err(&pdev->dev, "Couldn't resume the device\n"); | |
507 | goto err_free_master; | |
508 | } | |
509 | ||
510 | pm_runtime_set_active(&pdev->dev); | |
511 | pm_runtime_enable(&pdev->dev); | |
512 | pm_runtime_idle(&pdev->dev); | |
513 | ||
514 | ret = devm_spi_register_master(&pdev->dev, master); | |
515 | if (ret) { | |
516 | dev_err(&pdev->dev, "cannot register SPI master\n"); | |
517 | goto err_pm_disable; | |
518 | } | |
519 | ||
520 | return 0; | |
521 | ||
522 | err_pm_disable: | |
523 | pm_runtime_disable(&pdev->dev); | |
524 | sun6i_spi_runtime_suspend(&pdev->dev); | |
525 | err_free_master: | |
526 | spi_master_put(master); | |
527 | return ret; | |
528 | } | |
529 | ||
530 | static int sun6i_spi_remove(struct platform_device *pdev) | |
531 | { | |
2d9bbd02 | 532 | pm_runtime_force_suspend(&pdev->dev); |
3558fe90 MR |
533 | |
534 | return 0; | |
535 | } | |
536 | ||
537 | static const struct of_device_id sun6i_spi_match[] = { | |
10565dfd MK |
538 | { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH }, |
539 | { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH }, | |
3558fe90 MR |
540 | {} |
541 | }; | |
542 | MODULE_DEVICE_TABLE(of, sun6i_spi_match); | |
543 | ||
544 | static const struct dev_pm_ops sun6i_spi_pm_ops = { | |
545 | .runtime_resume = sun6i_spi_runtime_resume, | |
546 | .runtime_suspend = sun6i_spi_runtime_suspend, | |
547 | }; | |
548 | ||
549 | static struct platform_driver sun6i_spi_driver = { | |
550 | .probe = sun6i_spi_probe, | |
551 | .remove = sun6i_spi_remove, | |
552 | .driver = { | |
553 | .name = "sun6i-spi", | |
3558fe90 MR |
554 | .of_match_table = sun6i_spi_match, |
555 | .pm = &sun6i_spi_pm_ops, | |
556 | }, | |
557 | }; | |
558 | module_platform_driver(sun6i_spi_driver); | |
559 | ||
560 | MODULE_AUTHOR("Pan Nan <pannan@allwinnertech.com>"); | |
561 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); | |
562 | MODULE_DESCRIPTION("Allwinner A31 SPI controller driver"); | |
563 | MODULE_LICENSE("GPL"); |