Blame view

drivers/spi/spi-sirf.c 35.4 KB
a636cd6c4   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
2
3
4
5
  /*
   * SPI bus driver for CSR SiRFprimaII
   *
   * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
6
7
8
9
10
11
   */
  
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/slab.h>
  #include <linux/clk.h>
c908ef345   Qipan Li   spi: sirf: refact...
12
  #include <linux/completion.h>
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
13
14
15
16
17
18
19
20
21
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/of.h>
  #include <linux/bitops.h>
  #include <linux/err.h>
  #include <linux/platform_device.h>
  #include <linux/of_gpio.h>
  #include <linux/spi/spi.h>
  #include <linux/spi/spi_bitbang.h>
de39f5fa0   Barry Song   spi: sirf: use DM...
22
23
24
  #include <linux/dmaengine.h>
  #include <linux/dma-direction.h>
  #include <linux/dma-mapping.h>
8509c55fc   Qipan Li   spi: sirf: reset ...
25
  #include <linux/reset.h>
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
26
27
  
  #define DRIVER_NAME "sirfsoc_spi"
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  /* SPI CTRL register defines */
  #define SIRFSOC_SPI_SLV_MODE		BIT(16)
  #define SIRFSOC_SPI_CMD_MODE		BIT(17)
  #define SIRFSOC_SPI_CS_IO_OUT		BIT(18)
  #define SIRFSOC_SPI_CS_IO_MODE		BIT(19)
  #define SIRFSOC_SPI_CLK_IDLE_STAT	BIT(20)
  #define SIRFSOC_SPI_CS_IDLE_STAT	BIT(21)
  #define SIRFSOC_SPI_TRAN_MSB		BIT(22)
  #define SIRFSOC_SPI_DRV_POS_EDGE	BIT(23)
  #define SIRFSOC_SPI_CS_HOLD_TIME	BIT(24)
  #define SIRFSOC_SPI_CLK_SAMPLE_MODE	BIT(25)
  #define SIRFSOC_SPI_TRAN_DAT_FORMAT_8	(0 << 26)
  #define SIRFSOC_SPI_TRAN_DAT_FORMAT_12	(1 << 26)
  #define SIRFSOC_SPI_TRAN_DAT_FORMAT_16	(2 << 26)
  #define SIRFSOC_SPI_TRAN_DAT_FORMAT_32	(3 << 26)
9593e6158   Qipan Li   spi: sirf: cleanu...
43
44
45
  #define SIRFSOC_SPI_CMD_BYTE_NUM(x)	((x & 3) << 28)
  #define SIRFSOC_SPI_ENA_AUTO_CLR	BIT(30)
  #define SIRFSOC_SPI_MUL_DAT_MODE	BIT(31)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
46
47
  
  /* Interrupt Enable */
9593e6158   Qipan Li   spi: sirf: cleanu...
48
49
50
51
  #define SIRFSOC_SPI_RX_DONE_INT_EN	BIT(0)
  #define SIRFSOC_SPI_TX_DONE_INT_EN	BIT(1)
  #define SIRFSOC_SPI_RX_OFLOW_INT_EN	BIT(2)
  #define SIRFSOC_SPI_TX_UFLOW_INT_EN	BIT(3)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
52
53
54
55
56
57
58
  #define SIRFSOC_SPI_RX_IO_DMA_INT_EN	BIT(4)
  #define SIRFSOC_SPI_TX_IO_DMA_INT_EN	BIT(5)
  #define SIRFSOC_SPI_RXFIFO_FULL_INT_EN	BIT(6)
  #define SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN	BIT(7)
  #define SIRFSOC_SPI_RXFIFO_THD_INT_EN	BIT(8)
  #define SIRFSOC_SPI_TXFIFO_THD_INT_EN	BIT(9)
  #define SIRFSOC_SPI_FRM_END_INT_EN	BIT(10)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
59
60
61
62
63
  /* Interrupt status */
  #define SIRFSOC_SPI_RX_DONE		BIT(0)
  #define SIRFSOC_SPI_TX_DONE		BIT(1)
  #define SIRFSOC_SPI_RX_OFLOW		BIT(2)
  #define SIRFSOC_SPI_TX_UFLOW		BIT(3)
41148c3a7   Qipan Li   spi: sirf: decrea...
64
  #define SIRFSOC_SPI_RX_IO_DMA		BIT(4)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  #define SIRFSOC_SPI_RX_FIFO_FULL	BIT(6)
  #define SIRFSOC_SPI_TXFIFO_EMPTY	BIT(7)
  #define SIRFSOC_SPI_RXFIFO_THD_REACH	BIT(8)
  #define SIRFSOC_SPI_TXFIFO_THD_REACH	BIT(9)
  #define SIRFSOC_SPI_FRM_END		BIT(10)
  
  /* TX RX enable */
  #define SIRFSOC_SPI_RX_EN		BIT(0)
  #define SIRFSOC_SPI_TX_EN		BIT(1)
  #define SIRFSOC_SPI_CMD_TX_EN		BIT(2)
  
  #define SIRFSOC_SPI_IO_MODE_SEL		BIT(0)
  #define SIRFSOC_SPI_RX_DMA_FLUSH	BIT(2)
  
  /* FIFO OPs */
  #define SIRFSOC_SPI_FIFO_RESET		BIT(0)
  #define SIRFSOC_SPI_FIFO_START		BIT(1)
  
  /* FIFO CTRL */
  #define SIRFSOC_SPI_FIFO_WIDTH_BYTE	(0 << 0)
  #define SIRFSOC_SPI_FIFO_WIDTH_WORD	(1 << 0)
  #define SIRFSOC_SPI_FIFO_WIDTH_DWORD	(2 << 0)
e3fb57c83   Qipan Li   spi: sirf: add su...
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  /* USP related */
  #define SIRFSOC_USP_SYNC_MODE		BIT(0)
  #define SIRFSOC_USP_SLV_MODE		BIT(1)
  #define SIRFSOC_USP_LSB			BIT(4)
  #define SIRFSOC_USP_EN			BIT(5)
  #define SIRFSOC_USP_RXD_FALLING_EDGE	BIT(6)
  #define SIRFSOC_USP_TXD_FALLING_EDGE	BIT(7)
  #define SIRFSOC_USP_CS_HIGH_VALID	BIT(9)
  #define SIRFSOC_USP_SCLK_IDLE_STAT	BIT(11)
  #define SIRFSOC_USP_TFS_IO_MODE		BIT(14)
  #define SIRFSOC_USP_TFS_IO_INPUT	BIT(19)
  
  #define SIRFSOC_USP_RXD_DELAY_LEN_MASK	0xFF
  #define SIRFSOC_USP_TXD_DELAY_LEN_MASK	0xFF
  #define SIRFSOC_USP_RXD_DELAY_OFFSET	0
  #define SIRFSOC_USP_TXD_DELAY_OFFSET	8
  #define SIRFSOC_USP_RXD_DELAY_LEN	1
  #define SIRFSOC_USP_TXD_DELAY_LEN	1
  #define SIRFSOC_USP_CLK_DIVISOR_OFFSET	21
  #define SIRFSOC_USP_CLK_DIVISOR_MASK	0x3FF
  #define SIRFSOC_USP_CLK_10_11_MASK	0x3
  #define SIRFSOC_USP_CLK_10_11_OFFSET	30
  #define SIRFSOC_USP_CLK_12_15_MASK	0xF
  #define SIRFSOC_USP_CLK_12_15_OFFSET	24
  
  #define SIRFSOC_USP_TX_DATA_OFFSET	0
  #define SIRFSOC_USP_TX_SYNC_OFFSET	8
  #define SIRFSOC_USP_TX_FRAME_OFFSET	16
  #define SIRFSOC_USP_TX_SHIFTER_OFFSET	24
  
  #define SIRFSOC_USP_TX_DATA_MASK	0xFF
  #define SIRFSOC_USP_TX_SYNC_MASK	0xFF
  #define SIRFSOC_USP_TX_FRAME_MASK	0xFF
  #define SIRFSOC_USP_TX_SHIFTER_MASK	0x1F
  
  #define SIRFSOC_USP_RX_DATA_OFFSET	0
  #define SIRFSOC_USP_RX_FRAME_OFFSET	8
  #define SIRFSOC_USP_RX_SHIFTER_OFFSET	16
  
  #define SIRFSOC_USP_RX_DATA_MASK	0xFF
  #define SIRFSOC_USP_RX_FRAME_MASK	0xFF
  #define SIRFSOC_USP_RX_SHIFTER_MASK	0x1F
  #define SIRFSOC_USP_CS_HIGH_VALUE	BIT(1)
  
  #define SIRFSOC_SPI_FIFO_SC_OFFSET	0
  #define SIRFSOC_SPI_FIFO_LC_OFFSET	10
  #define SIRFSOC_SPI_FIFO_HC_OFFSET	20
  
  #define SIRFSOC_SPI_FIFO_FULL_MASK(s)	(1 << ((s)->fifo_full_offset))
  #define SIRFSOC_SPI_FIFO_EMPTY_MASK(s)	(1 << ((s)->fifo_full_offset + 1))
  #define SIRFSOC_SPI_FIFO_THD_MASK(s)	((s)->fifo_size - 1)
  #define SIRFSOC_SPI_FIFO_THD_OFFSET	2
  #define SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(s, val)	\
  	((val) & (s)->fifo_level_chk_mask)
  
  enum sirf_spi_type {
  	SIRF_REAL_SPI,
  	SIRF_USP_SPI_P2,
  	SIRF_USP_SPI_A7,
  };
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
147

