SPI driver, searching where to start

Viewed 912

I'm new with Android developpemnent but I want to write a SPI driver to connect a SPI IC and then an Android application to send and receive data from and to the IC.

From there, I don't really know where to create the driver (and what it should contain) and how to link an application in top of that. I have a customisable Android kernel (9.0 Pie, APQ8096_LA.UM.7.5.r1-03100-8x96.0_P_v5.0) with all its .dts, .dtsi, .c, and so on. I also got an eval board and the adequate documentation for the mapping.

I googled for a week and didn't found what I was looking for. I learned a bit about the device tree system. Since I have a Snapdragon 820 msm8996, I modified "msm8996-blsp.dtsi" and "msm8996-pinctrl.dtsi". I had this bit of code:

msm8996-pinctrl.dtsi

&soc {
...
    spi_0 {
        spi_0_active: spi_0_active {
            spi_0 {
                pins = "gpio0", "gpio1", "gpio2", "gpio3";
                function = "blsp_spi1";
                drive-strength = <6>;
                bias-disable;
            };

        };

        spi_0_sleep: spi_0_sleep {
            spi_0 {
                pins = "gpio0", "gpio1", "gpio2", "gpio3";
                function = "blsp_spi1";
                drive-strength = <6>;
                bias-disable;
            };
        };
    };
...          

msm8996-blsp.dtsi

&soc {
...
    spi_0: spi@7575000 { //QUP Base address for BLSP1_QUP0
        compatible = "qcom,spi-qup-v2"; //Manufacturer and Model
        #address-cells = <1>;
        #size-cells = <0>;
        reg-names = "spi_physical", "spi_bam_physical";
        reg = <0x07575000 0x600>,
        <0x07544000 0x2b000>;
        interrupt-names = "spi_irq", "spi_bam_irq";
        interrupts = <0 95 0>, <0 238 0>;
        spi-max-frequency = <5000000>; //Maximum supported frequency in HZ
        qcom,infinite-mode = <0>;
        qcom,use-bam; // Enable BAM mode
        /* Add BAM pipes */
        qcom,bam-consumer-pipe-index = <12>;
        qcom,bam-producer-pipe-index = <13>;
        qcom,ver-reg-exists;
        qcom,master-id = <86>;
        qcom,use-pinctrl;
        pinctrl-names = "spi_default", "spi_sleep";
        pinctrl-0 = <&spi_0_active>;
        pinctrl-1 = <&spi_0_sleep>;
        clock-names = "iface_clk", "core_clk";
        clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
        <&clock_gcc clk_gcc_blsp1_qup1_spi_apps_clk>;
        status = "enabled";
    }
...

I build this kernel with

$ ./build.sh msm8996 -j $(nproc)

I flashed my eval board with fastboot and then I went in adb.

$ adb root
$ adb wait-for-device
$ adb shell
# cd /sys/class/spi_master
# ls
// Nothing here

Considering my spi adress is defined at @7575000, I expected the output to be

# spi_0

Is my code correct to enable it (I'm not good with device tree yet)? If so, why isn't visible with adb and how should I make it visible? What should be the next steps to access this SPI with an Android application?

I searched stackoverflow and so many places, but writing device drivers for Android doesn't seem to be common...

1 Answers

There is no need for you to write a SPI driver for snapdragon it is already in the kernel. Maybe you need to write something to connect it to your device.

The easiest way to expose a spi controller to userspace is by mapping spidev to your device

There must be support for this in your kernel (which is added with the CONFIG_SPI_SPIDEV=y config flag) and in the device tree under the bus

Something like this:

&spi_0 {
   spidev@1 {
      #address-cells = <1>;
      #size-cells = <1>;
      compatible = "linux, spidev";
      spi-max-frequency = <20000000>;
      reg = <1>;   
   };
};

The device tree is compiled together with the kernel and contains among other things your gpio mappings and DMA configurations so the same kernel can serve multiple boards. Make sure android is using your newly compiled kernel and device tree, sometimes it accidentally builds with one of the prebuilt kernels.

After those steps you should have a /dev/spidev0.0 (or some other number) in /dev With ioctl complex operations can be used.

To verify if your software have full connection to your SPI bus connect a wire from MOSI to MISO the SPI writeread command will echo the same data it receives - remove the wire and verify there is nothing.

At this point should you start communicate with your sensor, and develop its control software.

In above case I would have started to check the log prints from kernel booting to verify it identifies the hardware correctly and the driver is loaded.

Related