 Okay. Hello everybody. So, my name is Geert Höttehofer. I started programming a long time ago as a hobbyist on the Commodore line of home computers. Then about 25 years ago I learned about Linux and a bit later I started contributing to Linux by supporting the port for to the Amiga with the M68K processor. Later I ported Linux to the Common Hardware Reference platform which had a PowerPC processor and for a while I was Linux framework for device maintainer. In the meantime I started working for Sony and while at Sony I started working on Linux for the PlayStation 3 game computer with the cell processor. It was a really fun time. And a few years ago I became a freelance embedded Linux kernel hacker and since then I've mostly been doing upstream Linux work for Renesa's ARM-based SOCs. Something, it seems the titles are not on the screen, but... So something about me and FOSDEM. So in 2000 I heard about this interesting new small conference here in Brussels called FOSDEM so I decided to attend it. It was great. Next year it was FOSDEM, greater and greater and greater. And since 2004 I've been a member of the program committee for the embedded track and I've kept on attending FOSDEM until now. But I've been presenting at many other conferences but actually this is the first time I'm presenting at FOSDEM so welcome to Linux as an SPI slave. So about three years ago Linux got support for I2C slave support. And then people started wondering could we have SPI slave support as well where Linux is doing the slave part of the SPI side and not the master side. And yeah, the answer is yes, but... And in this presentation I will tell you what is possible, why it was difficult, what's different about SPI compared to other buses. So let's start with the basic SPI bus. It's a bit annoying that the titles are not there but we can handle. So SPI it started as, it was developed by Motorola in the 80s to control different simple peripherals from a microcontroller without using too many wires. So it's a bus and you have a data outline from the master to the slave called master out slave in. You have data inline going from slaves to the master. There's a clock line controlled by the master and there are one or more ship selects to select the individual slaves. So basically it's just a glorified shift register. So the heart rate is actually quite simple. Important to notice is that the master was in charge and that there can be multiple slaves. So and the master is in control and we have simultaneous transmit from master to slave and receive from slave to master and speeds can actually be fairly high. They go from tens of kilohertz to a few tens of megahertz. So a sample SPI transfer is shown here. So at the top we have the line with data going from master to slave below that from slave to master then the clock signal and the ship select. So when the ship select is selected by the master a bit later it starts clocking and then data goes out from master to slave and goes in from slave to master. This is really low level hardware and of course lower level hardware can be done in many different ways. So there are lots of options. Do we sample data lines that's rising edges or falling edges of clocks? What's the polarity of the clock? Ship select polarities. They can also be active high or active low. Which bit do we transfer first? And in this case it has to be taken into account. As a slow hardware and not always used for 8-bit systems you can have different bits of words. 8 and 16 are fairly simple to handle but sometimes you can have 12-bit words something like that and one important parameter of course is the transfer speed. You should transfer data not faster than the slave can handle. There are also a few simplifications possible not SPI systems implement the same thing. Some slaves you can only write to so they do not connect the master in slave out. An example is digital to analog converter. You can have slaves where you just want to read data like a sensor so you don't have to connect the other wire. There are also slaves where they combine the data in and data out lines so it becomes a half-duplex protocol and if there's only one slave you don't need a ship select. That's even further simplification. Besides simplifications there are also extensions. So people wanted higher speeds so they thought maybe we can combine the two data lines to transfer two bits of data from master to slave or from slave to master. Obviously it becomes half-duplex then. Later that was extended to what SPI where you add two extra wires and then you can transfer four bits of data at the same time. This is typically used for SPI flashes. Another way to make it even faster is to add double data rate support so you sample the data at the rising and the falling edge of the clock. So far Linux SPI supports that maybe in some specialized SPI flash controllers that show up as MTD device and not as SPI. Probably they do. And then recently we've been seeing systems where they just add two QSPI flashes and address them in parallel and then you have eight bits of data and sometimes that's also called hyper flash and that's even faster. So this is about the SPI protocol. So an actual SPI message in a protocol consists of several transfers and each transfer can be half-duplex or full-duplex. It can be a single transfer or dual and a quad. You can have some dummy cycles to give the slave some time to calculate some data or something like that but that's all highly slave device specific and it's dictated by the protocol. And typically as the ship select is assertive for the whole message usually. An example for that is a simple SPI flash read. So it consists of two transfers. As you can see here the ship select is assertive for the whole message and this is the first transfer. Here will be the second transfer. The first transfer sends a command for this particular SPI flash three means read data. Then the 2A is the offset where to read in memory. You see that the data is transferred from the master to the slave and the second part of the transfer data goes from the slave to the master and that's actually the data that you read from the SPI flash. So far the simple basic SPI. Now if you want to have support for SPI slave in Linux there are a few challenges. So the biggest one is basically that you have simultaneous transmit and receive and that the master has control. So the master controls the ship select, the master controls the clocking, the slave has to follow data. So it's a real hard to real-time system. That also means that if the master requests you to send data that you must have already written the data on the slave side in the transmit FIFO. It also means that if the master sends a command for example reading from a flash that the response has to be prepared before by the slave if it's software based. So that means that if you want to do software SPI slave that the slave response cannot be a reply to a command in the exact same SPI message. So if we want to do that then we need SPI protocol where the slave response will be in the next message. So how did I start working on this? So as I told you before I'm doing contract work for Renesas and one day they asked me can you please upstream SPI slave support? Well we have it for SPI. We have it for SPI. I had my doubts about that. But yeah, then we actually had something. So inside the Renesas ArcR BSP there was code to support that. So she probably know a BSP that's a board support package. It's an old or not so old Linux kernel source tree with lots of patches on top that add, change, remove, break, various levels of functionality. So usually the code is not ready for upstream. But yeah, there was something. Then I asked so what kind of use case do we have for this SPI slave implementation because there are many challenges and up till now I didn't manage to get out the real use case there. So most probably they're using SPI there from user space. But we don't really know why. But important part here was that the customer from Renesas they were happy with the implementation. So it must do something. So who am I to say that it cannot be done? So I decided yeah okay let's do it. Create my own use case there. Get it working and then make the code fit for upstreaming. Make the required changes to have it nicely fit into the SPI subsystem. Yeah to find a good use case and to overcome the challenges I compare I like to compare the SPI bus with a few other buses where we do have some kind of slave support in the kernel. The first example is the I2C. I'm not going into all detail but most information is on the slides which you can download later. So on I2C we did get slave support a few years ago. And the major reason why that's workable is that on I2C the clocking is also controlled by the master but it's an open drain signal and the slave can actually if the master asserts the clock and the slave is not yet ready it can the slave can also assert the clock. So because it's open drain it will stay asserted and that's called clock stretching. So during that mechanism the slave can delay everything until it's really ready. Another bus is the UART bus, the serial standard serial port if you're on the receiving side as a UART then your received buffer can overflow but apart from that that's such big issues because unlike for SPI the other side controls itself when it wants to transmit something so it can wait until it's ready. So the both channels are both bidirectional channels are really separate and optionally you have hardware flow control like request to send clear to send which makes it easier. Third bus I looked at was it's really a shame that the titles are not visible is Ethernet yes. So Ethernet used to be half duplex these days which switches its full duplex but again here each side controls its own when it's ready to transmit something and on top of that Ethernet is usually used for network transmissions if packets are dropped or lost the driver can drop them and the upper layers will usually handle it fine later. This is about USB so in USB everything is basically controlled by the master but the master pulls the bus and then there are also packets and acknowledgment so it's quite complex but basically it means that there's no real issue with slave data getting lost. The last one is Onewire that's not so interesting here because we don't have any support in Linux I think it's more or less similar like SPI if you want to implement it but that's still something to be done. So this is a summary of all the things that we have in the various buses I went over that make it simpler to design a slave protocol later things like hardware flow control and upper layers handling it's interesting if you want to design your own SPI slave control so what kind of use cases can we have with SPI slaves that are definitely possible to implement one of them is just the master sending data to a slave no data going from slave to master so as long as you don't overflow the receive file everything should work so if the speeds you don't go to too high speeds you can get it working you could control another thing is reading data from the slave to the master the issue is when you know when the slave has data to send could also be handled by polling bidirectional is a combination of both there you have to consider that the response can never be replied to come out in the same message a nice example of an existing SPI protocol that shows these limitations is in the Nordic semiconductor NRF 8001 bluetooth low energy controller they basically show what you have to do there and in that system they don't really use a ship select but use two separate signals there's a master request which is being some kind of ship select and the slave ready so when the master wants to send something he asserts the master request the data he asserts the slave ready then the master sends commands which are always first the length byte followed first of data at the same time it reads data from the slave which also starts with the length byte followed by data if the length is zero the slave doesn't have to say anything now if the slave has something to some information to send to the master it will assert the slave ready signal first after that the master will assert master request send to dummy command and read the event from the slave so and data sheet there states explicitly that the event is received from the master it's never reply to the command from the master to the slave so yeah what we definitely can do is receive streams of data with simple messages but I don't go into detail because we're already lowing running a bit out of time so when Linux gained i2c slave support the first example that Wolfram Zang wrote there was an eProm simulator so with i2c that worked because you have clock scratching for SPI it's more complicated so I was wondering whether we could do something similar but if you look at all the various SPI slave drivers that are in Linux there was not really anything that I found interesting I would have loved to write a SPI slave that you could just connect another Linux system over SPI and it would behave like a fake network interface but all the SPI Ethernet drivers they use protocols where the response to a command is part of the same message so you could not do that for a slave so I had to come up with something myself and one example was that you can query the system uptime of a system and another one is that you can send some commands to a system for remote control and reboot and of course you can use SPI there so this brings us to the actual implementation so there were first steps to be done the first one was to get the device three bindings in extent then extent SPI subsystems to support for slaves extent one of the existing renaissance SPI master drivers to support slave and then some example SPI slave hunters device three bindings this is a sample for a normal SPI bus with the master controller so you have the device node for the master then you have a bus with one or more devices in this case it's a PMIC and that's how it is described for a master controller so for a slave controller we just add SPI slave property and a single sub node without a unit address and without a register representing the slave the compatible value here specifies what protocol is used that sub node is optional we also made it that you can configure it from user space later the subsystem changes SPI slave support is completely optional to a new K config signal there's a new SPI class device was added and a mechanism to bind the slave protocol to the actual slave controller so as I said there are two ways one of them was a compatible value in DT which is optional and the second one is to write a value of the actually the driver identifier to a virtual file in CISFS the subsystem also gained three new API calls instead of allocating a master controller you know allocate a slave controller the second one is because I told you before that a slave has to prepare data to be received by the master before it receives the master request so suppose that you have already prepared the data and then you want to unload the driver or something like that you have to abort that operation so a new API call for that is added and the third one is just a simple check with the check with the controller master and slave and it takes into account the configuration option so for drivers that support both master and slave and as a last step we generalized that the current SPI master naming was changed to controller because everything stayed the same but master was not a good name for that anymore and that's actually the largest part of the patch so how does a SPI master driver looks like this one this is a very simple one you create a SPI master structure you fill in capabilities a few callbacks and you register and that's it what needs to be changed for a slave controller instead of SPI master we now have SPI controller which is basically just exactly the same thing you call alloc slave instead of alloc master of the new callback register everything and that's it now the changes that had to be made to the Renesas SPI master driver they were actually quite small so the low level core of that was based on the sample patch we had in the BSP so from the hardware point of view it's actually quite simple and you just consider the clock an input instead of an output and the rest of the hardware will handle it fine on top of that are the more complex things you have to register as a master or a slave controller based on the DT SPI slave property whether it's present or not when writing hardware drivers you typically program the hardware to do something and then you wait for an interrupt to happen that will trigger completion for a master controller driver it's something waiting for completion with a very short time out just in case the hardware hangs for a slave controller you never know when the master is going to send you a command could be in one second could be in one hour so you have to use a different wait for completion call and one that can be aborted through the slave abort callback and with the current Renesas MSIOF driver there's a limitation that the message size must be known in advance I think that can be relaxed because the hardware doesn't know when the message is ended but that hasn't been implemented yet now the final part is the SPI slave handlers so the existing SPI slave drivers in the kernel they all assume that they're talking to a slave device through a master controller so the new SPI slave handlers they are used to listen to requests from a remote master we manage to keep most of the existing infrastructure as is so everything can be reused as much as possible SPI slave handlers use almost the same API the only differences are is that when you send data to the master it will not be sent immediately but only when the master requests for it and you can abort it when it's you want to unload the driver for example we don't have support for the ready signal yet which is part of some protocols but can easily be implemented on top by the driver because mostly driver specific it can be handled with the GPIO or GPIO type or interrupt or something like that example normal SPI slave handler in SPI driver property it can set up some stuff and then send messages to the slave different APIs are listed most of them here and SPI slave handler is really very similar there's one big difference though is that if you want to do something for example your probe function yet you have to use a non-blocking SPI transfer because the probe function should return and the data will not really be sent here if you want to do blocking stuff then you have to do it from a threat and the second big change is that in your remove function you have to abort anything that has been programmed into the hardware yet and then of course you have to wait for some way for the other threats to complete something like that now on a simple example of this you have a question yes you showed at the beginning some three wire SPIs so this half duplex SPI in that as a slave you might get interrupted or you might get a conflict on your master input slave output this single day usually use the data line I wonder why we didn't or you didn't implement an extra callback on the interface to signal that to the other layer I think the three wire interface handling it in slave mode is not that simple and actually the slave needs to know the protocol and needs to know when it switches from transmit to receive if you know the protocol you just put a different transfer then you don't need a wire because at any point you might get interrupted you might get a master trying to write in something on its own on the data line but most of the slave should know what protocol they will have to talk to each other so else it breaks down anyway so back to the example so I wrote three small examples here that's the last part after that with the questions so a first example here is that this is the slave time handler which will respond with the uptime of the system so this uses the virtual file in CISFS to convert the slave handler so this time you write the name of the driver to it and after that I used SPI def test to write some dummy bytes and in the response you will see here the uptime in seconds and in microseconds from the remote system note that this is the uptime when the previous message was on the other system was received because it had to it's not when the master sends a message to the slave it's a time from when the slave prepared it this could be used as a simple deadman switch for example because if this remote system dies then you will no longer receive a valid time but all zeros are one or something like that the second example is system control handler which you can use to suspend or resume a system you just write a specific command to it the weird hex numbers here are chosen such that I connected some shift registers and a 7-segment LEDs to the bus so I could see an interesting character on that one like CZ when you suspend something like that and the third example is using SPI def if you have more information about the tester of this Elinux org wiki page, yes I did use DT overlays just for people who are interested in that and we got this in 4.13, thank you Mark and then I'd like to say what things you could we could use in the future more support for other slave controllers for now we have renaissance MSI OF free scale IMX more handlers for real world protocols perhaps IP networking I'd like to thank a few people so if we have questions I think we have one minute back in 2016 during google summer of code there was a project to implement SPI slave for the big bone black do you know if patches from renaissance BSP are based on this work or it's totally unrelated has been dropped or something so the question is whether the patches for the big bone black are related to this in 2016 they must definitely be newer than the ones from the renaissance BSP because I think those date back to 2014 or something like that some silicon supports other signaling besides the red light interrupt so when the slave wants to transmit something back to the master as well they use an incline they have some offline signal your proposal is also to implement as part of your driver yeah so the question is about signals from interrupt signals from the slave to the master that you have to implement them in the driver yes so the idea is that you do that on top and technically you would do a right and during the right you would want your driver which is threaded and wait to stop the flow yeah so if the slave wants to send interrupt it can use GPIO to assert the signal and connect it to the interrupt light could you use that slave support to emulate the SPI flash the device would kind of software SPI flash for example use case would be testing for example FBGAs or other boards just kind of load the bitstream or other configurations from the SPI so you can kind of change that quickly without flashing and real SPI flash all the time yeah so the question was can you use that SPI flash I didn't implement SPI flash support because it has an annoying protocol where it relies on the commands in the same message so you send the command to read data and then the slave has to respond with data in that same message and that's not possible but SPI flash right you could implement that's true yeah so the question is that you could just ignore the read command and just send data anyway yes but if you know in advance what the other side will request that you can do it but then basically that becomes part of the protocol yeah for FBGAs programming it's a have you investigated the possibility to implement SD card emulation using the slave protocol so the question is that but are considered SD card emulation SD card emulation is a similar issue as that's reading from SPI flash so you can access the SD card and treat it like SPI slave I'm talking to it but unless it's just for writing you cannot do it any more questions no? yeah I think I missed mixed up the times