10

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.

11
  • 150MHz is a configuration limit, but the GPIO drivers (transistors) are limited, in most conditions to 10MHz or less.Officially, when driven as a clock, with 1.2V IO Supply and minimal load, the maximum GPIO switching frequency is 125MHZ
    – crasic
    Jun 6, 2019 at 1:01
  • @crasic with the BCM2835 library I’m capable of getting at least 32 MHz. Jun 6, 2019 at 1:03
  • " I have successfully used higher frequencies in the user space when using the BCM2835 library, so I know it is possible." was this done on exactly the same setup hardware wise?
    – crasic
    Jun 6, 2019 at 1:03
  • Yes, identical. I actually can do them side by side, running the user space program using the library, and then using the kernel module. Jun 6, 2019 at 1:04
  • 3
    As confirmation of my rule of thumb (10MHz is conservative). Library doc says "Although it is possible to select high speeds for the SPI interface, up to 125MHz (see bcm2835_spi_setClockDivider()) you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. Dont expect any speed faster than 31MHz to work reliably."
    – crasic
    Jun 6, 2019 at 1:06

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.