de39f5fa0   Barry Song   spi: sirf: use DM...
148
149
150
151
152
153
154
  /*
   * only if the rx/tx buffer and transfer size are 4-bytes aligned, we use dma
   * due to the limitation of dma controller
   */
  
  #define ALIGNED(x) (!((u32)x & 0x3))
  #define IS_DMA_VALID(x) (x && ALIGNED(x->tx_buf) && ALIGNED(x->rx_buf) && \
692fb0fe5   Qipan Li   spi/sirf: fix the...
155
  	ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
de39f5fa0   Barry Song   spi: sirf: use DM...
156

eeb713952   Qipan Li   spi: sirf: provid...
157
  #define SIRFSOC_MAX_CMD_BYTES	4
fcc50e5cd   Qipan Li   spi: sirf: assign...
158
  #define SIRFSOC_SPI_DEFAULT_FRQ 1000000
eeb713952   Qipan Li   spi: sirf: provid...
159

e3fb57c83   Qipan Li   spi: sirf: add su...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  struct sirf_spi_register {
  	/*SPI and USP-SPI common*/
  	u32 tx_rx_en;
  	u32 int_en;
  	u32 int_st;
  	u32 tx_dma_io_ctrl;
  	u32 tx_dma_io_len;
  	u32 txfifo_ctrl;
  	u32 txfifo_level_chk;
  	u32 txfifo_op;
  	u32 txfifo_st;
  	u32 txfifo_data;
  	u32 rx_dma_io_ctrl;
  	u32 rx_dma_io_len;
  	u32 rxfifo_ctrl;
  	u32 rxfifo_level_chk;
  	u32 rxfifo_op;
  	u32 rxfifo_st;
  	u32 rxfifo_data;
  	/*SPI self*/
  	u32 spi_ctrl;
  	u32 spi_cmd;
  	u32 spi_dummy_delay_ctrl;
  	/*USP-SPI self*/
  	u32 usp_mode1;
  	u32 usp_mode2;
  	u32 usp_tx_frame_ctrl;
  	u32 usp_rx_frame_ctrl;
  	u32 usp_pin_io_data;
  	u32 usp_risc_dsp_mode;
  	u32 usp_async_param_reg;
  	u32 usp_irda_x_mode_div;
  	u32 usp_sm_cfg;
  	u32 usp_int_en_clr;
  };
  
  static const struct sirf_spi_register real_spi_register = {
  	.tx_rx_en		= 0x8,
  	.int_en		= 0xc,
  	.int_st		= 0x10,
  	.tx_dma_io_ctrl	= 0x100,
  	.tx_dma_io_len	= 0x104,
  	.txfifo_ctrl	= 0x108,
  	.txfifo_level_chk	= 0x10c,
  	.txfifo_op		= 0x110,
  	.txfifo_st		= 0x114,
  	.txfifo_data	= 0x118,
  	.rx_dma_io_ctrl	= 0x120,
  	.rx_dma_io_len	= 0x124,
  	.rxfifo_ctrl	= 0x128,
  	.rxfifo_level_chk	= 0x12c,
  	.rxfifo_op		= 0x130,
  	.rxfifo_st		= 0x134,
  	.rxfifo_data	= 0x138,
  	.spi_ctrl		= 0x0,
  	.spi_cmd		= 0x4,
  	.spi_dummy_delay_ctrl	= 0x144,
  };
  
  static const struct sirf_spi_register usp_spi_register = {
  	.tx_rx_en		= 0x10,
  	.int_en		= 0x14,
  	.int_st		= 0x18,
  	.tx_dma_io_ctrl	= 0x100,
  	.tx_dma_io_len	= 0x104,
  	.txfifo_ctrl	= 0x108,
  	.txfifo_level_chk	= 0x10c,
  	.txfifo_op		= 0x110,
  	.txfifo_st		= 0x114,
  	.txfifo_data	= 0x118,
  	.rx_dma_io_ctrl	= 0x120,
  	.rx_dma_io_len	= 0x124,
  	.rxfifo_ctrl	= 0x128,
  	.rxfifo_level_chk	= 0x12c,
  	.rxfifo_op		= 0x130,
  	.rxfifo_st		= 0x134,
  	.rxfifo_data	= 0x138,
  	.usp_mode1		= 0x0,
  	.usp_mode2		= 0x4,
  	.usp_tx_frame_ctrl	= 0x8,
  	.usp_rx_frame_ctrl	= 0xc,
  	.usp_pin_io_data	= 0x1c,
  	.usp_risc_dsp_mode	= 0x20,
  	.usp_async_param_reg	= 0x24,
  	.usp_irda_x_mode_div	= 0x28,
  	.usp_sm_cfg		= 0x2c,
  	.usp_int_en_clr		= 0x140,
  };
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
248
249
  struct sirfsoc_spi {
  	struct spi_bitbang bitbang;
de39f5fa0   Barry Song   spi: sirf: use DM...
250
251
  	struct completion rx_done;
  	struct completion tx_done;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
252
253
254
255
  
  	void __iomem *base;
  	u32 ctrl_freq;  /* SPI controller clock speed */
  	struct clk *clk;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
256
257
258
259
260
261
262
263
264
265
266
  
  	/* rx & tx bufs from the spi_transfer */
  	const void *tx;
  	void *rx;
  
  	/* place received word into rx buffer */
  	void (*rx_word) (struct sirfsoc_spi *);
  	/* get word from tx buffer for sending */
  	void (*tx_word) (struct sirfsoc_spi *);
  
  	/* number of words left to be tranmitted/received */
692fb0fe5   Qipan Li   spi/sirf: fix the...
267
268
  	unsigned int left_tx_word;
  	unsigned int left_rx_word;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
269

de39f5fa0   Barry Song   spi: sirf: use DM...
270
271
272
273
274
  	/* rx & tx DMA channels */
  	struct dma_chan *rx_chan;
  	struct dma_chan *tx_chan;
  	dma_addr_t src_start;
  	dma_addr_t dst_start;
de39f5fa0   Barry Song   spi: sirf: use DM...
275
  	int word_width; /* in bytes */
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
276

eeb713952   Qipan Li   spi: sirf: provid...
277
278
279
280
281
  	/*
  	 * if tx size is not more than 4 and rx size is NULL, use
  	 * command model
  	 */
  	bool	tx_by_cmd;
7850cdfc8   Qipan Li   spi: sirf: correc...
282
  	bool	hw_cs;
e3fb57c83   Qipan Li   spi: sirf: add su...
283
284
285
286
287
288
289
290
  	enum sirf_spi_type type;
  	const struct sirf_spi_register *regs;
  	unsigned int fifo_size;
  	/* fifo empty offset is (fifo full offset + 1)*/
  	unsigned int fifo_full_offset;
  	/* fifo_level_chk_mask is (fifo_size/4 - 1) */
  	unsigned int fifo_level_chk_mask;
  	unsigned int dat_max_frm_len;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
291
  };
