aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/caif
diff options
context:
space:
mode:
authorSjur Braendeland <sjur.brandeland@stericsson.com>2010-06-29 03:08:21 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-29 03:08:21 -0400
commit529d6dad5bc69de14cdd24831e2a14264e93daa4 (patch)
treea89d7b8cdd3692e96a64c5d7196bcefc9f1e7f24 /drivers/net/caif
parent01eebb53a65996dfbfb892bf5eb21ae831fbe3a6 (diff)
caif-driver: Add CAIF-SPI Protocol driver.
This patch introduces the CAIF SPI Protocol Driver for CAIF Link Layer. This driver implements a platform driver to accommodate for a platform specific SPI device. A general platform driver is not possible as there are no SPI Slave side Kernel API defined. A sample CAIF SPI Platform device can be found in .../Documentation/networking/caif/spi_porting.txt Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/caif')
-rw-r--r--drivers/net/caif/Kconfig19
-rw-r--r--drivers/net/caif/Makefile4
-rw-r--r--drivers/net/caif/caif_spi.c847
-rw-r--r--drivers/net/caif/caif_spi_slave.c252
4 files changed, 1122 insertions, 0 deletions
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 6f33ee453f4..631a6242b01 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -12,3 +12,22 @@ config CAIF_TTY
12 The CAIF TTY transport driver is a Line Discipline (ldisc) 12 The CAIF TTY transport driver is a Line Discipline (ldisc)
13 identified as N_CAIF. When this ldisc is opened from user space 13 identified as N_CAIF. When this ldisc is opened from user space
14 it will redirect the TTY's traffic into the CAIF stack. 14 it will redirect the TTY's traffic into the CAIF stack.
15
16config CAIF_SPI_SLAVE
17 tristate "CAIF SPI transport driver for slave interface"
18 depends on CAIF
19 default n
20 ---help---
21 The CAIF Link layer SPI Protocol driver for Slave SPI interface.
22 This driver implements a platform driver to accommodate for a
23 platform specific SPI device. A sample CAIF SPI Platform device is
24 provided in Documentation/networking/caif/spi_porting.txt
25
26config CAIF_SPI_SYNC
27 bool "Next command and length in start of frame"
28 depends on CAIF_SPI_SLAVE
29 default n
30 ---help---
31 Putting the next command and length in the start of the frame can
32 help to synchronize to the next transfer in case of over or under-runs.
33 This option also needs to be enabled on the modem.
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index e6d3ca06ecf..3a11d619452 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -4,3 +4,7 @@ endif
4 4
5# Serial interface 5# Serial interface
6obj-$(CONFIG_CAIF_TTY) += caif_serial.o 6obj-$(CONFIG_CAIF_TTY) += caif_serial.o
7
8# SPI slave physical interfaces module
9cfspi_slave-objs := caif_spi.o caif_spi_slave.o
10obj-$(CONFIG_CAIF_SPI_SLAVE) += cfspi_slave.o
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
new file mode 100644
index 00000000000..03049e86e8a
--- /dev/null
+++ b/drivers/net/caif/caif_spi.c
@@ -0,0 +1,847 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
4 * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2.
6 */
7
8#include <linux/version.h>
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/device.h>
12#include <linux/platform_device.h>
13#include <linux/string.h>
14#include <linux/workqueue.h>
15#include <linux/completion.h>
16#include <linux/list.h>
17#include <linux/interrupt.h>
18#include <linux/dma-mapping.h>
19#include <linux/delay.h>
20#include <linux/sched.h>
21#include <linux/debugfs.h>
22#include <linux/if_arp.h>
23#include <net/caif/caif_layer.h>
24#include <net/caif/caif_spi.h>
25
26#ifndef CONFIG_CAIF_SPI_SYNC
27#define FLAVOR "Flavour: Vanilla.\n"
28#else
29#define FLAVOR "Flavour: Master CMD&LEN at start.\n"
30#endif /* CONFIG_CAIF_SPI_SYNC */
31
32MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Daniel Martensson<daniel.martensson@stericsson.com>");
34MODULE_DESCRIPTION("CAIF SPI driver");
35
36static int spi_loop;
37module_param(spi_loop, bool, S_IRUGO);
38MODULE_PARM_DESC(spi_loop, "SPI running in loopback mode.");
39
40/* SPI frame alignment. */
41module_param(spi_frm_align, int, S_IRUGO);
42MODULE_PARM_DESC(spi_frm_align, "SPI frame alignment.");
43
44/* SPI padding options. */
45module_param(spi_up_head_align, int, S_IRUGO);
46MODULE_PARM_DESC(spi_up_head_align, "SPI uplink head alignment.");
47
48module_param(spi_up_tail_align, int, S_IRUGO);
49MODULE_PARM_DESC(spi_up_tail_align, "SPI uplink tail alignment.");
50
51module_param(spi_down_head_align, int, S_IRUGO);
52MODULE_PARM_DESC(spi_down_head_align, "SPI downlink head alignment.");
53
54module_param(spi_down_tail_align, int, S_IRUGO);
55MODULE_PARM_DESC(spi_down_tail_align, "SPI downlink tail alignment.");
56
57#ifdef CONFIG_ARM
58#define BYTE_HEX_FMT "%02X"
59#else
60#define BYTE_HEX_FMT "%02hhX"
61#endif
62
63#define SPI_MAX_PAYLOAD_SIZE 4096
64/*
65 * Threshold values for the SPI packet queue. Flowcontrol will be asserted
66 * when the number of packets exceeds HIGH_WATER_MARK. It will not be
67 * deasserted before the number of packets drops below LOW_WATER_MARK.
68 */
69#define LOW_WATER_MARK 100
70#define HIGH_WATER_MARK (LOW_WATER_MARK*5)
71
72#ifdef CONFIG_UML
73
74/*
75 * We sometimes use UML for debugging, but it cannot handle
76 * dma_alloc_coherent so we have to wrap it.
77 */
78static inline void *dma_alloc(dma_addr_t *daddr)
79{
80 return kmalloc(SPI_DMA_BUF_LEN, GFP_KERNEL);
81}
82
83static inline void dma_free(void *cpu_addr, dma_addr_t handle)
84{
85 kfree(cpu_addr);
86}
87
88#else
89
90static inline void *dma_alloc(dma_addr_t *daddr)
91{
92 return dma_alloc_coherent(NULL, SPI_DMA_BUF_LEN, daddr,
93 GFP_KERNEL);
94}
95
96static inline void dma_free(void *cpu_addr, dma_addr_t handle)
97{
98 dma_free_coherent(NULL, SPI_DMA_BUF_LEN, cpu_addr, handle);
99}
100#endif /* CONFIG_UML */
101
102#ifdef CONFIG_DEBUG_FS
103
104#define DEBUGFS_BUF_SIZE 4096
105
106static struct dentry *dbgfs_root;
107
108static inline void driver_debugfs_create(void)
109{
110 dbgfs_root = debugfs_create_dir(cfspi_spi_driver.driver.name, NULL);
111}
112
113static inline void driver_debugfs_remove(void)
114{
115 debugfs_remove(dbgfs_root);
116}
117
118static inline void dev_debugfs_rem(struct cfspi *cfspi)
119{
120 debugfs_remove(cfspi->dbgfs_frame);
121 debugfs_remove(cfspi->dbgfs_state);
122 debugfs_remove(cfspi->dbgfs_dir);
123}
124
125static int dbgfs_open(struct inode *inode, struct file *file)
126{
127 file->private_data = inode->i_private;
128 return 0;
129}
130
131static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
132 size_t count, loff_t *ppos)
133{
134 char *buf;
135 int len = 0;
136 ssize_t size;
137 struct cfspi *cfspi = (struct cfspi *)file->private_data;
138
139 buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
140 if (!buf)
141 return 0;
142
143 /* Print out debug information. */
144 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
145 "CAIF SPI debug information:\n");
146
147 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), FLAVOR);
148
149 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
150 "STATE: %d\n", cfspi->dbg_state);
151 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
152 "Previous CMD: 0x%x\n", cfspi->pcmd);
153 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
154 "Current CMD: 0x%x\n", cfspi->cmd);
155 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
156 "Previous TX len: %d\n", cfspi->tx_ppck_len);
157 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
158 "Previous RX len: %d\n", cfspi->rx_ppck_len);
159 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
160 "Current TX len: %d\n", cfspi->tx_cpck_len);
161 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
162 "Current RX len: %d\n", cfspi->rx_cpck_len);
163 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
164 "Next TX len: %d\n", cfspi->tx_npck_len);
165 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
166 "Next RX len: %d\n", cfspi->rx_npck_len);
167
168 size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
169 kfree(buf);
170
171 return size;
172}
173
174static ssize_t print_frame(char *buf, size_t size, char *frm,
175 size_t count, size_t cut)
176{
177 int len = 0;
178 int i;
179 for (i = 0; i < count; i++) {
180 len += snprintf((buf + len), (size - len),
181 "[0x" BYTE_HEX_FMT "]",
182 frm[i]);
183 if ((i == cut) && (count > (cut * 2))) {
184 /* Fast forward. */
185 i = count - cut;
186 len += snprintf((buf + len), (size - len),
187 "--- %u bytes skipped ---\n",
188 (int)(count - (cut * 2)));
189 }
190
191 if ((!(i % 10)) && i) {
192 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
193 "\n");
194 }
195 }
196 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), "\n");
197 return len;
198}
199
200static ssize_t dbgfs_frame(struct file *file, char __user *user_buf,
201 size_t count, loff_t *ppos)
202{
203 char *buf;
204 int len = 0;
205 ssize_t size;
206 struct cfspi *cfspi;
207
208 cfspi = (struct cfspi *)file->private_data;
209 buf = kzalloc(DEBUGFS_BUF_SIZE, GFP_KERNEL);
210 if (!buf)
211 return 0;
212
213 /* Print out debug information. */
214 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
215 "Current frame:\n");
216
217 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
218 "Tx data (Len: %d):\n", cfspi->tx_cpck_len);
219
220 len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
221 cfspi->xfer.va_tx,
222 (cfspi->tx_cpck_len + SPI_CMD_SZ), 100);
223
224 len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len),
225 "Rx data (Len: %d):\n", cfspi->rx_cpck_len);
226
227 len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len),
228 cfspi->xfer.va_rx,
229 (cfspi->rx_cpck_len + SPI_CMD_SZ), 100);
230
231 size = simple_read_from_buffer(user_buf, count, ppos, buf, len);
232 kfree(buf);
233
234 return size;
235}
236
237static const struct file_operations dbgfs_state_fops = {
238 .open = dbgfs_open,
239 .read = dbgfs_state,
240 .owner = THIS_MODULE
241};
242
243static const struct file_operations dbgfs_frame_fops = {
244 .open = dbgfs_open,
245 .read = dbgfs_frame,
246 .owner = THIS_MODULE
247};
248
249static inline void dev_debugfs_add(struct cfspi *cfspi)
250{
251 cfspi->dbgfs_dir = debugfs_create_dir(cfspi->pdev->name, dbgfs_root);
252 cfspi->dbgfs_state = debugfs_create_file("state", S_IRUGO,
253 cfspi->dbgfs_dir, cfspi,
254 &dbgfs_state_fops);
255 cfspi->dbgfs_frame = debugfs_create_file("frame", S_IRUGO,
256 cfspi->dbgfs_dir, cfspi,
257 &dbgfs_frame_fops);
258}
259
260inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
261{
262 cfspi->dbg_state = state;
263};
264#else
265
266static inline void driver_debugfs_create(void)
267{
268}
269
270static inline void driver_debugfs_remove(void)
271{
272}
273
274static inline void dev_debugfs_add(struct cfspi *cfspi)
275{
276}
277
278static inline void dev_debugfs_rem(struct cfspi *cfspi)
279{
280}
281
282inline void cfspi_dbg_state(struct cfspi *cfspi, int state)
283{
284}
285#endif /* CONFIG_DEBUG_FS */
286
287static LIST_HEAD(cfspi_list);
288static spinlock_t cfspi_list_lock;
289
290/* SPI uplink head alignment. */
291static ssize_t show_up_head_align(struct device_driver *driver, char *buf)
292{
293 return sprintf(buf, "%d\n", spi_up_head_align);
294}
295
296static DRIVER_ATTR(up_head_align, S_IRUSR, show_up_head_align, NULL);
297
298/* SPI uplink tail alignment. */
299static ssize_t show_up_tail_align(struct device_driver *driver, char *buf)
300{
301 return sprintf(buf, "%d\n", spi_up_tail_align);
302}
303
304static DRIVER_ATTR(up_tail_align, S_IRUSR, show_up_tail_align, NULL);
305
306/* SPI downlink head alignment. */
307static ssize_t show_down_head_align(struct device_driver *driver, char *buf)
308{
309 return sprintf(buf, "%d\n", spi_down_head_align);
310}
311
312static DRIVER_ATTR(down_head_align, S_IRUSR, show_down_head_align, NULL);
313
314/* SPI downlink tail alignment. */
315static ssize_t show_down_tail_align(struct device_driver *driver, char *buf)
316{
317 return sprintf(buf, "%d\n", spi_down_tail_align);
318}
319
320static DRIVER_ATTR(down_tail_align, S_IRUSR, show_down_tail_align, NULL);
321
322/* SPI frame alignment. */
323static ssize_t show_frame_align(struct device_driver *driver, char *buf)
324{
325 return sprintf(buf, "%d\n", spi_frm_align);
326}
327
328static DRIVER_ATTR(frame_align, S_IRUSR, show_frame_align, NULL);
329
330int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len)
331{
332 u8 *dst = buf;
333 caif_assert(buf);
334
335 do {
336 struct sk_buff *skb;
337 struct caif_payload_info *info;
338 int spad = 0;
339 int epad;
340
341 skb = skb_dequeue(&cfspi->chead);
342 if (!skb)
343 break;
344
345 /*
346 * Calculate length of frame including SPI padding.
347 * The payload position is found in the control buffer.
348 */
349 info = (struct caif_payload_info *)&skb->cb;
350
351 /*
352 * Compute head offset i.e. number of bytes to add to
353 * get the start of the payload aligned.
354 */
355 if (spi_up_head_align) {
356 spad = 1 + ((info->hdr_len + 1) & spi_up_head_align);
357 *dst = (u8)(spad - 1);
358 dst += spad;
359 }
360
361 /* Copy in CAIF frame. */
362 skb_copy_bits(skb, 0, dst, skb->len);
363 dst += skb->len;
364 cfspi->ndev->stats.tx_packets++;
365 cfspi->ndev->stats.tx_bytes += skb->len;
366
367 /*
368 * Compute tail offset i.e. number of bytes to add to
369 * get the complete CAIF frame aligned.
370 */
371 epad = (skb->len + spad) & spi_up_tail_align;
372 dst += epad;
373
374 dev_kfree_skb(skb);
375
376 } while ((dst - buf) < len);
377
378 return dst - buf;
379}
380
381int cfspi_xmitlen(struct cfspi *cfspi)
382{
383 struct sk_buff *skb = NULL;
384 int frm_len = 0;
385 int pkts = 0;
386
387 /*
388 * Decommit previously commited frames.
389 * skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead)
390 */
391 while (skb_peek(&cfspi->chead)) {
392 skb = skb_dequeue_tail(&cfspi->chead);
393 skb_queue_head(&cfspi->qhead, skb);
394 }
395
396 do {
397 struct caif_payload_info *info = NULL;
398 int spad = 0;
399 int epad = 0;
400
401 skb = skb_dequeue(&cfspi->qhead);
402 if (!skb)
403 break;
404
405 /*
406 * Calculate length of frame including SPI padding.
407 * The payload position is found in the control buffer.
408 */
409 info = (struct caif_payload_info *)&skb->cb;
410
411 /*
412 * Compute head offset i.e. number of bytes to add to
413 * get the start of the payload aligned.
414 */
415 if (spi_up_head_align)
416 spad = 1 + ((info->hdr_len + 1) & spi_up_head_align);
417
418 /*
419 * Compute tail offset i.e. number of bytes to add to
420 * get the complete CAIF frame aligned.
421 */
422 epad = (skb->len + spad) & spi_up_tail_align;
423
424 if ((skb->len + spad + epad + frm_len) <= CAIF_MAX_SPI_FRAME) {
425 skb_queue_tail(&cfspi->chead, skb);
426 pkts++;
427 frm_len += skb->len + spad + epad;
428 } else {
429 /* Put back packet. */
430 skb_queue_head(&cfspi->qhead, skb);
431 }
432 } while (pkts <= CAIF_MAX_SPI_PKTS);
433
434 /*
435 * Send flow on if previously sent flow off
436 * and now go below the low water mark
437 */
438 if (cfspi->flow_off_sent && cfspi->qhead.qlen < cfspi->qd_low_mark &&
439 cfspi->cfdev.flowctrl) {
440 cfspi->flow_off_sent = 0;
441 cfspi->cfdev.flowctrl(cfspi->ndev, 1);
442 }
443
444 return frm_len;
445}
446
447static void cfspi_ss_cb(bool assert, struct cfspi_ifc *ifc)
448{
449 struct cfspi *cfspi = (struct cfspi *)ifc->priv;
450
451 if (!in_interrupt())
452 spin_lock(&cfspi->lock);
453 if (assert) {
454 set_bit(SPI_SS_ON, &cfspi->state);
455 set_bit(SPI_XFER, &cfspi->state);
456 } else {
457 set_bit(SPI_SS_OFF, &cfspi->state);
458 }
459 if (!in_interrupt())
460 spin_unlock(&cfspi->lock);
461
462 /* Wake up the xfer thread. */
463 wake_up_interruptible(&cfspi->wait);
464}
465
466static void cfspi_xfer_done_cb(struct cfspi_ifc *ifc)
467{
468 struct cfspi *cfspi = (struct cfspi *)ifc->priv;
469
470 /* Transfer done, complete work queue */
471 complete(&cfspi->comp);
472}
473
474static int cfspi_xmit(struct sk_buff *skb, struct net_device *dev)
475{
476 struct cfspi *cfspi = NULL;
477 unsigned long flags;
478 if (!dev)
479 return -EINVAL;
480
481 cfspi = netdev_priv(dev);
482
483 skb_queue_tail(&cfspi->qhead, skb);
484
485 spin_lock_irqsave(&cfspi->lock, flags);
486 if (!test_and_set_bit(SPI_XFER, &cfspi->state)) {
487 /* Wake up xfer thread. */
488 wake_up_interruptible(&cfspi->wait);
489 }
490 spin_unlock_irqrestore(&cfspi->lock, flags);
491
492 /* Send flow off if number of bytes is above high water mark */
493 if (!cfspi->flow_off_sent &&
494 cfspi->qhead.qlen > cfspi->qd_high_mark &&
495 cfspi->cfdev.flowctrl) {
496 cfspi->flow_off_sent = 1;
497 cfspi->cfdev.flowctrl(cfspi->ndev, 0);
498 }
499
500 return 0;
501}
502
503int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len)
504{
505 u8 *src = buf;
506
507 caif_assert(buf != NULL);
508
509 do {
510 int res;
511 struct sk_buff *skb = NULL;
512 int spad = 0;
513 int epad = 0;
514 u8 *dst = NULL;
515 int pkt_len = 0;
516
517 /*
518 * Compute head offset i.e. number of bytes added to
519 * get the start of the payload aligned.
520 */
521 if (spi_down_head_align) {
522 spad = 1 + *src;
523 src += spad;
524 }
525
526 /* Read length of CAIF frame (little endian). */
527 pkt_len = *src;
528 pkt_len |= ((*(src+1)) << 8) & 0xFF00;
529 pkt_len += 2; /* Add FCS fields. */
530
531 /* Get a suitable caif packet and copy in data. */
532
533 skb = netdev_alloc_skb(cfspi->ndev, pkt_len + 1);
534 caif_assert(skb != NULL);
535
536 dst = skb_put(skb, pkt_len);
537 memcpy(dst, src, pkt_len);
538 src += pkt_len;
539
540 skb->protocol = htons(ETH_P_CAIF);
541 skb_reset_mac_header(skb);
542 skb->dev = cfspi->ndev;
543
544 /*
545 * Push received packet up the stack.
546 */
547 if (!spi_loop)
548 res = netif_rx_ni(skb);
549 else
550 res = cfspi_xmit(skb, cfspi->ndev);
551
552 if (!res) {
553 cfspi->ndev->stats.rx_packets++;
554 cfspi->ndev->stats.rx_bytes += pkt_len;
555 } else
556 cfspi->ndev->stats.rx_dropped++;
557
558 /*
559 * Compute tail offset i.e. number of bytes added to
560 * get the complete CAIF frame aligned.
561 */
562 epad = (pkt_len + spad) & spi_down_tail_align;
563 src += epad;
564 } while ((src - buf) < len);
565
566 return src - buf;
567}
568
569static int cfspi_open(struct net_device *dev)
570{
571 netif_wake_queue(dev);
572 return 0;
573}
574
575static int cfspi_close(struct net_device *dev)
576{
577 netif_stop_queue(dev);
578 return 0;
579}
580static const struct net_device_ops cfspi_ops = {
581 .ndo_open = cfspi_open,
582 .ndo_stop = cfspi_close,
583 .ndo_start_xmit = cfspi_xmit
584};
585
586static void cfspi_setup(struct net_device *dev)
587{
588 struct cfspi *cfspi = netdev_priv(dev);
589 dev->features = 0;
590 dev->netdev_ops = &cfspi_ops;
591 dev->type = ARPHRD_CAIF;
592 dev->flags = IFF_NOARP | IFF_POINTOPOINT;
593 dev->tx_queue_len = 0;
594 dev->mtu = SPI_MAX_PAYLOAD_SIZE;
595 dev->destructor = free_netdev;
596 skb_queue_head_init(&cfspi->qhead);
597 skb_queue_head_init(&cfspi->chead);
598 cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW;
599 cfspi->cfdev.use_frag = false;
600 cfspi->cfdev.use_stx = false;
601 cfspi->cfdev.use_fcs = false;
602 cfspi->ndev = dev;
603}
604
605int cfspi_spi_probe(struct platform_device *pdev)
606{
607 struct cfspi *cfspi = NULL;
608 struct net_device *ndev;
609 struct cfspi_dev *dev;
610 int res;
611 dev = (struct cfspi_dev *)pdev->dev.platform_data;
612
613 ndev = alloc_netdev(sizeof(struct cfspi),
614 "cfspi%d", cfspi_setup);
615 if (!dev)
616 return -ENODEV;
617
618 cfspi = netdev_priv(ndev);
619 netif_stop_queue(ndev);
620 cfspi->ndev = ndev;
621 cfspi->pdev = pdev;
622
623 /* Set flow info */
624 cfspi->flow_off_sent = 0;
625 cfspi->qd_low_mark = LOW_WATER_MARK;
626 cfspi->qd_high_mark = HIGH_WATER_MARK;
627
628 /* Assign the SPI device. */
629 cfspi->dev = dev;
630 /* Assign the device ifc to this SPI interface. */
631 dev->ifc = &cfspi->ifc;
632
633 /* Allocate DMA buffers. */
634 cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx);
635 if (!cfspi->xfer.va_tx) {
636 printk(KERN_WARNING
637 "CFSPI: failed to allocate dma TX buffer.\n");
638 res = -ENODEV;
639 goto err_dma_alloc_tx;
640 }
641
642 cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx);
643
644 if (!cfspi->xfer.va_rx) {
645 printk(KERN_WARNING
646 "CFSPI: failed to allocate dma TX buffer.\n");
647 res = -ENODEV;
648 goto err_dma_alloc_rx;
649 }
650
651 /* Initialize the work queue. */
652 INIT_WORK(&cfspi->work, cfspi_xfer);
653
654 /* Initialize spin locks. */
655 spin_lock_init(&cfspi->lock);
656
657 /* Initialize flow control state. */
658 cfspi->flow_stop = false;
659
660 /* Initialize wait queue. */
661 init_waitqueue_head(&cfspi->wait);
662
663 /* Create work thread. */
664 cfspi->wq = create_singlethread_workqueue(dev->name);
665 if (!cfspi->wq) {
666 printk(KERN_WARNING "CFSPI: failed to create work queue.\n");
667 res = -ENODEV;
668 goto err_create_wq;
669 }
670
671 /* Initialize work queue. */
672 init_completion(&cfspi->comp);
673
674 /* Create debugfs entries. */
675 dev_debugfs_add(cfspi);
676
677 /* Set up the ifc. */
678 cfspi->ifc.ss_cb = cfspi_ss_cb;
679 cfspi->ifc.xfer_done_cb = cfspi_xfer_done_cb;
680 cfspi->ifc.priv = cfspi;
681
682 /* Add CAIF SPI device to list. */
683 spin_lock(&cfspi_list_lock);
684 list_add_tail(&cfspi->list, &cfspi_list);
685 spin_unlock(&cfspi_list_lock);
686
687 /* Schedule the work queue. */
688 queue_work(cfspi->wq, &cfspi->work);
689
690 /* Register network device. */
691 res = register_netdev(ndev);
692 if (res) {
693 printk(KERN_ERR "CFSPI: Reg. error: %d.\n", res);
694 goto err_net_reg;
695 }
696 return res;
697
698 err_net_reg:
699 dev_debugfs_rem(cfspi);
700 set_bit(SPI_TERMINATE, &cfspi->state);
701 wake_up_interruptible(&cfspi->wait);
702 destroy_workqueue(cfspi->wq);
703 err_create_wq:
704 dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
705 err_dma_alloc_rx:
706 dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
707 err_dma_alloc_tx:
708 free_netdev(ndev);
709
710 return res;
711}
712
713int cfspi_spi_remove(struct platform_device *pdev)
714{
715 struct list_head *list_node;
716 struct list_head *n;
717 struct cfspi *cfspi = NULL;
718 struct cfspi_dev *dev;
719
720 dev = (struct cfspi_dev *)pdev->dev.platform_data;
721 spin_lock(&cfspi_list_lock);
722 list_for_each_safe(list_node, n, &cfspi_list) {
723 cfspi = list_entry(list_node, struct cfspi, list);
724 /* Find the corresponding device. */
725 if (cfspi->dev == dev) {
726 /* Remove from list. */
727 list_del(list_node);
728 /* Free DMA buffers. */
729 dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx);
730 dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx);
731 set_bit(SPI_TERMINATE, &cfspi->state);
732 wake_up_interruptible(&cfspi->wait);
733 destroy_workqueue(cfspi->wq);
734 /* Destroy debugfs directory and files. */
735 dev_debugfs_rem(cfspi);
736 unregister_netdev(cfspi->ndev);
737 spin_unlock(&cfspi_list_lock);
738 return 0;
739 }
740 }
741 spin_unlock(&cfspi_list_lock);
742 return -ENODEV;
743}
744
745static void __exit cfspi_exit_module(void)
746{
747 struct list_head *list_node;
748 struct list_head *n;
749 struct cfspi *cfspi = NULL;
750
751 list_for_each_safe(list_node, n, &cfspi_list) {
752 cfspi = list_entry(list_node, struct cfspi, list);
753 platform_device_unregister(cfspi->pdev);
754 }
755
756 /* Destroy sysfs files. */
757 driver_remove_file(&cfspi_spi_driver.driver,
758 &driver_attr_up_head_align);
759 driver_remove_file(&cfspi_spi_driver.driver,
760 &driver_attr_up_tail_align);
761 driver_remove_file(&cfspi_spi_driver.driver,
762 &driver_attr_down_head_align);
763 driver_remove_file(&cfspi_spi_driver.driver,
764 &driver_attr_down_tail_align);
765 driver_remove_file(&cfspi_spi_driver.driver, &driver_attr_frame_align);
766 /* Unregister platform driver. */
767 platform_driver_unregister(&cfspi_spi_driver);
768 /* Destroy debugfs root directory. */
769 driver_debugfs_remove();
770}
771
772static int __init cfspi_init_module(void)
773{
774 int result;
775
776 /* Initialize spin lock. */
777 spin_lock_init(&cfspi_list_lock);
778
779 /* Register platform driver. */
780 result = platform_driver_register(&cfspi_spi_driver);
781 if (result) {
782 printk(KERN_ERR "Could not register platform SPI driver.\n");
783 goto err_dev_register;
784 }
785
786 /* Create sysfs files. */
787 result =
788 driver_create_file(&cfspi_spi_driver.driver,
789 &driver_attr_up_head_align);
790 if (result) {
791 printk(KERN_ERR "Sysfs creation failed 1.\n");
792 goto err_create_up_head_align;
793 }
794
795 result =
796 driver_create_file(&cfspi_spi_driver.driver,
797 &driver_attr_up_tail_align);
798 if (result) {
799 printk(KERN_ERR "Sysfs creation failed 2.\n");
800 goto err_create_up_tail_align;
801 }
802
803 result =
804 driver_create_file(&cfspi_spi_driver.driver,
805 &driver_attr_down_head_align);
806 if (result) {
807 printk(KERN_ERR "Sysfs creation failed 3.\n");
808 goto err_create_down_head_align;
809 }
810
811 result =
812 driver_create_file(&cfspi_spi_driver.driver,
813 &driver_attr_down_tail_align);
814 if (result) {
815 printk(KERN_ERR "Sysfs creation failed 4.\n");
816 goto err_create_down_tail_align;
817 }
818
819 result =
820 driver_create_file(&cfspi_spi_driver.driver,
821 &driver_attr_frame_align);
822 if (result) {
823 printk(KERN_ERR "Sysfs creation failed 5.\n");
824 goto err_create_frame_align;
825 }
826 driver_debugfs_create();
827 return result;
828
829 err_create_frame_align:
830 driver_remove_file(&cfspi_spi_driver.driver,
831 &driver_attr_down_tail_align);
832 err_create_down_tail_align:
833 driver_remove_file(&cfspi_spi_driver.driver,
834 &driver_attr_down_head_align);
835 err_create_down_head_align:
836 driver_remove_file(&cfspi_spi_driver.driver,
837 &driver_attr_up_tail_align);
838 err_create_up_tail_align:
839 driver_remove_file(&cfspi_spi_driver.driver,
840 &driver_attr_up_head_align);
841 err_create_up_head_align:
842 err_dev_register:
843 return result;
844}
845
846module_init(cfspi_init_module);
847module_exit(cfspi_exit_module);
diff --git a/drivers/net/caif/caif_spi_slave.c b/drivers/net/caif/caif_spi_slave.c
new file mode 100644
index 00000000000..077ccf840ed
--- /dev/null
+++ b/drivers/net/caif/caif_spi_slave.c
@@ -0,0 +1,252 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Contact: Sjur Brendeland / sjur.brandeland@stericsson.com
4 * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
5 * License terms: GNU General Public License (GPL) version 2.
6 */
7#include <linux/version.h>
8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/device.h>
11#include <linux/platform_device.h>
12#include <linux/string.h>
13#include <linux/semaphore.h>
14#include <linux/workqueue.h>
15#include <linux/completion.h>
16#include <linux/list.h>
17#include <linux/interrupt.h>
18#include <linux/dma-mapping.h>
19#include <linux/delay.h>
20#include <linux/sched.h>
21#include <linux/debugfs.h>
22#include <net/caif/caif_spi.h>
23
24#ifndef CONFIG_CAIF_SPI_SYNC
25#define SPI_DATA_POS SPI_CMD_SZ
26static inline int forward_to_spi_cmd(struct cfspi *cfspi)
27{
28 return cfspi->rx_cpck_len;
29}
30#else
31#define SPI_DATA_POS 0
32static inline int forward_to_spi_cmd(struct cfspi *cfspi)
33{
34 return 0;
35}
36#endif
37
38int spi_frm_align = 2;
39int spi_up_head_align = 1;
40int spi_up_tail_align;
41int spi_down_head_align = 3;
42int spi_down_tail_align = 1;
43
44#ifdef CONFIG_DEBUG_FS
45static inline void debugfs_store_prev(struct cfspi *cfspi)
46{
47 /* Store previous command for debugging reasons.*/
48 cfspi->pcmd = cfspi->cmd;
49 /* Store previous transfer. */
50 cfspi->tx_ppck_len = cfspi->tx_cpck_len;
51 cfspi->rx_ppck_len = cfspi->rx_cpck_len;
52}
53#else
54static inline void debugfs_store_prev(struct cfspi *cfspi)
55{
56}
57#endif
58
59void cfspi_xfer(struct work_struct *work)
60{
61 struct cfspi *cfspi;
62 u8 *ptr = NULL;
63 unsigned long flags;
64 int ret;
65 cfspi = container_of(work, struct cfspi, work);
66
67 /* Initialize state. */
68 cfspi->cmd = SPI_CMD_EOT;
69
70 for (;;) {
71
72 cfspi_dbg_state(cfspi, CFSPI_STATE_WAITING);
73
74 /* Wait for master talk or transmit event. */
75 wait_event_interruptible(cfspi->wait,
76 test_bit(SPI_XFER, &cfspi->state) ||
77 test_bit(SPI_TERMINATE, &cfspi->state));
78
79 if (test_bit(SPI_TERMINATE, &cfspi->state))
80 return;
81
82#if CFSPI_DBG_PREFILL
83 /* Prefill buffers for easier debugging. */
84 memset(cfspi->xfer.va_tx, 0xFF, SPI_DMA_BUF_LEN);
85 memset(cfspi->xfer.va_rx, 0xFF, SPI_DMA_BUF_LEN);
86#endif /* CFSPI_DBG_PREFILL */
87
88 cfspi_dbg_state(cfspi, CFSPI_STATE_AWAKE);
89
90 /* Check whether we have a committed frame. */
91 if (cfspi->tx_cpck_len) {
92 int len;
93
94 cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);
95
96 /* Copy commited SPI frames after the SPI indication. */
97 ptr = (u8 *) cfspi->xfer.va_tx;
98 ptr += SPI_IND_SZ;
99 len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
100 WARN_ON(len != cfspi->tx_cpck_len);
101 }
102
103 cfspi_dbg_state(cfspi, CFSPI_STATE_GET_NEXT);
104
105 /* Get length of next frame to commit. */
106 cfspi->tx_npck_len = cfspi_xmitlen(cfspi);
107
108 WARN_ON(cfspi->tx_npck_len > SPI_DMA_BUF_LEN);
109
110 /*
111 * Add indication and length at the beginning of the frame,
112 * using little endian.
113 */
114 ptr = (u8 *) cfspi->xfer.va_tx;
115 *ptr++ = SPI_CMD_IND;
116 *ptr++ = (SPI_CMD_IND & 0xFF00) >> 8;
117 *ptr++ = cfspi->tx_npck_len & 0x00FF;
118 *ptr++ = (cfspi->tx_npck_len & 0xFF00) >> 8;
119
120 /* Calculate length of DMAs. */
121 cfspi->xfer.tx_dma_len = cfspi->tx_cpck_len + SPI_IND_SZ;
122 cfspi->xfer.rx_dma_len = cfspi->rx_cpck_len + SPI_CMD_SZ;
123
124 /* Add SPI TX frame alignment padding, if necessary. */
125 if (cfspi->tx_cpck_len &&
126 (cfspi->xfer.tx_dma_len % spi_frm_align)) {
127
128 cfspi->xfer.tx_dma_len += spi_frm_align -
129 (cfspi->xfer.tx_dma_len % spi_frm_align);
130 }
131
132 /* Add SPI RX frame alignment padding, if necessary. */
133 if (cfspi->rx_cpck_len &&
134 (cfspi->xfer.rx_dma_len % spi_frm_align)) {
135
136 cfspi->xfer.rx_dma_len += spi_frm_align -
137 (cfspi->xfer.rx_dma_len % spi_frm_align);
138 }
139
140 cfspi_dbg_state(cfspi, CFSPI_STATE_INIT_XFER);
141
142 /* Start transfer. */
143 ret = cfspi->dev->init_xfer(&cfspi->xfer, cfspi->dev);
144 WARN_ON(ret);
145
146 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_ACTIVE);
147
148 /*
149 * TODO: We might be able to make an assumption if this is the
150 * first loop. Make sure that minimum toggle time is respected.
151 */
152 udelay(MIN_TRANSITION_TIME_USEC);
153
154 cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);
155
156 /* Signal that we are ready to recieve data. */
157 cfspi->dev->sig_xfer(true, cfspi->dev);
158
159 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);
160
161 /* Wait for transfer completion. */
162 wait_for_completion(&cfspi->comp);
163
164 cfspi_dbg_state(cfspi, CFSPI_STATE_XFER_DONE);
165
166 if (cfspi->cmd == SPI_CMD_EOT) {
167 /*
168 * Clear the master talk bit. A xfer is always at
169 * least two bursts.
170 */
171 clear_bit(SPI_SS_ON, &cfspi->state);
172 }
173
174 cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_INACTIVE);
175
176 /* Make sure that the minimum toggle time is respected. */
177 if (SPI_XFER_TIME_USEC(cfspi->xfer.tx_dma_len,
178 cfspi->dev->clk_mhz) <
179 MIN_TRANSITION_TIME_USEC) {
180
181 udelay(MIN_TRANSITION_TIME_USEC -
182 SPI_XFER_TIME_USEC
183 (cfspi->xfer.tx_dma_len, cfspi->dev->clk_mhz));
184 }
185
186 cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_INACTIVE);
187
188 /* De-assert transfer signal. */
189 cfspi->dev->sig_xfer(false, cfspi->dev);
190
191 /* Check whether we received a CAIF packet. */
192 if (cfspi->rx_cpck_len) {
193 int len;
194
195 cfspi_dbg_state(cfspi, CFSPI_STATE_DELIVER_PKT);
196
197 /* Parse SPI frame. */
198 ptr = ((u8 *)(cfspi->xfer.va_rx + SPI_DATA_POS));
199
200 len = cfspi_rxfrm(cfspi, ptr, cfspi->rx_cpck_len);
201 WARN_ON(len != cfspi->rx_cpck_len);
202 }
203
204 /* Check the next SPI command and length. */
205 ptr = (u8 *) cfspi->xfer.va_rx;
206
207 ptr += forward_to_spi_cmd(cfspi);
208
209 cfspi->cmd = *ptr++;
210 cfspi->cmd |= ((*ptr++) << 8) & 0xFF00;
211 cfspi->rx_npck_len = *ptr++;
212 cfspi->rx_npck_len |= ((*ptr++) << 8) & 0xFF00;
213
214 WARN_ON(cfspi->rx_npck_len > SPI_DMA_BUF_LEN);
215 WARN_ON(cfspi->cmd > SPI_CMD_EOT);
216
217 debugfs_store_prev(cfspi);
218
219 /* Check whether the master issued an EOT command. */
220 if (cfspi->cmd == SPI_CMD_EOT) {
221 /* Reset state. */
222 cfspi->tx_cpck_len = 0;
223 cfspi->rx_cpck_len = 0;
224 } else {
225 /* Update state. */
226 cfspi->tx_cpck_len = cfspi->tx_npck_len;
227 cfspi->rx_cpck_len = cfspi->rx_npck_len;
228 }
229
230 /*
231 * Check whether we need to clear the xfer bit.
232 * Spin lock needed for packet insertion.
233 * Test and clear of different bits
234 * are not supported.
235 */
236 spin_lock_irqsave(&cfspi->lock, flags);
237 if (cfspi->cmd == SPI_CMD_EOT && !cfspi_xmitlen(cfspi)
238 && !test_bit(SPI_SS_ON, &cfspi->state))
239 clear_bit(SPI_XFER, &cfspi->state);
240
241 spin_unlock_irqrestore(&cfspi->lock, flags);
242 }
243}
244
245struct platform_driver cfspi_spi_driver = {
246 .probe = cfspi_spi_probe,
247 .remove = cfspi_spi_remove,
248 .driver = {
249 .name = "cfspi_sspi",
250 .owner = THIS_MODULE,
251 },
252};