diff options
author | Sjur Braendeland <sjur.brandeland@stericsson.com> | 2010-06-29 03:08:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-29 03:08:21 -0400 |
commit | 529d6dad5bc69de14cdd24831e2a14264e93daa4 (patch) | |
tree | a89d7b8cdd3692e96a64c5d7196bcefc9f1e7f24 /Documentation/networking/caif | |
parent | 01eebb53a65996dfbfb892bf5eb21ae831fbe3a6 (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 'Documentation/networking/caif')
-rw-r--r-- | Documentation/networking/caif/spi_porting.txt | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/Documentation/networking/caif/spi_porting.txt b/Documentation/networking/caif/spi_porting.txt new file mode 100644 index 00000000000..61d7c924745 --- /dev/null +++ b/Documentation/networking/caif/spi_porting.txt | |||
@@ -0,0 +1,208 @@ | |||
1 | - CAIF SPI porting - | ||
2 | |||
3 | - CAIF SPI basics: | ||
4 | |||
5 | Running CAIF over SPI needs some extra setup, owing to the nature of SPI. | ||
6 | Two extra GPIOs have been added in order to negotiate the transfers | ||
7 | between the master and the slave. The minimum requirement for running | ||
8 | CAIF over SPI is a SPI slave chip and two GPIOs (more details below). | ||
9 | Please note that running as a slave implies that you need to keep up | ||
10 | with the master clock. An overrun or underrun event is fatal. | ||
11 | |||
12 | - CAIF SPI framework: | ||
13 | |||
14 | To make porting as easy as possible, the CAIF SPI has been divided in | ||
15 | two parts. The first part (called the interface part) deals with all | ||
16 | generic functionality such as length framing, SPI frame negotiation | ||
17 | and SPI frame delivery and transmission. The other part is the CAIF | ||
18 | SPI slave device part, which is the module that you have to write if | ||
19 | you want to run SPI CAIF on a new hardware. This part takes care of | ||
20 | the 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 | |||
83 | In order to optimize throughput, a number of SPI padding options are provided. | ||
84 | Padding can be enabled independently for uplink and downlink transfers. | ||
85 | Padding can be enabled for the head, the tail and for the total frame size. | ||
86 | The padding needs to be correctly configured on both sides of the link. | ||
87 | The padding can be changed via module parameters in cfspi_sspi.c or via | ||
88 | the 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 | |||
107 | MODULE_LICENSE("GPL"); | ||
108 | |||
109 | struct sspi_struct { | ||
110 | struct cfspi_dev sdev; | ||
111 | struct cfspi_xfer *xfer; | ||
112 | }; | ||
113 | |||
114 | static struct sspi_struct slave; | ||
115 | static struct platform_device slave_device; | ||
116 | |||
117 | static 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 | |||
128 | static 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 | |||
137 | static 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 | |||
150 | void 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 | |||
161 | static void sspi_release(struct device *dev) | ||
162 | { | ||
163 | /* | ||
164 | * Here you should release your SPI device resources. | ||
165 | */ | ||
166 | } | ||
167 | |||
168 | static 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 | |||
202 | static void __exit sspi_exit(void) | ||
203 | { | ||
204 | platform_device_del(&slave_device); | ||
205 | } | ||
206 | |||
207 | module_init(sspi_init); | ||
208 | module_exit(sspi_exit); | ||