5bcc3b0bb   Qipan Li   spi: sirf: add th...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  struct sirf_spi_comp_data {
  	const struct sirf_spi_register *regs;
  	enum sirf_spi_type type;
  	unsigned int dat_max_frm_len;
  	unsigned int fifo_size;
  	void (*hwinit)(struct sirfsoc_spi *sspi);
  };
  
  static void sirfsoc_usp_hwinit(struct sirfsoc_spi *sspi)
  {
  	/* reset USP and let USP can operate */
  	writel(readl(sspi->base + sspi->regs->usp_mode1) &
  		~SIRFSOC_USP_EN, sspi->base + sspi->regs->usp_mode1);
  	writel(readl(sspi->base + sspi->regs->usp_mode1) |
  		SIRFSOC_USP_EN, sspi->base + sspi->regs->usp_mode1);
  }
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
308
309
310
311
  static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi)
  {
  	u32 data;
  	u8 *rx = sspi->rx;
e3fb57c83   Qipan Li   spi: sirf: add su...
312
  	data = readl(sspi->base + sspi->regs->rxfifo_data);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
313
314
315
316
317
  
  	if (rx) {
  		*rx++ = (u8) data;
  		sspi->rx = rx;
  	}
692fb0fe5   Qipan Li   spi/sirf: fix the...
318
  	sspi->left_rx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
319
320
321
322
323
324
325
326
327
328
329
  }
  
  static void spi_sirfsoc_tx_word_u8(struct sirfsoc_spi *sspi)
  {
  	u32 data = 0;
  	const u8 *tx = sspi->tx;
  
  	if (tx) {
  		data = *tx++;
  		sspi->tx = tx;
  	}
e3fb57c83   Qipan Li   spi: sirf: add su...
330
  	writel(data, sspi->base + sspi->regs->txfifo_data);
692fb0fe5   Qipan Li   spi/sirf: fix the...
331
  	sspi->left_tx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
332
333
334
335
336
337
  }
  
  static void spi_sirfsoc_rx_word_u16(struct sirfsoc_spi *sspi)
  {
  	u32 data;
  	u16 *rx = sspi->rx;
e3fb57c83   Qipan Li   spi: sirf: add su...
338
  	data = readl(sspi->base + sspi->regs->rxfifo_data);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
339
340
341
342
343
  
  	if (rx) {
  		*rx++ = (u16) data;
  		sspi->rx = rx;
  	}
692fb0fe5   Qipan Li   spi/sirf: fix the...
344
  	sspi->left_rx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
345
346
347
348
349
350
351
352
353
354
355
  }
  
  static void spi_sirfsoc_tx_word_u16(struct sirfsoc_spi *sspi)
  {
  	u32 data = 0;
  	const u16 *tx = sspi->tx;
  
  	if (tx) {
  		data = *tx++;
  		sspi->tx = tx;
  	}
e3fb57c83   Qipan Li   spi: sirf: add su...
356
  	writel(data, sspi->base + sspi->regs->txfifo_data);
692fb0fe5   Qipan Li   spi/sirf: fix the...
357
  	sspi->left_tx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
358
359
360
361
362
363
  }
  
  static void spi_sirfsoc_rx_word_u32(struct sirfsoc_spi *sspi)
  {
  	u32 data;
  	u32 *rx = sspi->rx;
e3fb57c83   Qipan Li   spi: sirf: add su...
364
  	data = readl(sspi->base + sspi->regs->rxfifo_data);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
365
366
367
368
369
  
  	if (rx) {
  		*rx++ = (u32) data;
  		sspi->rx = rx;
  	}
692fb0fe5   Qipan Li   spi/sirf: fix the...
370
  	sspi->left_rx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
371
372
373
374
375
376
377
378
379
380
381
382
  
  }
  
  static void spi_sirfsoc_tx_word_u32(struct sirfsoc_spi *sspi)
  {
  	u32 data = 0;
  	const u32 *tx = sspi->tx;
  
  	if (tx) {
  		data = *tx++;
  		sspi->tx = tx;
  	}
e3fb57c83   Qipan Li   spi: sirf: add su...
383
  	writel(data, sspi->base + sspi->regs->txfifo_data);
692fb0fe5   Qipan Li   spi/sirf: fix the...
384
  	sspi->left_tx_word--;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
385
  }
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
386
387
388
  static irqreturn_t spi_sirfsoc_irq(int irq, void *dev_id)
  {
  	struct sirfsoc_spi *sspi = dev_id;
e3fb57c83   Qipan Li   spi: sirf: add su...
389
390
391
392
393
  	u32 spi_stat;
  
  	spi_stat = readl(sspi->base + sspi->regs->int_st);
  	if (sspi->tx_by_cmd && sspi->type == SIRF_REAL_SPI
  		&& (spi_stat & SIRFSOC_SPI_FRM_END)) {
eeb713952   Qipan Li   spi: sirf: provid...
394
  		complete(&sspi->tx_done);
e3fb57c83   Qipan Li   spi: sirf: add su...
395
396
397
  		writel(0x0, sspi->base + sspi->regs->int_en);
  		writel(readl(sspi->base + sspi->regs->int_st),
  				sspi->base + sspi->regs->int_st);
eeb713952   Qipan Li   spi: sirf: provid...
398
399
  		return IRQ_HANDLED;
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
400
401
402
  	/* Error Conditions */
  	if (spi_stat & SIRFSOC_SPI_RX_OFLOW ||
  			spi_stat & SIRFSOC_SPI_TX_UFLOW) {
41148c3a7   Qipan Li   spi: sirf: decrea...
403
  		complete(&sspi->tx_done);
de39f5fa0   Barry Song   spi: sirf: use DM...
404
  		complete(&sspi->rx_done);
e3fb57c83   Qipan Li   spi: sirf: add su...
405
406
407
408
409
410
411
412
413
414
415
  		switch (sspi->type) {
  		case SIRF_REAL_SPI:
  		case SIRF_USP_SPI_P2:
  			writel(0x0, sspi->base + sspi->regs->int_en);
  			break;
  		case SIRF_USP_SPI_A7:
  			writel(~0UL, sspi->base + sspi->regs->usp_int_en_clr);
  			break;
  		}
  		writel(readl(sspi->base + sspi->regs->int_st),
  				sspi->base + sspi->regs->int_st);
41148c3a7   Qipan Li   spi: sirf: decrea...
416
  		return IRQ_HANDLED;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
417
  	}
41148c3a7   Qipan Li   spi: sirf: decrea...
418
419
  	if (spi_stat & SIRFSOC_SPI_TXFIFO_EMPTY)
  		complete(&sspi->tx_done);
e3fb57c83   Qipan Li   spi: sirf: add su...
420
  	while (!(readl(sspi->base + sspi->regs->int_st) &
41148c3a7   Qipan Li   spi: sirf: decrea...
421
422
423
  		SIRFSOC_SPI_RX_IO_DMA))
  		cpu_relax();
  	complete(&sspi->rx_done);
e3fb57c83   Qipan Li   spi: sirf: add su...
424
425
426
427
428
429
430
431
432
433
434
  	switch (sspi->type) {
  	case SIRF_REAL_SPI:
  	case SIRF_USP_SPI_P2:
  		writel(0x0, sspi->base + sspi->regs->int_en);
  		break;
  	case SIRF_USP_SPI_A7:
  		writel(~0UL, sspi->base + sspi->regs->usp_int_en_clr);
  		break;
  	}
  	writel(readl(sspi->base + sspi->regs->int_st),
  			sspi->base + sspi->regs->int_st);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
435

1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
436
437
  	return IRQ_HANDLED;
  }
de39f5fa0   Barry Song   spi: sirf: use DM...
438
439
440
441
442
443
  static void spi_sirfsoc_dma_fini_callback(void *data)
  {
  	struct completion *dma_complete = data;
  
  	complete(dma_complete);
  }
0021d9733   Qipan Li   spi: sirf: fix 'c...
444
  static void spi_sirfsoc_cmd_transfer(struct spi_device *spi,
c908ef345   Qipan Li   spi: sirf: refact...
445
  	struct spi_transfer *t)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
446
447
448
  {
  	struct sirfsoc_spi *sspi;
  	int timeout = t->len * 10;
c908ef345   Qipan Li   spi: sirf: refact...
449
  	u32 cmd;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
450

c908ef345   Qipan Li   spi: sirf: refact...
451
  	sspi = spi_master_get_devdata(spi->master);
e3fb57c83   Qipan Li   spi: sirf: add su...
452
453
  	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + sspi->regs->txfifo_op);
  	writel(SIRFSOC_SPI_FIFO_START, sspi->base + sspi->regs->txfifo_op);
c908ef345   Qipan Li   spi: sirf: refact...
454
455
456
457
458
459
460
  	memcpy(&cmd, sspi->tx, t->len);
  	if (sspi->word_width == 1 && !(spi->mode & SPI_LSB_FIRST))
  		cmd = cpu_to_be32(cmd) >>
  			((SIRFSOC_MAX_CMD_BYTES - t->len) * 8);
  	if (sspi->word_width == 2 && t->len == 4 &&
  			(!(spi->mode & SPI_LSB_FIRST)))
  		cmd = ((cmd & 0xffff) << 16) | (cmd >> 16);
e3fb57c83   Qipan Li   spi: sirf: add su...
461
  	writel(cmd, sspi->base + sspi->regs->spi_cmd);
c908ef345   Qipan Li   spi: sirf: refact...
462
  	writel(SIRFSOC_SPI_FRM_END_INT_EN,
e3fb57c83   Qipan Li   spi: sirf: add su...
463
  		sspi->base + sspi->regs->int_en);
c908ef345   Qipan Li   spi: sirf: refact...
464
  	writel(SIRFSOC_SPI_CMD_TX_EN,
e3fb57c83   Qipan Li   spi: sirf: add su...
465
  		sspi->base + sspi->regs->tx_rx_en);
c908ef345   Qipan Li   spi: sirf: refact...
466
467
468
  	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
  		dev_err(&spi->dev, "cmd transfer timeout
  ");
0021d9733   Qipan Li   spi: sirf: fix 'c...
469
  		return;
c908ef345   Qipan Li   spi: sirf: refact...
470
  	}
0021d9733   Qipan Li   spi: sirf: fix 'c...
471
  	sspi->left_rx_word -= t->len;
c908ef345   Qipan Li   spi: sirf: refact...
472
  }
eeb713952   Qipan Li   spi: sirf: provid...
473

