From patchwork Sun Dec 13 16:11:41 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josh Bendavid X-Patchwork-Id: 556193 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1BCEF140AB4 for ; Mon, 14 Dec 2015 03:12:07 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=hC9YpQQV; dkim-atps=neutral Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 8D2F5280704; Sun, 13 Dec 2015 17:11:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, HTML_MESSAGE,T_DKIM_INVALID autolearn=unavailable version=3.3.2 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 0E73E280704 for ; Sun, 13 Dec 2015 17:11:31 +0100 (CET) X-policyd-weight: using cached result; rate: -8.5 Received: from mail-pf0-f179.google.com (mail-pf0-f179.google.com [209.85.192.179]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Sun, 13 Dec 2015 17:11:30 +0100 (CET) Received: by pfnn128 with SMTP id n128so92381840pfn.0 for ; Sun, 13 Dec 2015 08:11:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:date:message-id:subject:from:to:cc:content-type; bh=xv4961+qp/w1sZC07MGpwaZuwUazaYJb/2H89nr2k8Q=; b=hC9YpQQVF0L/skJzDafphP3dXlq+799YbBZ62bYuqwHOpkxRyCw2EFHnRcNo0yg4XL PP/PtXh3dZ2/IxHk4MqvldpbOsfJKtZtLrG+VGDxquHl2KwqAinWAMwImmL/lI7gyg0R Yt0lkEL1NqH7WA0peHqXMcSCne0X9NpiwIMLXG4jV+3LbXwVW48YIJeBpFqD73D5ZXbL xd9Mbt3Wa7sptHaPaTK7erYcLvJ+ihU9ywjo4Md7o6yXkcA7QiVU7nM7cbUPiwf19IfG IoxKrYuumDPxjACzG5h3GbRhWZi5HXTI2yOMOakIUb8p8RKFQeHMS28iqiEL60gMC60h AkOA== MIME-Version: 1.0 X-Received: by 10.98.72.14 with SMTP id v14mr17176225pfa.159.1450023101852; Sun, 13 Dec 2015 08:11:41 -0800 (PST) Received: by 10.66.50.69 with HTTP; Sun, 13 Dec 2015 08:11:41 -0800 (PST) Date: Sun, 13 Dec 2015 17:11:41 +0100 X-Google-Sender-Auth: JuCBK6ldjy5mBg7AX4G2P8R6fS0 Message-ID: From: Josh Bendavid To: John Crispin , OpenWrt Development List Cc: Jonas Gorski Subject: [OpenWrt-Devel] [PATCH] [ipq806x] Add initial support for TP-Link Archer C2600 X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" From: Josh Bendavid Add initial support for Archer C2600 to Makefiles and profiles along with needed modifications to tplink-safeloader in firmware-tools. The device tree file is similar to the current ap148 dts, with sata and nand removed, and buttons/led's added. This is sufficient to build a working factory image flashable both from stock web ui and bootloader tftp recovery. Sysupgrade is working as well. There is a patch added here to ath10k to bypass some checks on startup. I believe this is related to the calibration data being provided in external files (dumped from the ART mtd partition at init time) rather than directly from the pcie board. The patch and related discussion is from here: http://lists.infradead.org/pipermail/ath10k/2015-November/006489.html, but will follow up further on the ath10k list, since it may also be related to the board bin files in ath10k-firmware. Working: Wired network, wireless (both bands), power/status/lan/wan/usb led's Not working: wireless status led's (these are not controlled through gpio, but rather through the QCA9980 pcie chips). Also there is no way to set the wan led to orange, which is possible in the stock firmware. Not tested: Hardware buttons. Signed-off-by: Josh Bendavid diff --git a/include/image.mk b/include/image.mk index 6b2fb1a..70b7f4f 100644 --- a/include/image.mk +++ b/include/image.mk @@ -327,6 +327,17 @@ define Build/netgear-dni mv $@.new $@ endef +define Build/tplink-safe + $(STAGING_DIR_HOST)/bin/tplink-safeloader \ + -B $(TPLINK_BOARD_ID) -V OpenWrt.$(REVISION) \ + -k $(word 1,$^) \ + -r $(word 2,$^) \ + -j \ + $(if $(findstring sysupgrade,$1),-S) \ + -o $@.new + mv $@.new $@ +endef + define Build/fit $(TOPDIR)/scripts/mkits.sh \ -D $(DEVICE_NAME) -o $@.its -k $@ \ diff --git a/package/kernel/mac80211/patches/941-ath10k_skip_otp_check.patch b/package/kernel/mac80211/patches/941-ath10k_skip_otp_check.patch new file mode 100644 index 0000000..09cf82c --- /dev/null +++ b/package/kernel/mac80211/patches/941-ath10k_skip_otp_check.patch @@ -0,0 +1,15 @@ +diff -ur ../../old/compat-wireless-2015-12-03/drivers/net/wireless/ath/ath10k/core.c ./drivers/net/wireless/ath/ath10k/core.c +--- a/drivers/net/wireless/ath/ath10k/core.c 2015-12-06 23:36:07.696995166 +0100 ++++ b/drivers/net/wireless/ath/ath10k/core.c 2015-12-07 00:01:50.390388435 +0100 +@@ -1800,9 +1800,9 @@ + + ret = ath10k_core_get_board_id_from_otp(ar); + if (ret && ret != -EOPNOTSUPP) { +- ath10k_err(ar, "failed to get board id from otp: %d\n", ++ ath10k_err(ar, "failed to get board id from otp: %d, ignoring\n", + ret); +- return ret; ++// return ret; + } + + ret = ath10k_core_fetch_board_file(ar); 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 07b5b06..46070ad6 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -19,6 +19,13 @@ r7500) ucidef_set_led_default "wps" "WPS" "r7500:white:wps" "0" ucidef_set_led_default "rfkill" "rfkill" "r7500:white:rfkill" "0" ;; +c2600) + ucidef_set_led_usbdev "usb1" "USB 1" "usb_2:blue" "2-1" + ucidef_set_led_usbdev "usb2" "USB 2" "usb_4:blue" "4-1" + ucidef_set_led_netdev "wan" "WAN" "wan:blue" "eth0" + ucidef_set_led_netdev "lan" "LAN" "lan:blue" "br-lan" + ucidef_set_led_default "general" "general" "ledgnr:blue" "1" + ;; *) ;; esac 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 1302a55..9f061e4 100755 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -13,7 +13,8 @@ board=$(ipq806x_board_name) case "$board" in ap148 |\ -r7500) +r7500 |\ +c2600) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "4:lan" "6@eth1" "5:wan" "0@eth0" ;; 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 new file mode 100644 index 0000000..7a423de --- /dev/null +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata @@ -0,0 +1,66 @@ +#!/bin/sh + +ath10kcal_die() { + echo "ath10cal: " "$*" + exit 1 +} + +ath10kcal_from_file() { + local source=$1 + local offset=$2 + local count=$3 + + dd if=$source of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract calibration data from $source" +} + +ath10kcal_extract() { + local part=$1 + local offset=$2 + local count=$3 + local mtd + + mtd=$(find_mtd_chardev $part) + [ -n "$mtd" ] || \ + ath10kcal_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + ath10kcal_die "failed to extract calibration data from $mtd" +} + +ath10kcal_patch_mac() { + local mac=$1 + + [ -z "$mac" ] && return + + macaddr_2bin $mac | dd of=/lib/firmware/$FIRMWARE conv=notrunc bs=1 seek=6 count=6 +} + +[ -e /lib/firmware/$FIRMWARE ] && exit 0 + +. /lib/ipq806x.sh +. /lib/functions.sh +. /lib/functions/system.sh + +board=$(ipq806x_board_name) + + +case "$FIRMWARE" in +"ath10k/cal-pci-0000:01:00.0.bin") + case $board in + c2600) + ath10kcal_extract "0:ART" 4096 12064 + ;; + esac + ;; +"ath10k/cal-pci-0001:01:00.0.bin") + case $board in + c2600) + ath10kcal_extract "0:ART" 20480 12064 + ;; + esac + ;; +*) + exit 1 + ;; +esac diff --git a/target/linux/ipq806x/base-files/lib/ipq806x.sh b/target/linux/ipq806x/base-files/lib/ipq806x.sh index 5b27bde..262183f 100644 --- a/target/linux/ipq806x/base-files/lib/ipq806x.sh +++ b/target/linux/ipq806x/base-files/lib/ipq806x.sh @@ -23,6 +23,9 @@ ipq806x_board_detect() { *"R7500") name="r7500" ;; + *"C2600") + name="c2600" + ;; esac [ -z "$name" ] && name="unknown" diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index c0e19a1..7fc08bb 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -11,6 +11,14 @@ platform_check_image() { nand_do_platform_check $board $1 return $?; ;; + c2600) + local magic_long="$(get_magic_long "$1")" + [ "$magic_long" != "27051956" ] && { + echo "Invalid image, bad magic: $magic_long" + return 1 + } + return 0; + ;; *) return 1; esac @@ -27,4 +35,28 @@ platform_pre_upgrade() { esac } -# use default for platform_do_upgrade() +platform_do_upgrade() { + local board=$(ipq806x_board_name) + + case "$board" in + c2600) + platform_do_upgrade_c2600 "$ARGV" + ;; + esac +} + +platform_do_upgrade_c2600() { + local kernpart="0:HLOS" + local rootfspart="rootfs" + + local kernel_mtd="$(find_mtd_index $kernpart)" + + local kerndev="/dev/mtd${kernel_mtd}" + local rootfsdev=$rootfspart + + PART_NAME="${kerndev}:${rootfsdev}" + MTD_CONFIG_ARGS="-s 0x200000" + + default_do_upgrade "$ARGV" + +} diff --git a/target/linux/ipq806x/image/Makefile b/target/linux/ipq806x/image/Makefile index 14cf442..956d724 100644 --- a/target/linux/ipq806x/image/Makefile +++ b/target/linux/ipq806x/image/Makefile @@ -85,6 +85,19 @@ define Device/DniImage endef DEVICE_VARS += KERNEL_SIZE NETGEAR_BOARD_ID NETGEAR_HW_ID DEVICE_BLOCK_SIZE DEVICE_PAGE_SIZE +define Device/TpSafeImage + PROFILES += $$(DEVICE_NAME) + FILESYSTEMS := squashfs + KERNEL_SUFFIX := -uImage + KERNEL = kernel-bin | append-dtb | uImage none + KERNEL_NAME := zImage + TPLINK_BOARD_ID := + IMAGES := factory.bin sysupgrade.bin + IMAGE/factory.bin := tplink-safe factory + IMAGE/sysupgrade.bin := tplink-safe sysupgrade +endef +DEVICE_VARS += TPLINK_BOARD_ID + define Device/AP148 $(call Device/FitImage) $(call Device/UbiFit) @@ -103,6 +116,15 @@ define Device/AP148-legacy BOARD_NAME := ap148 endef +define Device/C2600 + $(call Device/TpSafeImage) + DEVICE_DTS := qcom-ipq8064-c2600 + BLOCKSIZE := 128KiB + PAGESIZE := 2048 + BOARD_NAME := c2600 + TPLINK_BOARD_ID := C2600 +endef + define Device/DB149 $(call Device/FitImage) DEVICE_DTS := qcom-ipq8064-db149 @@ -121,6 +143,6 @@ define Device/R7500 BOARD_NAME := r7500 endef -TARGET_DEVICES += AP148 AP148-legacy DB149 R7500 +TARGET_DEVICES += AP148 AP148-legacy C2600 DB149 R7500 $(eval $(call BuildImage)) diff --git a/target/linux/ipq806x/patches-3.18/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch b/target/linux/ipq806x/patches-3.18/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch new file mode 100644 index 0000000..536ae57 --- /dev/null +++ b/target/linux/ipq806x/patches-3.18/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch @@ -0,0 +1,300 @@ +diff -urN a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2015-11-25 22:51:15.148899604 +0100 ++++ b/arch/arm/boot/dts/Makefile 2015-12-06 14:33:31.092396982 +0100 +@@ -362,6 +362,7 @@ + qcom-ipq8064-ap148.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-r7500.dtb \ ++ qcom-ipq8064-c2600.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ + qcom-msm8974-sony-xperia-honami.dtb +diff -urN a/arch/arm/boot/dts/qcom-ipq8064-c2600.dts b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +--- a/arch/arm/boot/dts/qcom-ipq8064-c2600.dts 1970-01-01 01:00:00.000000000 +0100 ++++ b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts 2015-12-06 14:20:05.152365670 +0100 +@@ -0,0 +1,285 @@ ++#include "qcom-ipq8064-v1.0.dtsi" ++#include ++ ++/ { ++ model = "TP-Link Archer C2600"; ++ compatible = "tplink,c2600", "qcom,ipq8064"; ++ ++ memory@0 { ++ reg = <0x42000000 0x1e000000>; ++ device_type = "memory"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ rsvd@41200000 { ++ reg = <0x41200000 0x300000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ mdio-gpio0 = &mdio0; ++ }; ++ ++ chosen { ++ linux,stdout-path = "serial0:115200n8"; ++ }; ++ ++ soc { ++ pinmux@800000 { ++ i2c4_pins: i2c4_pinmux { ++ pins = "gpio12", "gpio13"; ++ function = "gsbi4"; ++ bias-disable; ++ }; ++ ++ spi_pins: spi_pins { ++ mux { ++ pins = "gpio18", "gpio19", "gpio21"; ++ function = "gsbi5"; ++ drive-strength = <10>; ++ bias-none; ++ }; ++ }; ++ ++ nand_pins: nand_pins { ++ mux { ++ pins = "gpio34", "gpio35", "gpio36", ++ "gpio37", "gpio38", "gpio39", ++ "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ function = "nand"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++ ++ pullups { ++ pins = "gpio39"; ++ bias-pull-up; ++ }; ++ ++ hold { ++ pins = "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ bias-bus-hold; ++ }; ++ }; ++ ++ mdio0_pins: mdio0_pins { ++ mux { ++ pins = "gpio0", "gpio1"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ ++ rgmii2_pins: rgmii2_pins { ++ mux { ++ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", ++ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; ++ function = "rgmii2"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ gsbi@16300000 { ++ qcom,mode = ; ++ status = "ok"; ++ serial@16340000 { ++ status = "ok"; ++ }; ++ /* ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ ++ }; ++ ++ gsbi5: gsbi@1a200000 { ++ qcom,mode = ; ++ status = "ok"; ++ ++ spi4: spi@1a280000 { ++ status = "ok"; ++ spi-max-frequency = <50000000>; ++ ++ pinctrl-0 = <&spi_pins>; ++ pinctrl-names = "default"; ++ ++ cs-gpios = <&qcom_pinmux 20 0>; ++ ++ flash: m25p80@0 { ++ compatible = "s25fl256s1"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ spi-max-frequency = <50000000>; ++ reg = <0>; ++ ++ linux,part-probe = "qcom-smem"; ++ }; ++ }; ++ }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; ++ ++ pcie0: pci@1b500000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ pcie1: pci@1b700000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ mdio0: mdio { ++ compatible = "virtual,mdio-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; ++ pinctrl-0 = <&mdio0_pins>; ++ pinctrl-names = "default"; ++ ++ phy0: ethernet-phy@0 { ++ device_type = "ethernet-phy"; ++ 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 */ ++ >; ++ }; ++ ++ phy4: ethernet-phy@4 { ++ device_type = "ethernet-phy"; ++ reg = <4>; ++ }; ++ }; ++ ++ gmac1: ethernet@37200000 { ++ status = "ok"; ++ phy-mode = "rgmii"; ++ qcom,id = <1>; ++ ++ pinctrl-0 = <&rgmii2_pins>; ++ pinctrl-names = "default"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ gmac2: ethernet@37400000 { ++ status = "ok"; ++ phy-mode = "sgmii"; ++ qcom,id = <2>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wifi { ++ label = "wifi"; ++ gpios = <&qcom_pinmux 49 1>; ++ linux,code = ; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&qcom_pinmux 64 1>; ++ linux,code = ; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&qcom_pinmux 65 1>; ++ linux,code = ; ++ }; ++ ledgeneral { ++ label = "ledgeneral"; ++ gpios = <&qcom_pinmux 16 1>; ++ linux,code = ; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ lan { ++ label = "lan:blue"; ++ gpios = <&qcom_pinmux 6 0>; ++ }; ++ usb4 { ++ label = "usb_4:blue"; ++ gpios = <&qcom_pinmux 7 0>; ++ }; ++ usb2 { ++ label = "usb_2:blue"; ++ gpios = <&qcom_pinmux 8 0>; ++ }; ++ wps { ++ label = "wps:blue"; ++ gpios = <&qcom_pinmux 9 0>; ++ }; ++ wan_blue { ++ label = "wan:blue"; ++ gpios = <&qcom_pinmux 33 1>; ++ }; ++ status { ++ label = "status:blue"; ++ gpios = <&qcom_pinmux 53 0>; ++ default-state = "on"; ++ }; ++ ledgnr { ++ label = "ledgnr:blue"; ++ gpios = <&qcom_pinmux 66 0>; ++ }; ++ }; ++}; ++ ++&adm_dma { ++ status = "ok"; ++}; diff --git a/target/linux/ipq806x/patches-4.1/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch b/target/linux/ipq806x/patches-4.1/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch new file mode 100644 index 0000000..ada5254 --- /dev/null +++ b/target/linux/ipq806x/patches-4.1/711-ARM-qcom-add-TP-Link-Archer-C2600-device-tree.patch @@ -0,0 +1,300 @@ +diff -urN a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +--- a/arch/arm/boot/dts/Makefile 2015-11-25 22:51:15.148899604 +0100 ++++ b/arch/arm/boot/dts/Makefile 2015-12-06 14:33:31.092396982 +0100 +@@ -453,6 +453,7 @@ + qcom-ipq8064-ap148.dtb \ + qcom-ipq8064-db149.dtb \ + qcom-ipq8064-r7500.dtb \ ++ qcom-ipq8064-c2600.dtb \ + qcom-msm8660-surf.dtb \ + qcom-msm8960-cdp.dtb \ + qcom-msm8974-sony-xperia-honami.dtb +diff -urN a/arch/arm/boot/dts/qcom-ipq8064-c2600.dts b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts +--- a/arch/arm/boot/dts/qcom-ipq8064-c2600.dts 1970-01-01 01:00:00.000000000 +0100 ++++ b/arch/arm/boot/dts/qcom-ipq8064-c2600.dts 2015-12-06 14:20:05.152365670 +0100 +@@ -0,0 +1,285 @@ ++#include "qcom-ipq8064-v1.0.dtsi" ++#include ++ ++/ { ++ model = "TP-Link Archer C2600"; ++ compatible = "tplink,c2600", "qcom,ipq8064"; ++ ++ memory@0 { ++ reg = <0x42000000 0x1e000000>; ++ device_type = "memory"; ++ }; ++ ++ reserved-memory { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges; ++ rsvd@41200000 { ++ reg = <0x41200000 0x300000>; ++ no-map; ++ }; ++ }; ++ ++ aliases { ++ serial0 = &uart4; ++ mdio-gpio0 = &mdio0; ++ }; ++ ++ chosen { ++ linux,stdout-path = "serial0:115200n8"; ++ }; ++ ++ soc { ++ pinmux@800000 { ++ i2c4_pins: i2c4_pinmux { ++ pins = "gpio12", "gpio13"; ++ function = "gsbi4"; ++ bias-disable; ++ }; ++ ++ spi_pins: spi_pins { ++ mux { ++ pins = "gpio18", "gpio19", "gpio21"; ++ function = "gsbi5"; ++ drive-strength = <10>; ++ bias-none; ++ }; ++ }; ++ ++ nand_pins: nand_pins { ++ mux { ++ pins = "gpio34", "gpio35", "gpio36", ++ "gpio37", "gpio38", "gpio39", ++ "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ function = "nand"; ++ drive-strength = <10>; ++ bias-disable; ++ }; ++ ++ pullups { ++ pins = "gpio39"; ++ bias-pull-up; ++ }; ++ ++ hold { ++ pins = "gpio40", "gpio41", "gpio42", ++ "gpio43", "gpio44", "gpio45", ++ "gpio46", "gpio47"; ++ bias-bus-hold; ++ }; ++ }; ++ ++ mdio0_pins: mdio0_pins { ++ mux { ++ pins = "gpio0", "gpio1"; ++ function = "gpio"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ ++ rgmii2_pins: rgmii2_pins { ++ mux { ++ pins = "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32", ++ "gpio51", "gpio52", "gpio59", "gpio60", "gpio61", "gpio62" ; ++ function = "rgmii2"; ++ drive-strength = <8>; ++ bias-disable; ++ }; ++ }; ++ }; ++ ++ gsbi@16300000 { ++ qcom,mode = ; ++ status = "ok"; ++ serial@16340000 { ++ status = "ok"; ++ }; ++ /* ++ * The i2c device on gsbi4 should not be enabled. ++ * On ipq806x designs gsbi4 i2c is meant for exclusive ++ * RPM usage. Turning this on in kernel manifests as ++ * i2c failure for the RPM. ++ */ ++ }; ++ ++ gsbi5: gsbi@1a200000 { ++ qcom,mode = ; ++ status = "ok"; ++ ++ spi4: spi@1a280000 { ++ status = "ok"; ++ spi-max-frequency = <50000000>; ++ ++ pinctrl-0 = <&spi_pins>; ++ pinctrl-names = "default"; ++ ++ cs-gpios = <&qcom_pinmux 20 0>; ++ ++ flash: m25p80@0 { ++ compatible = "s25fl256s1"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ spi-max-frequency = <50000000>; ++ reg = <0>; ++ ++ linux,part-probe = "qcom-smem"; ++ }; ++ }; ++ }; ++ ++ phy@100f8800 { /* USB3 port 1 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@100f8830 { /* USB3 port 1 SS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8800 { /* USB3 port 0 HS phy */ ++ status = "ok"; ++ }; ++ ++ phy@110f8830 { /* USB3 port 0 SS phy */ ++ status = "ok"; ++ }; ++ ++ usb30@0 { ++ status = "ok"; ++ }; ++ ++ usb30@1 { ++ status = "ok"; ++ }; ++ ++ pcie0: pci@1b500000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ pcie1: pci@1b700000 { ++ status = "ok"; ++ phy-tx0-term-offset = <7>; ++ }; ++ ++ mdio0: mdio { ++ compatible = "virtual,mdio-gpio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ gpios = <&qcom_pinmux 1 0 &qcom_pinmux 0 0>; ++ pinctrl-0 = <&mdio0_pins>; ++ pinctrl-names = "default"; ++ ++ phy0: ethernet-phy@0 { ++ device_type = "ethernet-phy"; ++ 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 */ ++ >; ++ }; ++ ++ phy4: ethernet-phy@4 { ++ device_type = "ethernet-phy"; ++ reg = <4>; ++ }; ++ }; ++ ++ gmac1: ethernet@37200000 { ++ status = "ok"; ++ phy-mode = "rgmii"; ++ qcom,id = <1>; ++ ++ pinctrl-0 = <&rgmii2_pins>; ++ pinctrl-names = "default"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ ++ gmac2: ethernet@37400000 { ++ status = "ok"; ++ phy-mode = "sgmii"; ++ qcom,id = <2>; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wifi { ++ label = "wifi"; ++ gpios = <&qcom_pinmux 49 1>; ++ linux,code = ; ++ }; ++ ++ reset { ++ label = "reset"; ++ gpios = <&qcom_pinmux 64 1>; ++ linux,code = ; ++ }; ++ ++ wps { ++ label = "wps"; ++ gpios = <&qcom_pinmux 65 1>; ++ linux,code = ; ++ }; ++ ledgeneral { ++ label = "ledgeneral"; ++ gpios = <&qcom_pinmux 16 1>; ++ linux,code = ; ++ }; ++ }; ++ ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ lan { ++ label = "lan:blue"; ++ gpios = <&qcom_pinmux 6 0>; ++ }; ++ usb4 { ++ label = "usb_4:blue"; ++ gpios = <&qcom_pinmux 7 0>; ++ }; ++ usb2 { ++ label = "usb_2:blue"; ++ gpios = <&qcom_pinmux 8 0>; ++ }; ++ wps { ++ label = "wps:blue"; ++ gpios = <&qcom_pinmux 9 0>; ++ }; ++ wan_blue { ++ label = "wan:blue"; ++ gpios = <&qcom_pinmux 33 1>; ++ }; ++ status { ++ label = "status:blue"; ++ gpios = <&qcom_pinmux 53 0>; ++ default-state = "on"; ++ }; ++ ledgnr { ++ label = "ledgnr:blue"; ++ gpios = <&qcom_pinmux 66 0>; ++ }; ++ }; ++}; ++ ++&adm_dma { ++ status = "ok"; ++}; diff --git a/target/linux/ipq806x/profiles/tplink.mk b/target/linux/ipq806x/profiles/tplink.mk new file mode 100644 index 0000000..d3f5a6c --- /dev/null +++ b/target/linux/ipq806x/profiles/tplink.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2014 The Linux Foundation. All rights reserved. +# Copyright (C) 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/C2600 + NAME:=TP-Link Archer C2600 + PACKAGES:= \ + kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-usb3 kmod-usb-dwc3-qcom kmod-usb-phy-qcom-dwc3 \ + kmod-ath10k ath10k-firmware-qca99x0 wpad-mini +endef + +define Profile/C2600/Description + Package set for the TP-Link Archer C2600. +endef +$(eval $(call Profile,C2600)) diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c index 77a894b..f43ffd5 100644 --- a/tools/firmware-utils/src/tplink-safeloader.c +++ b/tools/firmware-utils/src/tplink-safeloader.c @@ -105,6 +105,8 @@ static const uint8_t md5_salt[16] = { /** Vendor information for CPE210/220/510/520 */ static const char cpe510_vendor[] = "CPE510(TP-LINK|UN|N300-5):1.0\r\n"; +/** Vendor information for C2600 */ +static const char c2600_vendor[] = ""; /** The flash partition table for CPE210/220/510/520; @@ -128,6 +130,39 @@ static const struct flash_partition_entry cpe510_partitions[] = { }; /** + The flash partition table for C2600; + it is the same as the one used by the stock images. +*/ +static const struct flash_partition_entry c2600_partitions[] = { + {"SBL1", 0x00000, 0x20000}, + {"MIBIB", 0x20000, 0x20000}, + {"SBL2", 0x40000, 0x20000}, + {"SBL3", 0x60000, 0x30000}, + {"DDRCONFIG", 0x90000, 0x10000}, + {"SSD", 0xa0000, 0x10000}, + {"TZ", 0xb0000, 0x30000}, + {"RPM", 0xe0000, 0x20000}, + {"fs-uboot", 0x100000, 0x70000}, + {"uboot-env", 0x170000, 0x40000}, + {"radio", 0x1b0000, 0x40000}, + {"os-image", 0x1f0000, 0x200000}, + {"file-system", 0x3f0000, 0x1b00000}, + {"default-mac", 0x1ef0000, 0x00200}, + {"pin", 0x1ef0200, 0x00200}, + {"product-info", 0x1ef0400, 0x0fc00}, + {"partition-table", 0x1f00000, 0x10000}, + {"soft-version", 0x1f10000, 0x10000}, + {"support-list", 0x1f20000, 0x10000}, + {"profile", 0x1f30000, 0x10000}, + {"default-config", 0x1f40000, 0x10000}, + {"user-config", 0x1f50000, 0x40000}, + {"qos-db", 0x1f90000, 0x40000}, + {"usb-config", 0x1fd0000, 0x10000}, + {"log", 0x1fe0000, 0x20000}, + {NULL, 0, 0} +}; + +/** The support list for CPE210/220/510/520 */ static const char cpe510_support_list[] = @@ -141,6 +176,13 @@ static const char cpe510_support_list[] = "CPE220(TP-LINK|UN|N300-2):1.0\r\n" "CPE220(TP-LINK|UN|N300-2):1.1\r\n"; +/** + The support list for C2600 +*/ +static const char c2600_support_list[] = + "SupportList:\r\n" + "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n"; + #define error(_ret, _errno, _str, ...) \ do { \ fprintf(stderr, _str ": %s\n", ## __VA_ARGS__, \ @@ -240,14 +282,14 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { } /** Generates the support-list partition */ -static struct image_partition_entry make_support_list(const char *support_list) { +static struct image_partition_entry make_support_list(const char *support_list, bool trailzero) { size_t len = strlen(support_list); struct image_partition_entry entry = alloc_image_partition("support-list", len + 9); put32(entry.data, len); memset(entry.data+4, 0, 4); memcpy(entry.data+8, support_list, len); - entry.data[len+8] = '\xff'; + entry.data[len+8] = trailzero ? '\x00' : '\xff'; return entry; } @@ -436,6 +478,37 @@ static void * generate_sysupgrade_image(const struct flash_partition_entry *flas return image; } +static void * generate_sysupgrade_image_c2600(const struct flash_partition_entry *flash_parts, const struct image_partition_entry *image_parts, size_t *len) { + const struct flash_partition_entry *flash_os_image = &flash_parts[11]; + const struct flash_partition_entry *flash_file_system = &flash_parts[12]; + + const struct image_partition_entry *image_os_image = &image_parts[3]; + const struct image_partition_entry *image_file_system = &image_parts[4]; + + assert(strcmp(flash_os_image->name, "os-image") == 0); + assert(strcmp(flash_file_system->name, "file-system") == 0); + + assert(strcmp(image_os_image->name, "os-image") == 0); + assert(strcmp(image_file_system->name, "file-system") == 0); + + if (image_os_image->size > flash_os_image->size) + error(1, 0, "kernel image too big (more than %u bytes)", (unsigned)flash_os_image->size); + if (image_file_system->size > flash_file_system->size) + error(1, 0, "rootfs image too big (more than %u bytes)", (unsigned)flash_file_system->size); + + *len = flash_file_system->base - flash_os_image->base + image_file_system->size; + + uint8_t *image = malloc(*len); + if (!image) + error(1, errno, "malloc"); + + memset(image, 0xff, *len); + + memcpy(image, image_os_image->data, image_os_image->size); + memcpy(image + flash_file_system->base - flash_os_image->base, image_file_system->data, image_file_system->size); + + return image; +} /** Generates an image for CPE210/220/510/520 and writes it to a file */ static void do_cpe510(const char *output, const char *kernel_image, const char *rootfs_image, uint32_t rev, bool add_jffs2_eof, bool sysupgrade) { @@ -443,7 +516,7 @@ static void do_cpe510(const char *output, const char *kernel_image, const char * parts[0] = make_partition_table(cpe510_partitions); parts[1] = make_soft_version(rev); - parts[2] = make_support_list(cpe510_support_list); + parts[2] = make_support_list(cpe510_support_list,false); parts[3] = read_file("os-image", kernel_image, false); parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); @@ -470,6 +543,39 @@ static void do_cpe510(const char *output, const char *kernel_image, const char * free_image_partition(parts[i]); } +/** Generates an image for C2600 and writes it to a file */ +static void do_c2600(const char *output, const char *kernel_image, const char *rootfs_image, uint32_t rev, bool add_jffs2_eof, bool sysupgrade) { + struct image_partition_entry parts[6] = {}; + + parts[0] = make_partition_table(c2600_partitions); + parts[1] = make_soft_version(rev); + parts[2] = make_support_list(c2600_support_list,true); + parts[3] = read_file("os-image", kernel_image, false); + parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); + + size_t len; + void *image; + if (sysupgrade) + image = generate_sysupgrade_image_c2600(c2600_partitions, parts, &len); + else + image = generate_factory_image(c2600_vendor, parts, &len); + + FILE *file = fopen(output, "wb"); + if (!file) + error(1, errno, "unable to open output file"); + + if (fwrite(image, len, 1, file) != 1) + error(1, 0, "unable to write output file"); + + fclose(file); + + free(image); + + size_t i; + for (i = 0; parts[i].name; i++) + free_image_partition(parts[i]); +} + /** Usage output */ static void usage(const char *argv0) { @@ -552,6 +658,8 @@ int main(int argc, char *argv[]) { if (strcmp(board, "CPE510") == 0) do_cpe510(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade); + else if (strcmp(board, "C2600") == 0) + do_c2600(output, kernel_image, rootfs_image, rev, add_jffs2_eof, sysupgrade); else error(1, 0, "unsupported board %s", board);