How to write a simple Linux device driver?

前端 未结 4 1900
温柔的废话
温柔的废话 2020-12-22 15:24

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

4条回答
  •  一生所求
    2020-12-22 16:23

    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.

提交回复
热议问题