[PATCH v2 7/7] ipq806x: Initial TP-Link and ASUS OnHub support

Brian Norris computersforpeace at gmail.com
Fri Jan 6 23:49:45 PST 2023


TP-Link and ASUS OnHub devices are very similar, sharing many of the
same characteristics and much of their Device Tree. They both run a
version of ChromeOS for their factory firmware, and so installation
instructions look very similar to Google Wifi [1].

Things that work:

 * Ethernet
 * WiFi (2.4 and 5 GHz)
 * LEDs
 * USB
 * eMMC
 * Serial console (if you wire it up yourself)
 * 1 CPU
 * Speaker; I think I've worked out the kinks (with the parent patches,
   and tweaking pin configuration a bit)

Things that don't work:

 * The second CPU; bringing up the second CPU seems to hang right now,
   so I disable it with "maxcpus=1".

== Installation instructions summary ==

1. Flash *-factory.bin to a USB drive (e.g., with `dd`)
2. Enter Developer Mode
3. Insert USB drive, to boot OpenWrt from USB
4. Copy the same *-factory.bin over to device, and flash it to eMMC to
   make OpenWrt permanent

== Developer mode (Step 2) ==

To enter Developer Mode [2], follow these steps:

1. Unplug power
2. Gain access to the "developer switch" through the bottom of the
   device
3. Plug a USB keyboard into the device's USB port
4. Hold down the "reset switch" (near the USB port / power plug)
5. Plug power back in
6. The LED on the device should turn white, then blink orange, then
   red. Release the reset switch.
7. Press CTRL+D on the keyboard. The LED should now start blinking
   purple.
8. Press and release the hidden "developer switch" under the device.
9. The device should reboot, and start blinking purple again. You have
   successfully entered developer mode.
10. Unplug power

These instructions are derived from:

https://www.exploitee.rs/index.php/Rooting_The_Google_OnHub#Enabling_%22Developer_Mode%22_on_the_OnHub
https://www.exploitee.rs/index.php/Asus_OnHub#Enabling_%22Developer_Mode%22_on_the_OnHub

~~Finding the developer switch:~~ for TP-Link, the developer switch is
on the bottom of the device, underneath some of the rubber padding and a
screw. For ASUS, remove the entire base, via 4 screws under the rubber
feet. See the Exploitee instructions for more info and photos.

== Booting from USB (Step 3) ==

After entering developer mode:

1. Unplug power
2. Insert USB drive with OpenWrt factory.bin
3. Plug power; after a few seconds, the device should start blinking
   purple
4. Press the hidden developer switch under the device to boot to USB;
   you should see some activity lights (if you have any) on your USB
   drive
5. Depending on your configuration, the router's LED(s) should come on.
   You're now running OpenWrt off a USB stick.

== Making OpenWrt permanent (on eMMC) (Step 4) ==

Once you're running OpenWrt via USB:

1. Connect Ethernet to the LAN port; router's LAN address should be at
   192.168.1.1
2. Connect another system to the router's LAN, and copy the factory.bin
   image over, via SCP and SSH:

     scp -O openwrt-ipq806x-chromium-tplink_onhub-squashfs-factory.bin root at 192.168.1.1:
     ssh root at 192.168.1.1 -C "dd if=/dev/zero bs=512 seek=7552991 of=/dev/mmcblk0 count=33 && \
     dd if=/root/openwrt-ipq806x-chromium-tplink_onhub-squashfs-factory.bin of=/dev/mmcblk0"
3. Reboot and remove the USB drive.

== Developer mode beep ==

Note that every time you boot the OnHub in developer mode, the device
will play a loud "beep" after a few seconds. This is described in the
Chromium docs [2], and is intended to make it clear that the device is
not running Google software. It is nontrivial to completely disable this
beep, although it's possible to "acknowledge" developer mode (and skip
the beep) by using a USB keyboard to press CTRL+D every time you boot.

