Make adis16505 driver work for the rockpi
New kernel has a slightly different API.
We also want to leave the driver probed all the time. So, set
everything up, and disable interrupts until userspace opens the device.
This makes it safe to probe everywhere.
Change-Id: Ia7044b9d9c9a502dc9fd112bd1cf2a62ee375055
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/frc971/rockpi/.config b/frc971/rockpi/.config
index a386534..5fe3348 100644
--- a/frc971/rockpi/.config
+++ b/frc971/rockpi/.config
@@ -538,18 +538,14 @@
# CPU Idle
#
CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_IDLE_GOV_LADDER=y
# CONFIG_CPU_IDLE_GOV_MENU is not set
# CONFIG_CPU_IDLE_GOV_TEO is not set
-CONFIG_DT_IDLE_STATES=y
-CONFIG_DT_IDLE_GENPD=y
#
# ARM CPU Idle Drivers
#
-CONFIG_ARM_PSCI_CPUIDLE=y
-CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y
+# CONFIG_ARM_PSCI_CPUIDLE is not set
# end of ARM CPU Idle Drivers
# end of CPU Idle
@@ -3833,7 +3829,7 @@
# CONFIG_DRM_PANEL_BOE_TV101WUM_NL6 is not set
# CONFIG_DRM_PANEL_DSI_CM is not set
# CONFIG_DRM_PANEL_LVDS is not set
-CONFIG_DRM_PANEL_SIMPLE=m
+# CONFIG_DRM_PANEL_SIMPLE is not set
# CONFIG_DRM_PANEL_EDP is not set
# CONFIG_DRM_PANEL_EBBG_FT8719 is not set
# CONFIG_DRM_PANEL_ELIDA_KD35T133 is not set
@@ -4176,10 +4172,9 @@
CONFIG_USB_DEFAULT_PERSIST=y
# CONFIG_USB_FEW_INIT_RETRIES is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
-CONFIG_USB_OTG=y
+# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_PRODUCTLIST is not set
# CONFIG_USB_OTG_DISABLE_EXTERNAL_HUB is not set
-# CONFIG_USB_OTG_FSM is not set
# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set
CONFIG_USB_AUTOSUSPEND_DELAY=2
# CONFIG_USB_MON is not set
diff --git a/frc971/rockpi/build_kernel.sh b/frc971/rockpi/build_kernel.sh
index 73c0a51..9bdd9a0 100755
--- a/frc971/rockpi/build_kernel.sh
+++ b/frc971/rockpi/build_kernel.sh
@@ -39,4 +39,13 @@
VERSION="$(cat linux/include/config/kernel.release)"
+(
+ cd ../../y2022/localizer/kernel/
+ make rockpi
+)
+
+cp ../../y2022/localizer/kernel/adis16505.ko "kernel-install/lib/modules/${VERSION}/kernel/"
+
+depmod -b ./kernel-install ${VERSION}
+
tar -cvf "linux-kernel-${VERSION}.tar.xz" -C kernel-install .
diff --git a/frc971/rockpi/build_rootfs.sh b/frc971/rockpi/build_rootfs.sh
index a1d0a0a..e5706fc 100755
--- a/frc971/rockpi/build_rootfs.sh
+++ b/frc971/rockpi/build_rootfs.sh
@@ -154,8 +154,9 @@
target "apt-get update"
target "apt-get -y install -t bullseye-backports systemd"
+target "apt-get -y install -t bullseye-backports bpfcc-tools"
-target "apt-get install -y sudo openssh-server python3 bash-completion git v4l-utils cpufrequtils pmount rsync vim-nox chrony libopencv-calib3d4.5 libopencv-contrib4.5 libopencv-core4.5 libopencv-features2d4.5 libopencv-flann4.5 libopencv-highgui4.5 libopencv-imgcodecs4.5 libopencv-imgproc4.5 libopencv-ml4.5 libopencv-objdetect4.5 libopencv-photo4.5 libopencv-shape4.5 libopencv-stitching4.5 libopencv-superres4.5 libopencv-video4.5 libopencv-videoio4.5 libopencv-videostab4.5 libopencv-viz4.5 libnice10 pmount libnice-dev feh libgstreamer1.0-0 libgstreamer-plugins-base1.0-0 libgstreamer-plugins-bad1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-nice usbutils locales"
+target "apt-get install -y sudo openssh-server python3 bash-completion git v4l-utils cpufrequtils pmount rsync vim-nox chrony libopencv-calib3d4.5 libopencv-contrib4.5 libopencv-core4.5 libopencv-features2d4.5 libopencv-flann4.5 libopencv-highgui4.5 libopencv-imgcodecs4.5 libopencv-imgproc4.5 libopencv-ml4.5 libopencv-objdetect4.5 libopencv-photo4.5 libopencv-shape4.5 libopencv-stitching4.5 libopencv-superres4.5 libopencv-video4.5 libopencv-videoio4.5 libopencv-videostab4.5 libopencv-viz4.5 libnice10 pmount libnice-dev feh libgstreamer1.0-0 libgstreamer-plugins-base1.0-0 libgstreamer-plugins-bad1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-nice usbutils locales trace-cmd"
target "usermod -a -G sudo pi"
target "usermod -a -G video pi"
@@ -175,11 +176,14 @@
copyfile root.root 644 etc/systemd/system/grow-rootfs.service
copyfile root.root 644 etc/sysctl.d/sctp.conf
copyfile root.root 644 etc/systemd/logind.conf
+copyfile root.root 555 etc/bash_completion.d/aos_dump_autocomplete
+copyfile root.root 444 etc/modules-load.d/adis16505.conf
copyfile root.root 644 etc/security/limits.d/rt.conf
copyfile root.root 644 etc/systemd/system/frc971.service
copyfile root.root 644 etc/systemd/system/frc971chrt.service
copyfile root.root 644 etc/systemd/system/usb-mount@.service
copyfile root.root 644 etc/udev/rules.d/99-usb-mount.rules
+copyfile root.root 644 etc/udev/rules.d/99-adis16505.rules
target "apt-get update"
target "apt-get -y install -t bullseye-backports systemd"
diff --git a/frc971/rockpi/contents/etc/bash_completion.d/aos_dump_autocomplete b/frc971/rockpi/contents/etc/bash_completion.d/aos_dump_autocomplete
new file mode 100644
index 0000000..1b82c46
--- /dev/null
+++ b/frc971/rockpi/contents/etc/bash_completion.d/aos_dump_autocomplete
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+if [[ -e "/home/pi/bin/aos_dump_autocomplete.sh" ]]; then
+ . /home/pi/bin/aos_dump_autocomplete.sh
+fi
diff --git a/frc971/rockpi/contents/etc/modules-load.d/adis16505.conf b/frc971/rockpi/contents/etc/modules-load.d/adis16505.conf
new file mode 100644
index 0000000..0e7b16b
--- /dev/null
+++ b/frc971/rockpi/contents/etc/modules-load.d/adis16505.conf
@@ -0,0 +1 @@
+adis16505
diff --git a/frc971/rockpi/contents/etc/udev/rules.d/99-adis16505.rules b/frc971/rockpi/contents/etc/udev/rules.d/99-adis16505.rules
new file mode 100644
index 0000000..02f591e
--- /dev/null
+++ b/frc971/rockpi/contents/etc/udev/rules.d/99-adis16505.rules
@@ -0,0 +1 @@
+ACTION=="add",KERNEL=="adis16505",MODE="0666"
diff --git a/y2022/localizer/kernel/Makefile b/y2022/localizer/kernel/Makefile
index ad4b9b0..184f8a3 100644
--- a/y2022/localizer/kernel/Makefile
+++ b/y2022/localizer/kernel/Makefile
@@ -2,6 +2,9 @@
PWD := $(CURDIR)
+rockpi:
+ ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -C ../../../frc971/rockpi/linux M=$(PWD) modules
+
all:
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -C ../../../../linux M=$(PWD) modules
diff --git a/y2022/localizer/kernel/adis16505.c b/y2022/localizer/kernel/adis16505.c
index a91006e..963ca4a 100644
--- a/y2022/localizer/kernel/adis16505.c
+++ b/y2022/localizer/kernel/adis16505.c
@@ -49,7 +49,7 @@
char tx_buff[128];
char rx_buff[128];
- int count;
+ atomic_t count;
spinlock_t lock;
@@ -62,21 +62,18 @@
static int adis16505_dev_open(struct inode *in, struct file *f) {
struct adis16505_state *ts =
container_of(in->i_cdev, struct adis16505_state, handle_cdev);
- int count;
+ int count = 0;
f->private_data = ts;
+ count = atomic_cmpxchg(&ts->count, 0, 1);
- spin_lock(&ts->lock);
- count = ts->count;
- if (count == 0) {
- ++(ts->count);
- }
- spin_unlock(&ts->lock);
-
- printk("open %p, count %d\n", ts, count);
if (count > 0) {
return -EBUSY;
}
+
+ // Enable the IRQ after we've declared the device open.
+ enable_irq(ts->spi->irq);
+
return 0;
}
@@ -84,10 +81,13 @@
struct adis16505_state *ts;
ts = container_of(in->i_cdev, struct adis16505_state, handle_cdev);
- printk("release %p\n", ts);
- spin_lock(&ts->lock);
- --(ts->count);
- spin_unlock(&ts->lock);
+ // Disable before declaring ourselves closed so we don't fire the IRQ when we
+ // are disabled, or let someone else open it up again before we disable it.
+ disable_irq(ts->spi->irq);
+
+ if (atomic_cmpxchg(&ts->count, 1, 0) != 1) {
+ BUG_ON(true);
+ }
return 0;
}
@@ -230,7 +230,7 @@
spin_lock_init(&ts->lock);
spin_lock_init(&ts->fifo_read_lock);
- ts->count = 0;
+ atomic_set(&ts->count, 0);
INIT_KFIFO(ts->fifo);
init_waitqueue_head(&ts->wq);
@@ -241,11 +241,20 @@
err = request_threaded_irq(spi->irq, NULL, adis16505_irq, IRQF_ONESHOT,
spi->dev.driver->name, ts);
- if (!ts) {
+ if (err < 0) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
goto err_free_mem;
}
+ // Immediately disable the IRQ. Opening the device will enable it, so this
+ // lets us leave the driver probed all the time and only use it when userspace
+ // asks.
+ //
+ // Note: the IRQ will fire probably once before we get it disabled... It
+ // might initiate a transfer from a device which isn't connected, which should
+ // just return 0 for everything. This isn't actually a huge concern.
+ disable_irq(spi->irq);
+
err = alloc_chrdev_region(&ts->character_device, 0, 1, "adis16505");
if (err < 0) {
dev_dbg(&spi->dev, "alloc_chrdev_region error %i", err);
@@ -295,7 +304,7 @@
return err;
}
-static int adis16505_remove(struct spi_device *spi) {
+static void adis16505_remove(struct spi_device *spi) {
struct adis16505_state *ts = spi_get_drvdata(spi);
device_destroy(ts->device_class, ts->character_device);
@@ -309,7 +318,6 @@
kfree(ts);
dev_dbg(&spi->dev, "unregistered adis16505\n");
- return 0;
}
static struct spi_driver adis16505_driver = {