Skip to content
Snippets Groups Projects
Commit 8d629bb3 authored by David Bauer's avatar David Bauer
Browse files

ramips-mt7621: backport Genexis Pulse EX400 to OpenWrt 23.05


Implement support for the Genexis EX400 on OpenWrt 23.05.

Don't pick specific commits, as support was initially introduced for a
finish OEM version we are not interested in.

Signed-off-by: default avatarDavid Bauer <mail@david-bauer.net>
parent 285e1814
No related branches found
No related tags found
No related merge requests found
From: David Bauer <mail@david-bauer.net>
Date: Mon, 12 May 2025 19:15:55 +0200
Subject: ramips-mt7621: add support for Genexis Pulse EX400
diff --git a/package/boot/uboot-envtools/files/ramips b/package/boot/uboot-envtools/files/ramips
index dac61be02e4b3231a391fdc76ba4c73156572f6a..110e24c978cd8fe428433297ca123749120c56dc 100644
--- a/package/boot/uboot-envtools/files/ramips
+++ b/package/boot/uboot-envtools/files/ramips
@@ -141,6 +141,10 @@ xiaomi,mi-router-cr6608|\
xiaomi,mi-router-cr6609)
ubootenv_add_uci_config "/dev/mtd1" "0x0" "0x10000" "0x20000"
;;
+genexis,pulse-ex400)
+ ubootenv_add_uci_config "/dev/ubi0_0" "0x0" "0x1f000" "0x1f000" "1"
+ ubootenv_add_uci_config "/dev/ubi0_1" "0x0" "0x1f000" "0x1f000" "1"
+ ;;
esac
config_load ubootenv
diff --git a/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts
new file mode 100644
index 0000000000000000000000000000000000000000..a566e356d103a65dca3d53fa40bc2cd0d920444c
--- /dev/null
+++ b/target/linux/ramips/dts/mt7621_genexis_pulse-ex400.dts
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include "mt7621.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+
+/ {
+ compatible = "genexis,pulse-ex400", "mediatek,mt7621-soc";
+ model = "Genexis Pulse EX400";
+
+ aliases {
+ led-boot = &led_status_red;
+ led-failsafe = &led_status_red;
+ led-running = &led_status_green;
+ led-upgrade = &led_status_red;
+
+ ethernet0 = &gmac0;
+ label-mac-device = &gmac0;
+ };
+
+ chosen {
+ bootargs-override = "console=ttyS0,115200 rootfstype=squashfs,jffs2";
+ };
+
+ keys {
+ compatible = "gpio-keys";
+
+ reset {
+ label = "reset";
+ gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_RESTART>;
+ };
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+
+ led_status_green: led-0 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
+ };
+
+ led_status_red: led-1 {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&gpio 11 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ i2c_gpio: i2c-gpio {
+ compatible = "i2c-gpio";
+
+ sda-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
+ scl-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>;
+
+ i2c-gpio,delay-us = <50>;
+ i2c-gpio,timeout-ms = <100>;
+
+ /* Semtech SX9512 */
+ };
+};
+
+&leds {
+ led_wps_green: led-2 {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WPS;
+ gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&i2c_gpio {
+ touch@2b {
+ compatible = "semtech,sx9512";
+
+ reg = <0x2b>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ poll-interval = <150>;
+
+ /* Touch area 2.4 GHz */
+ channel@1 {
+ reg = <1>;
+
+ semtech,cin-delta = <0x3>;
+ semtech,sense-threshold = <0x04>;
+
+ linux,keycodes = <KEY_A>;
+ };
+
+ /* Touch area 5 GHz */
+ channel@2 {
+ reg = <2>;
+
+ semtech,cin-delta = <0x3>;
+ semtech,sense-threshold = <0x04>;
+
+ linux,keycodes = <KEY_B>;
+ };
+ /* Touch area WPS */
+ channel@3 {
+ reg = <3>;
+
+ semtech,cin-delta = <0x3>;
+ semtech,sense-threshold = <0x04>;
+
+ linux,keycodes = <KEY_WPS_BUTTON>;
+ };
+
+ channel@4 {
+ reg = <4>;
+
+ led {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_WAN;
+ };
+ };
+
+ channel@5 {
+ reg = <5>;
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WAN;
+ };
+ };
+
+ channel@6 {
+ reg = <6>;
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WLAN_5GHZ;
+ linux,default-trigger = "phy1tpt";
+ };
+ };
+
+ channel@7 {
+ reg = <7>;
+
+ led {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_WLAN_2GHZ;
+ linux,default-trigger = "phy0tpt";
+ };
+ };
+ };
+};
+
+&pcie {
+ status = "okay";
+};
+
+&nand {
+ status = "okay";
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ reg = <0x00 0x100000>;
+ label = "uboot";
+ read-only;
+ };
+
+ partition@100000 {
+ reg = <0x100000 0xff00000>;
+ label = "ubi";
+ };
+ };
+};
+
+&mdio {
+ ethphy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+};
+
+&gmac1 {
+ label = "wan";
+ phy-handle = <&ethphy0>;
+ status = "okay";
+};
+
+&i2c {
+ /* Uses i2c-gpio */
+ status = "disabled";
+};
+
+&ethphy0 {
+ /delete-property/ interrupts;
+};
+
+&state_default {
+ gpio {
+ groups = "i2c", "uart2", "uart3";
+ function = "gpio";
+ };
+};
+
+&switch0 {
+ ports {
+ port@1 {
+ label = "lan";
+ status = "okay";
+ };
+ };
+};
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
index 0b1d1b6dfc0c60d0aaed4818f3646059805409f3..b98989c1fcb2b31bebf49fe00939371268470494 100644
--- a/target/linux/ramips/image/mt7621.mk
+++ b/target/linux/ramips/image/mt7621.mk
@@ -45,6 +45,19 @@ define Build/arcadyan-trx
rm $@.hsqs $@.tail
endef
+define Build/inteno-bootfs
+ mkdir -p $@.ubifs-dir/boot
+
+ # populate the boot fs with the dtb and the kernel image
+ $(CP) $(KDIR)/image-$(firstword $(DEVICE_DTS)).dtb $@.ubifs-dir/boot/dtb
+ $(CP) $@ $@.ubifs-dir/boot/uImage
+
+ # create ubifs
+ $(STAGING_DIR_HOST)/bin/mkfs.ubifs ${MKUBIFS_OPTS} -r $@.ubifs-dir/ -o $@.new
+ rm -rf $@.ubifs-dir
+ mv $@.new $@
+endef
+
define Build/gemtek-trailer
printf "%s%08X" ".GEMTEK." "$$(cksum $@ | cut -d ' ' -f1)" >> $@
endef
@@ -1091,6 +1104,30 @@ define Device/gehua_ghl-r-001
endef
TARGET_DEVICES += gehua_ghl-r-001
+# Common definitions shared between genexis_pulse-ex400 and dna_valokuitu-plus-ex400
+define Device/genexis_pulse-ex400/common
+ $(Device/dsa-migration)
+ IMAGE_SIZE := 117m
+ PAGESIZE := 2048
+ MKUBIFS_OPTS := --min-io-size=$$(PAGESIZE) --leb-size=124KiB --max-leb-cnt=96 \
+ --log-lebs=2 --space-fixup --squash-uids
+ KERNEL := kernel-bin | lzma | uImage lzma
+ KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | uImage lzma
+ IMAGE/sysupgrade.bin := append-kernel | inteno-bootfs | \
+ sysupgrade-tar kernel=$$$$@ | check-size | append-metadata
+ DEVICE_IMG_NAME = $$(DEVICE_IMG_PREFIX)-$$(2)
+ DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 kmod-keyboard-sx951x kmod-button-hotplug
+endef
+
+define Device/genexis_pulse-ex400
+ $(Device/genexis_pulse-ex400/common)
+ DEVICE_VENDOR := Genexis
+ DEVICE_MODEL := Pulse EX400
+ DEVICE_ALT0_VENDOR := Inteno
+ DEVICE_ALT0_MODEL := Pulse EX400
+endef
+TARGET_DEVICES += genexis_pulse-ex400
+
define Device/glinet_gl-mt1300
$(Device/dsa-migration)
IMAGE_SIZE := 32448k
diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds
index a903969965b3bd8a05de8074e1742fa0377415a2..e8ac29af328d07f6db5e54f482b6c91153e77fac 100644
--- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds
+++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds
@@ -183,6 +183,7 @@ netgear,r7450)
netgear,wax202)
ucidef_set_led_netdev "internet" "Internet" "green:net" "wan"
;;
+genexis,pulse-ex400|\
netis,n6)
ucidef_set_led_netdev "wan" "wan" "green:wan" "wan" "link tx rx"
;;
diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
index 71e6f9386205f238147c04b442eb09ccee7df70b..ef04afcfa2c173df59f7ff8a7e2d0af4bcab00b5 100644
--- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
+++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network
@@ -92,6 +92,7 @@ ramips_setup_interfaces()
uci add_list firewall.@zone[1].network='eth_om'
;;
cudy,m1800|\
+ genexis,pulse-ex400|\
yuncore,ax820|\
zyxel,nr7101)
ucidef_set_interfaces_lan_wan "lan" "wan"
diff --git a/target/linux/ramips/mt7621/base-files/etc/init.d/bootcount b/target/linux/ramips/mt7621/base-files/etc/init.d/bootcount
index 9db700bff5560bde52bb88f02d97a0199b4bb787..4110a35528610712f7783902c222b5905f18668a 100755
--- a/target/linux/ramips/mt7621/base-files/etc/init.d/bootcount
+++ b/target/linux/ramips/mt7621/base-files/etc/init.d/bootcount
@@ -29,6 +29,10 @@ boot() {
samknows,whitebox-v8)
fw_setenv bootcount 0
;;
+ genexis,pulse-ex400)
+ fw_setenv boot_cnt_primary 0
+ fw_setenv boot_cnt_alt 0
+ ;;
zyxel,lte3301-plus)
[ $(printf %d $(fw_printenv -n DebugFlag)) -gt 0 ] || fw_setenv DebugFlag 1
[ $(printf %d $(fw_printenv -n Image1Stable)) -gt 0 ] || fw_setenv Image1Stable 1
diff --git a/target/linux/ramips/mt7621/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/ramips/mt7621/base-files/lib/preinit/10_fix_eth_mac.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a688deea0bfa56a45178f4cdee76d0a18ee0fce0
--- /dev/null
+++ b/target/linux/ramips/mt7621/base-files/lib/preinit/10_fix_eth_mac.sh
@@ -0,0 +1,14 @@
+. /lib/functions/system.sh
+
+preinit_set_mac_address() {
+ case $(board_name) in
+ genexis,pulse-ex400)
+ ethaddr=$(get_mac_ascii /dev/ubi0_0 ethaddr)
+ ip link set dev wan address $(macaddr_add $ethaddr 1)
+ ip link set dev eth0 address $ethaddr
+ ip link set dev lan address $ethaddr
+ ;;
+ esac
+}
+
+boot_hook_add preinit_main preinit_set_mac_address
diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/inteno.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/inteno.sh
new file mode 100644
index 0000000000000000000000000000000000000000..677000f6b1aef7223e98aeb9ec000281af0722ed
--- /dev/null
+++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/inteno.sh
@@ -0,0 +1,49 @@
+#
+# Copyright (C) 2023 Mauri Sandberg
+#
+
+# The vendor UBI is split in volumes 0-3. Volumes 0 and 1 contain U-Boot
+# environments env1 and env2, respectively. The vendor root file systems
+# are in volumes 2 (rootfs_0) and 3 (rootfs_1). Drop the two roots and
+# explicitly use rootfs_0 as a boot partition that contains the dtb and the
+# OpenWrt kernel. This is because the vendor U-Boot expects to find them there.
+# Then continue upgrade with the default method - a SquashFS rootfs will be
+# installed and the rest of UBI will be used as an overlay.
+
+# The 'kernel' inside the sysupgrage.tar is an UBIFS image that contains
+# /boot/dtb and /boot/kernel. The 'root' is an OpenWrt SquashFS root
+
+. /lib/functions.sh
+. /lib/upgrade/nand.sh
+
+inteno_do_upgrade () {
+ local tar_file=$1
+ local cmd=cat
+ # WARNING: This fails if tar contains more than one 'sysupgrade-*' directory.
+ local board_dir="$(tar tf "$tar_file" | grep -m 1 '^sysupgrade-.*/$')"
+ board_dir="${board_dir%/}"
+ tar -xaf "$tar_file"
+
+ # get the size of the new bootfs
+ local _bootfs_size=$(wc -c < "$board_dir/kernel")
+ [ -n "$_bootfs_size" -a "$_bootfs_size" -gt "0" ] || nand_do_upgrade_failed
+
+ # remove existing rootfses and recreate rootfs_0
+ ubirmvol /dev/ubi0 --name=rootfs_0 > /dev/null 2>&1
+ ubirmvol /dev/ubi0 --name=rootfs_1 > /dev/null 2>&1
+ ubirmvol /dev/ubi0 --name=rootfs > /dev/null 2>&1
+ ubirmvol /dev/ubi0 --name=rootfs_data > /dev/null 2>&1
+ ubimkvol /dev/ubi0 --type=static --size=${_bootfs_size} --name=rootfs_0
+
+ # update the rootfs_0 contents
+ local _kern_ubivol=$( nand_find_volume "ubi0" "rootfs_0" )
+ ubiupdatevol "/dev/$_kern_ubivol" "$board_dir/kernel"
+
+ fw_setenv root_vol rootfs_0
+ fw_setenv boot_cnt_primary 0
+ fw_setenv boot_cnt_alt 0
+
+ # proceed to upgrade the default way
+ CI_KERNPART=none
+ nand_do_upgrade "$1"
+}
diff --git a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
index 60dba1bdec540ac5173d53d6c9c3cb6ef5907bd1..027cfd711ceb805e6ec8539810e17b2f9ccd5fe2 100755
--- a/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ramips/mt7621/base-files/lib/upgrade/platform.sh
@@ -125,6 +125,9 @@ platform_do_upgrade() {
zyxel,nwa55axe)
nand_do_upgrade "$1"
;;
+ genexis,pulse-ex400)
+ inteno_do_upgrade "$1"
+ ;;
iodata,wn-ax1167gr2|\
iodata,wn-ax2033gr|\
iodata,wn-dx1167r|\
From: David Bauer <mail@david-bauer.net>
Date: Sun, 4 May 2025 04:47:32 +0200
Subject: ramips: add Semtech SX9512 touch input driver
This driver is required for the touch-inputs as well as some LEDs on the
Genexis Pulse EX400.
The driver was also sent upstream. As the EX400 is currently the only
consumer, the driver is added target-specific for ramips.
Once the driver has been accepted upstream and is provided in a kernel
release used by OpenWrt, the package should be moved to the global input
drivers.
Link: https://www.spinics.net/lists/kernel/msg5669349.html
Signed-off-by: David Bauer <mail@david-bauer.net>
(cherry picked from commit 0842e793381a1e60f8acdcbea0e8c59be1ac9a88)
diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk
index 6f199c46a225c99c2a7f931f6e90a08af246aa80..d7e01583172ff00de40ec0d8d5c3267d0bc8d926 100644
--- a/target/linux/ramips/modules.mk
+++ b/target/linux/ramips/modules.mk
@@ -133,3 +133,21 @@ define KernelPackage/sound-mt7620/description
endef
$(eval $(call KernelPackage,sound-mt7620))
+
+
+define KernelPackage/keyboard-sx951x
+ SUBMENU:=Other modules
+ TITLE:=Semtech SX9512/SX9513
+ DEPENDS:=@TARGET_ramips_mt7621 +kmod-input-core
+ KCONFIG:= \
+ CONFIG_KEYBOARD_SX951X \
+ CONFIG_INPUT_KEYBOARD=y
+ FILES:=$(LINUX_DIR)/drivers/input/keyboard/sx951x.ko
+ AUTOLOAD:=$(call AutoProbe,sx951x)
+endef
+
+define KernelPackage/keyboard-sx951x/description
+ Enable support for SX9512/SX9513 capacitive touch controllers
+endef
+
+$(eval $(call KernelPackage,keyboard-sx951x))
diff --git a/target/linux/ramips/patches-5.15/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch b/target/linux/ramips/patches-5.15/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch
new file mode 100644
index 0000000000000000000000000000000000000000..340fb3c342697ec142bdd642f719e0258942cbeb
--- /dev/null
+++ b/target/linux/ramips/patches-5.15/870-Input-sx951x-add-Semtech-SX9512-SX9513-driver.patch
@@ -0,0 +1,560 @@
+From ba92c0187006e2a6eae9573a569d275b0bd31732 Mon Sep 17 00:00:00 2001
+From: David Bauer <mail@david-bauer.net>
+Date: Fri, 2 May 2025 23:04:27 +0200
+Subject: [PATCH] Input sx951x: add Semtech SX9512/SX9513 driver
+
+The Semtech SX9512/SX9513 is a family of capacitive touch-keyboard
+controllers.
+
+All chips offer 8 channel touch sensitive inputs with one LED driver per
+output channel.
+
+The also SX9512 supports proximity detection which is currently not
+supported with the driver.
+
+This chip can be found on the Genexis Pulse EX400 repeater platform.
+
+Link: https://www.mouser.com/datasheet/2/761/SEMTS05226_1-2575172.pdf
+Link: https://www.spinics.net/lists/kernel/msg5669349.html
+
+Signed-off-by: David Bauer <mail@david-bauer.net>
+---
+ drivers/input/keyboard/Kconfig | 11 +
+ drivers/input/keyboard/Makefile | 1 +
+ drivers/input/keyboard/sx951x.c | 490 ++++++++++++++++++++++++++++++++
+ 3 files changed, 502 insertions(+)
+ create mode 100644 drivers/input/keyboard/sx951x.c
+
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 1d0c5f4c0f99..6dc397389c64 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -616,6 +616,17 @@ config KEYBOARD_SUNKBD
+ To compile this driver as a module, choose M here: the
+ module will be called sunkbd.
+
++config KEYBOARD_SX951X
++ tristate "Semtech SX951X capacitive touch controller"
++ depends on OF && I2C
++ select REGMAP_I2C
++ help
++ Say Y here to enable the Semtech SX9512/SX9153 capacitive
++ touch controller driver.
++
++ To compile this driver as a module, choose M here: the
++ module will be called sx951x.
++
+ config KEYBOARD_SH_KEYSC
+ tristate "SuperH KEYSC keypad support"
+ depends on ARCH_SHMOBILE || COMPILE_TEST
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index aecef00c5d09..e59ca83c30ec 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -66,6 +66,7 @@ obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
+ obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o
+ obj-$(CONFIG_KEYBOARD_SUN4I_LRADC) += sun4i-lradc-keys.o
+ obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
++obj-$(CONFIG_KEYBOARD_SX951X) += sx951x.o
+ obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o
+ obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
+ obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY) += tm2-touchkey.o
+diff --git a/drivers/input/keyboard/sx951x.c b/drivers/input/keyboard/sx951x.c
+new file mode 100644
+index 000000000000..66355036aa95
+--- /dev/null
++++ b/drivers/input/keyboard/sx951x.c
+@@ -0,0 +1,490 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Input driver for Semtech SX9512/SX9513 capacitive touch sensors.
++ *
++ * The difference between SX9512 and SX9513 is the presence of proximity
++ * sensing capabilities on the SX9512.
++ *
++ * SX951xB is the identical chip but with a different I2C address.
++ *
++ * (c) 2025 David Bauer <mail@david-bauer.net>
++ */
++
++ #include <linux/kernel.h>
++ #include <linux/module.h>
++ #include <linux/input.h>
++ #include <linux/leds.h>
++ #include <linux/of.h>
++ #include <linux/regmap.h>
++ #include <linux/i2c.h>
++ #include <linux/gpio/consumer.h>
++ #include <linux/bitfield.h>
++
++ /* Generic properties */
++#define SX951X_I2C_ADDRESS 0x2b
++#define SX951XB_I2C_ADDRESS_ 0x2d
++#define SX951X_NUM_CHANNELS 8
++#define SX951X_POLL_INTERVAL 100
++
++/* Registers*/
++#define SX951X_REG_IRQ_SRC 0x00
++#define SX951X_REG_TOUCH_STATUS 0x01
++#define SX951X_REG_PROXIMITY_STATUS 0x02
++#define SX951X_REG_COMPENSATION_STATUS 0x03
++#define SX951X_REG_IRQ_NVM_CTRL 0x04
++#define SX951X_REG_SPO2_MODE_CTRL 0x07
++#define SX951X_REG_PWR_KEY_CTRL 0x08
++#define SX951X_REG_IRQ_MASK 0x09
++
++/* LED registers */
++#define SX951X_REG_LED_MAP_ENG1 0x0c
++#define SX951X_REG_LED_MAP_ENG2 0x0d
++#define SX951X_REG_LED_PWM_FREQ 0x0e
++#define SX951X_REG_LED_MODE 0x0f
++#define SX951X_REG_LED_IDLE 0x10
++#define SX951X_REG_LED_OFF_DELAY 0x11
++#define SX951X_REG_LED_ON_ENG1 0x12
++#define SX951X_REG_LED_FADE_ENG1 0x13
++#define SX951X_REG_LED_ON_ENG2 0x14
++#define SX951X_REG_LED_FADE_ENG2 0x15
++#define SX951X_REG_LED_POWER_IDLE 0x16
++#define SX951X_REG_LED_POWER_ON 0x17
++#define SX951X_REG_LED_POWER_OFF 0x18
++#define SX951X_REG_LED_POWER_FADE 0x19
++#define SX951X_REG_LED_POWER_ON_PULSE 0x1a
++#define SX951X_REG_LED_POWER_MODE 0x1b
++
++/* Capacitive touch sensing registers*/
++#define SX951X_REG_CAP_SENSE_ENABLE 0x1e
++
++#define SX951X_REG_CAP_SENSE_RANGE(x) (0x1f + (x))
++#define SX951X_REG_CAP_SENSE_RANGE_CIN_DELTA_MASK GENMASK(1, 0)
++
++#define SX951X_REG_CAP_SENSE_THRESH(x) (0x28 + (x))
++#define SX951X_REG_CAP_SENSE_THRESH_ALL 0x30
++
++#define SX951X_REG_CAP_SENSE_OP 0x31
++#define SX951X_REG_CAP_SENSE_MODE 0x32
++#define SX951X_REG_CAP_SENSE_DEBOUNCE 0x33
++
++/* Reset register*/
++#define SX951X_REG_SOFT_RESET 0xff
++
++/* Default properties (keys)*/
++#define SX951X_KEY_DEFAULT_CIN_DELTA 0x03
++#define SX951X_KEY_DEFAULT_SENSE_THRESHOLD 0x04
++
++struct sx951x_key_data {
++ u32 cin_delta;
++ u32 sense_threshold;
++};
++
++struct sx951x_led {
++#ifdef CONFIG_LEDS_CLASS
++ struct led_classdev cdev;
++ struct sx951x_priv *priv;
++
++ u32 reg;
++ bool registered;
++#endif
++};
++
++struct sx951x_priv {
++ struct regmap *regmap;
++ struct device *dev;
++ struct input_dev *idev;
++ const struct sx951x_hw_data *hw;
++
++ struct sx951x_led leds[SX951X_NUM_CHANNELS];
++
++ /* device-config */
++ u32 poll_interval;
++
++ /* key-config */
++ u32 keycodes[SX951X_NUM_CHANNELS];
++ struct sx951x_key_data key_data[SX951X_NUM_CHANNELS];
++};
++
++struct sx951x_hw_data {
++ bool has_proximity_sensing;
++};
++
++static const struct reg_default sx951x_reg_defaults[] = {
++ { SX951X_REG_LED_MAP_ENG1, 0x00 },
++ { SX951X_REG_LED_MAP_ENG2, 0x00 },
++ { SX951X_REG_LED_PWM_FREQ, 0x10 },
++ { SX951X_REG_LED_IDLE, 0xff },
++ { SX951X_REG_LED_ON_ENG1, 0xff },
++ { SX951X_REG_LED_ON_ENG2, 0xff },
++ { SX951X_REG_LED_POWER_IDLE, 0xff },
++ { SX951X_REG_LED_POWER_ON, 0xff },
++ { SX951X_REG_CAP_SENSE_ENABLE, 0x00 },
++ { SX951X_REG_CAP_SENSE_RANGE(0), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(1), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(2), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(3), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(4), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(5), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(6), 0x40 },
++ { SX951X_REG_CAP_SENSE_RANGE(7), 0x40 },
++ { SX951X_REG_CAP_SENSE_THRESH(0), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(1), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(2), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(3), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(4), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(5), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(6), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH(7), 0x0f },
++ { SX951X_REG_CAP_SENSE_THRESH_ALL, 0x0f },
++ { SX951X_REG_CAP_SENSE_OP, 0x14 },
++ { SX951X_REG_CAP_SENSE_MODE, 0x70 },
++ { SX951X_REG_CAP_SENSE_DEBOUNCE, 0xff },
++};
++
++static bool sx951x_volatile_reg(struct device *dev, unsigned int reg)
++{
++ switch (reg) {
++ case SX951X_REG_TOUCH_STATUS:
++ return true;
++ default:
++ return false;
++ }
++}
++
++static const struct regmap_config sx951x_regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 8,
++
++ .max_register = SX951X_REG_SOFT_RESET,
++
++ .reg_defaults = sx951x_reg_defaults,
++ .num_reg_defaults = ARRAY_SIZE(sx951x_reg_defaults),
++
++ .cache_type = REGCACHE_MAPLE,
++ .volatile_reg = sx951x_volatile_reg,
++};
++
++#ifdef CONFIG_LEDS_CLASS
++static int sx951x_led_set(struct led_classdev *cdev, enum led_brightness value)
++{
++ struct sx951x_led *led = container_of(cdev, struct sx951x_led, cdev);
++ struct sx951x_priv *priv = led->priv;
++
++ return regmap_update_bits(priv->regmap,
++ SX951X_REG_LED_MAP_ENG2,
++ BIT(led->reg),
++ value ? BIT(led->reg) : 0);
++}
++
++static int sx951x_led_init(struct sx951x_priv *priv,
++ struct device_node *channel_node, u32 reg)
++{
++ struct device_node *led_node;
++ struct sx951x_led *led = &priv->leds[reg];
++ struct led_init_data init_data = {};
++ int error;
++
++ if (led->registered) {
++ dev_err(priv->dev,
++ "LED %d already registered\n", reg);
++ return -EINVAL;
++ }
++
++ led_node = of_get_child_by_name(channel_node, "led");
++ if (!led_node) {
++ /* No LED */
++ return 0;
++ }
++
++ led->cdev.flags = 0;
++ led->cdev.brightness_set_blocking = sx951x_led_set;
++ led->cdev.max_brightness = 1;
++ led->cdev.brightness = LED_OFF;
++
++ init_data.default_label = of_get_property(led_node, "label", NULL);
++ init_data.fwnode = of_fwnode_handle(led_node);
++
++ led->reg = reg;
++ led->priv = priv;
++
++ error = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
++ if (error)
++ return error;
++
++ return 0;
++}
++#endif
++
++static void sx951x_poll(struct input_dev *input)
++{
++ struct sx951x_priv *priv = input_get_drvdata(input);
++ struct device *dev = priv->dev;
++ unsigned int val;
++ int error;
++ int i;
++
++ error = regmap_read(priv->regmap, SX951X_REG_TOUCH_STATUS, &val);
++ if (error) {
++ dev_err(dev, "Failed to read touch status: %d\n", error);
++ return;
++ }
++
++ for (i = 0; i < SX951X_NUM_CHANNELS; i++) {
++ if (priv->keycodes[i] == KEY_RESERVED)
++ continue;
++
++ input_report_key(input, priv->keycodes[i], !!(val & BIT(i)));
++ input_sync(input);
++ }
++}
++
++static int sx951x_channel_init(struct sx951x_priv *priv, struct device_node *of_node,
++ u32 chan_idx)
++{
++ struct sx951x_key_data *key_data;
++ struct device *dev = priv->dev;
++ int error;
++
++ key_data = &priv->key_data[chan_idx];
++
++ /* Defaults */
++ key_data->cin_delta = SX951X_KEY_DEFAULT_CIN_DELTA;
++ key_data->sense_threshold = SX951X_KEY_DEFAULT_SENSE_THRESHOLD;
++
++ error = of_property_read_u32(of_node, "linux,keycodes",
++ &priv->keycodes[chan_idx]);
++ if (error) {
++ /* Not configured */
++ return 0;
++ }
++
++ error = of_property_read_u32(of_node, "semtech,cin-delta",
++ &key_data->cin_delta);
++ if (key_data->cin_delta > 0x03) {
++ dev_err(dev, "Failed to read cin-delta for channel %d: %d\n",
++ chan_idx, error);
++ return error;
++ }
++
++ error = of_property_read_u32(of_node, "semtech,sense-threshold",
++ &key_data->sense_threshold);
++ if (key_data->sense_threshold > 0xff) {
++ dev_err(dev, "Failed to read sense-threshold for channel %d: %d\n",
++ chan_idx, error);
++ return error;
++ }
++
++ error = regmap_update_bits(priv->regmap,
++ SX951X_REG_CAP_SENSE_RANGE(chan_idx),
++ SX951X_REG_CAP_SENSE_RANGE_CIN_DELTA_MASK,
++ key_data->cin_delta);
++
++ if (error) {
++ dev_err(dev, "Failed to set cin-delta for channel %d: %d\n",
++ chan_idx, error);
++ return error;
++ }
++
++ error = regmap_write(priv->regmap,
++ SX951X_REG_CAP_SENSE_THRESH(chan_idx),
++ key_data->sense_threshold);
++ if (error) {
++ dev_err(dev, "Failed to set sense-threshold for channel %d: %d\n",
++ chan_idx, error);
++ return error;
++ }
++
++ return 0;
++}
++
++static int sx951x_channels_init(struct sx951x_priv *priv)
++{
++ struct device *dev = priv->dev;
++ unsigned int channels = 0;
++ int error;
++ u32 reg;
++
++ for_each_child_of_node_scoped(dev->of_node, child) {
++ error = of_property_read_u32(child, "reg", &reg);
++ if (error != 0 || reg >= SX951X_NUM_CHANNELS) {
++ dev_err(dev, "Invalid channel %d\n", reg);
++ return -EINVAL;
++ }
++
++ priv->keycodes[reg] = KEY_RESERVED;
++
++ error = sx951x_channel_init(priv, child, reg);
++ if (error) {
++ dev_err(dev, "Failed to initialize channel %d: %d\n",
++ reg, error);
++ return error;
++ }
++
++ if (priv->keycodes[reg] != KEY_RESERVED)
++ channels |= BIT(reg);
++
++#ifdef CONFIG_LEDS_CLASS
++ error = sx951x_led_init(priv, child, reg);
++ if (error) {
++ dev_err(dev, "Failed to initialize LED %d: %d\n",
++ reg, error);
++ return error;
++ }
++#endif
++ }
++
++ /* Enable sensing on channels with keycode configured */
++ error = regmap_write(priv->regmap,
++ SX951X_REG_CAP_SENSE_ENABLE,
++ channels);
++
++ return 0;
++}
++
++static int sx951x_input_init(struct sx951x_priv *priv)
++{
++ struct device *dev = priv->dev;
++ int i, error;
++
++ priv->idev = devm_input_allocate_device(dev);
++ if (!priv->idev)
++ return -ENOMEM;
++
++ priv->idev->name = "SX9512/SX9513 capacitive touch sensor";
++ priv->idev->id.bustype = BUS_I2C;
++ __set_bit(EV_KEY, priv->idev->evbit);
++
++ for (i = 0; i < SX951X_NUM_CHANNELS; i++)
++ __set_bit(priv->keycodes[i], priv->idev->keybit);
++
++ __clear_bit(KEY_RESERVED, priv->idev->keybit);
++
++ priv->idev->keycode = priv->keycodes;
++ priv->idev->keycodesize = sizeof(priv->keycodes[0]);
++ priv->idev->keycodemax = SX951X_NUM_CHANNELS;
++
++ input_set_drvdata(priv->idev, priv);
++
++ error = input_setup_polling(priv->idev, sx951x_poll);
++ if (error) {
++ dev_err(dev, "Unable to set up polling: %d\n", error);
++ return error;
++ }
++
++ input_set_poll_interval(priv->idev, priv->poll_interval);
++
++ error = input_register_device(priv->idev);
++ if (error) {
++ dev_err(dev, "Unable to register polled device: %d\n",
++ error);
++ return error;
++ }
++
++ return 0;
++}
++
++static int sx951x_probe(struct i2c_client *i2c_client)
++{
++ const struct i2c_device_id *id;
++ const struct sx951x_hw_data *hw;
++ struct device *dev = &i2c_client->dev;
++ struct sx951x_priv *priv;
++ int error;
++
++ if (i2c_client->addr != SX951X_I2C_ADDRESS &&
++ i2c_client->addr != SX951XB_I2C_ADDRESS_) {
++ dev_err(dev, "Invalid I2C address: 0x%02x\n",
++ i2c_client->addr);
++ return -ENODEV;
++ }
++
++ id = i2c_client_get_device_id(i2c_client);
++ hw = i2c_get_match_data(i2c_client);
++ if (!id || !hw) {
++ dev_err(dev, "Invalid device configuration\n");
++ return -EINVAL;
++ }
++
++ priv = devm_kzalloc(dev,
++ sizeof(struct sx951x_priv),
++ GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->dev = dev;
++ priv->hw = hw;
++
++ priv->regmap = devm_regmap_init_i2c(i2c_client, &sx951x_regmap_config);
++ if (IS_ERR(priv->regmap))
++ return PTR_ERR(priv->regmap);
++
++ /* Parse device configuration */
++ if (of_property_read_u32(dev->of_node, "poll-interval",
++ &priv->poll_interval))
++ priv->poll_interval = SX951X_POLL_INTERVAL;
++
++ /* Register LED and input channels */
++ error = sx951x_channels_init(priv);
++ if (error) {
++ dev_err(dev, "Failed to initialize channels: %d\n", error);
++ return error;
++ }
++
++ /* Register input device */
++ error = sx951x_input_init(priv);
++ if (error) {
++ dev_err(dev, "Failed to register input device: %d\n", error);
++ return error;
++ }
++
++ return 0;
++}
++
++static void sx951x_remove(struct i2c_client *i2c_client)
++{
++ struct sx951x_priv *priv = i2c_get_clientdata(i2c_client);
++
++ /* Disable sensing */
++ regmap_write(priv->regmap, SX951X_REG_CAP_SENSE_ENABLE, 0x00);
++
++ /* Turn off all LEDs */
++ regmap_write(priv->regmap, SX951X_REG_LED_MAP_ENG2, 0x00);
++}
++
++static const struct sx951x_hw_data sx9512_hw_data = {
++ .has_proximity_sensing = true,
++};
++
++static const struct sx951x_hw_data sx9513_hw_data = {
++ .has_proximity_sensing = false,
++};
++
++static const struct of_device_id sx951x_dt_ids[] = {
++ { .compatible = "semtech,sx9512", .data = &sx9512_hw_data },
++ { .compatible = "semtech,sx9513", .data = &sx9513_hw_data },
++ { }
++};
++MODULE_DEVICE_TABLE(of, sx951x_dt_ids);
++
++static const struct i2c_device_id sx951x_i2c_ids[] = {
++ { "sx9512", (kernel_ulong_t)&sx9512_hw_data },
++ { "sx9513", (kernel_ulong_t)&sx9513_hw_data },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, sx951x_i2c_ids);
++
++static struct i2c_driver sx951x_i2c_driver = {
++ .driver = {
++ .name = "sx951x",
++ .of_match_table = sx951x_dt_ids,
++ },
++ .id_table = sx951x_i2c_ids,
++ .probe = sx951x_probe,
++ .remove = sx951x_remove,
++};
++
++module_i2c_driver(sx951x_i2c_driver);
++
++MODULE_DESCRIPTION("Semtech SX9512/SX9513 driver");
++MODULE_AUTHOR("David Bauer <mail@david-bauer.net>");
++MODULE_LICENSE("GPL");
+--
+2.47.2
+
From: David Bauer <mail@david-bauer.net>
Date: Mon, 12 May 2025 20:15:07 +0200
Subject: Input sx951x: make Kernel 5.15 compatible
diff --git a/target/linux/ramips/patches-5.15/871-Input-sx951x-make-Kernel-5.15-compatible.patch b/target/linux/ramips/patches-5.15/871-Input-sx951x-make-Kernel-5.15-compatible.patch
new file mode 100644
index 0000000000000000000000000000000000000000..ff64db97750dadcfa43276b75e56eead764375bf
--- /dev/null
+++ b/target/linux/ramips/patches-5.15/871-Input-sx951x-make-Kernel-5.15-compatible.patch
@@ -0,0 +1,105 @@
+From 6e27a79444f0f3ff640e5e14d9f72bf6f94fe32f Mon Sep 17 00:00:00 2001
+From: David Bauer <mail@david-bauer.net>
+Date: Mon, 12 May 2025 20:14:16 +0200
+Subject: [PATCH] Input sx951x: make Kernel 5.15 compatible
+
+---
+ drivers/input/keyboard/sx951x.c | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/input/keyboard/sx951x.c b/drivers/input/keyboard/sx951x.c
+index 66355036aa95..29296d583d58 100644
+--- a/drivers/input/keyboard/sx951x.c
++++ b/drivers/input/keyboard/sx951x.c
+@@ -20,6 +20,8 @@
+ #include <linux/gpio/consumer.h>
+ #include <linux/bitfield.h>
+
++ #include <linux/version.h>
++
+ /* Generic properties */
+ #define SX951X_I2C_ADDRESS 0x2b
+ #define SX951XB_I2C_ADDRESS_ 0x2d
+@@ -160,7 +162,11 @@ static const struct regmap_config sx951x_regmap_config = {
+ .reg_defaults = sx951x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(sx951x_reg_defaults),
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++ .cache_type = REGCACHE_FLAT,
++#else
+ .cache_type = REGCACHE_MAPLE,
++#endif
+ .volatile_reg = sx951x_volatile_reg,
+ };
+
+@@ -301,10 +307,17 @@ static int sx951x_channels_init(struct sx951x_priv *priv)
+ {
+ struct device *dev = priv->dev;
+ unsigned int channels = 0;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++ struct device_node *child;
++#endif
+ int error;
+ u32 reg;
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++ for_each_child_of_node(dev->of_node, child) {
++#else
+ for_each_child_of_node_scoped(dev->of_node, child) {
++#endif
+ error = of_property_read_u32(child, "reg", &reg);
+ if (error != 0 || reg >= SX951X_NUM_CHANNELS) {
+ dev_err(dev, "Invalid channel %d\n", reg);
+@@ -383,9 +396,15 @@ static int sx951x_input_init(struct sx951x_priv *priv)
+ return 0;
+ }
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++static int sx951x_probe(struct i2c_client *i2c_client, const struct i2c_device_id *id)
++#else
+ static int sx951x_probe(struct i2c_client *i2c_client)
++#endif
+ {
++#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 0, 0)
+ const struct i2c_device_id *id;
++#endif
+ const struct sx951x_hw_data *hw;
+ struct device *dev = &i2c_client->dev;
+ struct sx951x_priv *priv;
+@@ -398,7 +417,9 @@ static int sx951x_probe(struct i2c_client *i2c_client)
+ return -ENODEV;
+ }
+
++#if LINUX_VERSION_CODE > KERNEL_VERSION(6, 0, 0)
+ id = i2c_client_get_device_id(i2c_client);
++#endif
+ hw = i2c_get_match_data(i2c_client);
+ if (!id || !hw) {
+ dev_err(dev, "Invalid device configuration\n");
+@@ -440,7 +461,12 @@ static int sx951x_probe(struct i2c_client *i2c_client)
+ return 0;
+ }
+
+-static void sx951x_remove(struct i2c_client *i2c_client)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++static int sx951x_remove(struct i2c_client *i2c_client)
++#else
++static int sx951x_remove(struct i2c_client *i2c_client,
++ const struct i2c_device_id *id)
++#endif
+ {
+ struct sx951x_priv *priv = i2c_get_clientdata(i2c_client);
+
+@@ -449,6 +475,9 @@ static void sx951x_remove(struct i2c_client *i2c_client)
+
+ /* Turn off all LEDs */
+ regmap_write(priv->regmap, SX951X_REG_LED_MAP_ENG2, 0x00);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
++ return 0;
++#endif
+ }
+
+ static const struct sx951x_hw_data sx9512_hw_data = {
+--
+2.47.2
+
From: David Bauer <mail@david-bauer.net>
Date: Wed, 14 May 2025 01:49:44 +0200
Subject: ramips: pad EX400 kernel partition to retain web recovery
The web-recovery of the Genexis EX400 validates uploaded images to fit
in the rootf_0 partition.
With OpenWrt, only the kernel is stored in this partition, leaving the
partition very small. Currently, the first factory release image won't
be accepted by the recovery interface after the OpenWrt installation.
Pad the image of the ubifs to 10MB. This allows the 24.10 release image
to be uploaded, enabling device recovery.
Signed-off-by: David Bauer <mail@david-bauer.net>
(cherry picked from commit eea4689654e1b07cffe62bc97ad8fef0474bb3b7)
diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk
index b98989c1fcb2b31bebf49fe00939371268470494..b2e32851947b10112f8be24c88e0321666781e0d 100644
--- a/target/linux/ramips/image/mt7621.mk
+++ b/target/linux/ramips/image/mt7621.mk
@@ -1113,7 +1113,7 @@ define Device/genexis_pulse-ex400/common
--log-lebs=2 --space-fixup --squash-uids
KERNEL := kernel-bin | lzma | uImage lzma
KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | uImage lzma
- IMAGE/sysupgrade.bin := append-kernel | inteno-bootfs | \
+ IMAGE/sysupgrade.bin := append-kernel | inteno-bootfs | pad-to 10M | \
sysupgrade-tar kernel=$$$$@ | check-size | append-metadata
DEVICE_IMG_NAME = $$(DEVICE_IMG_PREFIX)-$$(2)
DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615-firmware kmod-usb3 kmod-keyboard-sx951x kmod-button-hotplug
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment