[RFC PATCH 5/5] ipq40xx: add target for Google WiFi (Gale)

Brian Norris computersforpeace at gmail.com
Sat Jul 18 16:51:48 EDT 2020


Google WiFi (codename: Gale) is an IPQ4019-based AP, with 2 Ethernet
ports, 2x2 2.4+5GHz WiFi, 512 MB RAM, 4 GB eMMC, and a USB type C port.
In its stock configuration, it runs a Chromium OS-based system, but you
wouldn't know it, since you can only manage it via a "cloud" +
mobile-app system.

The "v2" label is coded into the bootloader, which prefers the
"google,gale-v2" compatible string. I believe "v1" must have been
pre-release hardware.

Note: this is *not* the Google Nest WiFi, released in 2019.

I include "factory.bin" support, where we generate a GPT-based disk
image with 2 partitions -- a kernel partition (using the custom "Chrome
OS kernel" GUID type) and a root filesystem partition. If the AP is in
Developer Mode, the stock bootloader can boot it via a USB disk or
(after gaining access via USB boot) flashed to the eMMC.

Sysupgrade also seems to work OK, although I've omitted some of the
(re)partitioning handling. I also hard-code /dev/mmcblk0 -- while MMC
device numbering can technically change, there's no other MMC controller
present (e.g., no SD card slot).

"FEATURES=boot-part rootfs-part" is required to get kernel and rootfs
partition sizes established. This adds extra (unused) configuration
parameters for other ipq40xx targets, so I'm not sure if this is the
"right" thing to do either.

Features I have tested:

 * Ethernet, both WAN and LAN ports
 * eMMC
 * USB-C (hub, power-delivery, peripherals)
 * LED0 (R/G/B)
 * WiFi (limited testing)
 * SPI flash
 * Serial console: once in developer mode, console can be accessed via
   the USB-C port with SuzyQable, or other similar "Closed Case
   Debugging" tools:
     https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/master/docs/ccd.md#suzyq-suzyqable

Not tested:

 * TPM
 * LED1, LED2: I'm not even confident they are actually populated
   anywhere

Known not working:

 * Reboot: this seems to require some additional TrustZone / SCM
   configuration; with additional local patches, I have this working,
   but I'm still trying to figure out exactly the right way I should
   integrate this. Ideally, I could propose it upstream, instead of just
   adding a custom OpenWRT patch. Without this patch, reboot just hangs
   the system. (NB: I've found at least one other user report of this on
   an "IPQ4019" device, but I don't know yet if that's the same.)
 * There's a single external button, and a few useful internal GPIO
   switches. I haven't hooked them up.

Much of the DTS is pulled from the Chrome OS kernel 3.18 branch, which
the manufacturer image uses.

Note: the manufacturer bootloader knows how to patch in calibration data
via the wifi{0,1} aliases in the DTB, so while these properties aren't
present in the DTS, they are available at runtime:

  # ls -l
/sys/firmware/devicetree/base/soc/wifi at a*/qcom,ath10k-pre-calibration-data
  -r--r--r--    1 root     root         12064 Jul 15 19:11 /sys/firmware/devicetree/base/soc/wifi at a000000/qcom,ath10k-pre-calibration-data
  -r--r--r--    1 root     root         12064 Jul 15 19:11 /sys/firmware/devicetree/base/soc/wifi at a800000/qcom,ath10k-pre-calibration-data

Ethernet MAC addresses are similarly patched in via the ethernet{0,1} aliases.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 target/linux/ipq40xx/Makefile                 |   2 +-
 .../ipq40xx/base-files/etc/board.d/02_network |   1 +
 .../base-files/lib/upgrade/platform.sh        |  13 +
 .../arm/boot/dts/qcom-ipq4019-gale-v2.dts     | 402 ++++++++++++++++++
 target/linux/ipq40xx/image/Makefile           |  14 +
 .../901-arm-boot-add-dts-files.patch          |   3 +-
 6 files changed, 433 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gale-v2.dts

diff --git a/target/linux/ipq40xx/Makefile b/target/linux/ipq40xx/Makefile
index 94b47c4c96de..c114df620d5c 100644
--- a/target/linux/ipq40xx/Makefile
+++ b/target/linux/ipq40xx/Makefile
@@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
 ARCH:=arm
 BOARD:=ipq40xx
 BOARDNAME:=Qualcomm Atheros IPQ40XX
-FEATURES:=squashfs fpu ramdisk nand
+FEATURES:=squashfs fpu ramdisk nand boot-part rootfs-part
 CPU_TYPE:=cortex-a7
 CPU_SUBTYPE:=neon-vfpv4
 SUBTARGETS:=generic
diff --git a/target/linux/ipq40xx/base-files/etc/board.d/02_network b/target/linux/ipq40xx/base-files/etc/board.d/02_network
index 61d02a17bcc9..f6b2f47e6ce6 100755
--- a/target/linux/ipq40xx/base-files/etc/board.d/02_network
+++ b/target/linux/ipq40xx/base-files/etc/board.d/02_network
@@ -38,6 +38,7 @@ ipq40xx_setup_interfaces()
 		;;
 	asus,map-ac2200|\
 	cilab,meshpoint-one|\
+	google,gale-v2|\
 	openmesh,a42|\
 	openmesh,a62)
 		ucidef_set_interfaces_lan_wan "eth1" "eth0"
