Plebian-Linux / quartz64-images

GitHub Actions Repository for automatically generated images for the Quartz64 family of single board computers
https://plebian.org
GNU General Public License v3.0
41 stars 10 forks source link

Question: Activating/using SPI on SOQuartz #32

Open hughsheehy opened 1 year ago

hughsheehy commented 1 year ago

Just realized I should probably be commenting/asking here

Discussion was here. https://www.reddit.com/r/PINE64official/comments/122qcyv/comment/jenpkh2/?utm_source=share&utm_medium=web2x&context=3

Argh. Confusion reigns.

The devices I'd like to use are "normal" devices and don't seem to need or have fancy drivers in other hardware like Pis. (Or where there's a standard Qualcomm driver).

And when I look in the Linux kernel, I see things like this. https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts

Which shows the board for the SOQuartz, but with SPI "disabled". If I set that to "okay" then i still don't see any SPI devices in /dev (which is what I naively expect).

And there's https://github.com/torvalds/linux/blob/master/drivers/spi/spi-rockchip.c, which seems to be the SPI config for the underlying chip. And this, https://github.com/torvalds/linux/blob/master/drivers/spi/spidev.c , which is the definition of spidev which (again naively) I expected to use with the generic devices I'm aiming to use. spiidev might be hacky, but many code examples use it.

So I'm not sure what i need to add...what I'd put in a device tree overlay. I just want to get a Pine64 SOQuartz running SPI in the same (simple) way that a Pi CM4 does.

If there's something I can do to help support this, I would be happy to. But now I'm just confused.

With Plebian, it seems like a great start to be able to use SOQuartz in a fairly normal way as if it was a Pi CM4. But with SPI I'm stuck.

H

CounterPillow commented 1 year ago

Okay, first we need to enable the SPI bus and add a "dummy" device on chip select 0. This is SPI3, so we need the following overlay, which you can save as enable-spi.dts:

/dts-v1/;
/plugin/;

&spi3 {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";

    spidev: spidev@0 {
        compatible = "somethingmadeuphere";
        reg = <0>;
    };
};

Install device-tree-compiler with sudo apt install device-tree-compiler and run dtc -O dtb -o enable-spi.dtbo -@ enable-spi.dts

Then, copy the resulting enable-spi.dtbo into the directory /boot/dtbo/ (create it if it doesn't exist) and run sudo u-boot-update. Then, reboot so the device tree overlay gets applied.

This only enabled the bus for us with a dummy device that won't bind a driver, not yet the spidev character device. The spidev character device is enabled by binding the spidev driver to our dummy device, which we will do now.

We should now have a /sys/bus/spi/devices/spi3.0/ directory. Open a root shell with sudo -i and run the following to "bind" the spidev driver:

echo spidev > /sys/bus/spi/devices/spi3.0/driver_override
echo spi3.0 > /sys/bus/spi/drivers/spidev/bind

Tada, you should now have a /dev/spidev3.0 device. Do keep in mind that you'll have to do the echo commands on each reboot if you want to use this, so consider running them before any spidev script you've got.

Please note that if the particular SPI device you're trying to interface with already has a kernel driver, you should use that instead, and not some python jank that bashes around spidevs.

Let me know if this works for you.

hughsheehy commented 1 year ago

Working on it!

The echo is working to create the spidev. Stuck now on the chip select.

Gerriko commented 1 year ago

I came across this issue online. Having similar problems.

It is not clear to me from the rk36xx.dtsi file if both chip select pins are activated when you change &spi3 status to "okay".

I thought that if I use the following, it would activate cs1.

/dts-v1/;
/plugin/;

&spi3 {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";

    spidev: spidev@1 {
        compatible = "somethingmadeuphere";
        reg = <1>;
    };
};

If I do that I correctly get the following:

/proc/device-tree/spi@fe640000/status: okay
/proc/device-tree/spi@fe640000/spidev@1/status: okay

But if I then check in this directory (/sys/bus/spi/devices) nothing shows up, where if I use reg=<0> I get something for spi3.0:

lrwxrwxrwx 1 root root 0 Apr 4 15:17 spi3.0 -> ../../../devices/platform/fe640000.spi/spi_master/spi3/spi3.0

For /sys/bus/platform/drivers/rockchip-spi, we get for both cases (attempting 3.1. and 3.0):

lrwxrwxrwx   1 root root    0 Apr  4 14:59 fe640000.spi -> ../../../../devices/platform/fe640000.spi
lrwxrwxrwx   1 root root    0 Apr  4 14:59 module -> ../../../../module/spi_rockchip
Gerriko commented 1 year ago

Problem solved... you need to add this:

cs-gpio = <0>,<0>;

as in:

/dts-v1/;
/plugin/;

&spi3 {
    #address-cells = <1>;
    #size-cells = <0>;
    status = "okay";
        cs-gpio = <0>,<0>;

    spidev: spidev@1 {
        compatible = "somethingmadeuphere";
        reg = <1>;
    };
};

Now can see: lrwxrwxrwx 1 root root 0 Apr 5 16:43 spi3.1 -> ../../../devices/platform/fe640000.spi/spi_master/spi3/spi3.1

Then applying the binding (echo commands) we get - note here I changed overlay to include both cs pins:

pleb@plebian-soquartz-cm4:~$ ls -all /dev/spi*
crw------- 1 root root 153, 0 Apr  5 17:23 /dev/spidev3.0
crw------- 1 root root 153, 1 Apr  5 17:27 /dev/spidev3.1
hughsheehy commented 1 year ago

Just I2C now!

bitmoji

Gerriko commented 1 year ago

@CounterPillow, I have a question for you about creating and then using your own SPI driver. The above only explains how to link SPIDEV.

Creating the overlay is fairly straightforward but then I am stuck on the rest.

E.g.

/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target = <&spi3>;

        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;
            cs-gpio = <0>,<0>;

            eth1: qca7000@0 {
                compatible = "qca, qca7000";
                status = "okay";
                reg=<0>;
                interrupt-parent = <&gpio4>;
                interrupts = <3 0x0001>;
                spi-cpha;
                spi-cpol;
                spi-max-frequency=<8000000>;
            };

            spidev@1 {
                compatible = "spidev";
                status = "okay";
                reg = <1>;
                spi-max-frequency=<8000000>;
            };
        };
    };
};

