| - CAIF SPI porting - | |
| - CAIF SPI basics: | |
| Running CAIF over SPI needs some extra setup, owing to the nature of SPI. | |
| Two extra GPIOs have been added in order to negotiate the transfers | |
| between the master and the slave. The minimum requirement for running | |
| CAIF over SPI is a SPI slave chip and two GPIOs (more details below). | |
| Please note that running as a slave implies that you need to keep up | |
| with the master clock. An overrun or underrun event is fatal. | |
| - CAIF SPI framework: | |
| To make porting as easy as possible, the CAIF SPI has been divided in | |
| two parts. The first part (called the interface part) deals with all | |
| generic functionality such as length framing, SPI frame negotiation | |
| and SPI frame delivery and transmission. The other part is the CAIF | |
| SPI slave device part, which is the module that you have to write if | |
| you want to run SPI CAIF on a new hardware. This part takes care of | |
| the physical hardware, both with regard to SPI and to GPIOs. | |
| - Implementing a CAIF SPI device: | |
| - Functionality provided by the CAIF SPI slave device: | |
| In order to implement a SPI device you will, as a minimum, | |
| need to implement the following | |
| functions: | |
| int (*init_xfer) (struct cfspi_xfer * xfer, struct cfspi_dev *dev): | |
| This function is called by the CAIF SPI interface to give | |
| you a chance to set up your hardware to be ready to receive | |
| a stream of data from the master. The xfer structure contains | |
| both physical and logical addresses, as well as the total length | |
| of the transfer in both directions.The dev parameter can be used | |
| to map to different CAIF SPI slave devices. | |
| void (*sig_xfer) (bool xfer, struct cfspi_dev *dev): | |
| This function is called by the CAIF SPI interface when the output | |
| (SPI_INT) GPIO needs to change state. The boolean value of the xfer | |
| variable indicates whether the GPIO should be asserted (HIGH) or | |
| deasserted (LOW). The dev parameter can be used to map to different CAIF | |
| SPI slave devices. | |
| - Functionality provided by the CAIF SPI interface: | |
| void (*ss_cb) (bool assert, struct cfspi_ifc *ifc); | |
| This function is called by the CAIF SPI slave device in order to | |
| signal a change of state of the input GPIO (SS) to the interface. | |
| Only active edges are mandatory to be reported. | |
| This function can be called from IRQ context (recommended in order | |
| not to introduce latency). The ifc parameter should be the pointer | |
| returned from the platform probe function in the SPI device structure. | |
| void (*xfer_done_cb) (struct cfspi_ifc *ifc); | |
| This function is called by the CAIF SPI slave device in order to | |
| report that a transfer is completed. This function should only be | |
| called once both the transmission and the reception are completed. | |
| This function can be called from IRQ context (recommended in order | |
| not to introduce latency). The ifc parameter should be the pointer | |
| returned from the platform probe function in the SPI device structure. | |
| - Connecting the bits and pieces: | |
| - Filling in the SPI slave device structure: | |
| Connect the necessary callback functions. | |
| Indicate clock speed (used to calculate toggle delays). | |
| Chose a suitable name (helps debugging if you use several CAIF | |
| SPI slave devices). | |
| Assign your private data (can be used to map to your structure). | |
| - Filling in the SPI slave platform device structure: | |
| Add name of driver to connect to ("cfspi_sspi"). | |
| Assign the SPI slave device structure as platform data. | |
| - Padding: | |
| In order to optimize throughput, a number of SPI padding options are provided. | |
| Padding can be enabled independently for uplink and downlink transfers. | |
| Padding can be enabled for the head, the tail and for the total frame size. | |
| The padding needs to be correctly configured on both sides of the link. | |
| The padding can be changed via module parameters in cfspi_sspi.c or via | |
| the sysfs directory of the cfspi_sspi driver (before device registration). | |
| - CAIF SPI device template: | |
| /* | |
| * Copyright (C) ST-Ericsson AB 2010 | |
| * Author: Daniel Martensson / Daniel.Martensson@stericsson.com | |
| * License terms: GNU General Public License (GPL), version 2. | |
| * | |
| */ | |
| #include <linux/init.h> | |
| #include <linux/module.h> | |
| #include <linux/device.h> | |
| #include <linux/wait.h> | |
| #include <linux/interrupt.h> | |
| #include <linux/dma-mapping.h> | |
| #include <net/caif/caif_spi.h> | |
| MODULE_LICENSE("GPL"); | |
| struct sspi_struct { | |
| struct cfspi_dev sdev; | |
| struct cfspi_xfer *xfer; | |
| }; | |
| static struct sspi_struct slave; | |
| static struct platform_device slave_device; | |
| static irqreturn_t sspi_irq(int irq, void *arg) | |
| { | |
| /* You only need to trigger on an edge to the active state of the | |
| * SS signal. Once a edge is detected, the ss_cb() function should be | |
| * called with the parameter assert set to true. It is OK | |
| * (and even advised) to call the ss_cb() function in IRQ context in | |
| * order not to add any delay. */ | |
| return IRQ_HANDLED; | |
| } | |
| static void sspi_complete(void *context) | |
| { | |
| /* Normally the DMA or the SPI framework will call you back | |
| * in something similar to this. The only thing you need to | |
| * do is to call the xfer_done_cb() function, providing the pointer | |
| * to the CAIF SPI interface. It is OK to call this function | |
| * from IRQ context. */ | |
| } | |
| static int sspi_init_xfer(struct cfspi_xfer *xfer, struct cfspi_dev *dev) | |
| { | |
| /* Store transfer info. For a normal implementation you should | |
| * set up your DMA here and make sure that you are ready to | |
| * receive the data from the master SPI. */ | |
| struct sspi_struct *sspi = (struct sspi_struct *)dev->priv; | |
| sspi->xfer = xfer; | |
| return 0; | |
| } | |
| void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev) | |
| { | |
| /* If xfer is true then you should assert the SPI_INT to indicate to | |
| * the master that you are ready to receive the data from the master | |
| * SPI. If xfer is false then you should de-assert SPI_INT to indicate | |
| * that the transfer is done. | |
| */ | |
| struct sspi_struct *sspi = (struct sspi_struct *)dev->priv; | |
| } | |
| static void sspi_release(struct device *dev) | |
| { | |
| /* | |
| * Here you should release your SPI device resources. | |
| */ | |
| } | |
| static int __init sspi_init(void) | |
| { | |
| /* Here you should initialize your SPI device by providing the | |
| * necessary functions, clock speed, name and private data. Once | |
| * done, you can register your device with the | |
| * platform_device_register() function. This function will return | |
| * with the CAIF SPI interface initialized. This is probably also | |
| * the place where you should set up your GPIOs, interrupts and SPI | |
| * resources. */ | |
| int res = 0; | |
| /* Initialize slave device. */ | |
| slave.sdev.init_xfer = sspi_init_xfer; | |
| slave.sdev.sig_xfer = sspi_sig_xfer; | |
| slave.sdev.clk_mhz = 13; | |
| slave.sdev.priv = &slave; | |
| slave.sdev.name = "spi_sspi"; | |
| slave_device.dev.release = sspi_release; | |
| /* Initialize platform device. */ | |
| slave_device.name = "cfspi_sspi"; | |
| slave_device.dev.platform_data = &slave.sdev; | |
| /* Register platform device. */ | |
| res = platform_device_register(&slave_device); | |
| if (res) { | |
| printk(KERN_WARNING "sspi_init: failed to register dev.\n"); | |
| return -ENODEV; | |
| } | |
| return res; | |
| } | |
| static void __exit sspi_exit(void) | |
| { | |
| platform_device_del(&slave_device); | |
| } | |
| module_init(sspi_init); | |
| module_exit(sspi_exit); |