c908ef345   Qipan Li   spi: sirf: refact...
474
475
476
477
478
479
  static void spi_sirfsoc_dma_transfer(struct spi_device *spi,
  	struct spi_transfer *t)
  {
  	struct sirfsoc_spi *sspi;
  	struct dma_async_tx_descriptor *rx_desc, *tx_desc;
  	int timeout = t->len * 10;
eeb713952   Qipan Li   spi: sirf: provid...
480

c908ef345   Qipan Li   spi: sirf: refact...
481
  	sspi = spi_master_get_devdata(spi->master);
e3fb57c83   Qipan Li   spi: sirf: add su...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + sspi->regs->rxfifo_op);
  	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + sspi->regs->txfifo_op);
  	switch (sspi->type) {
  	case SIRF_REAL_SPI:
  		writel(SIRFSOC_SPI_FIFO_START,
  			sspi->base + sspi->regs->rxfifo_op);
  		writel(SIRFSOC_SPI_FIFO_START,
  			sspi->base + sspi->regs->txfifo_op);
  		writel(0, sspi->base + sspi->regs->int_en);
  		break;
  	case SIRF_USP_SPI_P2:
  		writel(0x0, sspi->base + sspi->regs->rxfifo_op);
  		writel(0x0, sspi->base + sspi->regs->txfifo_op);
  		writel(0, sspi->base + sspi->regs->int_en);
  		break;
  	case SIRF_USP_SPI_A7:
  		writel(0x0, sspi->base + sspi->regs->rxfifo_op);
  		writel(0x0, sspi->base + sspi->regs->txfifo_op);
  		writel(~0UL, sspi->base + sspi->regs->usp_int_en_clr);
  		break;
  	}
  	writel(readl(sspi->base + sspi->regs->int_st),
  		sspi->base + sspi->regs->int_st);
  	if (sspi->left_tx_word < sspi->dat_max_frm_len) {
  		switch (sspi->type) {
  		case SIRF_REAL_SPI:
  			writel(readl(sspi->base + sspi->regs->spi_ctrl) |
  				SIRFSOC_SPI_ENA_AUTO_CLR |
  				SIRFSOC_SPI_MUL_DAT_MODE,
  				sspi->base + sspi->regs->spi_ctrl);
  			writel(sspi->left_tx_word - 1,
  				sspi->base + sspi->regs->tx_dma_io_len);
  			writel(sspi->left_tx_word - 1,
  				sspi->base + sspi->regs->rx_dma_io_len);
  			break;
  		case SIRF_USP_SPI_P2:
  		case SIRF_USP_SPI_A7:
  			/*USP simulate SPI, tx/rx_dma_io_len indicates bytes*/
  			writel(sspi->left_tx_word * sspi->word_width,
  				sspi->base + sspi->regs->tx_dma_io_len);
  			writel(sspi->left_tx_word * sspi->word_width,
  				sspi->base + sspi->regs->rx_dma_io_len);
  			break;
  		}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
526
  	} else {
e3fb57c83   Qipan Li   spi: sirf: add su...
527
528
529
530
531
  		if (sspi->type == SIRF_REAL_SPI)
  			writel(readl(sspi->base + sspi->regs->spi_ctrl),
  				sspi->base + sspi->regs->spi_ctrl);
  		writel(0, sspi->base + sspi->regs->tx_dma_io_len);
  		writel(0, sspi->base + sspi->regs->rx_dma_io_len);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
532
  	}
