aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/caif/spi_porting.txt208
-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
-rw-r--r--include/net/caif/caif_spi.h153
6 files changed, 1483 insertions, 0 deletions
diff --git a/Documentation/networking/caif/spi_porting.txt b/Documentation/networking/caif/spi_porting.txt
new file mode 100644
index 000000000000..61d7c9247453
--- /dev/null
+++ b/Documentation/networking/caif/spi_porting.txt
@@ -0,0 +1,208 @@
1- CAIF SPI porting -
2
3- CAIF SPI basics:
4
5Running CAIF over SPI needs some extra setup, owing to the nature of SPI.
6Two extra GPIOs have been added in order to negotiate the transfers
7 between the master and the slave. The minimum requirement for running
8CAIF over SPI is a SPI slave chip and two GPIOs (more details below).
9Please note that running as a slave implies that you need to keep up
10with the master clock. An overrun or underrun event is fatal.
11
12- CAIF SPI framework:
13
14To make porting as easy as possible, the CAIF SPI has been divided in
15two parts. The first part (called the interface part) deals with all
16generic functionality such as length framing, SPI frame negotiation
17and SPI frame delivery and transmission. The other part is the CAIF
18SPI slave device part, which is the module that you have to write if
19you want to run SPI CAIF on a new hardware. This part takes care of
20the physical hardware, both with regard to SPI and to GPIOs.
21
22- Implementing a CAIF SPI device:
23
24 - Functionality provided by the CAIF SPI slave device:
25
26 In order to implement a SPI device you will, as a minimum,
27 need to implement the following
28 functions:
29
30 int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev):
31
32 This function is called by the CAIF SPI interface to give
33 you a chance to set up your hardware to be ready to receive
34 a stream of data from the master. The xfer structure contains
35 both physical and logical adresses, as well as the total length
36 of the transfer in both directions.The dev parameter can be used
37 to map to different CAIF SPI slave devices.
38
39 void (*sig_xfer) (bool xfer, struct cfspi_dev *dev):
40
41 This function is called by the CAIF SPI interface when the output
42 (SPI_INT) GPIO needs to change state. The boolean value of the xfer
43 variable indicates whether the GPIO should be asserted (HIGH) or
44 deasserted (LOW). The dev parameter can be used to map to different CAIF
45 SPI slave devices.
46
47 - Functionality provided by the CAIF SPI interface:
48
49 void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
50
51 This function is called by the CAIF SPI slave device in order to
52 signal a change of state of the input GPIO (SS) to the interface.
53 Only active edges are mandatory to be reported.
54 This function can be called from IRQ context (recommended in order
55 not to introduce latency). The ifc parameter should be the pointer
56 returned from the platform probe function in the SPI device structure.
57
58 void (*xfer_done_cb) (struct cfspi_ifc *ifc);
59
60 This function is called by the CAIF SPI slave device in order to
61 report that a transfer is completed. This function should only be
62 called once both the transmission and the reception are completed.
63 This function can be called from IRQ context (recommended in order
64 not to introduce latency). The ifc parameter should be the pointer
65 returned from the platform probe function in the SPI device structure.
66
67 - Connecting the bits and pieces:
68
69 - Filling in the SPI slave device structure:
70
71 Connect the necessary callback functions.
72 Indicate clock speed (used to calculate toggle delays).
73 Chose a suitable name (helps debugging if you use several CAIF
74 SPI slave devices).
75 Assign your private data (can be used to map to your structure).
76
77 - Filling in the SPI slave platform device structure:
78 Add name of driver to connect to ("cfspi_sspi").
79 Assign the SPI slave device structure as platform data.
80
81- Padding:
82
83In order to optimize throughput, a number of SPI padding options are provided.
84Padding can be enabled independently for uplink and downlink transfers.
85Padding can be enabled for the head, the tail and for the total frame size.
86The padding needs to be correctly configured on both sides of the link.
87The padding can be changed via module parameters in cfspi_sspi.c or via
88the sysfs directory of the cfspi_sspi driver (before device registration).
89
90- CAIF SPI device template:
91
92/*
93 * Copyright (C) ST-Ericsson AB 2010
94 * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
95 * License terms: GNU General Public License (GPL), version 2.
96 *
97 */
98
99#include <linux/init.h>
100#include <linux/module.h>
101#include <linux/device.h>
102#include <linux/wait.h>
103#include <linux/interrupt.h>
104#include <linux/dma-mapping.h>
105#include <net/caif/caif_spi.h>
106
107MODULE_LICENSE("GPL");
108
109struct sspi_struct {
110 struct cfspi_dev sdev;
111 struct cfspi_xfer *xfer;
112};
113
114static struct sspi_struct slave;
115static struct platform_device slave_device;
116
117static irqreturn_t sspi_irq(int irq, void *arg)
118{
119 /* You only need to trigger on an edge to the active state of the
120 * SS signal. Once a edge is detected, the ss_cb() function should be
121 * called with the parameter assert set to true. It is OK
122 * (and even advised) to call the ss_cb() function in IRQ context in
123 * order not to add any delay. */
124
125 return IRQ_HANDLED;
126}
127
128static void sspi_complete(void *context)
129{
130 /* Normally the DMA or the SPI framework will call you back
131 * in something similar to this. The only thing you need to
132 * do is to call the xfer_done_cb() function, providing the pointer
133 * to the CAIF SPI interface. It is OK to call this function
134 * from IRQ context. */
135}
136
137static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev)
138{
139 /* Store transfer info. For a normal implementation you should
140 * set up your DMA here and make sure that you are ready to
141 * receive the data from the master SPI. */
142
143 struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
144
145 sspi->xfer = xfer;
146
147 return 0;
148}
149
150void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
151{
152 /* If xfer is true then you should assert the SPI_INT to indicate to
153 * the master that you are ready to recieve the data from the master
154 * SPI. If xfer is false then you should de-assert SPI_INT to indicate
155 * that the transfer is done.
156 */
157
158 struct sspi_struct *sspi = (struct sspi_struct *)dev->priv;
159}
160
161static void sspi_release(struct device *dev)
162{
163 /*
164 * Here you should release your SPI device resources.
165 */
166}
167
168static int __init sspi_init(void)
169{
170 /* Here you should initialize your SPI device by providing the
171 * necessary functions, clock speed, name and private data. Once
172 * done, you can register your device with the
173 * platform_device_register() function. This function will return
174 * with the CAIF SPI interface initialized. This is probably also
175 * the place where you should set up your GPIOs, interrupts and SPI
176 * resources. */
177
178 int res = 0;
179
180 /* Initialize slave device. */
181 slave.sdev.init_xfer = sspi_init_xfer;
182 slave.sdev.sig_xfer = sspi_sig_xfer;
183 slave.sdev.clk_mhz = 13;
184 slave.sdev.priv = &slave;
185 slave.sdev.name = "spi_sspi";
186 slave_device.dev.release = sspi_release;
187
188 /* Initialize platform device. */
189 slave_device.name = "cfspi_sspi";
190 slave_device.dev.platform_data = &slave.sdev;
191
192 /* Register platform device. */
193 res = platform_device_register(&slave_device);
194 if (res) {
195 printk(KERN_WARNING "sspi_init: failed to register dev.\n");
196 return -ENODEV;
197 }
198
199 return res;
200}
201
202static void __exit sspi_exit(void)
203{
204 platform_device_del(&slave_device);
205}
206
207module_init(sspi_init);
208module_exit(sspi_exit);
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 6f33ee453f41..631a6242b011 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 e6d3ca06ecfe..3a11d619452b 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 000000000000..03049e86e8ae
--- /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 000000000000..077ccf840edf
--- /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};
diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h
new file mode 100644
index 000000000000..ce4570dff020
--- /dev/null
+++ b/include/net/caif/caif_spi.h
@@ -0,0 +1,153 @@
1/*
2 * Copyright (C) ST-Ericsson AB 2010
3 * Author: Daniel Martensson / Daniel.Martensson@stericsson.com
4 * License terms: GNU General Public License (GPL) version 2
5 */
6
7#ifndef CAIF_SPI_H_
8#define CAIF_SPI_H_
9
10#include <net/caif/caif_device.h>
11
12#define SPI_CMD_WR 0x00
13#define SPI_CMD_RD 0x01
14#define SPI_CMD_EOT 0x02
15#define SPI_CMD_IND 0x04
16
17#define SPI_DMA_BUF_LEN 8192
18
19#define WL_SZ 2 /* 16 bits. */
20#define SPI_CMD_SZ 4 /* 32 bits. */
21#define SPI_IND_SZ 4 /* 32 bits. */
22
23#define SPI_XFER 0
24#define SPI_SS_ON 1
25#define SPI_SS_OFF 2
26#define SPI_TERMINATE 3
27
28/* Minimum time between different levels is 50 microseconds. */
29#define MIN_TRANSITION_TIME_USEC 50
30
31/* Defines for calculating duration of SPI transfers for a particular
32 * number of bytes.
33 */
34#define SPI_MASTER_CLK_MHZ 13
35#define SPI_XFER_TIME_USEC(bytes, clk) (((bytes) * 8) / clk)
36
37/* Normally this should be aligned on the modem in order to benefit from full
38 * duplex transfers. However a size of 8188 provokes errors when running with
39 * the modem. These errors occur when packet sizes approaches 4 kB of data.
40 */
41#define CAIF_MAX_SPI_FRAME 4092
42
43/* Maximum number of uplink CAIF frames that can reside in the same SPI frame.
44 * This number should correspond with the modem setting. The application side
45 * CAIF accepts any number of embedded downlink CAIF frames.
46 */
47#define CAIF_MAX_SPI_PKTS 9
48
49/* Decides if SPI buffers should be prefilled with 0xFF pattern for easier
50 * debugging. Both TX and RX buffers will be filled before the transfer.
51 */
52#define CFSPI_DBG_PREFILL 0
53
54/* Structure describing a SPI transfer. */
55struct cfspi_xfer {
56 u16 tx_dma_len;
57 u16 rx_dma_len;
58 void *va_tx;
59 dma_addr_t pa_tx;
60 void *va_rx;
61 dma_addr_t pa_rx;
62};
63
64/* Structure implemented by the SPI interface. */
65struct cfspi_ifc {
66 void (*ss_cb) (bool assert, struct cfspi_ifc *ifc);
67 void (*xfer_done_cb) (struct cfspi_ifc *ifc);
68 void *priv;
69};
70
71/* Structure implemented by SPI clients. */
72struct cfspi_dev {
73 int (*init_xfer) (struct cfspi_xfer *xfer, struct cfspi_dev *dev);
74 void (*sig_xfer) (bool xfer, struct cfspi_dev *dev);
75 struct cfspi_ifc *ifc;
76 char *name;
77 u32 clk_mhz;
78 void *priv;
79};
80
81/* Enumeration describing the CAIF SPI state. */
82enum cfspi_state {
83 CFSPI_STATE_WAITING = 0,
84 CFSPI_STATE_AWAKE,
85 CFSPI_STATE_FETCH_PKT,
86 CFSPI_STATE_GET_NEXT,
87 CFSPI_STATE_INIT_XFER,
88 CFSPI_STATE_WAIT_ACTIVE,
89 CFSPI_STATE_SIG_ACTIVE,
90 CFSPI_STATE_WAIT_XFER_DONE,
91 CFSPI_STATE_XFER_DONE,
92 CFSPI_STATE_WAIT_INACTIVE,
93 CFSPI_STATE_SIG_INACTIVE,
94 CFSPI_STATE_DELIVER_PKT,
95 CFSPI_STATE_MAX,
96};
97
98/* Structure implemented by SPI physical interfaces. */
99struct cfspi {
100 struct caif_dev_common cfdev;
101 struct net_device *ndev;
102 struct platform_device *pdev;
103 struct sk_buff_head qhead;
104 struct sk_buff_head chead;
105 u16 cmd;
106 u16 tx_cpck_len;
107 u16 tx_npck_len;
108 u16 rx_cpck_len;
109 u16 rx_npck_len;
110 struct cfspi_ifc ifc;
111 struct cfspi_xfer xfer;
112 struct cfspi_dev *dev;
113 unsigned long state;
114 struct work_struct work;
115 struct workqueue_struct *wq;
116 struct list_head list;
117 int flow_off_sent;
118 u32 qd_low_mark;
119 u32 qd_high_mark;
120 struct completion comp;
121 wait_queue_head_t wait;
122 spinlock_t lock;
123 bool flow_stop;
124#ifdef CONFIG_DEBUG_FS
125 enum cfspi_state dbg_state;
126 u16 pcmd;
127 u16 tx_ppck_len;
128 u16 rx_ppck_len;
129 struct dentry *dbgfs_dir;
130 struct dentry *dbgfs_state;
131 struct dentry *dbgfs_frame;
132#endif /* CONFIG_DEBUG_FS */
133};
134
135extern int spi_frm_align;
136extern int spi_up_head_align;
137extern int spi_up_tail_align;
138extern int spi_down_head_align;
139extern int spi_down_tail_align;
140extern struct platform_driver cfspi_spi_driver;
141
142void cfspi_dbg_state(struct cfspi *cfspi, int state);
143int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
144int cfspi_xmitlen(struct cfspi *cfspi);
145int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
146int cfspi_spi_remove(struct platform_device *pdev);
147int cfspi_spi_probe(struct platform_device *pdev);
148int cfspi_xmitfrm(struct cfspi *cfspi, u8 *buf, size_t len);
149int cfspi_xmitlen(struct cfspi *cfspi);
150int cfspi_rxfrm(struct cfspi *cfspi, u8 *buf, size_t len);
151void cfspi_xfer(struct work_struct *work);
152
153#endif /* CAIF_SPI_H_ */