[1] https://openwrt.org/toh/google/wifi
[2] https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 * There might be better ways to handle the multi-color LED support,
   but for now, each color is a separate LED
 * A variety of people have been interested in this work, and a few have
   tested versions of it already:
     https://forum.openwrt.org/t/onhub-tp-link-tgr1900-future-support/17899
 * This is dependent on an fstools change, to ensure it can find our
   'rootfs_data' properly:
     [PATCH fstools v2] partname: Ignore root=PARTUUID...
     https://patchwork.ozlabs.org/project/openwrt/patch/20230107020424.1703752-1-computersforpeace@gmail.com/

Changes in v2:
 * Drop custom ath10k base64 property
 * Provide base64 caldata parsing via
   /etc/hotplug.d/firmware/11-ath10k-caldata instead
 * add coreutils-base64 dependency
 * add 3rd (rootfs_data) partition, to better handle sysupgrade and
   utilize the whole disk

 target/linux/ipq806x/Makefile                 |   4 +-
 .../ipq806x/base-files/etc/board.d/01_leds    |  11 +
 .../ipq806x/base-files/etc/board.d/02_network |   6 +
 .../etc/hotplug.d/firmware/11-ath10k-caldata  |  35 ++
 .../base-files/lib/upgrade/platform.sh        |  19 +
 target/linux/ipq806x/chromium/config-default  |  13 +
 target/linux/ipq806x/chromium/target.mk       |   2 +
 .../arm/boot/dts/qcom-ipq8064-asus-onhub.dts  |  95 ++++
 .../arch/arm/boot/dts/qcom-ipq8064-onhub.dtsi | 463 ++++++++++++++++++
 .../boot/dts/qcom-ipq8064-tplink-onhub.dts    | 207 ++++++++
 target/linux/ipq806x/generic/target.mk        |   1 +
 target/linux/ipq806x/image/chromium.mk        |  58 +++
 12 files changed, 912 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/ipq806x/chromium/config-default
 create mode 100644 target/linux/ipq806x/chromium/target.mk
 create mode 100644 target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-asus-onhub.dts
 create mode 100644 target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-onhub.dtsi
 create mode 100644 target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-tplink-onhub.dts
 create mode 100644 target/linux/ipq806x/image/chromium.mk

diff --git a/target/linux/ipq806x/Makefile b/target/linux/ipq806x/Makefile
index 862ad7da004b..5c89d413c0d3 100644
--- a/target/linux/ipq806x/Makefile
+++ b/target/linux/ipq806x/Makefile
@@ -5,10 +5,10 @@ include $(TOPDIR)/rules.mk
 ARCH:=arm
 BOARD:=ipq806x
 BOARDNAME:=Qualcomm Atheros IPQ806X
-FEATURES:=squashfs nand fpu ramdisk
+FEATURES:=squashfs fpu ramdisk
 CPU_TYPE:=cortex-a15
 CPU_SUBTYPE:=neon-vfpv4
-SUBTARGETS:=generic
+SUBTARGETS:=generic chromium
 
 KERNEL_PATCHVER:=5.15
 
diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds
index 2b259b903614..80a337c6a4d4 100644
--- a/target/linux/ipq806x/base-files/etc/board.d/01_leds
+++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds
@@ -9,6 +9,9 @@ board_config_update
 board=$(board_name)
 
 case "$board" in
+asus,onhub)
+	ucidef_set_led_default "status" "STATUS" "LED_Green" "1"
+	;;
 buffalo,wxr-2533dhp)
 	ucidef_set_led_wlan "wlan" "WLAN" "white:wireless" "phy0tpt"
 	ucidef_set_led_switch "wan" "WAN" "white:internet" "switch0" "0x20"
@@ -58,6 +61,14 @@ tplink,c2600)
 	ucidef_set_led_switch "wan" "wan" "white:wan" "switch0" "0x20"
 	ucidef_set_led_switch "lan" "lan" "white:lan" "switch0" "0x1e"
 	;;
