123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- - 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);
|