9

I am running Arch Linux ARM on a Raspberry Pi 2 Model B, and I am attempting to communicate with a TFT display. I am writing a kernel module to interface with the display using SPI, and it works, but I cannot get the SPI frequency to go above 500 kHz. I have successfully used higher frequencies in the user space when using the BCM2835 library, so I know it is possible.

Using the following command to parse the device tree:

dtc -I fs /sys/firmware/devicetree/base | grep max-frequency

I can see that spi-max-frequency = <0x7735940>, which is hexadecimal for 150 MHz.

hexdump /sys/class/spi_master/spi0/of_node/spi-max-frequency

gives me 7307 4059, hexadecimal for the same number (just with the byte order reversed). In my kernel module, I did the following:

struct spi_board_info spiBoardInfo = {
    .modalias = "spi",
    .max_speed_hz = 32000000,
    .bus_num = 0,
    .chip_select = 0,
    .mode = 0
};

master = spi_busnum_to_master(spiBoardInfo.bus_num); spiDevice = spi_new_device(master, &spiBoardInfo); spiDevice->bits_per_word = 8; ret = spi_setup(spiDevice); printk(KERN_INFO "TFT: device max speed %ld\n", spiDevice->max_speed_hz);

which prints out 32000000, as expected (error checking code was removed above for brevity). To write to the slave, I use the following command

spi_write(spiDevice, &data, sizeof(data));

(I have also tried using spi_sync_transfer() and setting the speed there as well, to no avail). This command successfully writes the data, but at a speed of 500 kHz.

Does anyone know why I am being limited to this frequency?

EDIT

After investigating further, I strongly feel it has to do with the device tree. I added the following overlay:

/dts-v1/;
/plugin/;
/ {
    compatible = "brcm,bcm2708";
    fragment@0 {
            target = <&spidev0>;
            __overlay__ {
                    status = "disabled";
            };
    };
    fragment@1 {
            target = <&spi0>;
            __overlay__ {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    status = "okay";
                    tft@0 {
                            compatible = "tft,st7789";
                            spi-max-frequency = <320000000>;
                            reg = <0>;
                    };
            };
    };
    __overrides__ {
            tft = <0>, "=0=1";
    };
};

And now receive:

spi-bcm2835 3f204000.spi: chipselect 0 already in use

The name of my kernel module is tft, and then I do the following:

static const struct of_device_id dtIDs[] = {
    {.compatible = "tft,st7789"},
    {}
};
MODULE_DEVICE_TABLE(of, dtIDs);

So it seems as if the SPI driver is not recognizing my kernel module as the owner of chipselect 0, and not letting me access SPI as a result. I feel as though if I got this working, I would get the correct speeds, as the spi-max-frequency will have been directly set for my driver.

goldilocks
  • 60,325
  • 17
  • 117
  • 234
j_lentini
  • 149
  • 6

1 Answers1

0
spi-bcm2835 3f204000.spi: chipselect 0 already in use

This error means something else (probably spidev) is still claiming CS0. Please check if you have disabled spidev.

tepalia
  • 151
  • 3