From 97c5cbc496e9cf8139994cd3ea987f4e9c70adbe Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Wed, 13 Jun 2018 21:14:49 +0800 Subject: [PATCH] ath79: add support for Phicomm K2T This patch adds dts for qca956x and also support for Phicomm K2T The qca965x.dtsi adds nearly all the necessary components. Both ath9k AHB and PCIe worked well. The Phicomm K2T uses MTD partition 'config' to store the mac addresses in JSON format. To extract these fields correctly, a script is introduced: /lib/functions/k2t.sh This script provides a helper function to extract mac addresses, and is used in three places. Hardware spec of Phicomm K2T: CPU: QCA9563 DRAM: 64MB DDR2 Flash: 16MB SPI-NOR Switch: QCA8337 WiFi 5.8GHz: QCA9886 Flash instruction: Apply sysupgrade.bin via serial console: tftp 0x80000000 sysupgrade.bin && erase 0x9f090000 +$filesize && cp.b $fileaddr 0x9f090000 $filesize Signed-off-by: Weijie Gao --- .../ath79/base-files/etc/board.d/02_network | 10 + .../etc/hotplug.d/firmware/11-ath10k-caldata | 52 ++++ .../etc/hotplug.d/ieee80211/10_fix_wifi_mac | 24 ++ .../ath79/base-files/lib/functions/k2t.sh | 55 ++++ .../linux/ath79/dts/qca9563_phicomm-k2t.dts | 151 ++++++++++ target/linux/ath79/dts/qca956x.dtsi | 281 ++++++++++++++++++ target/linux/ath79/image/generic.mk | 14 + 7 files changed, 587 insertions(+) create mode 100644 target/linux/ath79/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac create mode 100755 target/linux/ath79/base-files/lib/functions/k2t.sh create mode 100644 target/linux/ath79/dts/qca9563_phicomm-k2t.dts create mode 100644 target/linux/ath79/dts/qca956x.dtsi diff --git a/target/linux/ath79/base-files/etc/board.d/02_network b/target/linux/ath79/base-files/etc/board.d/02_network index 8e3c9177a22..0c9a5fa4e40 100755 --- a/target/linux/ath79/base-files/etc/board.d/02_network +++ b/target/linux/ath79/base-files/etc/board.d/02_network @@ -2,6 +2,7 @@ . /lib/functions/system.sh . /lib/functions/uci-defaults.sh +. /lib/functions/k2t.sh ath79_setup_interfaces() { @@ -60,6 +61,10 @@ ath79_setup_interfaces() ucidef_add_switch "switch0" \ "0@eth0" "2:lan" "3:lan" "4:lan" "5:lan" "1:wan" ;; + "phicomm,k2t") + ucidef_add_switch "switch0" \ + "0@eth0" "3:lan:1" "5:lan:2" "4:wan" + ;; *) ucidef_set_interfaces_lan_wan "eth0" "eth1" ;; @@ -74,9 +79,14 @@ ath79_setup_macs() avm,fritz300e) lan_mac=$(fritz_tffs -n maca -i $(find_mtd_part "tffs (1)")) ;; + phicomm,k2t) + lan_mac=$(k2t_get_mac "lan_mac") + wan_mac=$(k2t_get_mac "wan_mac") + ;; esac [ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac } board_config_update diff --git a/target/linux/ath79/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/base-files/etc/hotplug.d/firmware/11-ath10k-caldata index 2bbe5923bc3..d862f611e57 100644 --- a/target/linux/ath79/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +++ b/target/linux/ath79/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -1,5 +1,23 @@ #!/bin/sh +. /lib/functions/k2t.sh + +# xor multiple hex values of the same length +xor() { + local val + local ret="0x$1" + local retlen=${#1} + + shift + while [ -n "$1" ]; do + val="0x$1" + ret=$((ret ^ val)) + shift + done + + printf "%0${retlen}x" "$ret" +} + ath10kcal_die() { echo "ath10cal: " "$*" exit 1 @@ -36,6 +54,29 @@ ath10kcal_patch_mac() { macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6 } +ath10kcal_patch_mac_crc() { + local mac=$1 + local mac_offset=6 + local chksum_offset=2 + local xor_mac + local xor_fw_mac + local xor_fw_chksum + + xor_fw_mac=$(hexdump -v -n 6 -s $mac_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE) + xor_fw_mac="${xor_fw_mac:0:4} ${xor_fw_mac:4:4} ${xor_fw_mac:8:4}" + + ath10kcal_patch_mac "$mac" && { + xor_mac=${mac//:/} + xor_mac="${xor_mac:0:4} ${xor_mac:4:4} ${xor_mac:8:4}" + + xor_fw_chksum=$(hexdump -v -n 2 -s $chksum_offset -e '/1 "%02x"' /lib/firmware/$FIRMWARE) + xor_fw_chksum=$(xor $xor_fw_chksum $xor_fw_mac $xor_mac) + + printf "%b" "\x${xor_fw_chksum:0:2}\x${xor_fw_chksum:2:2}" | \ + dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=$chksum_offset count=2 + } +} + [ -e /lib/firmware/$FIRMWARE ] && exit 0 . /lib/functions.sh @@ -52,6 +93,17 @@ case "$FIRMWARE" in ;; esac ;; +"ath10k/pre-cal-pci-0000:00:00.0.bin") + case $board in + phicomm,k2t) + ath10kcal_extract "art" 20480 12064 + ath10kcal_patch_mac_crc $(k2t_get_mac "5g_mac") + + ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ + /lib/firmware/ath10k/QCA9888/hw2.0/board.bin + ;; + esac + ;; *) exit 1 ;; diff --git a/target/linux/ath79/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ath79/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac new file mode 100644 index 00000000000..59c58f9c674 --- /dev/null +++ b/target/linux/ath79/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac @@ -0,0 +1,24 @@ +#!/bin/ash + +[ "$ACTION" == "add" ] || exit 0 + +PHYNBR=${DEVPATH##*/phy} + +[ -n $PHYNBR ] || exit 0 + +. /lib/functions.sh +. /lib/functions/system.sh +. /lib/functions/k2t.sh + +board=$(board_name) + +case "$board" in + phicomm,k2t) + # The K2T factory firmware does use LAN mac address as the 2.4G wifi mac address + [ "$PHYNBR" -eq 1 ] && \ + echo $(k2t_get_mac "lan_mac") > /sys${DEVPATH}/macaddress + ;; + *) + ;; +esac + diff --git a/target/linux/ath79/base-files/lib/functions/k2t.sh b/target/linux/ath79/base-files/lib/functions/k2t.sh new file mode 100755 index 00000000000..1158df818bb --- /dev/null +++ b/target/linux/ath79/base-files/lib/functions/k2t.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright (C) 2018 Weijie Gao +# +# Helper function to extract mac addresses from mtd part for Phicomm K2T +# + +. /lib/functions.sh +. /lib/functions/system.sh +. /usr/share/libubox/jshn.sh + +k2t_config_load() { + local mtd_blk=$(find_mtd_part config) + + if [ -z "$mtd_blk" ]; then + echo "k2t_config_load: no mtd part named config" >&2 + exit 1 + fi + + local json_size=$(dd if=$mtd_blk bs=1 count=8 2>/dev/null) + + json_size="0x$json_size" + json_size=$((json_size)) + + if [ "$?" -ne 0 ]; then + echo "k2t_config_load: invalid json data size" >&2 + exit 2 + fi + + if [ "$json_size" -eq 0 ]; then + echo "k2t_config_load: empty json data" >&2 + exit 3 + fi + + local json_data=$(dd if=$mtd_blk bs=1 skip=8 count=$json_size 2>/dev/null) + + json_load "$json_data" +} + +k2t_get_mac() { + local old_ns + + json_set_namespace "k2t" old_ns + + if k2t_config_load; then + json_select "this_dev_info" + json_get_var val "$1" + json_select .. + fi + + json_set_namespace old_ns + + echo $val +} + diff --git a/target/linux/ath79/dts/qca9563_phicomm-k2t.dts b/target/linux/ath79/dts/qca9563_phicomm-k2t.dts new file mode 100644 index 00000000000..4ff9320d5ca --- /dev/null +++ b/target/linux/ath79/dts/qca9563_phicomm-k2t.dts @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/dts-v1/; + +#include +#include + +#include "qca956x.dtsi" + +/ { + model = "Phicomm K2T"; + compatible = "phicomm,k2t"; + + aliases { + led-status = &status_red; + }; + + chosen { + bootargs = "console=ttyS0,115200n8"; + }; + + leds { + compatible = "gpio-leds"; + + status_blue { + label = "phicomm:blue:status"; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + status_red: status_red { + label = "phicomm:red:status"; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + status_yellow { + label = "phicomm:yellow:status"; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + linux,code = ; + gpios = <&gpio 2 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; +}; + +&uart { + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&pcie { + status = "okay"; +}; + +&spi { + num-cs = <1>; + + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x000000 0x30000>; + read-only; + }; + + partition@30000 { + label = "config"; + reg = <0x030000 0x10000>; + read-only; + }; + + partition@40000 { + label = "permanent"; + reg = <0x040000 0x50000>; + read-only; + }; + + partition@90000 { + label = "firmware"; + reg = <0x090000 0xf60000>; + }; + + art: partition@ff0000 { + label = "art"; + reg = <0xff0000 0x010000>; + read-only; + }; + }; + }; +}; + +&mdio0 { + status = "okay"; + + phy-mask = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "sgmii"; + + qca,ar8327-initvals = < + 0x04 0x00080080 /* PORT0 PAD MODE CTRL */ + 0x10 0x81000080 /* POWER_ON_STRIP */ + 0x50 0xcc35cc35 /* LED_CTRL0 */ + 0x54 0xcb37cb37 /* LED_CTRL1 */ + 0x58 0x00000000 /* LED_CTRL2 */ + 0x5c 0x00f3cf00 /* LED_CTRL3 */ + 0x7c 0x0000007e /* PORT0_STATUS */ + >; + }; +}; + +ð0 { + status = "okay"; + + pll-data = <0x03000101 0x00000101 0x00001919>; + + phy-mode = "sgmii"; + phy-handle = <&phy0>; +}; + +&wmac { + status = "okay"; + mtd-cal-data = <&art 0x1000>; +}; diff --git a/target/linux/ath79/dts/qca956x.dtsi b/target/linux/ath79/dts/qca956x.dtsi new file mode 100644 index 00000000000..c7b6d6e7479 --- /dev/null +++ b/target/linux/ath79/dts/qca956x.dtsi @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +#include +#include "ath79.dtsi" + +/ { + compatible = "qca,qca9560"; + + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "mips,mips74Kc"; + clocks = <&pll ATH79_CLK_CPU>; + reg = <0>; + }; + }; + + extosc: ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "ref"; + clock-frequency = <25000000>; + }; + + ahb { + apb { + ddr_ctrl: memory-controller@18000000 { + compatible = "qca,qca9560-ddr-controller", + "qca,ar7240-ddr-controller"; + reg = <0x18000000 0x100>; + + #qca,ddr-wb-channel-cells = <1>; + }; + + uart: uart@18020000 { + compatible = "ns16550a"; + reg = <0x18020000 0x20>; + + interrupts = <3>; + + clocks = <&pll ATH79_CLK_REF>; + clock-names = "uart"; + + reg-io-width = <4>; + reg-shift = <2>; + no-loopback-test; + + status = "disabled"; + }; + + gpio: gpio@18040000 { + compatible = "qca,qca9560-gpio", + "qca,ar9340-gpio"; + reg = <0x18040000 0x28>; + + interrupts = <2>; + ngpios = <24>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + pinmux: pinmux@1804002c { + compatible = "pinctrl-single"; + + reg = <0x1804002c 0x40>; + + #size-cells = <0>; + + pinctrl-single,bit-per-mux; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0x1>; + #pinctrl-cells = <2>; + + jtag_disable_pins: pinmux_jtag_disable_pins { + pinctrl-single,bits = <0x40 0x2 0x2>; + }; + }; + + pll: pll-controller@18050000 { + compatible = "qca,qca9560-pll", "syscon"; + reg = <0x18050000 0x50>; + + #clock-cells = <1>; + clock-output-names = "cpu", "ddr", "ahb"; + + clocks = <&extosc>; + }; + + wdt: wdt@18060008 { + compatible = "qca,ar7130-wdt"; + reg = <0x18060008 0x8>; + + interrupts = <4>; + + clocks = <&pll ATH79_CLK_AHB>; + clock-names = "wdt"; + }; + + rst: reset-controller@1806001c { + compatible = "qca,qca9560-reset", + "qca,ar7100-reset", + "simple-bus"; + reg = <0x1806001c 0x4>; + + #reset-cells = <1>; + interrupt-parent = <&cpuintc>; + + intc3: interrupt-controller@3 { + compatible = "qcom,qca9556-intc"; + + interrupts = <3>; + + interrupt-controller; + #interrupt-cells = <1>; + + qcom,pending-bits = <0x1f000>, /* pcie rc */ + <0x1000000>, /* usb1 */ + <0x10000000>; /* usb2 */ + }; + }; + + rst2: reset-controller@180600c0 { + compatible = "qca,qca9560-reset", + "qca,ar7100-reset", + "simple-bus"; + reg = <0x180600c0 0x4>; + + #reset-cells = <1>; + }; + + wmac: wmac@18100000 { + compatible = "qca,qca9560-wmac"; + reg = <0x18100000 0x10000>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + + status = "disabled"; + }; + + pcie: pcie-controller@18250000 { + compatible = "qcom,ar7240-pci"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0x0>; + reg = <0x18250000 0x1000>, /* CRP */ + <0x18280000 0x100>, /* CTRL */ + <0x16000000 0x1000>; /* CFG */ + reg-names = "crp_base", "ctrl_base", "cfg_base"; + ranges = <0x2000000 0 0x12000000 0x12000000 0 0x02000000 /* pci memory */ + 0x1000000 0 0x00000000 0x0000000 0 0x000001>; /* io space */ + interrupt-parent = <&intc3>; + interrupts = <0>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-map-mask = <0 0 0 1>; + interrupt-map = <0 0 0 0 &pcie 0>; + status = "disabled"; + }; + }; + + usb0: usb@1b000000 { + compatible = "generic-ehci"; + reg = <0x1b000000 0x1d8>; + + interrupt-parent = <&intc3>; + interrupts = <1>; + + resets = <&rst 5>; + reset-names = "usb-host"; + + has-transaction-translator; + caps-offset = <0x100>; + + phy-names = "usb-phy0"; + phys = <&usb_phy0>; + + status = "disabled"; + }; + + usb1: usb@1b400000 { + compatible = "generic-ehci"; + reg = <0x1b400000 0x1d8>; + + interrupt-parent = <&intc3>; + interrupts = <2>; + + resets = <&rst2 5>; + reset-names = "usb-host"; + + has-transaction-translator; + caps-offset = <0x100>; + + phy-names = "usb-phy1"; + phys = <&usb_phy1>; + + status = "disabled"; + }; + + spi: spi@1f000000 { + compatible = "qca,qca9560-spi", "qca,ar7100-spi"; + reg = <0x1f000000 0x10>; + + clocks = <&pll ATH79_CLK_AHB>; + clock-names = "ahb"; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + usb_phy0: usb-phy { + compatible = "qca,qca9560-usb-phy", "qca,ar7200-usb-phy"; + + reset-names = "usb-phy", "usb-suspend-override"; + resets = <&rst 4>, <&rst 3>; + + #phy-cells = <0>; + + status = "disabled"; + }; + + usb_phy1: usb-phy { + compatible = "qca,qca9560-usb-phy", "qca,ar7200-usb-phy"; + + reset-names = "usb-phy", "usb-suspend-override"; + resets = <&rst2 4>, <&rst2 3>; + + #phy-cells = <0>; + + status = "disabled"; + }; +}; + +&mdio0 { + resets = <&rst 22>; + reset-names = "mdio"; +}; + +ð0 { + compatible = "qca,qca9560-eth", "syscon"; + + pll-data = <0x03000000 0x00000101 0x00001919>; + pll-reg = <0 0x48 0>; + pll-handle = <&pll>; + + phy-mode = "sgmii"; + + resets = <&rst 9>; + reset-names = "mac"; +}; + +&mdio1 { + resets = <&rst 23>; + reset-names = "mdio"; + builtin-switch; +}; + +ð1 { + compatible = "qca,qca9560-eth", "syscon"; + + phy-mode = "gmii"; + + resets = <&rst 13>; + reset-names = "mac"; + + status = "disabled"; +}; diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk index 6e662cea466..16a3c8ed530 100644 --- a/target/linux/ath79/image/generic.mk +++ b/target/linux/ath79/image/generic.mk @@ -75,3 +75,17 @@ define Device/buffalo_wzr-hp-g450h SUPPORTED_DEVICES += wzr-hp-g450h endef TARGET_DEVICES += buffalo_wzr-hp-g450h + +define Device/phicomm-k2t + ATH_SOC := qca9563 + DEVICE_TITLE := Phicomm K2T + KERNEL := kernel-bin | append-dtb | lzma | uImage lzma + KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | uImage lzma + IMAGE_SIZE := 15744k + IMAGES := sysupgrade.bin + IMAGE/default := append-kernel | append-rootfs | pad-rootfs + IMAGE/sysupgrade.bin := $$(IMAGE/default) | append-metadata | check-size $$$$(IMAGE_SIZE) + DEVICE_PACKAGES := kmod-leds-reset kmod-ath10k ath10k-firmware-qca9888 + SUPPORTED_DEVICES += phicomm,k2t +endef +TARGET_DEVICES += phicomm-k2t