+tplink,onhub)
+	ucidef_set_led_default "led0_red" "LED0_Red" "LED0_Red" "1"
+	ucidef_set_led_default "led1_green" "LED1_Green" "LED1_Green" "1"
+	ucidef_set_led_default "led2_blue" "LED2_Blue" "LED2_Blue" "1"
+	ucidef_set_led_default "led3_red" "LED3_Red" "LED3_Red" "1"
+	ucidef_set_led_default "led4_green" "LED4_Green" "LED4_Green" "1"
+	ucidef_set_led_default "led5_blue" "LED5_Blue" "LED5_Blue" "1"
+	;;
 tplink,vr2600v)
 	ucidef_set_led_usbport "usb" "USB" "white:usb" "usb1-port1" "usb2-port1" "usb3-port1" "usb4-port1"
 	ucidef_set_led_switch "lan" "lan" "white:lan" "switch0" "0x1e"
diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network
index dbff854731a4..f38876b69f08 100644
--- a/target/linux/ipq806x/base-files/etc/board.d/02_network
+++ b/target/linux/ipq806x/base-files/etc/board.d/02_network
@@ -79,6 +79,12 @@ tplink,ad7200)
 	ucidef_add_switch "switch0" \
 		"2:lan:1" "3:lan:2" "4:lan:3" "5:lan:4" "6 at eth1" "1:wan" "0 at eth0"
 	;;
+asus,onhub |\
+tplink,onhub)
+	ucidef_set_interfaces_lan_wan "eth1" "eth0"
+	ucidef_add_switch "switch0" \
+		"1:lan" "6 at eth1" "2:wan" "0 at eth0"
+	;;
 ubnt,unifi-ac-hd)
 	ucidef_set_interface_lan "eth0 eth1"
 	;;
diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index 398ddf9a290a..c5df07937832 100644
--- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -6,9 +6,32 @@
 
 board=$(board_name)
 
+dt_base64_extract() {
+	local target_dir="/sys$DEVPATH"
+	local source="$target_dir/../../of_node/qcom,ath10k-calibration-data-base64"
+
+	[ -e "$source" ] || caldata_die "cannot find base64 calibration data: $source"
+	[ -d "$target_dir" ] || \
+		caldata_die "no sysfs dir to write: $target"
+
+	echo 1 > "$target_dir/loading"
+	base64 -d "$source" > "$target_dir/data"
+	if [ $? != 0 ]; then
+		echo 1 > "$target_dir/loading"
+		caldata_die \
+			"failed to write calibration data to $target_dir/data"
+	else
+		echo 0 > "$target_dir/loading"
+	fi
+}
+
 case "$FIRMWARE" in
 "ath10k/cal-pci-0000:01:00.0.bin")
 	case "$board" in
+	asus,onhub |\
+	tplink,onhub)
+		dt_base64_extract
+		;;
 	meraki,mr52)
 		CI_UBIPART=art
 		caldata_extract_ubi "ART" 0x1000 0x844
@@ -35,6 +58,14 @@ case "$FIRMWARE" in
 		;;
 	esac
 	;;
+"ath10k/cal-pci-0001:01:00.0.bin")
+	case "$board" in
+	asus,onhub |\
+	tplink,onhub)
+		dt_base64_extract
+		;;
+	esac
+	;;
 "ath10k/pre-cal-pci-0001:01:00.0.bin")
 	case $board in
 	asrock,g10)
@@ -61,6 +92,10 @@ case "$FIRMWARE" in
 	;;
 "ath10k/cal-pci-0002:01:00.0.bin")
 	case "$board" in
+	asus,onhub |\
+	tplink,onhub)
+		dt_base64_extract
+		;;
 	meraki,mr42)
 		CI_UBIPART=art
 		caldata_extract_ubi "ART" 0x9000 0x844
diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
index f9e592f4bd8f..67ceaab24fb5 100644
--- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
@@ -57,6 +57,15 @@ platform_do_upgrade() {
 		MTD_CONFIG_ARGS="-s 0x200000"
 		default_do_upgrade "$1"
 		;;
+	asus,onhub |\
+	tplink,onhub)
+		export_bootdevice
+		export_partdevice CI_ROOTDEV 0
+		CI_KERNPART="kernel"
+		CI_ROOTPART="rootfs"
+		CI_DATAPART="rootfs_data"
+		emmc_do_upgrade "$1"
+		;;
 	tplink,vr2600v)
 		MTD_CONFIG_ARGS="-s 0x200000"
 		default_do_upgrade "$1"