Now from your above comments I can now "bind" spidev to spi 3 using the echo command and this then shows up in /dev/

However, I do not know how to get my qca7000 showing up in my /dev/ folder as well.

I assume I will first need to create a kernel driver module, but then what.

Any guidance is greatly appreciated.

Thanks

CounterPillow commented 1 year ago

@Gerriko compatible should be compatible = "qca,qca7000";, no space after the vendor prefix. Additionally, your kernel needs to be built with CONFIG_QCA7000 and CONFIG_QCA7000_SPI enabled (either =m or =y). The driver will then be loaded automatically, and it looks like it should show up like a regular networking device.

Gerriko commented 1 year ago

@CounterPillow thanks for feedback. I'm still figuring out the basics, so I could well be heading up the wrong path here, but my aim was to create a network device driver module and then load using something like modprobe (or insmod). However, when trying to install the kernel 6.1x header files to "make" my dummy test device driver, my Pine board with Plebian could not find them (when using apt-get install). So where would I get these?

Otherwise, are you suggesting that it's better to build a kernel with those parameters enabled. If so, which build routine are you using (Armbian?). Anyway, this touches on another unrelated point. If I need to downgrade the kernel to version 4.4, what would be the Plebian build process?

CounterPillow commented 1 year ago

but my aim was to create a network device driver module and then load using something like modprobe (or insmod).

That would be redundant as a driver for this already exists.

Otherwise, are you suggesting that it's better to build a kernel with those parameters enabled. If so, which build routine are you using (Armbian?)

