Closed shenghaoyang closed 2 years ago
Is a custom dtoverlay necessary, or will there be a helper dtbo like there is with i2c-gpio?
IE: something like dtoverlay=spi-gpio,mosi=A,miso=B,clk=C
And if there's a helper dtbo, is it possible to load it at runtime with the dtoverlay
command and have a new SPI bus pop up, or is it an on-boot-only deal (I haven't had any success loading i2c-gpio at runtime).
Don't worry if you don't know the answers, I can probably go digging, but I'm just trying to picture how Blinkt! (and other boards using bitbanged SPI for apa102s) might be able to detect and automatically switch between Python bitbanged GPIO and the kernel driver.
Is a custom dtoverlay necessary, or will there be a helper dtbo like there is with i2c-gpio?`
Well, the original pull request by the author over on raspberrypi/linux
included an overlay, but it wasn't configurable and overrode spi0
. In the end, the kernel functionality was enabled but overlay inclusion was skipped pending a better one. Not sure how good it would have been, though, since the software SPI driver can be configured in amazing ways. I had it drive the Blinkt without reserving a MISO pin or a SS pin. Maybe someone will come up with a generic overlay that provides a simple way of allocating those, but I think that would involve a bit of device tree parameter magic.
is it possible to load it at runtime with the dtoverlay command and have a new SPI bus pop up, or is it an on-boot-only deal (I haven't had any success loading i2c-gpio at runtime).
When I wrote the overlay for the blinkt, I had success loading it at runtime using configfs
and dtoverlay
, assuming ArchArm bundled the same dtoverlay
tool. The kernels should be roughly the same, though, so that should work.
I'm just trying to picture how Blinkt! (and other boards using bitbanged SPI for apa102s) might be able to detect and automatically switch between Python bitbanged GPIO and the kernel driver.
udev
rules seem to be perfect for this. The device node in the overlay can be given a unique name, and udev can be used to match on that name and create symlinks under /dev
like blinkt
, deadbeef
, etc, so you could check whether the HAT can be driven using the kernel bitbanged SPI.
Thanks for the super detailed reply. I'm particularly intrigued by the ability to exclude MISO/SS since write-only SPI busses are particularly common for displays/LEDs.
Regarding detection, I'm going to have to brush up on udev and see what I can cobble together! I think this will probably be of utility only to advanced users, but it's something worth investigating.
Thanks for the super detailed reply. I'm particularly intrigued by the ability to exclude MISO/SS since write-only SPI busses are particularly common for displays/LEDs.
No problem. I'd just want to try and see people shift away from using libraries that access GPIO through mapping the GPIO registers into the relevant processes' address space - feels a bit hacky, like you're going around the kernel instead of coexisting with it. Not to mention that this doesn't really play nice with restrictive environments, and could lead to conflicts between different users.
Hopefully people start moving towards using the GPIO character device and also taking advantage of using the kernel to bitbang interfaces (a-la spi-gpio, i2c-gpio). It'll probably make porting easier, too, since a comparable kernel on another device should offer the same interfaces.
I think this will probably be of utility only to advanced users, but it's something worth investigating.
Yeah, that might be true for now, but I think it's a much more stable path forward for these kinds of devices in the future.
Can someone share a blinkt .dts
? Something like this:
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2708";
fragment@0 {
target = <&spi0>;
#address-cells = <1>;
#size-cells = <0>;
__overlay__ {
compatible = "spi-gpio";
#address-cells = <1>;
#size-cells = <0>;
ranges;
mosi-gpios = <&gpio 23 0>;
sck-gpios = <&gpio 24 0>;
cs-gpios = <&gpio 25 1>;
num-chipselects = <1>;
status = "ok";
spidev@1{
compatible = "spidev";
reg = <0>;
spi-max-frequency = <2000000>;
};
};
};
};
This overrides spi0
, and cs-gpios
should be optional if num-chipselects = <0>
, but /dev/spidev0.0
does not show up if these parameters are not set.
Am I on the right track? To be honest, I quite don't know what I'm doing!
I don't have any experience with spi-gpio, but do you see /dev/spidev0
.
/dev/spidev0.0
implies Channel 0, Chip-select 0 and if you have 0 chip-select pins then it would strike me as redundant to specify a chip-select in the device node name since it's not possible to refer to the nth of an empty set.
No, I don't see any /dev/spi*
.
To be more precise:
num-chipselects = <1>;
and a dummy cs-gpios = <&gpio 25 1>;
, I see /dev/spidev0.0
/dev/spidev0
.Thanks for your answer!
Related, I wonder? https://patchwork.kernel.org/patch/11150619/
Yup:
static int spi_gpio_setup(struct spi_device *spi)
{
struct gpio_desc *cs;
int status = 0;
struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
/*
* The CS GPIOs have already been
* initialized from the descriptor lookup.
*/
cs = spi_gpio->cs_gpios[spi->chip_select];
if (!spi->controller_state && cs)
status = gpiod_direction_output(cs,
!(spi->mode & SPI_CS_HIGH));
if (!status)
status = spi_bitbang_setup(spi);
return status;
}
From: https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/spi/spi-gpio.c#L235-L254
https://raw.githubusercontent.com/shenghaoyang/e131_blinkt/master/blinkt-overlay.dts
That's what I had working in arch back in the day, but it seems it won't work so long as the bug in 4.19 remains unfixed.
This patch popped up on lkml. Seems someone wrote a driver for apa102 LEDs that exposes them to userspace as classic LEDs that I presume could be controlled from sysfs?
https://lwn.net/ml/linux-kernel/1582018657-5720-1-git-send-email-nbelin@baylibre.com/
On Thu, Dec 19, 2019, 00:11 Philip Howard notifications@github.com wrote:
Yup:
static int spi_gpio_setup(struct spi_device spi) { struct gpio_desc cs; int status = 0; struct spi_gpio *spi_gpio = spi_to_spi_gpio(spi);
/*
- The CS GPIOs have already been
initialized from the descriptor lookup. */ cs = spi_gpio->cs_gpios[spi->chip_select]; if (!spi->controller_state && cs) status = gpiod_direction_output(cs, !(spi->mode & SPI_CS_HIGH));
if (!status) status = spi_bitbang_setup(spi);
return status; }
From: https://github.com/raspberrypi/linux/blob/rpi-4.19.y/drivers/spi/spi-gpio.c#L235-L254
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/pimoroni/blinkt/issues/65?email_source=notifications&email_token=ACPEEDAQZTYW3NEMF55A7D3QZJDRJA5CNFSM4FERTZ62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHGUETA#issuecomment-567099980, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACPEEDHZ4VZIC6HYBSHNEZDQZJDRJANCNFSM4FERTZ6Q .
This is interesting- we're working on another board that involves apa102 LEDs that this kind of driver would be very well suited for. I wonder how long it will take to make it through the pipeline. Thanks for bringing it to our attention!
Upstream
raspberrypi/linux
recently put in a commit to enabe thespi-gpio
functionality in the kernel (might see the change trickling down soon). This allows the kernel to handle all the SPI bitbanging, and software simply accesses SPI functionality throughspidev
device files. This works over any chosen set of GPIOs, that are not in use by the kernel otherwise.Might it be possible to support this method of control as well? I've tested running the Blinkt! off this functionality on the Arch Linux ARM kernel, that has the module enabled a long time ago. Wrote a C++ application to relay E1.31 data to the Blinkt, but if anyone's interested I could port something to python.
Since the kernel now handles all the timing to achieve a particular data rate, there shouldn't be problems like #62 cropping up, since it knows when it has called into the hardware better than userspace, anyway. Might make the kernel GPIO maintainers happier too, see: https://www.kernel.org/doc/Documentation/gpio/drivers-on-gpio.txt (just a joke, heh.)
All that's needed is a device tree overlay, to specify the pins used to control the blinkt.