Final report: SPI slave implementation
The project’s initial version involved the creation of SPI driver in slave mode. The first implementation
of realized framework was supposed to be SPI Flash Emulator. To ensure optimal performance, the
driver was meant to use SPI controller, DMA and interrupt.
After contacting linux-spi and finding Marek Vašut, a developer who already had experience with
SPI slave drivers, we had a constructive exchange of ideas. Marek introduced me to many
critical elements. Michael noticed a limitation that made it impossible to create a fully generic
slave driver. The project needed a thorough reconstruction.
The project consists of three layers. The first and the lowest layer supports the SPI hardware controller.
McSPI controller is located in BeagleBone Black, and the driver was developed exactly to this controller.
The whole implementation is located in spi-mcspi-slave.c[1] file. The controller easily handles small
transfers to 32 bytes with clock to 24 MHz. It supports a variety of word lengths, from 4 bits to 32 bits per word.
DMA was supposed to provide support for longer transfer lengths; however, I was not able to develop it
before the end of GSoC. DMA support will be added after GSoC.
The second layer is responsible for communication between the lowest layer and userspace. This layer
consists of a core (bus) which connects the device and driver. It is a bus and a set of functions registering
and managing other SPI slave devices. It was implemented in files spi-slave-core.c [2] and spi-slave-core.h
[3]. Framework uses device tree overlay. On the basis of DTB, it matches the device to the driver. I have
created two files dts for McSPI 0 slave.dts [4] and SPI1_slave.dts [5].
A simple user interface, allowing to carry out the transfer has been added in spi-slave-dev.c [6]
and spi-slave-dev.h[7] files. For each installed device, the driver provides file in userspace
(/dev/spislave0 and /dev/spislave1). The driver has the usual fs operations and a number of IOCTL
functions (described in more detail in spi-slave-dev.h [7]), as well as POLL methods used to inform
about the end of transaction.
I have added a simple spislave_app.c [8] application, which is using SPI slave framework.
It is a good example on how to use SPI slave.
Documentation located on wiki page [9] and in the documentation directory [10] in repository
describes the driver, clarifies and explains its limitations and shows the main problems
because of which a fully generic spi driver in slave mode is difficult to obtain. It also
provides information concerning work plan for each GSoC week. Moreover, it shows
stage by stage how to compile, install and use the framework, as well as the way the
master is connected to the slave on example of BeagleBoard Black.
[1]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/driver/spi-mcspi-slave.c
[2]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/driver/spi-slave-core.c
[3]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/driver/spi-slave-core.h
[4]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/DTS/SPI0_slave.dts
[5]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/DTS/SPI1_slave.dts
[6]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/driver/spi-slave-dev.c
[7]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/driver/spi-slave-dev.h
[8]https://github.com/pmezydlo/SPI_slave_driver_implementation/blob/master/slave_app/slave_app.c
[9]https://github.com/pmezydlo/SPI_slave_driver_implementation/wiki
[10]https://github.com/pmezydlo/SPI_slave_driver_implementation/tree/master/documentation
What did not work and why:
DMA is the only part of the project which - despite being planned to be involved in the project’s
final version - was not successful. DMA was supposed to provide support for transactions larger
than 32 bytes. Support for DMA has been written, however, I could not merge it. This is the
element that I am going to add after GSoC, for it proved to be too difficult for such limited time.
What I have learned during GSoC:
- upstream process and interaction with maintainers,
-how to create a variety of types of modules connected to the linux kernel,
- handling devices mapped in memory,
-creating a correct and visually aesthetic code compatible with the linux kernel coding style,
-planning and describing a project
-how bus, device and driver work
-character device drivers and fs operations in practice,
-methods for debugging and fault finding,
-better git use
-and many more 
What’s next:
Currently I am after third review of my code. Greg pointed to many mistakes and provided me with
valuable advices, so my code looks a lot better now. I learned a lot thanks to his help.
As for upstream code for kernel, I am quite skeptical. It is difficult and my code does not necessarily
correspond to the image of SPI slave preferred by linux-spi. Nevertheless, I still wish to continue work
on this code. We will see what happens.
A few words in conclusion.
The final report does not end my adventure with linux kernel and BeagleBoard community. These three
months have shown me that writing elements of Linux is not quite that difficult. I have also met a great
BeagleBoard community and I have got to know many wonderful people. I would like to thank Michael for
rescuing me when I got stuck and for such great amount of knowledge he shared with me. I’m especially
thankful for Andrew for his support during the draft preparation. Many thanks to everyone who helped and
supported me during GSoC. You are amazing.
Thanks
Patryk Mężydło