Please do not use anything by Armbian. We can do things properly using mainline sources.

  1. Download whichever version of the kernel source you want, I suggest 6.1.x, ideally to a fast computer and not your board. You can get source tarballs from https://www.kernel.org
  2. Copy your board's /boot/config-versionhere to your kernel tree's .config
  3. If on x86, run make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig. If on your ARM board directly, just run make olddefconfig
  4. Run make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- xconfig (or just make xconfig if on ARM) to launch the graphical config editor, search for QCA7000 and enable the symbol. Save the config to .config. There's some other config editors available too if you prefer working through a terminal interface.
  5. Run make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bindeb-pkg to build the kernel as a .deb. The output will be thrown into your parent directory, make sure you grab the right .deb it outputs (the linux-image one, not the -dbg or headers)
  6. Copy the kernel deb to the board, dpkg -i it, and reboot. You can select which kernel to boot into from the u-boot prompt on serial, but the latest kernel should usually be the first (and thus default) choice I believe

If everything works, file a bug against Debian's kernel package asking them to turn on the option for you. That way you'll no longer have to build your own kernels, and everyone gets to enjoy the support for this hardware turned on.

If I need to downgrade the kernel to version 4.4, what would be the Plebian build process?

4.4 is literally older than this hardware so that won't work.

Gerriko commented 1 year ago

Would something like Buildroot not be easier to with work here... although upon checking I see the SOQuartz is not listed in the Buildroot configs folder - only pine64_defconfig and pine64_sopine_defconfig are available. So maybe not, but thought there is no harm in checking.

Otherwise when I try and use make menuconfig within my downloaded Linux kernel folder, to create my config UI, I am confronted with a stack of options that I am not familiar with. I used the "load" option to load in my board's old config file, but it would still take a good deal of time to check through (as not familiar) to see that it uploaded correctly. There is a good chance something can go wrong here.

Hence, I keep going back to this idea of simply copying the QCA7000 .c & .h source code (as commonly available) and then amending the Makefile to compile the .ko file for me (the part I am struggling with).

But if you say the kernel option is best bet, I will persevere with the kernel config and rebuild process.

Gerriko commented 1 year ago

I decided to at least give it a dry run through.

When following step 3 (with olddefconfig) on my x86 laptop it returned the message using defaults found in arch/arm64/configs/defconfig

So, it seems I have misunderstood step 2, in that I could not figure out where to place the board's /boot/config-version so I had simply copied that file, without renaming, to the downloaded Linux kernel root folder as could not find where "your kernel tree's .config" was.

As I couldn't find any documentation online to give direction, I am now wondering where to place the old config file and whether I need to also rename.

CounterPillow commented 1 year ago

Place your old config file into a file named .config in the root of the Linux kernel source tree.

Gerriko commented 1 year ago

@CounterPillow had a few hiccups along the way with missing packages on laptop (and not enough disk space) but after installing (and cleaning up space) it all worked fine and I now have the qcaspi as a kernel module on the Pine SOQuartz. Thank you for your assistance. It is very much appreciated.

adminy commented 1 year ago

Not too far from SPI, would GPIO pins be working out of the box? Anybody knows the physical pins for Cluster6C?

CounterPillow commented 1 year ago

GPIO is actually far from SPI, but yes they work out of the box. Use libgpiod to address them. You'll just need to translate the RK_P* constants to their respective line numbers if you want to understand how to toggle a specific pin in the schematic

CounterPillow commented 1 year ago

@adminy I wrote some documentation for GPIO here https://plebian.org/running/gpio/

But as I said, this has little to do with SPI.

However I intend to close this issue once I have a similar level of documentation for SPI.

Gerriko commented 1 year ago

Nice clear GPIO documentation, BTW 👍

On Fri 12 May 2023, 06:24 Nicolas F., @.***> wrote:

@adminy https://github.com/adminy I wrote some documentation for GPIO here https://plebian.org/running/gpio/

But as I said, this has little to do with SPI.

However I intend to close this issue once I have a similar level of documentation for SPI.

— Reply to this email directly, view it on GitHub https://github.com/Plebian-Linux/quartz64-images/issues/32#issuecomment-1545186210, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC23YAX3RHI4UYJDOZVSXFTXFXCRJANCNFSM6AAAAAAWQJ67RU . You are receiving this because you were mentioned.Message ID: @.***>