Sjur Braendeland | 529d6da | 2010-06-29 00:08:21 -0700 | [diff] [blame] | 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 |
Uwe Kleine-König | b595076 | 2010-11-01 15:38:34 -0400 | [diff] [blame] | 35 | both physical and logical addresses, as well as the total length |
Sjur Braendeland | 529d6da | 2010-06-29 00:08:21 -0700 | [diff] [blame] | 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 |
Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 153 | * the master that you are ready to receive the data from the master |
Sjur Braendeland | 529d6da | 2010-06-29 00:08:21 -0700 | [diff] [blame] | 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); |