Commit | Line | Data |
---|---|---|
529d6dad SB |
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 | |
b595076a | 35 | both physical and logical addresses, as well as the total length |
529d6dad SB |
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 | |
25985edc | 153 | * the master that you are ready to receive the data from the master |
529d6dad SB |
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); |