Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a simple Linux device driver?

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.

like image 598
Sagar Jain Avatar asked Mar 25 '14 11:03

Sagar Jain


People also ask

How are Linux drivers written?

The Linux kernel is written in the C and Assembler programming languages. C implements the main part of the kernel, while Assembler implements architecture-dependent parts. That's why we can use only these two languages for Linux device driver development.

What is a Linux device driver?

The software that handles or manages a hardware controller is known as a device driver. The Linux kernel device drivers are, essentially, a shared library of privileged, memory resident, low level hardware handling routines. It is Linux's device drivers that handle the peculiarities of the devices they are managing.


2 Answers

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 on 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 of 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 a 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 the struct descriptions in spi.h file for further details. Also, have a look at this alternative device driver API, too.

like image 173
Nenad Radulovic Avatar answered Oct 16 '22 09:10

Nenad Radulovic


I assume your OMAP4 linux uses one of arch/arm/boot/dts/{omap4.dtsi,am33xx.dtsi} device-tree, thus it compiles drivers/spi/spi-omap2-mcspi.c (if you don't know about device-tree, read this). Then:

  • the SPI master driver is done,
  • it (most probably) registers with Linux SPI core framework drivers/spi/spi.c,
  • it (probably) works fine on your OMAP4.

You actually don't need to care about the master driver to write your slave device driver. How do I know spi-omap2-mcspi.c is a master driver? It calls spi_register_master().

SPI master, SPI slave ?

Please refer to Documentation/spi/spi_summary. The doc refers to Controller driver (master) and Protocol drivers (slave). From your description, I understand you want to write a Protocol/Device driver.

SPI protocol ?

To understand that, you need your slave device datasheet, it shall tell you:

  • the SPI mode understood by your device,
  • the protocol it expects on the bus.

Contrary to i2c, SPI does not define a protocol or handshake, SPI chips manufacturers have to define their own. So check the datasheet.

SPI mode

From include/linux/spi/spi.h:

 * @mode: The spi mode defines how data is clocked out and in.
 *  This may be changed by the device's driver.
 *  The "active low" default for chipselect mode can be overridden
 *  (by specifying SPI_CS_HIGH) as can the "MSB first" default for
 *  each word in a transfer (by specifying SPI_LSB_FIRST).

Again, check your SPI device datasheet.

An example SPI device driver?

To give you a relevant example, I need to know your SPI device type. You would understand that a SPI flash device driver is different from a SPI FPGA device driver. Unfortunately there are not so many SPI device drivers out there. To find them:

$ cd linux 
$ git grep "spi_new_device\|spi_add_device"
like image 21
m-ric Avatar answered Oct 16 '22 09:10

m-ric