c908ef345   Qipan Li   spi: sirf: refact...
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  	sspi->dst_start = dma_map_single(&spi->dev, sspi->rx, t->len,
  					(t->tx_buf != t->rx_buf) ?
  					DMA_FROM_DEVICE : DMA_BIDIRECTIONAL);
  	rx_desc = dmaengine_prep_slave_single(sspi->rx_chan,
  		sspi->dst_start, t->len, DMA_DEV_TO_MEM,
  		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
  	rx_desc->callback = spi_sirfsoc_dma_fini_callback;
  	rx_desc->callback_param = &sspi->rx_done;
  
  	sspi->src_start = dma_map_single(&spi->dev, (void *)sspi->tx, t->len,
  					(t->tx_buf != t->rx_buf) ?
  					DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
  	tx_desc = dmaengine_prep_slave_single(sspi->tx_chan,
  		sspi->src_start, t->len, DMA_MEM_TO_DEV,
  		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
  	tx_desc->callback = spi_sirfsoc_dma_fini_callback;
  	tx_desc->callback_param = &sspi->tx_done;
  
  	dmaengine_submit(tx_desc);
  	dmaengine_submit(rx_desc);
  	dma_async_issue_pending(sspi->tx_chan);
  	dma_async_issue_pending(sspi->rx_chan);
d77ec5df4   Qipan Li   spi: sirf: fix li...
555
  	writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
e3fb57c83   Qipan Li   spi: sirf: add su...
556
557
558
559
560
561
562
563
  			sspi->base + sspi->regs->tx_rx_en);
  	if (sspi->type == SIRF_USP_SPI_P2 ||
  		sspi->type == SIRF_USP_SPI_A7) {
  		writel(SIRFSOC_SPI_FIFO_START,
  			sspi->base + sspi->regs->rxfifo_op);
  		writel(SIRFSOC_SPI_FIFO_START,
  			sspi->base + sspi->regs->txfifo_op);
  	}
c908ef345   Qipan Li   spi: sirf: refact...
564
  	if (wait_for_completion_timeout(&sspi->rx_done, timeout) == 0) {
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
565
566
  		dev_err(&spi->dev, "transfer timeout
  ");
de39f5fa0   Barry Song   spi: sirf: use DM...
567
568
  		dmaengine_terminate_all(sspi->rx_chan);
  	} else
692fb0fe5   Qipan Li   spi/sirf: fix the...
569
  		sspi->left_rx_word = 0;
de39f5fa0   Barry Song   spi: sirf: use DM...
570
571
572
573
574
  	/*
  	 * we only wait tx-done event if transferring by DMA. for PIO,
  	 * we get rx data by writing tx data, so if rx is done, tx has
  	 * done earlier
  	 */
c908ef345   Qipan Li   spi: sirf: refact...
575
576
577
  	if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
  		dev_err(&spi->dev, "transfer timeout
  ");
e3fb57c83   Qipan Li   spi: sirf: add su...
578
579
580
  		if (sspi->type == SIRF_USP_SPI_P2 ||
  			sspi->type == SIRF_USP_SPI_A7)
  			writel(0, sspi->base + sspi->regs->tx_rx_en);
c908ef345   Qipan Li   spi: sirf: refact...
581
  		dmaengine_terminate_all(sspi->tx_chan);
de39f5fa0   Barry Song   spi: sirf: use DM...
582
  	}
c908ef345   Qipan Li   spi: sirf: refact...
583
584
585
  	dma_unmap_single(&spi->dev, sspi->src_start, t->len, DMA_TO_DEVICE);
  	dma_unmap_single(&spi->dev, sspi->dst_start, t->len, DMA_FROM_DEVICE);
  	/* TX, RX FIFO stop */
e3fb57c83   Qipan Li   spi: sirf: add su...
586
587
588
589
590
591
592
  	writel(0, sspi->base + sspi->regs->rxfifo_op);
  	writel(0, sspi->base + sspi->regs->txfifo_op);
  	if (sspi->left_tx_word >= sspi->dat_max_frm_len)
  		writel(0, sspi->base + sspi->regs->tx_rx_en);
  	if (sspi->type == SIRF_USP_SPI_P2 ||
  		sspi->type == SIRF_USP_SPI_A7)
  		writel(0, sspi->base + sspi->regs->tx_rx_en);
c908ef345   Qipan Li   spi: sirf: refact...
593
  }
de39f5fa0   Barry Song   spi: sirf: use DM...
594

c908ef345   Qipan Li   spi: sirf: refact...
595
596
597
598
599
  static void spi_sirfsoc_pio_transfer(struct spi_device *spi,
  		struct spi_transfer *t)
  {
  	struct sirfsoc_spi *sspi;
  	int timeout = t->len * 10;
e3fb57c83   Qipan Li   spi: sirf: add su...
600
  	unsigned int data_units;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
601

c908ef345   Qipan Li   spi: sirf: refact...
602
  	sspi = spi_master_get_devdata(spi->master);
41148c3a7   Qipan Li   spi: sirf: decrea...
603
604
  	do {
  		writel(SIRFSOC_SPI_FIFO_RESET,
e3fb57c83   Qipan Li   spi: sirf: add su...
605
  			sspi->base + sspi->regs->rxfifo_op);
41148c3a7   Qipan Li   spi: sirf: decrea...
606
  		writel(SIRFSOC_SPI_FIFO_RESET,
e3fb57c83   Qipan Li   spi: sirf: add su...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
  			sspi->base + sspi->regs->txfifo_op);
  		switch (sspi->type) {
  		case SIRF_USP_SPI_P2:
  			writel(0x0, sspi->base + sspi->regs->rxfifo_op);
  			writel(0x0, sspi->base + sspi->regs->txfifo_op);
  			writel(0, sspi->base + sspi->regs->int_en);
  			writel(readl(sspi->base + sspi->regs->int_st),
  				sspi->base + sspi->regs->int_st);
  			writel(min((sspi->left_tx_word * sspi->word_width),
  				sspi->fifo_size),
  				sspi->base + sspi->regs->tx_dma_io_len);
  			writel(min((sspi->left_rx_word * sspi->word_width),
  				sspi->fifo_size),
  				sspi->base + sspi->regs->rx_dma_io_len);
  			break;
  		case SIRF_USP_SPI_A7:
  			writel(0x0, sspi->base + sspi->regs->rxfifo_op);
  			writel(0x0, sspi->base + sspi->regs->txfifo_op);
  			writel(~0UL, sspi->base + sspi->regs->usp_int_en_clr);
  			writel(readl(sspi->base + sspi->regs->int_st),
  				sspi->base + sspi->regs->int_st);
  			writel(min((sspi->left_tx_word * sspi->word_width),
  				sspi->fifo_size),
  				sspi->base + sspi->regs->tx_dma_io_len);
  			writel(min((sspi->left_rx_word * sspi->word_width),
  				sspi->fifo_size),
  				sspi->base + sspi->regs->rx_dma_io_len);
  			break;
  		case SIRF_REAL_SPI:
  			writel(SIRFSOC_SPI_FIFO_START,
  				sspi->base + sspi->regs->rxfifo_op);
  			writel(SIRFSOC_SPI_FIFO_START,
  				sspi->base + sspi->regs->txfifo_op);
  			writel(0, sspi->base + sspi->regs->int_en);
  			writel(readl(sspi->base + sspi->regs->int_st),
  				sspi->base + sspi->regs->int_st);
  			writel(readl(sspi->base + sspi->regs->spi_ctrl) |
  				SIRFSOC_SPI_MUL_DAT_MODE |
  				SIRFSOC_SPI_ENA_AUTO_CLR,
  				sspi->base + sspi->regs->spi_ctrl);
  			data_units = sspi->fifo_size / sspi->word_width;
  			writel(min(sspi->left_tx_word, data_units) - 1,
  				sspi->base + sspi->regs->tx_dma_io_len);
  			writel(min(sspi->left_rx_word, data_units) - 1,
  				sspi->base + sspi->regs->rx_dma_io_len);
  			break;
  		}
  		while (!((readl(sspi->base + sspi->regs->txfifo_st)
  			& SIRFSOC_SPI_FIFO_FULL_MASK(sspi))) &&
  			sspi->left_tx_word)
41148c3a7   Qipan Li   spi: sirf: decrea...
657
658
659
  			sspi->tx_word(sspi);
  		writel(SIRFSOC_SPI_TXFIFO_EMPTY_INT_EN |
  			SIRFSOC_SPI_TX_UFLOW_INT_EN |
f2a08b404   Qipan Li   spi: sirf: enable...
660
661
  			SIRFSOC_SPI_RX_OFLOW_INT_EN |
  			SIRFSOC_SPI_RX_IO_DMA_INT_EN,
e3fb57c83   Qipan Li   spi: sirf: add su...
662
  			sspi->base + sspi->regs->int_en);
41148c3a7   Qipan Li   spi: sirf: decrea...
663
  		writel(SIRFSOC_SPI_RX_EN | SIRFSOC_SPI_TX_EN,
e3fb57c83   Qipan Li   spi: sirf: add su...
664
665
666
667
668
669
670
671
  			sspi->base + sspi->regs->tx_rx_en);
  		if (sspi->type == SIRF_USP_SPI_P2 ||
  			sspi->type == SIRF_USP_SPI_A7) {
  			writel(SIRFSOC_SPI_FIFO_START,
  				sspi->base + sspi->regs->rxfifo_op);
  			writel(SIRFSOC_SPI_FIFO_START,
  				sspi->base + sspi->regs->txfifo_op);
  		}
41148c3a7   Qipan Li   spi: sirf: decrea...
672
673
674
675
  		if (!wait_for_completion_timeout(&sspi->tx_done, timeout) ||
  			!wait_for_completion_timeout(&sspi->rx_done, timeout)) {
  			dev_err(&spi->dev, "transfer timeout
  ");
e3fb57c83   Qipan Li   spi: sirf: add su...
676
677
678
  			if (sspi->type == SIRF_USP_SPI_P2 ||
  				sspi->type == SIRF_USP_SPI_A7)
  				writel(0, sspi->base + sspi->regs->tx_rx_en);
41148c3a7   Qipan Li   spi: sirf: decrea...
679
680
  			break;
  		}
e3fb57c83   Qipan Li   spi: sirf: add su...
681
682
683
  		while (!((readl(sspi->base + sspi->regs->rxfifo_st)
  			& SIRFSOC_SPI_FIFO_EMPTY_MASK(sspi))) &&
  			sspi->left_rx_word)
41148c3a7   Qipan Li   spi: sirf: decrea...
684
  			sspi->rx_word(sspi);
e3fb57c83   Qipan Li   spi: sirf: add su...
685
686
687
688
689
  		if (sspi->type == SIRF_USP_SPI_P2 ||
  			sspi->type == SIRF_USP_SPI_A7)
  			writel(0, sspi->base + sspi->regs->tx_rx_en);
  		writel(0, sspi->base + sspi->regs->rxfifo_op);
  		writel(0, sspi->base + sspi->regs->txfifo_op);
41148c3a7   Qipan Li   spi: sirf: decrea...
690
  	} while (sspi->left_tx_word != 0 || sspi->left_rx_word != 0);
c908ef345   Qipan Li   spi: sirf: refact...
691
692
693
694
695
  }
  
  static int spi_sirfsoc_transfer(struct spi_device *spi, struct spi_transfer *t)
  {
  	struct sirfsoc_spi *sspi;
c908ef345   Qipan Li   spi: sirf: refact...
696

e3fb57c83   Qipan Li   spi: sirf: add su...
697
  	sspi = spi_master_get_devdata(spi->master);
3aa7b1d66   Qipan Li   spi: sirf: remove...
698
699
  	sspi->tx = t->tx_buf;
  	sspi->rx = t->rx_buf;
c908ef345   Qipan Li   spi: sirf: refact...
700
701
702
703
704
705
706
707
  	sspi->left_tx_word = sspi->left_rx_word = t->len / sspi->word_width;
  	reinit_completion(&sspi->rx_done);
  	reinit_completion(&sspi->tx_done);
  	/*
  	 * in the transfer, if transfer data using command register with rx_buf
  	 * null, just fill command data into command register and wait for its
  	 * completion.
  	 */
e3fb57c83   Qipan Li   spi: sirf: add su...
708
  	if (sspi->type == SIRF_REAL_SPI && sspi->tx_by_cmd)
c908ef345   Qipan Li   spi: sirf: refact...
709
710
711
712
713
  		spi_sirfsoc_cmd_transfer(spi, t);
  	else if (IS_DMA_VALID(t))
  		spi_sirfsoc_dma_transfer(spi, t);
  	else
  		spi_sirfsoc_pio_transfer(spi, t);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
714

692fb0fe5   Qipan Li   spi/sirf: fix the...
715
  	return t->len - sspi->left_rx_word * sspi->word_width;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
716
717
718
719
720
  }
  
  static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
  {
  	struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master);
7850cdfc8   Qipan Li   spi: sirf: correc...
721
  	if (sspi->hw_cs) {
e3fb57c83   Qipan Li   spi: sirf: add su...
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
  		u32 regval;
  
  		switch (sspi->type) {
  		case SIRF_REAL_SPI:
  			regval = readl(sspi->base + sspi->regs->spi_ctrl);
  			switch (value) {
  			case BITBANG_CS_ACTIVE:
  				if (spi->mode & SPI_CS_HIGH)
  					regval |= SIRFSOC_SPI_CS_IO_OUT;
  				else
  					regval &= ~SIRFSOC_SPI_CS_IO_OUT;
  				break;
  			case BITBANG_CS_INACTIVE:
  				if (spi->mode & SPI_CS_HIGH)
  					regval &= ~SIRFSOC_SPI_CS_IO_OUT;
  				else
  					regval |= SIRFSOC_SPI_CS_IO_OUT;
  				break;
  			}
  			writel(regval, sspi->base + sspi->regs->spi_ctrl);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
742
  			break;
e3fb57c83   Qipan Li   spi: sirf: add su...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
  		case SIRF_USP_SPI_P2:
  		case SIRF_USP_SPI_A7:
  			regval = readl(sspi->base +
  					sspi->regs->usp_pin_io_data);
  			switch (value) {
  			case BITBANG_CS_ACTIVE:
  				if (spi->mode & SPI_CS_HIGH)
  					regval |= SIRFSOC_USP_CS_HIGH_VALUE;
  				else
  					regval &= ~(SIRFSOC_USP_CS_HIGH_VALUE);
  				break;
  			case BITBANG_CS_INACTIVE:
  				if (spi->mode & SPI_CS_HIGH)
  					regval &= ~(SIRFSOC_USP_CS_HIGH_VALUE);
  				else
  					regval |= SIRFSOC_USP_CS_HIGH_VALUE;
  				break;
  			}
  			writel(regval,
  				sspi->base + sspi->regs->usp_pin_io_data);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
763
764
  			break;
  		}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
765
  	} else {
6ee8a2f7d   Qipan Li   spi: sirf: make G...
766
767
  		switch (value) {
  		case BITBANG_CS_ACTIVE:
7850cdfc8   Qipan Li   spi: sirf: correc...
768
  			gpio_direction_output(spi->cs_gpio,
6ee8a2f7d   Qipan Li   spi: sirf: make G...
769
770
771
  					spi->mode & SPI_CS_HIGH ? 1 : 0);
  			break;
  		case BITBANG_CS_INACTIVE:
7850cdfc8   Qipan Li   spi: sirf: correc...
772
  			gpio_direction_output(spi->cs_gpio,
6ee8a2f7d   Qipan Li   spi: sirf: make G...
773
774
775
  					spi->mode & SPI_CS_HIGH ? 0 : 1);
  			break;
  		}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
776
777
  	}
  }
e3fb57c83   Qipan Li   spi: sirf: add su...
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
  static int spi_sirfsoc_config_mode(struct spi_device *spi)
  {
  	struct sirfsoc_spi *sspi;
  	u32 regval, usp_mode1;
  
  	sspi = spi_master_get_devdata(spi->master);
  	regval = readl(sspi->base + sspi->regs->spi_ctrl);
  	usp_mode1 = readl(sspi->base + sspi->regs->usp_mode1);
  	if (!(spi->mode & SPI_CS_HIGH)) {
  		regval |= SIRFSOC_SPI_CS_IDLE_STAT;
  		usp_mode1 &= ~SIRFSOC_USP_CS_HIGH_VALID;
  	} else {
  		regval &= ~SIRFSOC_SPI_CS_IDLE_STAT;
  		usp_mode1 |= SIRFSOC_USP_CS_HIGH_VALID;
  	}
  	if (!(spi->mode & SPI_LSB_FIRST)) {
  		regval |= SIRFSOC_SPI_TRAN_MSB;
  		usp_mode1 &= ~SIRFSOC_USP_LSB;
  	} else {
  		regval &= ~SIRFSOC_SPI_TRAN_MSB;
  		usp_mode1 |= SIRFSOC_USP_LSB;
  	}
  	if (spi->mode & SPI_CPOL) {
  		regval |= SIRFSOC_SPI_CLK_IDLE_STAT;
  		usp_mode1 |= SIRFSOC_USP_SCLK_IDLE_STAT;
  	} else {
  		regval &= ~SIRFSOC_SPI_CLK_IDLE_STAT;
  		usp_mode1 &= ~SIRFSOC_USP_SCLK_IDLE_STAT;
  	}
  	/*
  	 * Data should be driven at least 1/2 cycle before the fetch edge
  	 * to make sure that data gets stable at the fetch edge.
  	 */
  	if (((spi->mode & SPI_CPOL) && (spi->mode & SPI_CPHA)) ||
  	    (!(spi->mode & SPI_CPOL) && !(spi->mode & SPI_CPHA))) {
  		regval &= ~SIRFSOC_SPI_DRV_POS_EDGE;
  		usp_mode1 |= (SIRFSOC_USP_TXD_FALLING_EDGE |
  				SIRFSOC_USP_RXD_FALLING_EDGE);
  	} else {
  		regval |= SIRFSOC_SPI_DRV_POS_EDGE;
  		usp_mode1 &= ~(SIRFSOC_USP_RXD_FALLING_EDGE |
  				SIRFSOC_USP_TXD_FALLING_EDGE);
  	}
  	writel((SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, sspi->fifo_size - 2) <<
  		SIRFSOC_SPI_FIFO_SC_OFFSET) |
  		(SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, sspi->fifo_size / 2) <<
  		SIRFSOC_SPI_FIFO_LC_OFFSET) |
  		(SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, 2) <<
  		SIRFSOC_SPI_FIFO_HC_OFFSET),
  		sspi->base + sspi->regs->txfifo_level_chk);
  	writel((SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, 2) <<
  		SIRFSOC_SPI_FIFO_SC_OFFSET) |
  		(SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, sspi->fifo_size / 2) <<
  		SIRFSOC_SPI_FIFO_LC_OFFSET) |
  		(SIRFSOC_SPI_FIFO_LEVEL_CHK_MASK(sspi, sspi->fifo_size - 2) <<
  		SIRFSOC_SPI_FIFO_HC_OFFSET),
  		sspi->base + sspi->regs->rxfifo_level_chk);
  	/*
  	 * it should never set to hardware cs mode because in hardware cs mode,
  	 * cs signal can't controlled by driver.
  	 */
  	switch (sspi->type) {
  	case SIRF_REAL_SPI:
  		regval |= SIRFSOC_SPI_CS_IO_MODE;
  		writel(regval, sspi->base + sspi->regs->spi_ctrl);
  		break;
  	case SIRF_USP_SPI_P2:
  	case SIRF_USP_SPI_A7:
  		usp_mode1 |= SIRFSOC_USP_SYNC_MODE;
  		usp_mode1 |= SIRFSOC_USP_TFS_IO_MODE;
  		usp_mode1 &= ~SIRFSOC_USP_TFS_IO_INPUT;
  		writel(usp_mode1, sspi->base + sspi->regs->usp_mode1);
  		break;
  	}
  
  	return 0;
  }
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
855
856
857
858
859
860
  static int
  spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
  {
  	struct sirfsoc_spi *sspi;
  	u8 bits_per_word = 0;
  	int hz = 0;
e3fb57c83   Qipan Li   spi: sirf: add su...
861
  	u32 regval, txfifo_ctrl, rxfifo_ctrl, tx_frm_ctl, rx_frm_ctl, usp_mode2;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
862
863
  
  	sspi = spi_master_get_devdata(spi->master);
766ed7044   Laxman Dewangan   spi: remove check...
864
  	bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
865
  	hz = t && t->speed_hz ? t->speed_hz : spi->max_speed_hz;
e3fb57c83   Qipan Li   spi: sirf: add su...
866
  	usp_mode2 = regval = (sspi->ctrl_freq / (2 * hz)) - 1;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
867
868
869
870
871
  	if (regval > 0xFFFF || regval < 0) {
  		dev_err(&spi->dev, "Speed %d not supported
  ", hz);
  		return -EINVAL;
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
872
873
874
875
876
  	switch (bits_per_word) {
  	case 8:
  		regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_8;
  		sspi->rx_word = spi_sirfsoc_rx_word_u8;
  		sspi->tx_word = spi_sirfsoc_tx_word_u8;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
877
878
879
  		break;
  	case 12:
  	case 16:
d77ec5df4   Qipan Li   spi: sirf: fix li...
880
881
  		regval |= (bits_per_word ==  12) ?
  			SIRFSOC_SPI_TRAN_DAT_FORMAT_12 :
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
882
883
884
  			SIRFSOC_SPI_TRAN_DAT_FORMAT_16;
  		sspi->rx_word = spi_sirfsoc_rx_word_u16;
  		sspi->tx_word = spi_sirfsoc_tx_word_u16;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
885
886
887
888
889
  		break;
  	case 32:
  		regval |= SIRFSOC_SPI_TRAN_DAT_FORMAT_32;
  		sspi->rx_word = spi_sirfsoc_rx_word_u32;
  		sspi->tx_word = spi_sirfsoc_tx_word_u32;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
890
  		break;
804ae4380   Arnd Bergmann   spi: sirf: avoid ...
891
  	default:
f08654a2b   Qipan Li   spi: sirf: replac...
892
893
894
  		dev_err(&spi->dev, "bpw %d not supported
  ", bits_per_word);
  		return -EINVAL;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
895
  	}
8c328a262   Axel Lin   spi: sirf: Avoid ...
896
  	sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
e3fb57c83   Qipan Li   spi: sirf: add su...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
  	txfifo_ctrl = (((sspi->fifo_size / 2) &
  			SIRFSOC_SPI_FIFO_THD_MASK(sspi))
  			<< SIRFSOC_SPI_FIFO_THD_OFFSET) |
  			(sspi->word_width >> 1);
  	rxfifo_ctrl = (((sspi->fifo_size / 2) &
  			SIRFSOC_SPI_FIFO_THD_MASK(sspi))
  			<< SIRFSOC_SPI_FIFO_THD_OFFSET) |
  			(sspi->word_width >> 1);
  	writel(txfifo_ctrl, sspi->base + sspi->regs->txfifo_ctrl);
  	writel(rxfifo_ctrl, sspi->base + sspi->regs->rxfifo_ctrl);
  	if (sspi->type == SIRF_USP_SPI_P2 ||
  		sspi->type == SIRF_USP_SPI_A7) {
  		tx_frm_ctl = 0;
  		tx_frm_ctl |= ((bits_per_word - 1) & SIRFSOC_USP_TX_DATA_MASK)
  				<< SIRFSOC_USP_TX_DATA_OFFSET;
  		tx_frm_ctl |= ((bits_per_word + 1 + SIRFSOC_USP_TXD_DELAY_LEN
  				- 1) & SIRFSOC_USP_TX_SYNC_MASK) <<
  				SIRFSOC_USP_TX_SYNC_OFFSET;
  		tx_frm_ctl |= ((bits_per_word + 1 + SIRFSOC_USP_TXD_DELAY_LEN
  				+ 2 - 1) & SIRFSOC_USP_TX_FRAME_MASK) <<
  				SIRFSOC_USP_TX_FRAME_OFFSET;
  		tx_frm_ctl |= ((bits_per_word - 1) &
  				SIRFSOC_USP_TX_SHIFTER_MASK) <<
  				SIRFSOC_USP_TX_SHIFTER_OFFSET;
  		rx_frm_ctl = 0;
  		rx_frm_ctl |= ((bits_per_word - 1) & SIRFSOC_USP_RX_DATA_MASK)
  				<< SIRFSOC_USP_RX_DATA_OFFSET;
  		rx_frm_ctl |= ((bits_per_word + 1 + SIRFSOC_USP_RXD_DELAY_LEN
  				+ 2 - 1) & SIRFSOC_USP_RX_FRAME_MASK) <<
  				SIRFSOC_USP_RX_FRAME_OFFSET;
  		rx_frm_ctl |= ((bits_per_word - 1)
  				& SIRFSOC_USP_RX_SHIFTER_MASK) <<
  				SIRFSOC_USP_RX_SHIFTER_OFFSET;
  		writel(tx_frm_ctl | (((usp_mode2 >> 10) &
  			SIRFSOC_USP_CLK_10_11_MASK) <<
  			SIRFSOC_USP_CLK_10_11_OFFSET),
  			sspi->base + sspi->regs->usp_tx_frame_ctrl);
  		writel(rx_frm_ctl | (((usp_mode2 >> 12) &
  			SIRFSOC_USP_CLK_12_15_MASK) <<
  			SIRFSOC_USP_CLK_12_15_OFFSET),
  			sspi->base + sspi->regs->usp_rx_frame_ctrl);
  		writel(readl(sspi->base + sspi->regs->usp_mode2) |
  			((usp_mode2 & SIRFSOC_USP_CLK_DIVISOR_MASK) <<
  			SIRFSOC_USP_CLK_DIVISOR_OFFSET) |
  			(SIRFSOC_USP_RXD_DELAY_LEN <<
  			 SIRFSOC_USP_RXD_DELAY_OFFSET) |
  			(SIRFSOC_USP_TXD_DELAY_LEN <<
  			 SIRFSOC_USP_TXD_DELAY_OFFSET),
  			sspi->base + sspi->regs->usp_mode2);
  	}
  	if (sspi->type == SIRF_REAL_SPI)
  		writel(regval, sspi->base + sspi->regs->spi_ctrl);
  	spi_sirfsoc_config_mode(spi);
  	if (sspi->type == SIRF_REAL_SPI) {
  		if (t && t->tx_buf && !t->rx_buf &&
  			(t->len <= SIRFSOC_MAX_CMD_BYTES)) {
  			sspi->tx_by_cmd = true;
  			writel(readl(sspi->base + sspi->regs->spi_ctrl) |
  				(SIRFSOC_SPI_CMD_BYTE_NUM((t->len - 1)) |
  				SIRFSOC_SPI_CMD_MODE),
  				sspi->base + sspi->regs->spi_ctrl);
  		} else {
  			sspi->tx_by_cmd = false;
  			writel(readl(sspi->base + sspi->regs->spi_ctrl) &
  				~SIRFSOC_SPI_CMD_MODE,
  				sspi->base + sspi->regs->spi_ctrl);
  		}
eeb713952   Qipan Li   spi: sirf: provid...
964
  	}
de39f5fa0   Barry Song   spi: sirf: use DM...
965
966
  	if (IS_DMA_VALID(t)) {
  		/* Enable DMA mode for RX, TX */
e3fb57c83   Qipan Li   spi: sirf: add su...
967
  		writel(0, sspi->base + sspi->regs->tx_dma_io_ctrl);
d77ec5df4   Qipan Li   spi: sirf: fix li...
968
  		writel(SIRFSOC_SPI_RX_DMA_FLUSH,
e3fb57c83   Qipan Li   spi: sirf: add su...
969
  			sspi->base + sspi->regs->rx_dma_io_ctrl);
de39f5fa0   Barry Song   spi: sirf: use DM...
970
971
  	} else {
  		/* Enable IO mode for RX, TX */
d77ec5df4   Qipan Li   spi: sirf: fix li...
972
  		writel(SIRFSOC_SPI_IO_MODE_SEL,
e3fb57c83   Qipan Li   spi: sirf: add su...
973
  			sspi->base + sspi->regs->tx_dma_io_ctrl);
d77ec5df4   Qipan Li   spi: sirf: fix li...
974
  		writel(SIRFSOC_SPI_IO_MODE_SEL,
e3fb57c83   Qipan Li   spi: sirf: add su...
975
  			sspi->base + sspi->regs->rx_dma_io_ctrl);
de39f5fa0   Barry Song   spi: sirf: use DM...
976
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
977
978
979
980
981
  	return 0;
  }
  
  static int spi_sirfsoc_setup(struct spi_device *spi)
  {
7850cdfc8   Qipan Li   spi: sirf: correc...
982
  	struct sirfsoc_spi *sspi;
96bf40194   Qipan Li   spi: sirf: reques...
983
  	int ret = 0;
7850cdfc8   Qipan Li   spi: sirf: correc...
984

7850cdfc8   Qipan Li   spi: sirf: correc...
985
  	sspi = spi_master_get_devdata(spi->master);
7850cdfc8   Qipan Li   spi: sirf: correc...
986
987
  	if (spi->cs_gpio == -ENOENT)
  		sspi->hw_cs = true;
96bf40194   Qipan Li   spi: sirf: reques...
988
  	else {
7850cdfc8   Qipan Li   spi: sirf: correc...
989
  		sspi->hw_cs = false;
96bf40194   Qipan Li   spi: sirf: reques...
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  		if (!spi_get_ctldata(spi)) {
  			void *cs = kmalloc(sizeof(int), GFP_KERNEL);
  			if (!cs) {
  				ret = -ENOMEM;
  				goto exit;
  			}
  			ret = gpio_is_valid(spi->cs_gpio);
  			if (!ret) {
  				dev_err(&spi->dev, "no valid gpio
  ");
  				ret = -ENOENT;
  				goto exit;
  			}
  			ret = gpio_request(spi->cs_gpio, DRIVER_NAME);
  			if (ret) {
  				dev_err(&spi->dev, "failed to request gpio
  ");
  				goto exit;
  			}
  			spi_set_ctldata(spi, cs);
  		}
  	}
e3fb57c83   Qipan Li   spi: sirf: add su...
1012
  	spi_sirfsoc_config_mode(spi);
96bf40194   Qipan Li   spi: sirf: reques...
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
  	spi_sirfsoc_chipselect(spi, BITBANG_CS_INACTIVE);
  exit:
  	return ret;
  }
  
  static void spi_sirfsoc_cleanup(struct spi_device *spi)
  {
  	if (spi_get_ctldata(spi)) {
  		gpio_free(spi->cs_gpio);
  		kfree(spi_get_ctldata(spi));
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1024
  }
5bcc3b0bb   Qipan Li   spi: sirf: add th...
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  static const struct sirf_spi_comp_data sirf_real_spi = {
  	.regs = &real_spi_register,
  	.type = SIRF_REAL_SPI,
  	.dat_max_frm_len = 64 * 1024,
  	.fifo_size = 256,
  };
  
  static const struct sirf_spi_comp_data sirf_usp_spi_p2 = {
  	.regs = &usp_spi_register,
  	.type = SIRF_USP_SPI_P2,
  	.dat_max_frm_len = 1024 * 1024,
  	.fifo_size = 128,
  	.hwinit = sirfsoc_usp_hwinit,
  };
  
  static const struct sirf_spi_comp_data sirf_usp_spi_a7 = {
  	.regs = &usp_spi_register,
  	.type = SIRF_USP_SPI_A7,
  	.dat_max_frm_len = 1024 * 1024,
  	.fifo_size = 512,
  	.hwinit = sirfsoc_usp_hwinit,
  };
e3fb57c83   Qipan Li   spi: sirf: add su...
1047
1048
1049
1050
1051
1052
1053
  static const struct of_device_id spi_sirfsoc_of_match[] = {
  	{ .compatible = "sirf,prima2-spi", .data = &sirf_real_spi},
  	{ .compatible = "sirf,prima2-usp-spi", .data = &sirf_usp_spi_p2},
  	{ .compatible = "sirf,atlas7-usp-spi", .data = &sirf_usp_spi_a7},
  	{}
  };
  MODULE_DEVICE_TABLE(of, spi_sirfsoc_of_match);
fd4a319bc   Grant Likely   spi: Remove HOTPL...
1054
  static int spi_sirfsoc_probe(struct platform_device *pdev)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1055
1056
1057
  {
  	struct sirfsoc_spi *sspi;
  	struct spi_master *master;
9e327ce71   Julia Lawall   spi: sirf: accoun...
1058
  	const struct sirf_spi_comp_data *spi_comp_data;
7850cdfc8   Qipan Li   spi: sirf: correc...
1059
  	int irq;
96bf40194   Qipan Li   spi: sirf: reques...
1060
  	int ret;
e3fb57c83   Qipan Li   spi: sirf: add su...
1061
  	const struct of_device_id *match;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1062

8509c55fc   Qipan Li   spi: sirf: reset ...
1063
1064
1065
1066
1067
1068
  	ret = device_reset(&pdev->dev);
  	if (ret) {
  		dev_err(&pdev->dev, "SPI reset failed!
  ");
  		return ret;
  	}
7850cdfc8   Qipan Li   spi: sirf: correc...
1069
  	master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1070
1071
1072
1073
1074
  	if (!master) {
  		dev_err(&pdev->dev, "Unable to allocate SPI master
  ");
  		return -ENOMEM;
  	}
e3fb57c83   Qipan Li   spi: sirf: add su...
1075
  	match = of_match_node(spi_sirfsoc_of_match, pdev->dev.of_node);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1076
1077
  	platform_set_drvdata(pdev, master);
  	sspi = spi_master_get_devdata(master);
e3fb57c83   Qipan Li   spi: sirf: add su...
1078
  	sspi->fifo_full_offset = ilog2(sspi->fifo_size);
9e327ce71   Julia Lawall   spi: sirf: accoun...
1079
  	spi_comp_data = match->data;
e3fb57c83   Qipan Li   spi: sirf: add su...
1080
1081
1082
1083
1084
  	sspi->regs = spi_comp_data->regs;
  	sspi->type = spi_comp_data->type;
  	sspi->fifo_level_chk_mask = (sspi->fifo_size / 4) - 1;
  	sspi->dat_max_frm_len = spi_comp_data->dat_max_frm_len;
  	sspi->fifo_size = spi_comp_data->fifo_size;
a75500837   YueHaibing   spi: sirf: use de...
1085
  	sspi->base = devm_platform_ioremap_resource(pdev, 0);
b0ee56052   Thierry Reding   spi: Convert to d...
1086
1087
  	if (IS_ERR(sspi->base)) {
  		ret = PTR_ERR(sspi->base);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1088
1089
  		goto free_master;
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1090
1091
1092
1093
1094
1095
1096
1097
1098
  	irq = platform_get_irq(pdev, 0);
  	if (irq < 0) {
  		ret = -ENXIO;
  		goto free_master;
  	}
  	ret = devm_request_irq(&pdev->dev, irq, spi_sirfsoc_irq, 0,
  				DRIVER_NAME, sspi);
  	if (ret)
  		goto free_master;
94c69f765   Axel Lin   spi: bitbang: Let...
1099
  	sspi->bitbang.master = master;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1100
1101
1102
1103
  	sspi->bitbang.chipselect = spi_sirfsoc_chipselect;
  	sspi->bitbang.setup_transfer = spi_sirfsoc_setup_transfer;
  	sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer;
  	sspi->bitbang.master->setup = spi_sirfsoc_setup;
96bf40194   Qipan Li   spi: sirf: reques...
1104
  	sspi->bitbang.master->cleanup = spi_sirfsoc_cleanup;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1105
  	master->bus_num = pdev->id;
94b1f0dfa   Qipan Li   spi: sirf: add mi...
1106
  	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
24778be20   Stephen Warren   spi: convert driv...
1107
1108
  	master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
  					SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
fcc50e5cd   Qipan Li   spi: sirf: assign...
1109
  	master->max_speed_hz = SIRFSOC_SPI_DEFAULT_FRQ;
3aa7b1d66   Qipan Li   spi: sirf: remove...
1110
  	master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1111
  	sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
de39f5fa0   Barry Song   spi: sirf: use DM...
1112
  	/* request DMA channels */
401abb764   Peter Ujfalusi   spi: sirf: Use dm...
1113
1114
  	sspi->rx_chan = dma_request_chan(&pdev->dev, "rx");
  	if (IS_ERR(sspi->rx_chan)) {
de39f5fa0   Barry Song   spi: sirf: use DM...
1115
1116
  		dev_err(&pdev->dev, "can not allocate rx dma channel
  ");
401abb764   Peter Ujfalusi   spi: sirf: Use dm...
1117
  		ret = PTR_ERR(sspi->rx_chan);
de39f5fa0   Barry Song   spi: sirf: use DM...
1118
1119
  		goto free_master;
  	}
401abb764   Peter Ujfalusi   spi: sirf: Use dm...
1120
1121
  	sspi->tx_chan = dma_request_chan(&pdev->dev, "tx");
  	if (IS_ERR(sspi->tx_chan)) {
de39f5fa0   Barry Song   spi: sirf: use DM...
1122
1123
  		dev_err(&pdev->dev, "can not allocate tx dma channel
  ");
401abb764   Peter Ujfalusi   spi: sirf: Use dm...
1124
  		ret = PTR_ERR(sspi->tx_chan);
de39f5fa0   Barry Song   spi: sirf: use DM...
1125
1126
  		goto free_rx_dma;
  	}
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1127
1128
  	sspi->clk = clk_get(&pdev->dev, NULL);
  	if (IS_ERR(sspi->clk)) {
de39f5fa0   Barry Song   spi: sirf: use DM...
1129
1130
  		ret = PTR_ERR(sspi->clk);
  		goto free_tx_dma;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1131
  	}
e5118cd2c   Barry Song   spi/sirf: use clk...
1132
  	clk_prepare_enable(sspi->clk);
5bcc3b0bb   Qipan Li   spi: sirf: add th...
1133
1134
  	if (spi_comp_data->hwinit)
  		spi_comp_data->hwinit(sspi);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1135
  	sspi->ctrl_freq = clk_get_rate(sspi->clk);
de39f5fa0   Barry Song   spi: sirf: use DM...
1136
1137
  	init_completion(&sspi->rx_done);
  	init_completion(&sspi->tx_done);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1138

1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1139
1140
  	ret = spi_bitbang_start(&sspi->bitbang);
  	if (ret)
a34bcbedf   Qipan Li   spi: sirf: replac...
1141
  		goto free_clk;
2d781e89e   Colin Ian King   spi: sirf: fix sp...
1142
1143
  	dev_info(&pdev->dev, "registered, bus number = %d
  ", master->bus_num);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1144
1145
  
  	return 0;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1146
  free_clk:
e5118cd2c   Barry Song   spi/sirf: use clk...
1147
  	clk_disable_unprepare(sspi->clk);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1148
  	clk_put(sspi->clk);
de39f5fa0   Barry Song   spi: sirf: use DM...
1149
1150
1151
1152
  free_tx_dma:
  	dma_release_channel(sspi->tx_chan);
  free_rx_dma:
  	dma_release_channel(sspi->rx_chan);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1153
1154
  free_master:
  	spi_master_put(master);
7850cdfc8   Qipan Li   spi: sirf: correc...
1155

1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1156
1157
  	return ret;
  }
fd4a319bc   Grant Likely   spi: Remove HOTPL...
1158
  static int  spi_sirfsoc_remove(struct platform_device *pdev)
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1159
1160
1161
  {
  	struct spi_master *master;
  	struct sirfsoc_spi *sspi;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1162
1163
1164
  
  	master = platform_get_drvdata(pdev);
  	sspi = spi_master_get_devdata(master);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1165
  	spi_bitbang_stop(&sspi->bitbang);
e5118cd2c   Barry Song   spi/sirf: use clk...
1166
  	clk_disable_unprepare(sspi->clk);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1167
  	clk_put(sspi->clk);
de39f5fa0   Barry Song   spi: sirf: use DM...
1168
1169
  	dma_release_channel(sspi->rx_chan);
  	dma_release_channel(sspi->tx_chan);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1170
1171
1172
  	spi_master_put(master);
  	return 0;
  }
facffed29   Qipan Li   spi: sirf: use SE...
1173
  #ifdef CONFIG_PM_SLEEP
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1174
1175
  static int spi_sirfsoc_suspend(struct device *dev)
  {
a1216394e   Axel Lin   spi: Use dev_get_...
1176
  	struct spi_master *master = dev_get_drvdata(dev);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1177
  	struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
a82ba3a31   Axel Lin   spi: sirf: Add mi...
1178
1179
1180
1181
1182
  	int ret;
  
  	ret = spi_master_suspend(master);
  	if (ret)
  		return ret;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1183
1184
1185
1186
1187
1188
1189
  
  	clk_disable(sspi->clk);
  	return 0;
  }
  
  static int spi_sirfsoc_resume(struct device *dev)
  {
a1216394e   Axel Lin   spi: Use dev_get_...
1190
  	struct spi_master *master = dev_get_drvdata(dev);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1191
1192
1193
  	struct sirfsoc_spi *sspi = spi_master_get_devdata(master);
  
  	clk_enable(sspi->clk);
e3fb57c83   Qipan Li   spi: sirf: add su...
1194
1195
1196
1197
1198
  	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + sspi->regs->txfifo_op);
  	writel(SIRFSOC_SPI_FIFO_RESET, sspi->base + sspi->regs->rxfifo_op);
  	writel(SIRFSOC_SPI_FIFO_START, sspi->base + sspi->regs->txfifo_op);
  	writel(SIRFSOC_SPI_FIFO_START, sspi->base + sspi->regs->rxfifo_op);
  	return 0;
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1199
  }
facffed29   Qipan Li   spi: sirf: use SE...
1200
  #endif
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1201

71aa2e320   Jingoo Han   spi: sirf: Use SI...
1202
1203
  static SIMPLE_DEV_PM_OPS(spi_sirfsoc_pm_ops, spi_sirfsoc_suspend,
  			 spi_sirfsoc_resume);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1204

1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1205
1206
1207
  static struct platform_driver spi_sirfsoc_driver = {
  	.driver = {
  		.name = DRIVER_NAME,
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1208
  		.pm     = &spi_sirfsoc_pm_ops,
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1209
1210
1211
  		.of_match_table = spi_sirfsoc_of_match,
  	},
  	.probe = spi_sirfsoc_probe,
fd4a319bc   Grant Likely   spi: Remove HOTPL...
1212
  	.remove = spi_sirfsoc_remove,
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1213
1214
  };
  module_platform_driver(spi_sirfsoc_driver);
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1215
  MODULE_DESCRIPTION("SiRF SoC SPI master driver");
d77ec5df4   Qipan Li   spi: sirf: fix li...
1216
1217
  MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>");
  MODULE_AUTHOR("Barry Song <Baohua.Song@csr.com>");
e3fb57c83   Qipan Li   spi: sirf: add su...
1218
  MODULE_AUTHOR("Qipan Li <Qipan.Li@csr.com>");
1cc2df9d6   Zhiwu Song   SPI: add CSR SiRF...
1219
  MODULE_LICENSE("GPL v2");