diff options
author | Harini Katakam <harinik@xilinx.com> | 2014-04-14 05:06:53 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-04-14 16:00:28 -0400 |
commit | c474b38665463d9017cd60cd3a8f8226cf8d562f (patch) | |
tree | 6da072961fbd44238072a135078589379ee7f222 | |
parent | c9eaa447e77efe77b7fa4c953bd62de8297fd6c5 (diff) |
spi: Add driver for Cadence SPI controller
Add driver for Cadence SPI controller. This is used in Xilinx Zynq.
Signed-off-by: Harini Katakam <harinik@xilinx.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | drivers/spi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/spi-cadence.c | 673 |
3 files changed, 681 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 60f2b41c7310..5f11568660c6 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -148,6 +148,13 @@ config SPI_BUTTERFLY | |||
148 | inexpensive battery powered microcontroller evaluation board. | 148 | inexpensive battery powered microcontroller evaluation board. |
149 | This same cable can be used to flash new firmware. | 149 | This same cable can be used to flash new firmware. |
150 | 150 | ||
151 | config SPI_CADENCE | ||
152 | tristate "Cadence SPI controller" | ||
153 | depends on SPI_MASTER | ||
154 | help | ||
155 | This selects the Cadence SPI controller master driver | ||
156 | used by Xilinx Zynq. | ||
157 | |||
151 | config SPI_CLPS711X | 158 | config SPI_CLPS711X |
152 | tristate "CLPS711X host SPI controller" | 159 | tristate "CLPS711X host SPI controller" |
153 | depends on ARCH_CLPS711X || COMPILE_TEST | 160 | depends on ARCH_CLPS711X || COMPILE_TEST |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index bd792669e563..3e503d6d3df3 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o | |||
22 | obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o | 22 | obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o |
23 | obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o | 23 | obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o |
24 | obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o | 24 | obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o |
25 | obj-$(CONFIG_SPI_CADENCE) += spi-cadence.o | ||
25 | obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o | 26 | obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o |
26 | obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o | 27 | obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o |
27 | obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o | 28 | obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o |
diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c new file mode 100644 index 000000000000..bb758978465d --- /dev/null +++ b/drivers/spi/spi-cadence.c | |||
@@ -0,0 +1,673 @@ | |||
1 | /* | ||
2 | * Cadence SPI controller driver (master mode only) | ||
3 | * | ||
4 | * Copyright (C) 2008 - 2014 Xilinx, Inc. | ||
5 | * | ||
6 | * based on Blackfin On-Chip SPI Driver (spi_bfin5xx.c) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it under | ||
9 | * the terms of the GNU General Public License version 2 as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of_irq.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | |||
24 | /* Name of this driver */ | ||
25 | #define CDNS_SPI_NAME "cdns-spi" | ||
26 | |||
27 | /* Register offset definitions */ | ||
28 | #define CDNS_SPI_CR_OFFSET 0x00 /* Configuration Register, RW */ | ||
29 | #define CDNS_SPI_ISR_OFFSET 0x04 /* Interrupt Status Register, RO */ | ||
30 | #define CDNS_SPI_IER_OFFSET 0x08 /* Interrupt Enable Register, WO */ | ||
31 | #define CDNS_SPI_IDR_OFFSET 0x0c /* Interrupt Disable Register, WO */ | ||
32 | #define CDNS_SPI_IMR_OFFSET 0x10 /* Interrupt Enabled Mask Register, RO */ | ||
33 | #define CDNS_SPI_ER_OFFSET 0x14 /* Enable/Disable Register, RW */ | ||
34 | #define CDNS_SPI_DR_OFFSET 0x18 /* Delay Register, RW */ | ||
35 | #define CDNS_SPI_TXD_OFFSET 0x1C /* Data Transmit Register, WO */ | ||
36 | #define CDNS_SPI_RXD_OFFSET 0x20 /* Data Receive Register, RO */ | ||
37 | #define CDNS_SPI_SICR_OFFSET 0x24 /* Slave Idle Count Register, RW */ | ||
38 | #define CDNS_SPI_THLD_OFFSET 0x28 /* Transmit FIFO Watermark Register,RW */ | ||
39 | |||
40 | /* | ||
41 | * SPI Configuration Register bit Masks | ||
42 | * | ||
43 | * This register contains various control bits that affect the operation | ||
44 | * of the SPI controller | ||
45 | */ | ||
46 | #define CDNS_SPI_CR_MANSTRT_MASK 0x00010000 /* Manual TX Start */ | ||
47 | #define CDNS_SPI_CR_CPHA_MASK 0x00000004 /* Clock Phase Control */ | ||
48 | #define CDNS_SPI_CR_CPOL_MASK 0x00000002 /* Clock Polarity Control */ | ||
49 | #define CDNS_SPI_CR_SSCTRL_MASK 0x00003C00 /* Slave Select Mask */ | ||
50 | #define CDNS_SPI_CR_BAUD_DIV_MASK 0x00000038 /* Baud Rate Divisor Mask */ | ||
51 | #define CDNS_SPI_CR_MSTREN_MASK 0x00000001 /* Master Enable Mask */ | ||
52 | #define CDNS_SPI_CR_MANSTRTEN_MASK 0x00008000 /* Manual TX Enable Mask */ | ||
53 | #define CDNS_SPI_CR_SSFORCE_MASK 0x00004000 /* Manual SS Enable Mask */ | ||
54 | #define CDNS_SPI_CR_BAUD_DIV_4_MASK 0x00000008 /* Default Baud Div Mask */ | ||
55 | #define CDNS_SPI_CR_DEFAULT_MASK (CDNS_SPI_CR_MSTREN_MASK | \ | ||
56 | CDNS_SPI_CR_SSCTRL_MASK | \ | ||
57 | CDNS_SPI_CR_SSFORCE_MASK | \ | ||
58 | CDNS_SPI_CR_BAUD_DIV_4_MASK) | ||
59 | |||
60 | /* | ||
61 | * SPI Configuration Register - Baud rate and slave select | ||
62 | * | ||
63 | * These are the values used in the calculation of baud rate divisor and | ||
64 | * setting the slave select. | ||
65 | */ | ||
66 | |||
67 | #define CDNS_SPI_BAUD_DIV_MAX 7 /* Baud rate divisor maximum */ | ||
68 | #define CDNS_SPI_BAUD_DIV_MIN 1 /* Baud rate divisor minimum */ | ||
69 | #define CDNS_SPI_BAUD_DIV_SHIFT 3 /* Baud rate divisor shift in CR */ | ||
70 | #define CDNS_SPI_SS_SHIFT 10 /* Slave Select field shift in CR */ | ||
71 | #define CDNS_SPI_SS0 0x1 /* Slave Select zero */ | ||
72 | |||
73 | /* | ||
74 | * SPI Interrupt Registers bit Masks | ||
75 | * | ||
76 | * All the four interrupt registers (Status/Mask/Enable/Disable) have the same | ||
77 | * bit definitions. | ||
78 | */ | ||
79 | #define CDNS_SPI_IXR_TXOW_MASK 0x00000004 /* SPI TX FIFO Overwater */ | ||
80 | #define CDNS_SPI_IXR_MODF_MASK 0x00000002 /* SPI Mode Fault */ | ||
81 | #define CDNS_SPI_IXR_RXNEMTY_MASK 0x00000010 /* SPI RX FIFO Not Empty */ | ||
82 | #define CDNS_SPI_IXR_DEFAULT_MASK (CDNS_SPI_IXR_TXOW_MASK | \ | ||
83 | CDNS_SPI_IXR_MODF_MASK) | ||
84 | #define CDNS_SPI_IXR_TXFULL_MASK 0x00000008 /* SPI TX Full */ | ||
85 | #define CDNS_SPI_IXR_ALL_MASK 0x0000007F /* SPI all interrupts */ | ||
86 | |||
87 | /* | ||
88 | * SPI Enable Register bit Masks | ||
89 | * | ||
90 | * This register is used to enable or disable the SPI controller | ||
91 | */ | ||
92 | #define CDNS_SPI_ER_ENABLE_MASK 0x00000001 /* SPI Enable Bit Mask */ | ||
93 | #define CDNS_SPI_ER_DISABLE_MASK 0x0 /* SPI Disable Bit Mask */ | ||
94 | |||
95 | /* SPI FIFO depth in bytes */ | ||
96 | #define CDNS_SPI_FIFO_DEPTH 128 | ||
97 | |||
98 | /* Default number of chip select lines */ | ||
99 | #define CDNS_SPI_DEFAULT_NUM_CS 4 | ||
100 | |||
101 | /** | ||
102 | * struct cdns_spi - This definition defines spi driver instance | ||
103 | * @regs: Virtual address of the SPI controller registers | ||
104 | * @ref_clk: Pointer to the peripheral clock | ||
105 | * @pclk: Pointer to the APB clock | ||
106 | * @speed_hz: Current SPI bus clock speed in Hz | ||
107 | * @txbuf: Pointer to the TX buffer | ||
108 | * @rxbuf: Pointer to the RX buffer | ||
109 | * @tx_bytes: Number of bytes left to transfer | ||
110 | * @rx_bytes: Number of bytes requested | ||
111 | * @dev_busy: Device busy flag | ||
112 | * @is_decoded_cs: Flag for decoder property set or not | ||
113 | */ | ||
114 | struct cdns_spi { | ||
115 | void __iomem *regs; | ||
116 | struct clk *ref_clk; | ||
117 | struct clk *pclk; | ||
118 | u32 speed_hz; | ||
119 | const u8 *txbuf; | ||
120 | u8 *rxbuf; | ||
121 | int tx_bytes; | ||
122 | int rx_bytes; | ||
123 | u8 dev_busy; | ||
124 | u32 is_decoded_cs; | ||
125 | }; | ||
126 | |||
127 | /* Macros for the SPI controller read/write */ | ||
128 | static inline u32 cdns_spi_read(struct cdns_spi *xspi, u32 offset) | ||
129 | { | ||
130 | return readl_relaxed(xspi->regs + offset); | ||
131 | } | ||
132 | |||
133 | static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val) | ||
134 | { | ||
135 | writel_relaxed(val, xspi->regs + offset); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller | ||
140 | * @xspi: Pointer to the cdns_spi structure | ||
141 | * | ||
142 | * On reset the SPI controller is configured to be in master mode, baud rate | ||
143 | * divisor is set to 4, threshold value for TX FIFO not full interrupt is set | ||
144 | * to 1 and size of the word to be transferred as 8 bit. | ||
145 | * This function initializes the SPI controller to disable and clear all the | ||
146 | * interrupts, enable manual slave select and manual start, deselect all the | ||
147 | * chip select lines, and enable the SPI controller. | ||
148 | */ | ||
149 | static void cdns_spi_init_hw(struct cdns_spi *xspi) | ||
150 | { | ||
151 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
152 | CDNS_SPI_ER_DISABLE_MASK); | ||
153 | cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, | ||
154 | CDNS_SPI_IXR_ALL_MASK); | ||
155 | |||
156 | /* Clear the RX FIFO */ | ||
157 | while (cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET) & | ||
158 | CDNS_SPI_IXR_RXNEMTY_MASK) | ||
159 | cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); | ||
160 | |||
161 | cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, | ||
162 | CDNS_SPI_IXR_ALL_MASK); | ||
163 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, | ||
164 | CDNS_SPI_CR_DEFAULT_MASK); | ||
165 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
166 | CDNS_SPI_ER_ENABLE_MASK); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * cdns_spi_chipselect - Select or deselect the chip select line | ||
171 | * @spi: Pointer to the spi_device structure | ||
172 | * @is_on: Select(0) or deselect (1) the chip select line | ||
173 | */ | ||
174 | static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) | ||
175 | { | ||
176 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); | ||
177 | u32 ctrl_reg; | ||
178 | |||
179 | ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); | ||
180 | |||
181 | if (is_high) { | ||
182 | /* Deselect the slave */ | ||
183 | ctrl_reg |= CDNS_SPI_CR_SSCTRL_MASK; | ||
184 | } else { | ||
185 | /* Select the slave */ | ||
186 | ctrl_reg &= ~CDNS_SPI_CR_SSCTRL_MASK; | ||
187 | if (!(xspi->is_decoded_cs)) | ||
188 | ctrl_reg |= ((~(CDNS_SPI_SS0 << spi->chip_select)) << | ||
189 | CDNS_SPI_SS_SHIFT) & | ||
190 | CDNS_SPI_CR_SSCTRL_MASK; | ||
191 | else | ||
192 | ctrl_reg |= (spi->chip_select << CDNS_SPI_SS_SHIFT) & | ||
193 | CDNS_SPI_CR_SSCTRL_MASK; | ||
194 | } | ||
195 | |||
196 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * cdns_spi_config_clock_mode - Sets clock polarity and phase | ||
201 | * @spi: Pointer to the spi_device structure | ||
202 | * | ||
203 | * Sets the requested clock polarity and phase. | ||
204 | */ | ||
205 | static void cdns_spi_config_clock_mode(struct spi_device *spi) | ||
206 | { | ||
207 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); | ||
208 | u32 ctrl_reg; | ||
209 | |||
210 | ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); | ||
211 | |||
212 | /* Set the SPI clock phase and clock polarity */ | ||
213 | ctrl_reg &= ~(CDNS_SPI_CR_CPHA_MASK | CDNS_SPI_CR_CPOL_MASK); | ||
214 | if (spi->mode & SPI_CPHA) | ||
215 | ctrl_reg |= CDNS_SPI_CR_CPHA_MASK; | ||
216 | if (spi->mode & SPI_CPOL) | ||
217 | ctrl_reg |= CDNS_SPI_CR_CPOL_MASK; | ||
218 | |||
219 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * cdns_spi_config_clock_freq - Sets clock frequency | ||
224 | * @spi: Pointer to the spi_device structure | ||
225 | * @transfer: Pointer to the spi_transfer structure which provides | ||
226 | * information about next transfer setup parameters | ||
227 | * | ||
228 | * Sets the requested clock frequency. | ||
229 | * Note: If the requested frequency is not an exact match with what can be | ||
230 | * obtained using the prescalar value the driver sets the clock frequency which | ||
231 | * is lower than the requested frequency (maximum lower) for the transfer. If | ||
232 | * the requested frequency is higher or lower than that is supported by the SPI | ||
233 | * controller the driver will set the highest or lowest frequency supported by | ||
234 | * controller. | ||
235 | */ | ||
236 | static void cdns_spi_config_clock_freq(struct spi_device *spi, | ||
237 | struct spi_transfer *transfer) | ||
238 | { | ||
239 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); | ||
240 | u32 ctrl_reg, baud_rate_val; | ||
241 | unsigned long frequency; | ||
242 | |||
243 | frequency = clk_get_rate(xspi->ref_clk); | ||
244 | |||
245 | ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR_OFFSET); | ||
246 | |||
247 | /* Set the clock frequency */ | ||
248 | if (xspi->speed_hz != transfer->speed_hz) { | ||
249 | /* first valid value is 1 */ | ||
250 | baud_rate_val = CDNS_SPI_BAUD_DIV_MIN; | ||
251 | while ((baud_rate_val < CDNS_SPI_BAUD_DIV_MAX) && | ||
252 | (frequency / (2 << baud_rate_val)) > transfer->speed_hz) | ||
253 | baud_rate_val++; | ||
254 | |||
255 | ctrl_reg &= ~CDNS_SPI_CR_BAUD_DIV_MASK; | ||
256 | ctrl_reg |= baud_rate_val << CDNS_SPI_BAUD_DIV_SHIFT; | ||
257 | |||
258 | xspi->speed_hz = frequency / (2 << baud_rate_val); | ||
259 | } | ||
260 | cdns_spi_write(xspi, CDNS_SPI_CR_OFFSET, ctrl_reg); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * cdns_spi_setup_transfer - Configure SPI controller for specified transfer | ||
265 | * @spi: Pointer to the spi_device structure | ||
266 | * @transfer: Pointer to the spi_transfer structure which provides | ||
267 | * information about next transfer setup parameters | ||
268 | * | ||
269 | * Sets the operational mode of SPI controller for the next SPI transfer and | ||
270 | * sets the requested clock frequency. | ||
271 | * | ||
272 | * Return: Always 0 | ||
273 | */ | ||
274 | static int cdns_spi_setup_transfer(struct spi_device *spi, | ||
275 | struct spi_transfer *transfer) | ||
276 | { | ||
277 | struct cdns_spi *xspi = spi_master_get_devdata(spi->master); | ||
278 | |||
279 | cdns_spi_config_clock_freq(spi, transfer); | ||
280 | |||
281 | dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u clock speed\n", | ||
282 | __func__, spi->mode, spi->bits_per_word, | ||
283 | xspi->speed_hz); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible | ||
290 | * @xspi: Pointer to the cdns_spi structure | ||
291 | */ | ||
292 | static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) | ||
293 | { | ||
294 | unsigned long trans_cnt = 0; | ||
295 | |||
296 | while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) && | ||
297 | (xspi->tx_bytes > 0)) { | ||
298 | if (xspi->txbuf) | ||
299 | cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, | ||
300 | *xspi->txbuf++); | ||
301 | else | ||
302 | cdns_spi_write(xspi, CDNS_SPI_TXD_OFFSET, 0); | ||
303 | |||
304 | xspi->tx_bytes--; | ||
305 | trans_cnt++; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * cdns_spi_irq - Interrupt service routine of the SPI controller | ||
311 | * @irq: IRQ number | ||
312 | * @dev_id: Pointer to the xspi structure | ||
313 | * | ||
314 | * This function handles TX empty and Mode Fault interrupts only. | ||
315 | * On TX empty interrupt this function reads the received data from RX FIFO and | ||
316 | * fills the TX FIFO if there is any data remaining to be transferred. | ||
317 | * On Mode Fault interrupt this function indicates that transfer is completed, | ||
318 | * the SPI subsystem will identify the error as the remaining bytes to be | ||
319 | * transferred is non-zero. | ||
320 | * | ||
321 | * Return: IRQ_HANDLED when handled; IRQ_NONE otherwise. | ||
322 | */ | ||
323 | static irqreturn_t cdns_spi_irq(int irq, void *dev_id) | ||
324 | { | ||
325 | struct spi_master *master = dev_id; | ||
326 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
327 | u32 intr_status, status; | ||
328 | |||
329 | status = IRQ_NONE; | ||
330 | intr_status = cdns_spi_read(xspi, CDNS_SPI_ISR_OFFSET); | ||
331 | cdns_spi_write(xspi, CDNS_SPI_ISR_OFFSET, intr_status); | ||
332 | |||
333 | if (intr_status & CDNS_SPI_IXR_MODF_MASK) { | ||
334 | /* Indicate that transfer is completed, the SPI subsystem will | ||
335 | * identify the error as the remaining bytes to be | ||
336 | * transferred is non-zero | ||
337 | */ | ||
338 | cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, | ||
339 | CDNS_SPI_IXR_DEFAULT_MASK); | ||
340 | spi_finalize_current_transfer(master); | ||
341 | status = IRQ_HANDLED; | ||
342 | } else if (intr_status & CDNS_SPI_IXR_TXOW_MASK) { | ||
343 | unsigned long trans_cnt; | ||
344 | |||
345 | trans_cnt = xspi->rx_bytes - xspi->tx_bytes; | ||
346 | |||
347 | /* Read out the data from the RX FIFO */ | ||
348 | while (trans_cnt) { | ||
349 | u8 data; | ||
350 | |||
351 | data = cdns_spi_read(xspi, CDNS_SPI_RXD_OFFSET); | ||
352 | if (xspi->rxbuf) | ||
353 | *xspi->rxbuf++ = data; | ||
354 | |||
355 | xspi->rx_bytes--; | ||
356 | trans_cnt--; | ||
357 | } | ||
358 | |||
359 | if (xspi->tx_bytes) { | ||
360 | /* There is more data to send */ | ||
361 | cdns_spi_fill_tx_fifo(xspi); | ||
362 | } else { | ||
363 | /* Transfer is completed */ | ||
364 | cdns_spi_write(xspi, CDNS_SPI_IDR_OFFSET, | ||
365 | CDNS_SPI_IXR_DEFAULT_MASK); | ||
366 | spi_finalize_current_transfer(master); | ||
367 | } | ||
368 | status = IRQ_HANDLED; | ||
369 | } | ||
370 | |||
371 | return status; | ||
372 | } | ||
373 | |||
374 | /** | ||
375 | * cdns_transfer_one - Initiates the SPI transfer | ||
376 | * @master: Pointer to spi_master structure | ||
377 | * @spi: Pointer to the spi_device structure | ||
378 | * @transfer: Pointer to the spi_transfer structure which provides | ||
379 | * information about next transfer parameters | ||
380 | * | ||
381 | * This function fills the TX FIFO, starts the SPI transfer and | ||
382 | * returns a positive transfer count so that core will wait for completion. | ||
383 | * | ||
384 | * Return: Number of bytes transferred in the last transfer | ||
385 | */ | ||
386 | static int cdns_transfer_one(struct spi_master *master, | ||
387 | struct spi_device *spi, | ||
388 | struct spi_transfer *transfer) | ||
389 | { | ||
390 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
391 | |||
392 | xspi->txbuf = transfer->tx_buf; | ||
393 | xspi->rxbuf = transfer->rx_buf; | ||
394 | xspi->tx_bytes = transfer->len; | ||
395 | xspi->rx_bytes = transfer->len; | ||
396 | |||
397 | cdns_spi_setup_transfer(spi, transfer); | ||
398 | |||
399 | cdns_spi_fill_tx_fifo(xspi); | ||
400 | |||
401 | cdns_spi_write(xspi, CDNS_SPI_IER_OFFSET, | ||
402 | CDNS_SPI_IXR_DEFAULT_MASK); | ||
403 | return transfer->len; | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * cdns_prepare_transfer_hardware - Prepares hardware for transfer. | ||
408 | * @master: Pointer to the spi_master structure which provides | ||
409 | * information about the controller. | ||
410 | * | ||
411 | * This function enables SPI master controller. | ||
412 | * | ||
413 | * Return: 0 always | ||
414 | */ | ||
415 | static int cdns_prepare_transfer_hardware(struct spi_master *master) | ||
416 | { | ||
417 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
418 | |||
419 | cdns_spi_config_clock_mode(master->cur_msg->spi); | ||
420 | |||
421 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
422 | CDNS_SPI_ER_ENABLE_MASK); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /** | ||
428 | * cdns_unprepare_transfer_hardware - Relaxes hardware after transfer | ||
429 | * @master: Pointer to the spi_master structure which provides | ||
430 | * information about the controller. | ||
431 | * | ||
432 | * This function disables the SPI master controller. | ||
433 | * | ||
434 | * Return: 0 always | ||
435 | */ | ||
436 | static int cdns_unprepare_transfer_hardware(struct spi_master *master) | ||
437 | { | ||
438 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
439 | |||
440 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
441 | CDNS_SPI_ER_DISABLE_MASK); | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * cdns_spi_probe - Probe method for the SPI driver | ||
448 | * @pdev: Pointer to the platform_device structure | ||
449 | * | ||
450 | * This function initializes the driver data structures and the hardware. | ||
451 | * | ||
452 | * Return: 0 on success and error value on error | ||
453 | */ | ||
454 | static int cdns_spi_probe(struct platform_device *pdev) | ||
455 | { | ||
456 | int ret = 0, irq; | ||
457 | struct spi_master *master; | ||
458 | struct cdns_spi *xspi; | ||
459 | struct resource *res; | ||
460 | u32 num_cs; | ||
461 | |||
462 | master = spi_alloc_master(&pdev->dev, sizeof(*xspi)); | ||
463 | if (master == NULL) | ||
464 | return -ENOMEM; | ||
465 | |||
466 | xspi = spi_master_get_devdata(master); | ||
467 | master->dev.of_node = pdev->dev.of_node; | ||
468 | platform_set_drvdata(pdev, master); | ||
469 | |||
470 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
471 | xspi->regs = devm_ioremap_resource(&pdev->dev, res); | ||
472 | if (IS_ERR(xspi->regs)) { | ||
473 | ret = PTR_ERR(xspi->regs); | ||
474 | goto remove_master; | ||
475 | } | ||
476 | |||
477 | xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); | ||
478 | if (IS_ERR(xspi->pclk)) { | ||
479 | dev_err(&pdev->dev, "pclk clock not found.\n"); | ||
480 | ret = PTR_ERR(xspi->pclk); | ||
481 | goto remove_master; | ||
482 | } | ||
483 | |||
484 | xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk"); | ||
485 | if (IS_ERR(xspi->ref_clk)) { | ||
486 | dev_err(&pdev->dev, "ref_clk clock not found.\n"); | ||
487 | ret = PTR_ERR(xspi->ref_clk); | ||
488 | goto remove_master; | ||
489 | } | ||
490 | |||
491 | ret = clk_prepare_enable(xspi->pclk); | ||
492 | if (ret) { | ||
493 | dev_err(&pdev->dev, "Unable to enable APB clock.\n"); | ||
494 | goto remove_master; | ||
495 | } | ||
496 | |||
497 | ret = clk_prepare_enable(xspi->ref_clk); | ||
498 | if (ret) { | ||
499 | dev_err(&pdev->dev, "Unable to enable device clock.\n"); | ||
500 | goto clk_dis_apb; | ||
501 | } | ||
502 | |||
503 | /* SPI controller initializations */ | ||
504 | cdns_spi_init_hw(xspi); | ||
505 | |||
506 | irq = platform_get_irq(pdev, 0); | ||
507 | if (irq <= 0) { | ||
508 | ret = -ENXIO; | ||
509 | dev_err(&pdev->dev, "irq number is invalid\n"); | ||
510 | goto remove_master; | ||
511 | } | ||
512 | |||
513 | ret = devm_request_irq(&pdev->dev, irq, cdns_spi_irq, | ||
514 | 0, pdev->name, master); | ||
515 | if (ret != 0) { | ||
516 | ret = -ENXIO; | ||
517 | dev_err(&pdev->dev, "request_irq failed\n"); | ||
518 | goto remove_master; | ||
519 | } | ||
520 | |||
521 | ret = of_property_read_u32(pdev->dev.of_node, "num-cs", &num_cs); | ||
522 | |||
523 | if (ret < 0) | ||
524 | master->num_chipselect = CDNS_SPI_DEFAULT_NUM_CS; | ||
525 | else | ||
526 | master->num_chipselect = num_cs; | ||
527 | |||
528 | ret = of_property_read_u32(pdev->dev.of_node, "is-decoded-cs", | ||
529 | &xspi->is_decoded_cs); | ||
530 | |||
531 | if (ret < 0) | ||
532 | xspi->is_decoded_cs = 0; | ||
533 | |||
534 | master->prepare_transfer_hardware = cdns_prepare_transfer_hardware; | ||
535 | master->transfer_one = cdns_transfer_one; | ||
536 | master->unprepare_transfer_hardware = cdns_unprepare_transfer_hardware; | ||
537 | master->set_cs = cdns_spi_chipselect; | ||
538 | master->mode_bits = SPI_CPOL | SPI_CPHA; | ||
539 | |||
540 | /* Set to default valid value */ | ||
541 | master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4; | ||
542 | xspi->speed_hz = master->max_speed_hz; | ||
543 | |||
544 | master->bits_per_word_mask = SPI_BPW_MASK(8); | ||
545 | |||
546 | ret = spi_register_master(master); | ||
547 | if (ret) { | ||
548 | dev_err(&pdev->dev, "spi_register_master failed\n"); | ||
549 | goto clk_dis_all; | ||
550 | } | ||
551 | |||
552 | return ret; | ||
553 | |||
554 | clk_dis_all: | ||
555 | clk_disable_unprepare(xspi->ref_clk); | ||
556 | clk_dis_apb: | ||
557 | clk_disable_unprepare(xspi->pclk); | ||
558 | remove_master: | ||
559 | spi_master_put(master); | ||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * cdns_spi_remove - Remove method for the SPI driver | ||
565 | * @pdev: Pointer to the platform_device structure | ||
566 | * | ||
567 | * This function is called if a device is physically removed from the system or | ||
568 | * if the driver module is being unloaded. It frees all resources allocated to | ||
569 | * the device. | ||
570 | * | ||
571 | * Return: 0 on success and error value on error | ||
572 | */ | ||
573 | static int cdns_spi_remove(struct platform_device *pdev) | ||
574 | { | ||
575 | struct spi_master *master = platform_get_drvdata(pdev); | ||
576 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
577 | |||
578 | cdns_spi_write(xspi, CDNS_SPI_ER_OFFSET, | ||
579 | CDNS_SPI_ER_DISABLE_MASK); | ||
580 | |||
581 | clk_disable_unprepare(xspi->ref_clk); | ||
582 | clk_disable_unprepare(xspi->pclk); | ||
583 | |||
584 | spi_unregister_master(master); | ||
585 | |||
586 | return 0; | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * cdns_spi_suspend - Suspend method for the SPI driver | ||
591 | * @dev: Address of the platform_device structure | ||
592 | * | ||
593 | * This function disables the SPI controller and | ||
594 | * changes the driver state to "suspend" | ||
595 | * | ||
596 | * Return: Always 0 | ||
597 | */ | ||
598 | static int __maybe_unused cdns_spi_suspend(struct device *dev) | ||
599 | { | ||
600 | struct platform_device *pdev = container_of(dev, | ||
601 | struct platform_device, dev); | ||
602 | struct spi_master *master = platform_get_drvdata(pdev); | ||
603 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
604 | |||
605 | spi_master_suspend(master); | ||
606 | |||
607 | clk_disable_unprepare(xspi->ref_clk); | ||
608 | |||
609 | clk_disable_unprepare(xspi->pclk); | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | /** | ||
615 | * cdns_spi_resume - Resume method for the SPI driver | ||
616 | * @dev: Address of the platform_device structure | ||
617 | * | ||
618 | * This function changes the driver state to "ready" | ||
619 | * | ||
620 | * Return: 0 on success and error value on error | ||
621 | */ | ||
622 | static int __maybe_unused cdns_spi_resume(struct device *dev) | ||
623 | { | ||
624 | struct platform_device *pdev = container_of(dev, | ||
625 | struct platform_device, dev); | ||
626 | struct spi_master *master = platform_get_drvdata(pdev); | ||
627 | struct cdns_spi *xspi = spi_master_get_devdata(master); | ||
628 | int ret = 0; | ||
629 | |||
630 | ret = clk_prepare_enable(xspi->pclk); | ||
631 | if (ret) { | ||
632 | dev_err(dev, "Cannot enable APB clock.\n"); | ||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | ret = clk_prepare_enable(xspi->ref_clk); | ||
637 | if (ret) { | ||
638 | dev_err(dev, "Cannot enable device clock.\n"); | ||
639 | clk_disable(xspi->pclk); | ||
640 | return ret; | ||
641 | } | ||
642 | spi_master_resume(master); | ||
643 | |||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | static SIMPLE_DEV_PM_OPS(cdns_spi_dev_pm_ops, cdns_spi_suspend, | ||
648 | cdns_spi_resume); | ||
649 | |||
650 | static struct of_device_id cdns_spi_of_match[] = { | ||
651 | { .compatible = "xlnx,zynq-spi-r1p6" }, | ||
652 | { .compatible = "cdns,spi-r1p6" }, | ||
653 | { /* end of table */ } | ||
654 | }; | ||
655 | MODULE_DEVICE_TABLE(of, cdns_spi_of_match); | ||
656 | |||
657 | /* cdns_spi_driver - This structure defines the SPI subsystem platform driver */ | ||
658 | static struct platform_driver cdns_spi_driver = { | ||
659 | .probe = cdns_spi_probe, | ||
660 | .remove = cdns_spi_remove, | ||
661 | .driver = { | ||
662 | .name = CDNS_SPI_NAME, | ||
663 | .owner = THIS_MODULE, | ||
664 | .of_match_table = cdns_spi_of_match, | ||
665 | .pm = &cdns_spi_dev_pm_ops, | ||
666 | }, | ||
667 | }; | ||
668 | |||
669 | module_platform_driver(cdns_spi_driver); | ||
670 | |||
671 | MODULE_AUTHOR("Xilinx, Inc."); | ||
672 | MODULE_DESCRIPTION("Cadence SPI driver"); | ||
673 | MODULE_LICENSE("GPL"); | ||