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 s
I don't know if I understood your question correctly. As m-ric pointed out, there are master drivers and slave drivers.
Usually master drivers are more hardware bound, I mean, they usually manipulate IO registers or do some memory mapped IO.
For some architectures already supported by linux kernel (like omap3 and omap4) master drivers are already implemented (McSPI).
So I assume you want to USE those SPI facilities of omap4 to implement a slave device driver (your protocol, to communicate with your external device through SPI).
I've written the following example for BeagleBoard-xM (omap3). The full code is at https://github.com/rslemos/itrigue/blob/master/alsadriver/itrigue.c (worth a view, but have more initialisation code, for ALSA, GPIO, module parameters). I've tried to set apart code that deals with SPI (maybe I forgot something, but anyway you should get the idea):
#include
#include
#include
/* MODULE PARAMETERS */
static uint spi_bus = 4;
static uint spi_cs = 0;
static uint spi_speed_hz = 1500000;
static uint spi_bits_per_word = 16;
/* THIS IS WHERE YOUR DEVICE IS CREATED; THROUGH THIS YOU INTERACT WITH YOUR EXTERNAL DEVICE */
static struct spi_device *spi_device;
/* SETUP SPI */
static inline __init int spi_init(void) {
struct spi_board_info spi_device_info = {
.modalias = "module name",
.max_speed_hz = spi_speed_hz,
.bus_num = spi_bus,
.chip_select = spi_cs,
.mode = 0,
};
struct spi_master *master;
int ret;
// get the master device, given SPI the bus number
master = spi_busnum_to_master( spi_device_info.bus_num );
if( !master )
return -ENODEV;
// create a new slave device, given the master and device info
spi_device = spi_new_device( master, &spi_device_info );
if( !spi_device )
return -ENODEV;
spi_device->bits_per_word = spi_bits_per_word;
ret = spi_setup( spi_device );
if( ret )
spi_unregister_device( spi_device );
return ret;
}
static inline void spi_exit(void) {
spi_unregister_device( spi_device );
}
To write data to your device:
spi_write( spi_device, &write_data, sizeof write_data );
The above code is independent of implementation, that is, it could use McSPI, bit-banged GPIO, or any other implementation of an SPI master device. This interface is described in linux/spi/spi.h
To make it work in BeagleBoard-XM I had to add the following to the kernel command line:
omap_mux=mcbsp1_clkr.mcspi4_clk=0x0000,mcbsp1_dx.mcspi4_simo=0x0000,mcbsp1_dr.mcspi4_somi=0x0118,mcbsp1_fsx.mcspi4_cs0=0x0000
So that an McSPI master device is created for omap3 McSPI4 hardware facility.
Hope that helps.