How to write a simple Linux device driver?

Sagar Jain picture Sagar Jain · Mar 25, 2014 · Viewed 81.1k times · Source

I need to write an SPI Linux character device driver for omap4 from scratch. I know some basics of writing device drivers. But, I don't know how to start writing platform specific device driver from scratch.

I've written some basic char drivers, and I thought writing SPI device driver would be similar to it. Char drivers have a structure file_operations which contains the functions implemented in the driver.

struct file_operations Fops = {
    .read = device_read,
    .write = device_write,
    .ioctl = device_ioctl,
    .open = device_open,
    .release = device_release,  /* a.k.a. close */
};

Now, I am going through spi-omap2-mcspi.c code as a reference to get an idea to start developing SPI driver from scratch.

But, I don't see functions such as open, read, write etc. Don't know from where the program starts.

Answer

Nenad Radulovic picture Nenad Radulovic · Mar 25, 2014

First start by writing a generic kernel module. There are multiple places to look up for information but I found this link to be very useful. After you have gone through all examples specified there you can start writing your own Linux Driver Module.

Please note, that you will not get away with just copy-pasting the example code and hope it will work, no. Kernel API can sometimes change and examples will not work. Examples provided there should be looked at as a guide how to do something. Depending on the kernel version you are using you have to modify the example in order to work.

Consider using TI platform provided functions as much as you can, because that can really do a lot work for you, like requesting and enabling needed clocks, buses and power supplies. If I recall correctly you can use the functions to acquire memory mapped address ranges for direct access to registers. I have to mention that I have bad experience with TI provided functions because they do not properly release/clean-up all acquired resources, so for some resources I had to call other kernel services to release them during module unload.

Edit 1:

I'm not entirely familiar with Linux SPI implementation but I would start by looking at omap2_mcspi_probe() function in drivers/spi/spi-omap2-mcspi.c file. As you can see there, it registers it's methods to Linux master SPI driver using this API: Linux/include/linux/spi/spi.h. In contrast to char driver the main functions here are *_transfer() functions. Look up at the struct descriptions in spi.h file for further details. Also, have a look at this alternative device driver API, too.