diff --git a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
index 5b89710a2255..9cc77e8cb4d0 100644
--- a/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ipq40xx/base-files/lib/upgrade/platform.sh
@@ -40,6 +40,16 @@ askey_do_upgrade() {
 	nand_do_upgrade "$1"
 }
 
+vboot_do_upgrade() {
+	local tar_file="$1"
+
+	echo "Preparing to flash to /dev/mmcblk0p{1,2}"
+	ask_bool 0 "Abort" && exit 1
+
+	tar Oxf "${tar_file}" '*/kernel' | dd of=/dev/mmcblk0p1 bs=1M
+	tar Oxf "${tar_file}" '*/root' | dd of=/dev/mmcblk0p2 bs=1M
+}
+
 zyxel_do_upgrade() {
 	local tar_file="$1"
 
@@ -98,6 +108,9 @@ platform_do_upgrade() {
 	compex,wpj419)
 		nand_do_upgrade "$1"
 		;;
+	google,gale-v2)
+		vboot_do_upgrade "$1"
+		;;
 	linksys,ea6350v3 |\
 	linksys,ea8300)
 		platform_do_upgrade_linksys "$1"
diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gale-v2.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gale-v2.dts
new file mode 100644
index 000000000000..ce0d2b91d05a
--- /dev/null
+++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4019-gale-v2.dts
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016 Google, Inc
+ */
+
+#include "qcom-ipq4019.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+&tlmm {
+	fw_pinmux {
+		wp {
+			pins = "gpio53";
+			output-low;
+		};
+		recovery {
+			pins = "gpio57";
+			bias-none;
+		};
+		developer {
+			pins = "gpio41";
+			bias-none;
+		};
+	};
+
+	reset802_15_4 {
+		pins = "gpio60";
+	};
+
+	led_reset {
+		pins = "gpio22";
+		output-high;
+	};
+
+	sys_reset {
+		pins = "gpio19";
+		output-high;
+	};
+
+	rx_active {
+		pins = "gpio43";
+		bias-pull,down;
+	};
+
+	spi_0_pins: spi_0_pinmux {
+		pinmux {
+			function = "blsp_spi0";
+			pins = "gpio13", "gpio14","gpio15";
+		};
+		pinmux_cs {
+			function = "gpio";
+			pins = "gpio12";
+		};
+		pinconf {
+			pins = "gpio13", "gpio14","gpio15";
+			drive-strength = <12>;
+			bias-disable;
+		};
+		pinconf_cs {
+			pins = "gpio12";
+			drive-strength = <2>;
+			bias-disable;
+			output-high;
+		};
+	};
+
+	spi_1_pins: spi_1_pinmux {
+		pinmux {
+			function = "blsp_spi1";
+			pins = "gpio44", "gpio46","gpio47";
+		};
+		pinmux_cs {
+			function = "gpio";
+			pins = "gpio45";
+		};
+		pinconf {
+			pins = "gpio44", "gpio46","gpio47";
+			drive-strength = <12>;
+			bias-disable;
+		};
+		pinconf_cs {
+			pins = "gpio45";
+			drive-strength = <2>;
+			bias-disable;
+			output-high;
+		};
+	};
+
+	serial_0_pins: serial0_pinmux {
+		mux {
+			pins = "gpio16", "gpio17";
+			function = "blsp_uart0";
+			bias-disable;
+		};
+	};
+
+	serial_1_pins: serial1_pinmux {
+		mux {
+			pins = "gpio8", "gpio9", "gpio10", "gpio11";
+			function = "blsp_uart1";
+			bias-disable;
+		};
+	};
+
+	i2c_0_pins: i2c_0_pinmux {
+		mux {
+			pins = "gpio20", "gpio21";
+			function = "blsp_i2c0";
+			drive-open-drain;
+		};
+	};
+
+	i2c_1_pins: i2c_1_pinmux {
+		mux {
+			pins = "gpio34", "gpio35";
+			function = "blsp_i2c1";
+			drive-open-drain;
+		};
+	};
+
+	sd_0_pins: sd_0_pinmux {
+		sd0 {
+			pins = "gpio23", "gpio24", "gpio25", "gpio26", "gpio29", "gpio30", "gpio31", "gpio32";
+			function = "sdio";
+			drive-strength = <10>;
+			bias-pull-up;
+			pull-up-res = <0>;
+		};
+		sdclk {
+			pins = "gpio27";
+			function = "sdio";
+			drive-strength = <2>;
+			bias-pull-up;
+			pull-up-res = <0>;
+		};
+		sdcmd {
+			pins = "gpio28";
+			function = "sdio";
+			drive-strength = <10>;
+			bias-pull-up;
+			pull-up-res = <0>;
+		};
+	};
+
+	mdio_pins: mdio_pinmux {
+		mux_1 {
+			pins = "gpio6";
+			function = "mdio";
+			bias-disable;
+		};
+		mux_2 {
+			pins = "gpio7";
+			function = "mdc";
+			bias-disable;
+		};
+		mux_3 {
+			pins = "gpio40";
+			function = "gpio";
+			bias-disable;
+			output-high;
+		};
+	};
+
+	wifi1_1_pins: wifi2_pinmux {
+		mux {
+			pins = "gpio58";
+			output-low;
+		};
+	};
+};
+
+/ {
+	model = "Google IPQ4019/Gale";
+	compatible = "google,gale-v2", "qcom,ipq4019";
+
+	chosen {
+		stdout-path = &blsp1_uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512MB */
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		rsvd at 87000000 {
+			/* Reserved for other subsystem */
+			reg = <0x87000000 0x01000000>;
+			no-map;
+		};
+	};
+
+	soc {
+		blsp_dma: dma at 7884000 {
+			status = "okay";
+		};
+
+		usb3: usb3 at 8af8800 {
+			status = "okay";
+		};
+
+		usb2: usb2 at 60f8800 {
+			status = "okay";
+		};
+
+		rng at 22000 {
+			status = "okay";
+		};
+
+		ess-switch at c000000 {
+			status = "okay";
+		};
+
+		edma at c080000 {
+			status = "okay";
+		};
+
+		ess-psgmii at 98000 {
+			status = "okay";
+		};
+
+		watchdog at b017000 {
+			status = "okay";
+		};
+	};
+};
+
+&blsp1_i2c3 {
+	pinctrl-0 = <&i2c_0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	trusted-platform-module at 20 {
+		compatible = "infineon,slb9645tt";
+		reg = <0x20>;
+		powered-while-suspended;
+	};
+};
+
+&blsp1_i2c4 {
+	pinctrl-0 = <&i2c_1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	lp55231 at 32 {
+		compatible = "national,lp5523";
+		reg = <0x32>;
+		clock-mode = [01];
+
+		chan0 {
+			chan-name = "LED0_Red";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan1 {
+			chan-name = "LED0_Green";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan2 {
+			chan-name = "LED0_Blue";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan3 {
+			chan-name = "LED1_Red";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan4 {
+			chan-name = "LED1_Green";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan5 {
+			chan-name = "LED1_Blue";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan6 {
+			chan-name = "LED2_Red";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan7 {
+			chan-name = "LED2_Green";
+			led-cur = [64];
+			max-cur = [78];
+		};
+
+		chan8 {
+			chan-name = "LED2_Blue";
+			led-cur = [64];
+			max-cur = [78];
+		};
+	};
+};
+
+&blsp1_spi1 {
+	pinctrl-0 = <&spi_0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	cs-gpios = <&tlmm 12 0>;
+
+	spidev at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <24000000>;
+	};
+};
+
+&blsp1_spi2 {
+	pinctrl-0 = <&spi_1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	cs-gpios = <&tlmm 45 0>;
+
+	spidev at 0 {
+		compatible = "spidev";
+		reg = <0>;
+		spi-max-frequency = <24000000>;
+	};
+};
+
+&blsp1_uart1 {
+	pinctrl-0 = <&serial_0_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&blsp1_uart2 {
+	pinctrl-0 = <&serial_1_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gmac0 {
+	qcom,phy_mdio_addr = <4>;
+	qcom,poll_required = <1>;
+	qcom,forced_speed = <1000>;
+	qcom,forced_duplex = <1>;
+	vlan_tag = <2 0x20>;
+};
+
+&gmac1 {
+	qcom,phy_mdio_addr = <3>;
+	qcom,forced_duplex = <1>;
+	vlan_tag = <1 0x10>;
+};
+
+&mdio {
+	status = "okay";
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+};
+
+&sdhci {
+	status = "okay";
+	pinctrl-0 = <&sd_0_pins>;
+	pinctrl-names = "default";
+	clock-frequency = <192000000>;
+	vqmmc-supply = <&vqmmc>;
+	non-removable;
+};
+
+&usb2_hs_phy {
+	status = "okay";
+};
+
+&usb3_ss_phy {
+	status = "okay";
+};
+
+&usb3_hs_phy {
+	status = "okay";
+};
+
+&vqmmc {
+	status = "okay";
+};
+
+&wifi0 {
+	status = "okay";
+};
+
+&wifi1 {
+	status = "okay";
+	pinctrl-0 = <&wifi1_1_pins>;
+	pinctrl-names = "default";
+};
diff --git a/target/linux/ipq40xx/image/Makefile b/target/linux/ipq40xx/image/Makefile
index 51e8bcc7e36d..83d148b90950 100644
--- a/target/linux/ipq40xx/image/Makefile
+++ b/target/linux/ipq40xx/image/Makefile
@@ -218,6 +218,20 @@ define Device/avm_fritzbox-4040
 endef
 TARGET_DEVICES += avm_fritzbox-4040
 
+define Device/google_gale-v2
+	DEVICE_VENDOR := Google
+	DEVICE_MODEL := WiFi (Gale)
+	SOC := qcom-ipq4019
+	DEVICE_DTS := qcom-ipq4019-gale-v2
+	KERNEL_SUFFIX := -fit-zImage.itb.vboot
+	KERNEL = kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb | cros-vboot
+	KERNEL_NAME := zImage
+	IMAGES += factory.bin
+	IMAGE/factory.bin := cros-image
+	DEVICE_PACKAGES := partx-utils mkf2fs e2fsprogs
+endef
+TARGET_DEVICES += google_gale-v2
+
 define Device/avm_fritzbox-7530
 	$(call Device/FitImageLzma)
 	DEVICE_VENDOR := AVM
diff --git a/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch b/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch
index d281bb468daf..04630a85d679 100644
--- a/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch
+++ b/target/linux/ipq40xx/patches-5.4/901-arm-boot-add-dts-files.patch
@@ -10,7 +10,7 @@ Signed-off-by: John Crispin <john at phrozen.org>
 
 --- a/arch/arm/boot/dts/Makefile
 +++ b/arch/arm/boot/dts/Makefile
-@@ -837,11 +837,50 @@ dtb-$(CONFIG_ARCH_QCOM) += \
+@@ -837,11 +837,51 @@ dtb-$(CONFIG_ARCH_QCOM) += \
  	qcom-apq8074-dragonboard.dtb \
  	qcom-apq8084-ifc6540.dtb \
  	qcom-apq8084-mtp.dtb \
@@ -43,6 +43,7 @@ Signed-off-by: John Crispin <john at phrozen.org>
 +	qcom-ipq4019-fritzbox-7530.dtb \
 +	qcom-ipq4019-fritzrepeater-1200.dtb \
 +	qcom-ipq4019-fritzrepeater-3000.dtb \
++	qcom-ipq4019-gale-v2.dtb \
 +	qcom-ipq4019-map-ac2200.dtb \
 +	qcom-ipq4019-e2600ac-c1.dtb \
 +	qcom-ipq4019-e2600ac-c2.dtb \
-- 
2.27.0




More information about the openwrt-devel mailing list