@@ -69,3 +78,13 @@ platform_do_upgrade() {
 		;;
 	esac
 }
+
+platform_copy_config() {
+	case "${board_name}" in
+	asus,onhub |\
+	tplink,onhub)
+		emmc_copy_config
+		;;
+	esac
+	return 0
+}
diff --git a/target/linux/ipq806x/chromium/config-default b/target/linux/ipq806x/chromium/config-default
new file mode 100644
index 000000000000..d7db9f7db35a
--- /dev/null
+++ b/target/linux/ipq806x/chromium/config-default
@@ -0,0 +1,13 @@
+CONFIG_BLK_DEV_SD=y
+CONFIG_LEDS_LP5523=y
+CONFIG_LEDS_LP55XX_COMMON=y
+CONFIG_PHY_QCOM_IPQ806X_USB=y
+CONFIG_SCSI=y
+CONFIG_SCSI_COMMON=y
+CONFIG_SG_POOL=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_HOST=y
+CONFIG_USB_DWC3_QCOM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
diff --git a/target/linux/ipq806x/chromium/target.mk b/target/linux/ipq806x/chromium/target.mk
new file mode 100644
index 000000000000..3983a9281a5d
--- /dev/null
+++ b/target/linux/ipq806x/chromium/target.mk
@@ -0,0 +1,2 @@
+BOARDNAME:=Google Chromium
+FEATURES += emmc boot-part rootfs-part
diff --git a/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-asus-onhub.dts b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-asus-onhub.dts
new file mode 100644
index 000000000000..7ce41bc92b80
--- /dev/null
+++ b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-asus-onhub.dts
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2014 The ChromiumOS Authors
+ */
+
+#include "qcom-ipq8064-onhub.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/qcom,gsbi.h>
+
+/ {
+	model = "ASUS OnHub";
+	compatible = "asus,onhub", "google,arkham", "qcom,ipq8064";
+
+	chosen {
+		bootargs-append = " maxcpus=1 rootwait";
+	};
+};
+
+&qcom_pinmux {
+	ap3223_pins: ap3223_pinmux {
+		pins = "gpio22";
+		function = "gpio";
+		bias-none;
+	};
+
+	i2c7_pins: i2c7_pinmux {
+		mux {
+			pins = "gpio8", "gpio9";
+			function = "gsbi7";
+		};
+		data {
+			pins = "gpio8";
+			bias-disable;
+		};
+		clk {
+			pins = "gpio9";
+			bias-disable;
+		};
+	};
+};
+
+&gsbi7 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+};
+
+&gsbi7_i2c {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c7_pins>;
+	pinctrl-names = "default";
+
+	ap3223 at 1c {
+		compatible = "dynaimage,ap3223";
+		reg = <0x1c>;
+
+		pinctrl-0 = <&ap3223_pins>;
+		pinctrl-names = "default";
+
+		int-gpio = <&qcom_pinmux 22 GPIO_ACTIVE_LOW>;
+	};
+
+	led-controller at 32 {
+		compatible = "national,lp5523";
+		reg = <0x32>;
+		clock-mode = /bits/ 8 <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		led at 4 {
+			reg = <4>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED_Green";
+			led-cur = /bits/ 8 <0xfa>;
+			max-cur = /bits/ 8 <0xff>;
+		};
+
+		led at 5 {
+			reg = <5>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED_Blue";
+			led-cur = /bits/ 8 <0xfa>;
+			max-cur = /bits/ 8 <0xff>;
+		};
+
+		led at 8 {
+			reg = <8>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED_Red";
+			led-cur = /bits/ 8 <0xfa>;
+			max-cur = /bits/ 8 <0xff>;
+		};
+	};
+};
diff --git a/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-onhub.dtsi b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-onhub.dtsi
new file mode 100644
index 000000000000..25ba71da00ef
--- /dev/null
+++ b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-onhub.dtsi
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2014 The ChromiumOS Authors
+ */
+
+#include "qcom-ipq8064-smb208.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/soc/qcom,tcsr.h>
+
+/ {
+	aliases {
+		ethernet0 = &gmac0;
+		ethernet1 = &gmac2;
+		mdio-gpio0 = &mdio;
+		serial0 = &gsbi4_serial;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		rsvd at 41200000 {
+			reg = <0x41200000 0x300000>;
+			no-map;
+		};
+	};
+
+	mdio: mdio {
+		compatible = "virtual,mdio-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>,
+			<&qcom_pinmux 0 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&mdio_pins>;
+		pinctrl-names = "default";
+
+		phy0: ethernet-phy at 0 {
+			reg = <0>;
+			qca,ar8327-initvals = <
+				0x00004 0x7600000   /* PAD0_MODE */
+				0x00008 0x1000000   /* PAD5_MODE */
+				0x0000c 0x80        /* PAD6_MODE */
+				0x000e4 0xaa545     /* MAC_POWER_SEL */
+				0x000e0 0xc74164de  /* SGMII_CTRL */
+				0x0007c 0x4e        /* PORT0_STATUS */
+				0x00094 0x4e        /* PORT6_STATUS */
+				>;
+		};
+
+		phy1: ethernet-phy at 1 {
+			reg = <1>;
+		};
+	};
+
+	soc {
+		rng at 1a500000 {
+			status = "disabled";
+		};
+
+		sound {
+			compatible = "google,storm-audio";
+			qcom,model = "ipq806x-storm";
+			cpu = <&lpass>;
+			codec = <&max98357a>;
+		};
+
+		lpass: lpass at 28100000 {
+			status = "okay";
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&mi2s_default>;
+			pinctrl-1 = <&mi2s_idle>;
+		};
+
+		max98357a: max98357a {
+			compatible = "maxim,max98357a";
+			#sound-dai-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&sdmode_pins>;
+			sdmode-gpios = <&qcom_pinmux 25 GPIO_ACTIVE_HIGH>;
+		};
+	};
+};
+
+&qcom_pinmux {
+	rgmii0_pins: rgmii0_pins {
+		mux {
+			pins = "gpio2", "gpio66";
+			drive-strength = <8>;
+			bias-disable;
+		};
+	};
+	mi2s_pins {
+		mi2s_default: mi2s_default {
+			dout {
+				pins = "gpio32";
+				function = "mi2s";
+				drive-strength = <16>;
+				bias-disable;
+			};
+			sync {
+				pins = "gpio27";
+				function = "mi2s";
+				drive-strength = <16>;
+				bias-disable;
+			};
+			clk {
+				pins = "gpio28";
+				function = "mi2s";
+				drive-strength = <16>;
+				bias-disable;
+			};
+		};
+		mi2s_idle: mi2s_idle {
+			dout {
+				pins = "gpio32";
+				function = "mi2s";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+			sync {
+				pins = "gpio27";
+				function = "mi2s";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+			clk {
+				pins = "gpio28";
+				function = "mi2s";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+	};
+
+	mdio_pins: mdio_pins {
+		mux {
+			pins = "gpio0", "gpio1";
+			function = "gpio";
+			drive-strength = <8>;
+			bias-disable;
+		};
+		rst {
+			pins = "gpio26";
+			output-low;
+		};
+	};
+
+	sdmode_pins: sdmode_pinmux {
+		pins = "gpio25";
+		function = "gpio";
+		drive-strength = <16>;
+		bias-disable;
+	};
+
+	sdcc1_pins: sdcc1_pinmux {
+		mux {
+			pins = "gpio38", "gpio39", "gpio40",
+			       "gpio41", "gpio42", "gpio43",
+			       "gpio44", "gpio45", "gpio46",
+			       "gpio47";
+			function = "sdc1";
+		};
+		cmd {
+			pins = "gpio45";
+			drive-strength = <10>;
+			bias-pull-up;
+		};
+		data {
+			pins = "gpio38", "gpio39", "gpio40",
+			       "gpio41", "gpio43", "gpio44",
+			       "gpio46", "gpio47";
+			drive-strength = <10>;
+			bias-pull-up;
+		};
+		clk {
+			pins = "gpio42";
+			drive-strength = <16>;
+			bias-pull-down;
+		};
+	};
+
+	i2c1_pins: i2c1_pinmux {
+		pins = "gpio53", "gpio54";
+		function = "gsbi1";
+		bias-disable;
+	};
+
+	rpm_i2c_pinmux: rpm_i2c_pinmux {
+		mux {
+			pins = "gpio12", "gpio13";
+			function = "gsbi4";
+			drive-strength = <12>;
+			bias-disable;
+		};
+	};
+
+	spi_pins: spi_pins {
+		mux {
+			pins = "gpio18", "gpio19", "gpio21";
+			function = "gsbi5";
+			bias-pull-down;
+			/delete-property/ bias-none;
+			/delete-property/ drive-strength;
+		};
+		data {
+			pins = "gpio18", "gpio19";
+			drive-strength = <10>;
+		};
+		cs {
+			pins = "gpio20";
+			drive-strength = <10>;
+			bias-pull-up;
+		};
+		clk {
+			pins = "gpio21";
+			drive-strength = <12>;
+		};
+	};
+
+	fw_pinmux {
+		wp {
+			pins = "gpio17";
+			output-low;
+		};
+		recovery {
+			pins = "gpio16";
+			bias-none;
+		};
+		developer {
+			pins = "gpio15";
+			bias-none;
+		};
+	};
+
+	spi6_pins: spi6_pins {
+		mux {
+			pins = "gpio55", "gpio56", "gpio58";
+			function = "gsbi6";
+			bias-pull-down;
+		};
+		data {
+			pins = "gpio55", "gpio56";
+			drive-strength = <10>;
+		};
+		cs {
+			pins = "gpio57";
+			drive-strength = <10>;
+			bias-pull-up;
+			output-high;
+		};
+		clk {
+			pins = "gpio58";
+			drive-strength = <12>;
+		};
+	};
+};
+
+&gmac0 {
+	status = "okay";
+	phy-mode = "rgmii";
+	qcom,id = <0>;
+	phy-handle = <&phy1>;
+
+	pinctrl-0 = <&rgmii0_pins>;
+	pinctrl-names = "default";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&gmac2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	qcom,id = <2>;
+	phy-handle = <&phy0>;
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&gsbi1 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+};
+
+&gsbi1_i2c {
+	status = "okay";
+
+	clock-frequency = <100000>;
+
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "default";
+
+	tpm at 20 {
+		compatible = "infineon,slb9645tt";
+		reg = <0x20>;
+		powered-while-suspended;
+	};
+};
+
+&gsbi4 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+};
+
+&gsbi4_serial {
+	status = "okay";
+};
+
+&gsbi5 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_SPI>;
+
+	spi4: spi at 1a280000 {
+		status = "okay";
+		spi-max-frequency = <50000000>;
+		pinctrl-0 = <&spi_pins>;
+		pinctrl-names = "default";
+
+		cs-gpios = <&qcom_pinmux 20 0>;
+
+		flash: flash at 0 {
+			compatible = "jedec,spi-nor";
+			spi-max-frequency = <50000000>;
+			reg = <0>;
+		};
+	};
+};
+
+&gsbi6 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_SPI>;
+};
+
+&gsbi6_spi {
+	status = "okay";
+	spi-max-frequency = <25000000>;
+
+	pinctrl-0 = <&spi6_pins>;
+	pinctrl-names = "default";
+
+	cs-gpios = <&qcom_pinmux 57 GPIO_ACTIVE_HIGH>;
+
+	dmas = <&adm_dma 8 0xb>,
+	       <&adm_dma 7 0x14>;
+	dma-names = "rx", "tx";
+
+	/*
+	 * This "spidev" was included in the manufacturer device tree. I suspect
+	 * it's the (unused) Zigbee radio -- SiliconLabs EM3581 Zigbee? There's
+	 * no driver or binding for this at the moment.
+	 */
+	spidev at 0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <25000000>;
+	};
+};
+
+&pcie0 {
+	status = "okay";
+
+	pcie at 0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+
+		ath10k at 0,0 {
+			reg = <0 0 0 0 0>;
+			device_type = "pci";
+			qcom,ath10k-sa-gpio = <2 3 4 0>;
+			qcom,ath10k-sa-gpio-func = <5 5 5 0>;
+		};
+	};
+};
+
+&pcie1 {
+	status = "okay";
+
+	pcie at 0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+
+		ath10k at 0,0 {
+			reg = <0 0 0 0 0>;
+			device_type = "pci";
+			qcom,ath10k-sa-gpio = <2 3 4 0>;
+			qcom,ath10k-sa-gpio-func = <5 5 5 0>;
+		};
+	};
+};
+
+&pcie2 {
+	status = "okay";
+
+	pcie at 0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+
+		ath10k at 0,0 {
+			reg = <0 0 0 0 0>;
+			device_type = "pci";
+		};
+	};
+};
+
+&rpm {
+	pinctrl-0 = <&rpm_i2c_pinmux>;
+	pinctrl-names = "default";
+};
+
+&sdcc1 {
+	status = "okay";
+	pinctrl-0 = <&sdcc1_pins>;
+	pinctrl-names = "default";
+	/delete-property/ mmc-ddr-1_8v;
+};
+
+&tcsr {
+	compatible = "qcom,tcsr-ipq8064", "qcom,tcsr", "syscon";
+	qcom,usb-ctrl-select = <TCSR_USB_SELECT_USB3_DUAL>;
+};
+
+&hs_phy_0 {
+	status = "okay";
+};
+
+&ss_phy_0 {
+	status = "okay";
+};
+
+&usb3_0 {
+	status = "okay";
+};
+
+&hs_phy_1 {
+	status = "okay";
+};
+
+&ss_phy_1 {
+	status = "okay";
+};
+
+&usb3_1 {
+	status = "okay";
+};
diff --git a/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-tplink-onhub.dts b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-tplink-onhub.dts
new file mode 100644
index 000000000000..112de6769f29
--- /dev/null
+++ b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8064-tplink-onhub.dts
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2014 The ChromiumOS Authors
+ */
+
+#include "qcom-ipq8064-onhub.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/soc/qcom,gsbi.h>
+
+/ {
+	model = "TP-Link OnHub";
+	compatible = "tplink,onhub", "google,whirlwind-sp5", "qcom,ipq8064";
+
+	chosen {
+		bootargs-append = " maxcpus=1 rootwait";
+	};
+};
+
+&qcom_pinmux {
+	i2c7_pins: i2c7_pinmux {
+		mux {
+			pins = "gpio8", "gpio9";
+			function = "gsbi7";
+		};
+		data {
+			pins = "gpio8";
+			bias-disable;
+		};
+		clk {
+			pins = "gpio9";
+			bias-disable;
+		};
+	};
+};
+
+&gsbi7 {
+	status = "okay";
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+};
+
+&gsbi7_i2c {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c7_pins>;
+	pinctrl-names = "default";
+
+	led-controller at 32 {
+		compatible = "national,lp5523";
+		reg = <0x32>;
+		clock-mode = /bits/ 8 <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		led at 0 {
+			reg = <0>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED0_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 1 {
+			reg = <1>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED0_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 2 {
+			reg = <2>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED0_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 3 {
+			reg = <3>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED1_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 4 {
+			reg = <4>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED1_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 5 {
+			reg = <5>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED1_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 6 {
+			reg = <6>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED2_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 7 {
+			reg = <7>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED2_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 8 {
+			reg = <8>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED2_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+	};
+
+	led-controller at 33 {
+		compatible = "national,lp5523";
+		reg = <0x33>;
+		clock-mode = /bits/ 8 <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		led at 0 {
+			reg = <0>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED3_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 1 {
+			reg = <1>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED3_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 2 {
+			reg = <2>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED3_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 3 {
+			reg = <3>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED4_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 4 {
+			reg = <4>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED4_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 5 {
+			reg = <5>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED4_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 6 {
+			reg = <6>;
+			color = <LED_COLOR_ID_RED>;
+			chan-name = "LED5_Red";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 7 {
+			reg = <7>;
+			color = <LED_COLOR_ID_GREEN>;
+			chan-name = "LED5_Green";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+
+		led at 8 {
+			reg = <8>;
+			color = <LED_COLOR_ID_BLUE>;
+			chan-name = "LED5_Blue";
+			led-cur = /bits/ 8 <0x64>;
+			max-cur = /bits/ 8 <0x78>;
+		};
+	};
+};
diff --git a/target/linux/ipq806x/generic/target.mk b/target/linux/ipq806x/generic/target.mk
index f5cb1fb19b94..4de636f0e0ae 100644
--- a/target/linux/ipq806x/generic/target.mk
+++ b/target/linux/ipq806x/generic/target.mk
@@ -1 +1,2 @@
 BOARDNAME:=Generic
+FEATURES += nand
diff --git a/target/linux/ipq806x/image/chromium.mk b/target/linux/ipq806x/image/chromium.mk
new file mode 100644
index 000000000000..aa602eb09941
--- /dev/null
+++ b/target/linux/ipq806x/image/chromium.mk
@@ -0,0 +1,58 @@
+define Build/cros-gpt
+	cp $@ $@.tmp 2>/dev/null || true
+	ptgen -o $@.tmp -g \
+		-T cros_kernel	-N kernel -p $(CONFIG_TARGET_KERNEL_PARTSIZE)m \
+				-N rootfs -p $(CONFIG_TARGET_ROOTFS_PARTSIZE)m \
+				-N rootfs_data -p \
+				$$((3687-$(CONFIG_TARGET_ROOTFS_PARTSIZE)-\
+				         $(CONFIG_TARGET_KERNEL_PARTSIZE)))m
+	cat $@.tmp >> $@
+	rm $@.tmp
+endef
+
+define Build/append-kernel-part
+	dd if=$(IMAGE_KERNEL) bs=$(CONFIG_TARGET_KERNEL_PARTSIZE)M conv=sync >> $@
+endef
+
+# NB: Chrome OS bootloaders replace the '%U' in command lines with the UUID of
+# the kernel partition it chooses to boot from. This gives a flexible way to
+# consistently build and sign kernels that always use the subsequent
+# (PARTNROFF=1) partition as their rootfs.
+define Build/cros-vboot
+	$(STAGING_DIR_HOST)/bin/cros-vbutil \
+		-k $@ -c "root=PARTUUID=%U/PARTNROFF=1" -o $@.new
+	@mv $@.new $@
+endef
+
+define Device/OnhubImage
+	KERNEL_LOADADDR = 0x44208000
+	SOC := qcom-ipq8064
+	KERNEL_SUFFIX := -fit-zImage.itb.vboot
+	KERNEL_NAME := zImage
+	KERNEL = kernel-bin | fit none $$(KDIR)/image-$$(DEVICE_DTS).dtb | cros-vboot
+	IMAGES := factory.bin sysupgrade.bin
+	IMAGE/factory.bin := cros-gpt | append-kernel-part | append-rootfs
+	IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
+	DEVICE_PACKAGES := ath10k-firmware-qca988x-ct e2fsprogs kmod-fs-ext4 losetup \
+			   partx-utils mkf2fs kmod-fs-f2fs \
+			   coreutils-base64 kmod-google-firmware kmod-tpm-i2c-infineon \
+			   kmod-sound-soc-ipq8064-storm kmod-usb-storage
+endef
+
+define Device/asus_onhub
+	$(call Device/OnhubImage)
+	DEVICE_VENDOR := ASUS
+	DEVICE_MODEL := OnHub SRT-AC1900
+	DEVICE_DTS := $$(SOC)-asus-onhub
+	BOARD_NAME := asus-onhub
+endef
+TARGET_DEVICES += asus_onhub
+
+define Device/tplink_onhub
+	$(call Device/OnhubImage)
+	DEVICE_VENDOR := TP-Link
+	DEVICE_MODEL := OnHub AC1900 Cloud Router
+	DEVICE_DTS := $$(SOC)-tplink-onhub
+	BOARD_NAME := tplink-onhub
+endef
+TARGET_DEVICES += tplink_onhub
-- 
2.39.0




More information about the openwrt-devel mailing list