Root/target/linux/cns3xxx/patches-2.6.31/207-cns3xxx_spi_support.patch

1--- a/drivers/spi/Kconfig
2+++ b/drivers/spi/Kconfig
3@@ -236,6 +236,39 @@ config SPI_XILINX
4       See the "OPB Serial Peripheral Interface (SPI) (v1.00e)"
5       Product Specification document (DS464) for hardware details.
6 
7+config SPI_CNS3XXX
8+ tristate "CNS3XXX SPI controller"
9+ depends on ARCH_CNS3XXX && SPI_MASTER && EXPERIMENTAL
10+ select SPI_BITBANG
11+ help
12+ This enables using the CNS3XXX SPI controller in master
13+ mode.
14+
15+config SPI_CNS3XXX_DEBUG
16+ boolean "Debug support for CNS3XXX SPI drivers"
17+ depends on SPI_CNS3XXX
18+ help
19+ Say "yes" to enable debug messaging
20+
21+config SPI_CNS3XXX_2IOREAD
22+ bool "CNS3XXX SPI 2 IO Read Mode"
23+ depends on SPI_CNS3XXX
24+ help
25+ This enables 2 IO Read Mode
26+
27+config SPI_CNS3XXX_USEDMA
28+ bool "CNS3XXX SPI DMA Mode"
29+ depends on SPI_CNS3XXX
30+ select CNS3XXX_DMAC
31+ help
32+ This enables DMA Mode
33+
34+config SPI_CNS3XXX_USEDMA_DEBUG
35+ boolean "Debug support for CNS3XXX SPI DMA drivers"
36+ depends on SPI_CNS3XXX_USEDMA
37+ help
38+ Say "yes" to enable debug messaging
39+
40 #
41 # Add new SPI master controllers in alphabetical order above this line
42 #
43--- a/drivers/spi/Makefile
44+++ b/drivers/spi/Makefile
45@@ -32,6 +32,7 @@ obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24x
46 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
47 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
48 obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
49+obj-$(CONFIG_SPI_CNS3XXX) += spi_cns3xxx.o
50 # ... add above this line ...
51 
52 # SPI protocol drivers (device/link on bus)
53--- a/drivers/spi/spi_bitbang.c
54+++ b/drivers/spi/spi_bitbang.c
55@@ -334,6 +334,14 @@ static void bitbang_work(struct work_str
56                  */
57                 if (!m->is_dma_mapped)
58                     t->rx_dma = t->tx_dma = 0;
59+
60+#ifdef CONFIG_ARCH_CNS3XXX
61+ if (t->transfer_list.next == &m->transfers) {
62+ t->last_in_message_list = 1;
63+ } else {
64+ t->last_in_message_list = 0;
65+ }
66+#endif
67                 status = bitbang->txrx_bufs(spi, t);
68             }
69             if (status > 0)
70--- a/drivers/spi/spi.c
71+++ b/drivers/spi/spi.c
72@@ -769,6 +769,89 @@ int spi_write_then_read(struct spi_devic
73 }
74 EXPORT_SYMBOL_GPL(spi_write_then_read);
75 
76+#ifdef CONFIG_ARCH_CNS3XXX
77+/**
78+ * spi_write_read_sync - SPI synchronous write & read
79+ * @spi: device with which data will be exchanged
80+ * @txbuf: data to be written (need not be dma-safe)
81+ * @n_tx: size of txbuf, in bytes
82+ * @rxbuf: buffer into which data will be read
83+ * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
84+ *
85+ * This performs a half duplex MicroWire style transaction with the
86+ * device, sending txbuf and then reading rxbuf. The return value
87+ * is zero for success, else a negative errno status code.
88+ * This call may only be used from a context that may sleep.
89+ *
90+ * Parameters to this routine are always copied using a small buffer;
91+ * performance-sensitive or bulk transfer code should instead use
92+ * spi_{async,sync}() calls with dma-safe buffers.
93+ */
94+int spi_write_read_sync(struct spi_device *spi,
95+ const u8 *txbuf, unsigned n_tx,
96+ u8 *rxbuf, unsigned n_rx)
97+{
98+ static DECLARE_MUTEX(lock);
99+
100+ int status;
101+ struct spi_message message;
102+ struct spi_transfer x;
103+ u8 *local_buf;
104+
105+ /* Use preallocated DMA-safe buffer. We can't avoid copying here,
106+ * (as a pure convenience thing), but we can keep heap costs
107+ * out of the hot path ...
108+ */
109+#if 0
110+ while (!str8131_spi_bus_idle()){
111+ printk("spi bus is not idle \n"); // do nothing
112+ }
113+ while (!str8131_spi_tx_buffer_empty()){
114+ printk("spi tx buffer is not empty \n"); // do nothing
115+ }
116+#endif
117+ if ((n_tx + n_rx) > SPI_BUFSIZ)
118+ return -EINVAL;
119+ spi_message_init(&message);
120+ memset(&x, 0, sizeof x);
121+ x.len = n_tx;
122+ spi_message_add_tail(&x, &message);
123+
124+ /* ... unless someone else is using the pre-allocated buffer */
125+ if (down_trylock(&lock)) {
126+ local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
127+ if (!local_buf)
128+ return -ENOMEM;
129+ } else
130+ local_buf = buf;
131+
132+ memcpy(local_buf, txbuf, n_tx);
133+ x.tx_buf = local_buf;
134+ x.rx_buf = local_buf + n_tx;
135+
136+ /* do the i/o */
137+ status = spi_sync(spi, &message);
138+ if (status == 0) {
139+ memcpy(rxbuf, x.rx_buf, n_rx);
140+ status = message.status;
141+ }
142+
143+ if (x.tx_buf == buf)
144+ up(&lock);
145+ else
146+ kfree(local_buf);
147+
148+ return status;
149+}
150+
151+EXPORT_SYMBOL_GPL(spi_write_read_sync);
152+#endif /* CONFIG_ARCH_CNS3XXX */
153+
154+
155+
156+
157+
158+
159 /*-------------------------------------------------------------------------*/
160 
161 static int __init spi_init(void)
162--- /dev/null
163+++ b/drivers/spi/spi_cns3xxx.c
164@@ -0,0 +1,878 @@
165+/*******************************************************************************
166+ *
167+ * CNS3XXX SPI controller driver (master mode only)
168+ *
169+ * Copyright (c) 2008 Cavium Networks
170+ *
171+ * This file is free software; you can redistribute it and/or modify
172+ * it under the terms of the GNU General Public License, Version 2, as
173+ * published by the Free Software Foundation.
174+ *
175+ * This file is distributed in the hope that it will be useful,
176+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
177+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
178+ * NONINFRINGEMENT. See the GNU General Public License for more details.
179+ *
180+ * You should have received a copy of the GNU General Public License
181+ * along with this file; if not, write to the Free Software
182+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
183+ * visit http://www.gnu.org/licenses/.
184+ *
185+ * This file may also be available under a different license from Cavium.
186+ * Contact Cavium Networks for more information
187+ *
188+ ******************************************************************************/
189+
190+#include <linux/init.h>
191+#include <linux/spinlock.h>
192+#include <linux/workqueue.h>
193+#include <linux/interrupt.h>
194+#include <linux/delay.h>
195+#include <linux/errno.h>
196+#include <linux/err.h>
197+#include <linux/clk.h>
198+#include <linux/platform_device.h>
199+
200+#include <linux/spi/spi.h>
201+#include <linux/spi/spi_bitbang.h>
202+#include <linux/mtd/partitions.h>
203+#include <linux/dma-mapping.h>
204+
205+#include <asm/io.h>
206+#include <asm/memory.h>
207+#include <asm/dma.h>
208+#include <asm/delay.h>
209+#include <mach/board.h>
210+#include <mach/dmac.h>
211+#include <linux/module.h>
212+#include <mach/misc.h>
213+#include <mach/gpio.h>
214+#include <mach/pm.h>
215+
216+#define LE8221_SPI_CS 1
217+#define SI3226_SPI_CS 1
218+
219+#define CNS3XXX_SPI_INTERRUPT
220+#undef CNS3XXX_SPI_INTERRUPT /* Interrupt is not supported for D2 and SEN */
221+
222+/*
223+ * define access macros
224+ */
225+#define SPI_MEM_MAP_VALUE(reg_offset) (*((u32 volatile *)(CNS3XXX_SSP_BASE_VIRT + reg_offset)))
226+
227+#define SPI_CONFIGURATION_REG SPI_MEM_MAP_VALUE(0x40)
228+#define SPI_SERVICE_STATUS_REG SPI_MEM_MAP_VALUE(0x44)
229+#define SPI_BIT_RATE_CONTROL_REG SPI_MEM_MAP_VALUE(0x48)
230+#define SPI_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x4C)
231+#define SPI_TRANSMIT_BUFFER_REG SPI_MEM_MAP_VALUE(0x50)
232+#define SPI_RECEIVE_CONTROL_REG SPI_MEM_MAP_VALUE(0x54)
233+#define SPI_RECEIVE_BUFFER_REG SPI_MEM_MAP_VALUE(0x58)
234+#define SPI_FIFO_TRANSMIT_CONFIG_REG SPI_MEM_MAP_VALUE(0x5C)
235+#define SPI_FIFO_TRANSMIT_CONTROL_REG SPI_MEM_MAP_VALUE(0x60)
236+#define SPI_FIFO_RECEIVE_CONFIG_REG SPI_MEM_MAP_VALUE(0x64)
237+#define SPI_INTERRUPT_STATUS_REG SPI_MEM_MAP_VALUE(0x68)
238+#define SPI_INTERRUPT_ENABLE_REG SPI_MEM_MAP_VALUE(0x6C)
239+
240+#define SPI_TRANSMIT_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x50)
241+#define SPI_RECEIVE_BUFFER_REG_ADDR (CNS3XXX_SSP_BASE +0x58)
242+
243+/* Structure for SPI controller of CNS3XXX SOCs */
244+struct cns3xxx_spi {
245+ /* bitbang has to be first */
246+ struct spi_bitbang bitbang;
247+ struct completion done;
248+ wait_queue_head_t wait;
249+
250+ int len;
251+ int count;
252+ int last_in_message_list;
253+
254+ /* data buffers */
255+ const unsigned char *tx;
256+ unsigned char *rx;
257+
258+ struct spi_master *master;
259+ struct platform_device *pdev;
260+ struct device *dev;
261+};
262+
263+static inline u8 cns3xxx_spi_bus_idle(void)
264+{
265+ return ((SPI_SERVICE_STATUS_REG & 0x1) ? 0 : 1);
266+}
267+
268+static inline u8 cns3xxx_spi_tx_buffer_empty(void)
269+{
270+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 3)) ? 1 : 0);
271+}
272+
273+static inline u8 cns3xxx_spi_rx_buffer_full(void)
274+{
275+ return ((SPI_INTERRUPT_STATUS_REG & (0x1 << 2)) ? 1 : 0);
276+}
277+
278+u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data,
279+ u32 * rx_data)
280+{
281+ u8 rx_channel;
282+ u8 rx_eof;
283+
284+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
285+
286+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
287+
288+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
289+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
290+
291+ SPI_TRANSMIT_BUFFER_REG = tx_data;
292+
293+ while (!cns3xxx_spi_rx_buffer_full()) ; // do nothing
294+
295+ rx_channel = SPI_RECEIVE_CONTROL_REG & 0x3;
296+ rx_eof = (SPI_RECEIVE_CONTROL_REG & (0x1 << 2)) ? 1 : 0;
297+
298+ *rx_data = SPI_RECEIVE_BUFFER_REG;
299+
300+ if ((tx_channel != rx_channel) || (tx_eof != rx_eof)) {
301+ return 0;
302+ } else {
303+ return 1;
304+ }
305+}
306+
307+u8 cns3xxx_spi_tx(u8 tx_channel, u8 tx_eof, u32 tx_data)
308+{
309+
310+ while (!cns3xxx_spi_bus_idle()) ; // do nothing
311+
312+ while (!cns3xxx_spi_tx_buffer_empty()) ; // do nothing
313+
314+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
315+ SPI_TRANSMIT_CONTROL_REG |= (tx_channel & 0x3) | ((tx_eof & 0x1) << 2);
316+
317+ SPI_TRANSMIT_BUFFER_REG = tx_data;
318+
319+ return 1;
320+}
321+
322+
323+
324+#ifdef CONFIG_SPI_CNS3XXX_DEBUG
325+static void spi_slave_probe(void)
326+{
327+ int i;
328+ u32 rx_data1, rx_data2, rx_data3;
329+
330+ cns3xxx_spi_tx_rx(0, 0, 0x9f, &rx_data1);
331+ cns3xxx_spi_tx_rx(0, 0, 0xff, &rx_data1);
332+ cns3xxx_spi_tx_rx(0, 0, 0xff, &rx_data2);
333+ cns3xxx_spi_tx_rx(0, 1, 0xff, &rx_data3);
334+ printk("[SPI_CNS3XXX_DEBUG] manufacturer: %x\n", rx_data1);
335+ printk("[SPI_CNS3XXX_DEBUG] device: %x\n",
336+ ((rx_data2 & 0xff) << 8) | (u16) (rx_data3 & 0xff));
337+
338+ cns3xxx_spi_tx_rx(0, 0, 0x03, &rx_data1);
339+ cns3xxx_spi_tx_rx(0, 0, 0x00, &rx_data1);
340+ cns3xxx_spi_tx_rx(0, 0, 0x00, &rx_data1);
341+ cns3xxx_spi_tx_rx(0, 0, 0x00, &rx_data1);
342+ for (i = 0; i < 15; i++) {
343+ cns3xxx_spi_tx_rx(0, 0, 0xff, &rx_data1);
344+ printk("[SPI_CNS3XXX_DEBUG] flash[%02d]:0x%02x\n", i,
345+ rx_data1 & 0xff);
346+ }
347+ cns3xxx_spi_tx_rx(0, 1, 0xff, &rx_data1);
348+ printk("[SPI_CNS3XXX_DEBUG] flash[%02d]:0x%02x\n", i, rx_data1 & 0xff);
349+}
350+#else
351+#define spi_slave_probe() do{}while(0)
352+#endif
353+
354+static inline struct cns3xxx_spi *to_hw(struct spi_device *sdev)
355+{
356+ return spi_master_get_devdata(sdev->master);
357+}
358+
359+static int cns3xxx_spi_setup_transfer(struct spi_device *spi,
360+ struct spi_transfer *t)
361+{
362+ return 0;
363+}
364+
365+static void cns3xxx_spi_chipselect(struct spi_device *spi, int value)
366+{
367+ unsigned int spi_config;
368+
369+ switch (value) {
370+ case BITBANG_CS_INACTIVE:
371+ break;
372+
373+ case BITBANG_CS_ACTIVE:
374+ spi_config = SPI_CONFIGURATION_REG;
375+
376+ if (spi->mode & SPI_CPHA)
377+ spi_config |= (0x1 << 13);
378+ else
379+ spi_config &= ~(0x1 << 13);
380+
381+ if (spi->mode & SPI_CPOL)
382+ spi_config |= (0x1 << 14);
383+ else
384+ spi_config &= ~(0x1 << 14);
385+
386+ /* write new configration */
387+ SPI_CONFIGURATION_REG = spi_config;
388+
389+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
390+ SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3);
391+
392+#if defined(CONFIG_LE8221_CONTROL)
393+ if (spi->chip_select == LE8221_SPI_CS) {
394+ SPI_CONFIGURATION_REG |= (0x1 << 9);
395+ }
396+#elif defined (CONFIG_SI3226_CONTROL_API)
397+ if (spi->chip_select == SI3226_SPI_CS) {
398+ SPI_CONFIGURATION_REG &= ~(0x1 << 9);
399+ }
400+#endif
401+ break;
402+ }
403+}
404+
405+static int cns3xxx_spi_setup(struct spi_device *spi)
406+{
407+ if (!spi->bits_per_word)
408+ spi->bits_per_word = 8;
409+
410+ return 0;
411+}
412+
413+#ifdef CONFIG_SPI_CNS3XXX_USEDMA
414+
415+int cns3xxx_spi_dma_irq_handler(void *pdata)
416+{
417+
418+ struct cns3xxx_spi *hw = pdata;
419+ complete(&hw->done);
420+
421+ return 0;
422+}
423+
424+static int cns3xxx_spi_dma_initialize(int *rxchan, int *txchan, int *rxevtno,
425+ int *txevtno, void *handlerargs)
426+{
427+ *rxchan = dmac_get_channel(cns3xxx_spi_dma_irq_handler, handlerargs);
428+ if ((*rxchan) == -1)
429+ goto fail1;
430+ *txchan = dmac_get_channel(NULL, NULL);
431+ if ((*txchan) == -1)
432+ goto fail2;
433+ *rxevtno = 9;
434+ if (dmac_get_event(*rxchan, *rxevtno) == -1)
435+ goto fail3;
436+ *txevtno = 10;
437+ if (dmac_get_event(*txchan, *txevtno) == -1)
438+ goto fail4;
439+ return 0;
440+
441+fail4:
442+ dmac_release_event(*rxchan, *rxevtno);
443+fail3:
444+ dmac_release_channel(*txchan);
445+fail2:
446+ dmac_release_channel(*rxchan);
447+fail1:
448+ return -1;
449+}
450+
451+static int cns3xxx_spi_start_dma(int rch, int tch, int rev, int tev,
452+ struct spi_transfer *t, struct cns3xxx_spi *hw)
453+{
454+ static void *dummy;
455+ static dma_addr_t dummy_dma;
456+ dma_addr_t rdma, tdma;
457+ int rx_inc, tx_inc;
458+ int lc0, totlps, lc1, rump;
459+ u32 rx_data;
460+
461+ if (!dummy) {
462+ dummy = dma_alloc_coherent(NULL, 16, &dummy_dma, GFP_KERNEL);
463+#ifdef CONFIG_SPI_CNS3XXX_DEBUG_DMA
464+ printk("Allocated Memory for dummy buffer va:%p,pa:%x\n", dummy,
465+ dummy_dma);
466+#endif
467+ }
468+ if (!dummy) {
469+ return -1;
470+ }
471+ *((uint32_t *) dummy) = 0xffffffff;
472+
473+ (t->tx_buf) ? (tdma = t->tx_dma, tx_inc = 1) :
474+ (tdma = dummy_dma, tx_inc = 0);
475+ (t->rx_buf) ? (rdma = t->rx_dma, rx_inc = 1) :
476+ (rdma = dummy_dma, rx_inc = 0);
477+
478+#ifdef CONFIG_SPI_CNS3XXX_DEBUG_DMA
479+ printk("Here with tdma %x, rdma %x\n", tdma, rdma);
480+#endif
481+
482+ if(t->len < 3) {
483+ if(t->len == 2){
484+ cns3xxx_spi_tx_rx(0,0,(t->tx_buf) ? hw->tx[0] : 0xff ,&rx_data);
485+ if(!(t->tx_buf))
486+ hw->rx[0] = rx_data & 0xff;
487+ }
488+ cns3xxx_spi_dma_irq_handler(hw);
489+ return 0;
490+ }
491+
492+
493+ totlps = t->len - 1 -1;
494+ if (totlps > 0x100) {
495+ lc0 = 0x100;
496+ lc1 = totlps / lc0;
497+ rump = totlps % lc0;
498+ } else {
499+ lc0 = totlps;
500+ lc1 = 0;
501+ rump = 0;
502+ }
503+
504+ if(t->tx_buf) {
505+ cns3xxx_spi_tx(0,0,*((uint32_t *) t->tx_buf));
506+ tdma+=1;
507+ }
508+ else {
509+ cns3xxx_spi_tx(0,0,0xff);
510+ }
511+
512+ //SPI_RECEIVE_BUFFER_REG;
513+ {
514+ DMAC_DMAMOV(tch, SAR, tdma);
515+ DMAC_DMAMOV(tch, DAR, SPI_TRANSMIT_BUFFER_REG_ADDR);
516+ DMAC_DMAMOV(tch, CCR,
517+ dmac_create_ctrlval(tx_inc, 1, 1, 0, 1, 1, 0));
518+ //DMAC_WFE(tch, rev);
519+ if (lc1)
520+ DMAC_DMALP(tch, 1, lc1);
521+ DMAC_DMALP(tch, 0, lc0);
522+ DMAC_WFE(tch, rev);
523+ DMAC_DMALDS(tch);
524+ DMAC_DMASTS(tch);
525+ DMAC_DMAWMB(tch);
526+ DMAC_DMASEV(tch, tev);
527+ DMAC_DMALPEND(tch, 0,
528+ DMAWFE_INSTR_SIZE + DMASEV_INSTR_SIZE +
529+ DMAWMB_INSTR_SIZE + DMAST_INSTR_SIZE +
530+ DMALD_INSTR_SIZE, 1);
531+ if (lc1)
532+ DMAC_DMALPEND(tch, 1,
533+ DMALP_INSTR_SIZE + DMALPEND_INSTR_SIZE +
534+ DMAWFE_INSTR_SIZE + DMASEV_INSTR_SIZE +
535+ DMAWMB_INSTR_SIZE + DMAST_INSTR_SIZE +
536+ DMALD_INSTR_SIZE, 1);
537+
538+ if (rump) {
539+ DMAC_DMALP(tch, 0, rump);
540+ DMAC_WFE(tch, rev);
541+ DMAC_DMALDS(tch);
542+ DMAC_DMASTS(tch);
543+ DMAC_DMAWMB(tch);
544+ DMAC_DMASEV(tch, tev);
545+ DMAC_DMALPEND(tch, 0,
546+ DMAWFE_INSTR_SIZE + DMASEV_INSTR_SIZE +
547+ DMAWMB_INSTR_SIZE + DMAST_INSTR_SIZE +
548+ DMALD_INSTR_SIZE, 1);
549+ }
550+
551+
552+ DMAC_DMAEND(tch);
553+ DMAC_DMAGO(tch);
554+ }
555+ {
556+ DMAC_DMAMOV(rch, SAR, SPI_RECEIVE_BUFFER_REG_ADDR);
557+ DMAC_DMAMOV(rch, DAR, rdma);
558+ DMAC_DMAMOV(rch, CCR,
559+ dmac_create_ctrlval(0, 1, 1, rx_inc, 1, 1, 0));
560+
561+ if (lc1)
562+ DMAC_DMALP(rch, 1, lc1);
563+ DMAC_DMALP(rch, 0, lc0);
564+ DMAC_DMAWFP(rch, DMAC_SPI_PERIPH_ID, PERIPHERAL);
565+ DMAC_DMALDP(rch, DMAC_SPI_PERIPH_ID, 0);
566+ DMAC_DMASTS(rch);
567+ DMAC_DMAWMB(rch);
568+ DMAC_DMASEV(rch, rev);
569+ DMAC_WFE(rch, tev);
570+ DMAC_DMALPEND(rch, 0,
571+ DMAWFE_INSTR_SIZE + DMASEV_INSTR_SIZE +
572+ DMAWMB_INSTR_SIZE + DMAST_INSTR_SIZE +
573+ DMALDP_INSTR_SIZE + DMAWFP_INSTR_SIZE, 1);
574+ if (lc1)
575+ DMAC_DMALPEND(rch, 1,
576+ DMAWFE_INSTR_SIZE +
577+ DMASEV_INSTR_SIZE + DMAWMB_INSTR_SIZE +
578+ DMAST_INSTR_SIZE + DMALDP_INSTR_SIZE +
579+ DMAWFP_INSTR_SIZE + DMALP_INSTR_SIZE +
580+ DMALPEND_INSTR_SIZE, 1);
581+
582+
583+ if (rump) {
584+ DMAC_DMALP(rch, 0, rump);
585+ DMAC_DMAWFP(rch, DMAC_SPI_PERIPH_ID, PERIPHERAL);
586+ DMAC_DMALDP(rch, DMAC_SPI_PERIPH_ID, 0);
587+ DMAC_DMASTS(rch);
588+ DMAC_DMAWMB(rch);
589+ DMAC_DMASEV(rch, rev);
590+ DMAC_WFE(rch, tev);
591+ DMAC_DMALPEND(rch, 0,
592+ DMAWFE_INSTR_SIZE +
593+ DMASEV_INSTR_SIZE + DMAWMB_INSTR_SIZE +
594+ DMAST_INSTR_SIZE + DMALDP_INSTR_SIZE +
595+ DMAWFP_INSTR_SIZE, 1);
596+ }
597+ // extra RX
598+ DMAC_DMAWFP(rch, DMAC_SPI_PERIPH_ID, PERIPHERAL);
599+ DMAC_DMALDP(rch, DMAC_SPI_PERIPH_ID, 0);
600+ DMAC_DMASTS(rch);
601+ DMAC_DMAWMB(rch);
602+
603+ DMAC_DMAFLUSHP(rch, DMAC_SPI_PERIPH_ID);
604+ DMAC_DMASEV(rch, rch); // This will generate an interrupt
605+ DMAC_DMAEND(rch);
606+ DMAC_DMAGO(rch);
607+ }
608+ return 0;
609+}
610+
611+static void cns3xxx_spi_dma_uninitialize(int rch, int tch, int revt, int tevt)
612+{
613+ dmac_release_event(rch, revt);
614+ dmac_release_event(tch, tevt);
615+ dmac_release_channel(rch);
616+ dmac_release_channel(tch);
617+ return;
618+}
619+
620+#endif /* CONFIG_SPI_CNS3XXX_USEDMA */
621+
622+static int cns3xxx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
623+{
624+ struct cns3xxx_spi *hw = to_hw(spi);
625+#ifdef CONFIG_SPI_CNS3XXX_USEDMA
626+ int spi_rxchan, spi_txchan, spi_rxevt, spi_txevt;
627+ int rx_data;
628+#endif
629+ dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf,
630+ t->len);
631+
632+ hw->tx = t->tx_buf;
633+ hw->rx = t->rx_buf;
634+ hw->len = t->len;
635+ hw->count = 0;
636+ hw->last_in_message_list = t->last_in_message_list;
637+
638+#ifdef CONFIG_SPI_CNS3XXX_USEDMA
639+ init_completion(&hw->done);
640+
641+ if (cns3xxx_spi_dma_initialize
642+ (&spi_rxchan, &spi_txchan, &spi_rxevt, &spi_txevt, hw)) {
643+ dev_dbg(&spi->dev, "%s:%d Could not initialize DMA. \n",
644+ __FUNCTION__, __LINE__);
645+ return 0;
646+ }
647+
648+ if (t->tx_buf)
649+ t->tx_dma =
650+ dma_map_single(NULL, t->tx_buf, t->len, DMA_TO_DEVICE);
651+ if (t->rx_buf)
652+ t->rx_dma =
653+ dma_map_single(NULL, t->rx_buf, t->len, DMA_FROM_DEVICE);
654+
655+ if (cns3xxx_spi_start_dma
656+ (spi_rxchan, spi_txchan, spi_rxevt, spi_txevt, t, hw)) {
657+ dev_dbg(&spi->dev, "Could not start DMA. \n");
658+ if (t->tx_buf)
659+ dma_unmap_single(NULL, t->tx_dma, t->len,
660+ DMA_TO_DEVICE);
661+ t->tx_dma = 0;
662+ if (t->rx_buf)
663+ dma_unmap_single(NULL, t->rx_dma, t->len,
664+ DMA_FROM_DEVICE);
665+ t->rx_dma = 0;
666+ cns3xxx_spi_dma_uninitialize(spi_rxchan, spi_txchan, spi_rxevt,
667+ spi_txevt);
668+ return 0;
669+ }
670+
671+ wait_for_completion(&hw->done);
672+
673+ dev_dbg(&spi->dev, "DMA reported completion of transfer of %d bytes\n",
674+ t->len - 1);
675+
676+ if (t->tx_buf)
677+ dma_unmap_single(NULL, t->tx_dma, t->len, DMA_TO_DEVICE);
678+ t->tx_dma = 0;
679+ if (t->rx_buf)
680+ dma_unmap_single(NULL, t->rx_dma, t->len, DMA_FROM_DEVICE);
681+ t->rx_dma = 0;
682+ cns3xxx_spi_dma_uninitialize(spi_rxchan, spi_txchan, spi_rxevt,
683+ spi_txevt);
684+
685+ if (t->last_in_message_list)
686+ cns3xxx_spi_tx_rx(spi->chip_select, 1,
687+ (hw->tx) ? hw->tx[hw->len - 1] : 0xff,
688+ &rx_data);
689+ else
690+ cns3xxx_spi_tx_rx(spi->chip_select, 0,
691+ (hw->tx) ? hw->tx[hw->len - 1] : 0xff,
692+ &rx_data);
693+
694+ if (hw->rx)
695+ hw->rx[hw->len - 1] = rx_data & 0xff;
696+
697+ return hw->len;
698+
699+#else /* !CONFIG_SPI_CNS3XXX_USEDMA */
700+
701+#ifdef CNS3XXX_SPI_INTERRUPT
702+
703+ init_completion(&hw->done);
704+
705+ /* Effectively, we are enabling only the Receive Buffer Interrupt Enable */
706+ /* TX Buf Underrun and RX Buf Overrun are not to happen */
707+ SPI_INTERRUPT_ENABLE_REG = (0x1 << 2);
708+// (0x0) | (0x1 << 2) | (0x0 << 3) | (0x1 << 6) | (0x1 << 7);
709+
710+ /* Write data and wait for completion */
711+ SPI_TRANSMIT_CONTROL_REG &= ~(0x7);
712+ SPI_TRANSMIT_CONTROL_REG |= (spi->chip_select & 0x3) |
713+ ((((hw->last_in_message_list) && (hw->len == 1)) ? 0x1 : 0x0) << 2);
714+
715+ SPI_TRANSMIT_BUFFER_REG = (hw->tx) ? hw->tx[hw->count] : 0xff;
716+
717+ wait_for_completion(&hw->done);
718+
719+ SPI_INTERRUPT_ENABLE_REG = 0;
720+
721+ return hw->count;
722+
723+#else /* !CNS3XXX_SPI_INTERRUPT */
724+
725+ init_completion(&hw->done);
726+
727+ if (hw->tx) {
728+ int i;
729+ u32 rx_data;
730+ for (i = 0; i < (hw->len - 1); i++) {
731+ dev_dbg(&spi->dev,
732+ "[SPI_CNS3XXX_DEBUG] hw->tx[%02d]: 0x%02x\n", i,
733+ hw->tx[i]);
734+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
735+ &rx_data);
736+ if (hw->rx) {
737+ hw->rx[i] = rx_data;
738+ dev_dbg(&spi->dev,
739+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
740+ i, hw->rx[i]);
741+ }
742+ }
743+
744+ if (t->last_in_message_list) {
745+ cns3xxx_spi_tx_rx(spi->chip_select, 1, hw->tx[i],
746+ &rx_data);
747+ if (hw->rx) {
748+ hw->rx[i] = rx_data;
749+ dev_dbg(&spi->dev,
750+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
751+ i, hw->rx[i]);
752+ }
753+ } else {
754+ cns3xxx_spi_tx_rx(spi->chip_select, 0, hw->tx[i],
755+ &rx_data);
756+ }
757+ goto done;
758+ }
759+
760+ if (hw->rx) {
761+ int i;
762+ u32 rx_data;
763+ for (i = 0; i < (hw->len - 1); i++) {
764+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
765+ hw->rx[i] = rx_data;
766+ dev_dbg(&spi->dev,
767+ "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n", i,
768+ hw->rx[i]);
769+ }
770+
771+ if (t->last_in_message_list) {
772+ cns3xxx_spi_tx_rx(spi->chip_select, 1, 0xff, &rx_data);
773+ } else {
774+ cns3xxx_spi_tx_rx(spi->chip_select, 0, 0xff, &rx_data);
775+ }
776+ hw->rx[i] = rx_data;
777+ dev_dbg(&spi->dev, "[SPI_CNS3XXX_DEBUG] hw->rx[%02d]: 0x%02x\n",
778+ i, hw->rx[i]);
779+ }
780+done:
781+ return hw->len;
782+
783+#endif /* CNS3XXX_SPI_INTERRUPT */
784+
785+#endif /* CONFIG_SPI_CNS3XXX_USEDMA */
786+}
787+
788+#ifdef CNS3XXX_SPI_INTERRUPT
789+/* Driver supports single master only.
790+ * We have disabled fifo, so we wait for the receive buff full interrupt.
791+ * Receive Buff overrun, transmit buff underrun are not to happen
792+ */
793+static irqreturn_t cns3xxx_spi_irq(int irq, void *dev)
794+{
795+ struct cns3xxx_spi *hw = dev;
796+ uint32_t int_status;
797+ uint8_t data;
798+ unsigned int count = hw->count;
799+
800+ /* Read the interrupt status and clear interrupt */
801+ int_status = SPI_INTERRUPT_STATUS_REG;
802+
803+ if (!(int_status & (0x1 << 2))) {
804+ printk("DEBUG THIS ! Unexpected interrupt (status = 0x%x)", int_status);
805+ /* Clearing spurious interrupts */
806+ SPI_INTERRUPT_STATUS_REG = (0xF << 4);
807+ goto irq_done;
808+ }
809+
810+ /* Read to clear */
811+ data = SPI_RECEIVE_BUFFER_REG & 0xff;
812+
813+ if (hw->rx)
814+ hw->rx[hw->count] = data;
815+
816+ hw->count++;
817+ hw->len--;
818+
819+ if (hw->len) {
820+ SPI_TRANSMIT_CONTROL_REG |=
821+ ((((hw->last_in_message_list) && (hw->len == 1)) ? 0x1 : 0x0) << 2);
822+ SPI_TRANSMIT_BUFFER_REG = (hw->tx) ? hw->tx[hw->count] : 0xff;
823+ } else {
824+ complete(&hw->done);
825+ }
826+
827+irq_done:
828+ return IRQ_HANDLED;
829+}
830+#endif
831+
832+static void __init cns3xxx_spi_initial(void)
833+{
834+
835+ /* share pin config. */
836+#if 1
837+#if 0
838+ /* GPIOB18 is set to PCM by default */
839+ MISC_GPIOB_PIN_ENABLE_REG &= ~(MISC_GSW_P0_CRS_PIN);
840+ gpio_direction_output(50, 1);
841+#endif
842+ PM_PLL_HM_PD_CTRL_REG &= ~(0x1 << 5);
843+ HAL_MISC_ENABLE_SPI_PINS();
844+ HAL_MISC_ENABLE_PCM_PINS(); /* this just for PCM test */
845+ cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SPI_PCM_I2C));
846+ cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SPI_PCM_I2C));
847+#endif
848+
849+ SPI_CONFIGURATION_REG = (((0x0 & 0x3) << 0) | /* 8bits shift length */
850+ (0x0 << 9) | /* SPI mode */
851+ (0x0 << 10) | /* disable FIFO */
852+ (0x1 << 11) | /* SPI master mode */
853+ (0x0 << 12) | /* disable SPI loopback mode */
854+ (0x1 << 13) | /* clock phase */
855+ (0x1 << 14) | /* clock polarity */
856+ (0x0 << 24) | /* disable - SPI data swap */
857+#ifdef CONFIG_SPI_CNS3XXX_2IOREAD
858+ (0x1 << 29) | /* enable - 2IO Read mode */
859+#else
860+ (0x0 << 29) | /* disablea - 2IO Read mode */
861+#endif
862+ (0x0 << 30) | /* disable - SPI high speed read for system boot up */
863+ (0x0 << 31)); /* disable - SPI */
864+
865+ /* Set SPI bit rate PCLK/2 */
866+ SPI_BIT_RATE_CONTROL_REG = 0x1;
867+
868+ /* Set SPI Tx channel 0 */
869+ SPI_TRANSMIT_CONTROL_REG = 0x0;
870+
871+ /* Set Tx FIFO Threshold, Tx FIFO has 2 words */
872+ SPI_FIFO_TRANSMIT_CONFIG_REG &= ~(0x03 << 4);
873+ SPI_FIFO_TRANSMIT_CONFIG_REG |= ((0x0 & 0x03) << 4);
874+
875+ /* Set Rx FIFO Threshold, Rx FIFO has 2 words */
876+ SPI_FIFO_RECEIVE_CONFIG_REG &= ~(0x03 << 4);
877+ SPI_FIFO_RECEIVE_CONFIG_REG |= ((0x0 & 0x03) << 4);
878+
879+ /* Disable all interrupt */
880+ SPI_INTERRUPT_ENABLE_REG = 0x0;
881+
882+ /* Clear spurious interrupt sources */
883+ SPI_INTERRUPT_STATUS_REG = (0x0F << 4);
884+
885+ /* Enable SPI */
886+ SPI_CONFIGURATION_REG |= (0x1 << 31);
887+
888+ return;
889+}
890+
891+static int __init cns3xxx_spi_probe(struct platform_device *pdev)
892+{
893+ struct spi_master *master;
894+ struct cns3xxx_spi *hw;
895+ int err = 0;
896+
897+ printk("%s: setup CNS3XXX SPI Controller", __FUNCTION__);
898+#ifdef CONFIG_SPI_CNS3XXX_USEDMA
899+ printk(" w/ DMA \n");
900+#else
901+#ifdef CNS3XXX_SPI_INTERRUPT
902+ printk(" in Interrupt mode, w/o DMA \n");
903+#else
904+ printk(" in polling mode, w/o DMA \n");
905+#endif
906+#endif
907+
908+ /* share pin config. */
909+// HAL_MISC_ENABLE_SPI_PINS();
910+
911+ /* Allocate master with space for cns3xxx_spi */
912+ master = spi_alloc_master(&pdev->dev, sizeof(struct cns3xxx_spi));
913+ if (master == NULL) {
914+ dev_err(&pdev->dev, "No memory for spi_master\n");
915+ err = -ENOMEM;
916+ goto err_nomem;
917+ }
918+
919+ hw = spi_master_get_devdata(master);
920+ memset(hw, 0, sizeof(struct cns3xxx_spi));
921+
922+ hw->master = spi_master_get(master);
923+ hw->dev = &pdev->dev;
924+
925+ platform_set_drvdata(pdev, hw);
926+ init_completion(&hw->done);
927+
928+ /* setup the master state. */
929+
930+ master->num_chipselect = 4;
931+ master->bus_num = 1;
932+
933+ /* setup the state for the bitbang driver */
934+
935+ hw->bitbang.master = hw->master;
936+ hw->bitbang.setup_transfer = cns3xxx_spi_setup_transfer;
937+ hw->bitbang.chipselect = cns3xxx_spi_chipselect;
938+ hw->bitbang.txrx_bufs = cns3xxx_spi_txrx;
939+ hw->bitbang.master->setup = cns3xxx_spi_setup;
940+
941+ dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang);
942+
943+#ifdef CNS3XXX_SPI_INTERRUPT
944+ err = request_irq(IRQ_CNS3XXX_SPI, cns3xxx_spi_irq, IRQF_SHARED, "cns3xxx_spi", hw);
945+ if (err) {
946+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
947+ goto err_no_irq;
948+ }
949+#endif
950+
951+ /* SPI controller initializations */
952+ cns3xxx_spi_initial();
953+
954+ /* register SPI controller */
955+
956+ err = spi_bitbang_start(&hw->bitbang);
957+ if (err) {
958+ dev_err(&pdev->dev, "Failed to register SPI master\n");
959+ goto err_register;
960+ }
961+
962+ spi_slave_probe();
963+
964+ return 0;
965+
966+err_register:
967+#ifdef CNS3XXX_SPI_INTERRUPT
968+err_no_irq:
969+#endif
970+ spi_master_put(hw->master);;
971+
972+err_nomem:
973+ return err;
974+}
975+
976+static int __devexit cns3xxx_spi_remove(struct platform_device *dev)
977+{
978+ struct cns3xxx_spi *hw = platform_get_drvdata(dev);
979+
980+ platform_set_drvdata(dev, NULL);
981+
982+ spi_unregister_master(hw->master);
983+
984+ //cns3xxx_spi_clk_disable();
985+
986+ spi_master_put(hw->master);
987+ return 0;
988+}
989+
990+#ifdef CONFIG_PM
991+
992+static int cns3xxx_spi_suspend(struct platform_device *pdev, pm_message_t msg)
993+{
994+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
995+
996+ //cns3xxx_spi_clk_disable();
997+ return 0;
998+}
999+
1000+static int cns3xxx_spi_resume(struct platform_device *pdev)
1001+{
1002+ struct cns3xxx_spi *hw = platform_get_drvdata(pdev);
1003+
1004+ //cns3xxx_spi_clk_enable()
1005+ return 0;
1006+}
1007+
1008+#else
1009+#define cns3xxx_spi_suspend NULL
1010+#define cns3xxx_spi_resume NULL
1011+#endif
1012+
1013+static struct platform_driver cns3xxx_spi_driver = {
1014+ .probe = cns3xxx_spi_probe,
1015+ .remove = __devexit_p(cns3xxx_spi_remove),
1016+ .suspend = cns3xxx_spi_suspend,
1017+ .resume = cns3xxx_spi_resume,
1018+ .driver = {
1019+ .name = "cns3xxx_spi",
1020+ .owner = THIS_MODULE,
1021+ },
1022+};
1023+
1024+static int __init cns3xxx_spi_init(void)
1025+{
1026+ return platform_driver_register(&cns3xxx_spi_driver);
1027+}
1028+
1029+static void __exit cns3xxx_spi_exit(void)
1030+{
1031+ platform_driver_unregister(&cns3xxx_spi_driver);
1032+}
1033+
1034+module_init(cns3xxx_spi_init);
1035+module_exit(cns3xxx_spi_exit);
1036+
1037+MODULE_AUTHOR("Cavium Networks");
1038+MODULE_DESCRIPTION("CNS3XXX SPI Controller Driver");
1039+MODULE_LICENSE("GPL");
1040+MODULE_ALIAS("platform:cns3xxx_spi");
1041+
1042+EXPORT_SYMBOL_GPL(cns3xxx_spi_tx_rx);
1043--- a/include/linux/spi/spi.h
1044+++ b/include/linux/spi/spi.h
1045@@ -424,6 +424,12 @@ struct spi_transfer {
1046     u16 delay_usecs;
1047     u32 speed_hz;
1048 
1049+#ifdef CONFIG_ARCH_CNS3XXX
1050+ unsigned last_in_message_list;
1051+#ifdef CONFIG_SPI_CNS3XXX_2IOREAD
1052+ u8 dio_read;
1053+#endif
1054+#endif
1055     struct list_head transfer_list;
1056 };
1057 
1058@@ -627,6 +633,13 @@ spi_read(struct spi_device *spi, u8 *buf
1059     return spi_sync(spi, &m);
1060 }
1061 
1062+#ifdef CONFIG_ARCH_CNS3XXX
1063+extern int spi_write_read_sync(struct spi_device *spi,
1064+ const u8 *txbuf, unsigned n_tx,
1065+ u8 *rxbuf, unsigned n_rx);
1066+
1067+#endif
1068+
1069 /* this copies txbuf and rxbuf data; for small transfers only! */
1070 extern int spi_write_then_read(struct spi_device *spi,
1071         const u8 *txbuf, unsigned n_tx,
1072

Archive Download this file



interactive