diff options
Diffstat (limited to 'target/linux/bcm47xx')
92 files changed, 8631 insertions, 0 deletions
diff --git a/target/linux/bcm47xx/Makefile b/target/linux/bcm47xx/Makefile new file mode 100644 index 0000000000..0fb8202ab2 --- /dev/null +++ b/target/linux/bcm47xx/Makefile @@ -0,0 +1,29 @@ +# +# Copyright (C) 2006-2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=mipsel +BOARD:=bcm47xx +BOARDNAME:=Broadcom BCM47xx/53xx (MIPS) +FEATURES:=squashfs usb +SUBTARGETS:=generic mips74k legacy +MAINTAINER:=Hauke Mehrtens <hauke@hauke-m.de> + +KERNEL_PATCHVER:=4.14 +KERNEL_TESTING_PATCHVER := 4.19 + +define Target/Description + Build firmware images for Broadcom based BCM47xx/53xx routers with MIPS CPU, *not* ARM. +endef + +include $(INCLUDE_DIR)/target.mk + +DEFAULT_PACKAGES += swconfig nvram otrx \ + kmod-leds-gpio kmod-gpio-button-hotplug \ + kmod-ledtrig-default-on kmod-ledtrig-timer kmod-ledtrig-netdev + +$(eval $(call BuildTarget)) diff --git a/target/linux/bcm47xx/base-files/etc/board.d/01_network b/target/linux/bcm47xx/base-files/etc/board.d/01_network new file mode 100755 index 0000000000..e6311d8139 --- /dev/null +++ b/target/linux/bcm47xx/base-files/etc/board.d/01_network @@ -0,0 +1,206 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2006-2015 OpenWrt.org + +. /lib/functions/system.sh +. /lib/functions/uci-defaults.sh + +configure_by_vlanports() { + local vlan0ports="$(nvram get vlan0ports)" + local vlan1ports="$(nvram get vlan1ports)" + local vlan2ports="$(nvram get vlan2ports)" + local cpuport="$(swconfig dev switch0 help 2>/dev/null | sed -ne "s|.*cpu @ \([0-9]*\).*|\1|p")" + + if [ "${vlan0ports:0:9}" = "0 1 2 3 8" -a "${vlan1ports:0:3}" = "4 8" -a ${cpuport:-0} -eq 8 ] || \ + [ "${vlan1ports:0:9}" = "0 1 2 3 8" -a "${vlan2ports:0:3}" = "4 8" -a ${cpuport:-0} -eq 8 ] || \ + [ "${vlan2ports:0:9}" = "0 1 2 3 8" -a "${vlan1ports:0:3}" = "4 8" -a ${cpuport:-0} -eq 8 ]; + then + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "8@eth0" + + elif [ "${vlan0ports:0:9}" = "1 2 3 4 8" -a "${vlan1ports:0:3}" = "0 8" -a ${cpuport:-0} -eq 8 ] || \ + [ "${vlan1ports:0:9}" = "1 2 3 4 8" -a "${vlan2ports:0:3}" = "0 8" -a ${cpuport:-0} -eq 8 ] || \ + [ "${vlan2ports:0:9}" = "1 2 3 4 8" -a "${vlan1ports:0:3}" = "0 8" -a ${cpuport:-0} -eq 8 ]; + then + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "8@eth0" + + elif [ "${vlan0ports:0:9}" = "0 1 2 3 5" -a "${vlan1ports:0:3}" = "4 5" -a ${cpuport:-0} -eq 5 ] || \ + [ "${vlan1ports:0:9}" = "0 1 2 3 5" -a "${vlan2ports:0:3}" = "4 5" -a ${cpuport:-0} -eq 5 ] || \ + [ "${vlan2ports:0:9}" = "0 1 2 3 5" -a "${vlan1ports:0:3}" = "4 5" -a ${cpuport:-0} -eq 5 ]; + then + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "5@eth0" + + elif [ "${vlan0ports:0:9}" = "1 2 3 4 5" -a "${vlan1ports:0:3}" = "0 5" -a ${cpuport:-0} -eq 5 ] || \ + [ "${vlan1ports:0:9}" = "1 2 3 4 5" -a "${vlan2ports:0:3}" = "0 5" -a ${cpuport:-0} -eq 5 ] || \ + [ "${vlan2ports:0:9}" = "1 2 3 4 5" -a "${vlan1ports:0:3}" = "0 5" -a ${cpuport:-0} -eq 5 ]; + then + ucidef_add_switch "switch0" \ + "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "5@eth0" + + else + logger -t "01_network" "Unable to determine network configuration" + ucidef_set_interface_lan "eth0" + fi +} + +configure_by_boardnum() { + local boardnum="$1" + + case "$boardnum" in + # WAP54G, Sitecom WL-105b + "2" | \ + "1024") + ucidef_set_interface_lan "eth0" + ;; + + # Generic detection fallback + *) + configure_by_vlanports + ;; + esac +} + +configure_by_boardtype() { + local boardtype="$1" + local boardnum="$2" + + case "$boardtype" in + "bcm94710r4") + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ;; + + "0x0467") + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "5@eth0" + ;; + + "0x042f" | \ + "0x0472") + # WL-500gP + if [ "$boardnum" = "45" ]; then + ucidef_add_switch "switch0" \ + "0:wan" "1:lan" "2:lan" "3:lan" "4:lan" "5@eth0" + + # Generic BCM94704 + else + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:lan" "5@eth0" + + # MAC addresses on 4704 tend to be screwed up. Add a workaround here + local mac="$(nvram get et0macaddr)" + local pat="[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]" + pat="$pat:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]" + pat="$pat:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]" + + case "$mac" in + $pat) + ucidef_set_interface_macaddr "lan" "$mac" + ucidef_set_interface_macaddr "wan" "$(macaddr_add "$mac" 1)" + ;; + esac + fi + ;; + + # Buffalo WBR-B11 and Buffalo WBR-G54 + "bcm94710ap") + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:lan" "5@eth0" + ;; + + *) + configure_by_boardnum "$boardnum" + ;; + esac +} + +configure_by_model() { + local model="$1" + local boardtype="$2" + local boardnum="$3" + + # Netgear WGT634U exception + if grep -sqE 'mtd0: 000(6|a)0000' /proc/mtd; then + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "5@eth0" + return + fi + + case "$model" in + "Asus WLHDD" | \ + "Asus WL300G") + ucidef_set_interface_lan "eth1" + ;; + + "Asus WL330GE") + ucidef_add_switch "switch0" "4:lan" "5t@eth0" + ;; + + "Asus WL500G" | \ + "Microsoft MN-700") + ucidef_set_interfaces_lan_wan "eth0" "eth1" + ;; + + "Asus WL500GP V2") + ucidef_add_switch "switch0" \ + "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "4:wan" "5@eth0" + ;; + + "Asus RT-N12"* | \ + "Buffalo WHR-G125" | \ + "D-Link DIR-330" | \ + "Motorola WR850G" | \ + "Siemens SE505 V2") + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "5@eth0" + ;; + + "Asus WL700") + ucidef_add_switch "switch0" \ + "0:wan" "1:lan" "2:lan" "3:lan" "4:lan" "5@eth0" + ;; + + "Asus WL500W" | \ + "Dell TrueMobile 2300") + ucidef_set_interface_wan "eth1" + ucidef_add_switch "switch0" \ + "0:lan" "1:lan" "2:lan" "3:lan" "5@eth0" + ;; + + "Asus RT-N16"* | \ + "Linksys E3000 V1" | \ + "Netgear WNR3500 V2" | \ + "Netgear WNR3500L") + ucidef_add_switch "switch0" \ + "0:wan" "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "8@eth0" + ;; + + "Netgear WN2500RP V1") + ucidef_add_switch "switch0" \ + "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth0" + ;; + + *) + configure_by_boardtype "$boardtype" "$boardnum" + ;; + esac +} + + +model="$(cat /tmp/sysinfo/model)" +boardtype="$(board_name)" + +case "$boardtype" in + *:*) + boardnum="${boardtype##*:}" + boardtype="${boardtype%:*}" + ;; +esac + +board_config_update + +configure_by_model "$model" "$boardtype" "$boardnum" + +board_config_flush diff --git a/target/linux/bcm47xx/base-files/etc/diag.sh b/target/linux/bcm47xx/base-files/etc/diag.sh new file mode 100644 index 0000000000..91cf4bdf4b --- /dev/null +++ b/target/linux/bcm47xx/base-files/etc/diag.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# Copyright (C) 2006 OpenWrt.org + +. /lib/functions/leds.sh + +get_status_led() { + for led in dmz power diag wps; do + status_led_file=$(find /sys/class/leds/ -name "*${led}*" | head -n1) + if [ ! -f $status_led_file ]; then + status_led=$(basename $status_led_file) + return + fi; + done +} + +set_state() { + get_status_led + + case "$1" in + preinit) + status_led_blink_preinit + ;; + failsafe) + status_led_blink_failsafe + ;; + preinit_regular) + status_led_blink_preinit_regular + ;; + done) + status_led_on + ;; + esac +} diff --git a/target/linux/bcm47xx/base-files/etc/init.d/wmacfixup b/target/linux/bcm47xx/base-files/etc/init.d/wmacfixup new file mode 100755 index 0000000000..ee1b752201 --- /dev/null +++ b/target/linux/bcm47xx/base-files/etc/init.d/wmacfixup @@ -0,0 +1,33 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2010 OpenWrt.org + +START=41 + +boot() { + [ -d /sys/class/ieee80211 ] || exit + + commit=0 + + fixup_wmac() { + local cfg="$1" + local cfmac + + config_get cfmac "$cfg" macaddr + + [ "$cfmac" != "00:90:4c:5f:00:2a" ] || { + local nvmac="$(nvram get il0macaddr 2>/dev/null)" + [ -n "$nvmac" ] && [ "$nvmac != "$cfmac ] && { + uci set wireless.$cfg.macaddr="$nvmac" + commit=1 + } + } + } + + config_load wireless + config_foreach fixup_wmac wifi-device + + [ "$commit" = 1 ] && uci commit wireless +} + +start() { :; } +stop() { :; } diff --git a/target/linux/bcm47xx/base-files/etc/uci-defaults/03_network_migration b/target/linux/bcm47xx/base-files/etc/uci-defaults/03_network_migration new file mode 100644 index 0000000000..e430b41d48 --- /dev/null +++ b/target/linux/bcm47xx/base-files/etc/uci-defaults/03_network_migration @@ -0,0 +1,29 @@ +#!/bin/sh +# +# Copyright (C) 2014-2015 OpenWrt.org +# + +uci show network | grep "\.vlan=0" +[ $? -ne 0 ] && exit 0 + +logger -t network "network config is invalid, creating new one" + +lan_proto="$(uci -q get network.lan.proto)" +lan_ipaddr="$(uci -q get network.lan.ipaddr)" +lan_netmask="$(uci -q get network.lan.netmask)" +wan_proto="$(uci -q get network.wan.proto)" +wan_ipaddr="$(uci -q get network.wan.ipaddr)" +wan_netmask="$(uci -q get network.wan.netmask)" + +echo "" > /etc/config/network +config_generate + +uci set network.lan.proto=$lan_proto +uci set network.lan.ipaddr=$lan_ipaddr +uci set network.lan.netmask=$lan_netmask +uci set network.wan.proto=$wan_proto +uci set network.wan.ipaddr=$wan_ipaddr +uci set network.wan.netmask=$wan_netmask +uci commit network + +exit 0 diff --git a/target/linux/bcm47xx/base-files/etc/uci-defaults/09_fix_crc b/target/linux/bcm47xx/base-files/etc/uci-defaults/09_fix_crc new file mode 100644 index 0000000000..346a532998 --- /dev/null +++ b/target/linux/bcm47xx/base-files/etc/uci-defaults/09_fix_crc @@ -0,0 +1,7 @@ +#!/bin/sh +# +# Copyright (C) 2007 OpenWrt.org +# +# + +mtd fixtrx firmware diff --git a/target/linux/bcm47xx/base-files/lib/preinit/01_sysinfo b/target/linux/bcm47xx/base-files/lib/preinit/01_sysinfo new file mode 100644 index 0000000000..8c7bd399da --- /dev/null +++ b/target/linux/bcm47xx/base-files/lib/preinit/01_sysinfo @@ -0,0 +1,16 @@ +#!/bin/sh + +do_sysinfo_bcm47xx() { + local boardtype="$(nvram get boardtype)" + local boardnum="$(nvram get boardnum)" + local model="$(sed -ne 's/^machine[ \t]*: //p' /proc/cpuinfo)" + + [ -z "$model" ] && model="unknown" + [ -z "$boardtype" ] && boardtype="unknown" + + [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/" + echo "$boardtype${boardnum:+:$boardnum}" > /tmp/sysinfo/board_name + echo "$model" > /tmp/sysinfo/model +} + +boot_hook_add preinit_main do_sysinfo_bcm47xx diff --git a/target/linux/bcm47xx/base-files/lib/upgrade/platform.sh b/target/linux/bcm47xx/base-files/lib/upgrade/platform.sh new file mode 100644 index 0000000000..45815d9fe2 --- /dev/null +++ b/target/linux/bcm47xx/base-files/lib/upgrade/platform.sh @@ -0,0 +1,247 @@ +PART_NAME=firmware + +LXL_FLAGS_VENDOR_LUXUL=0x00000001 + +# $(1): file to read magic from +# $(2): offset in bytes +get_magic_long_at() { + dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' +} + +# $(1): file to read LE long number from +# $(2): offset in bytes +get_le_long_at() { + echo $((0x$(dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/4 "%02x"'))) +} + +platform_expected_image() { + local model="$(cat /tmp/sysinfo/model)" + + case "$model" in + "Netgear WGR614 V8") echo "chk U12H072T00_NETGEAR"; return;; + "Netgear WGR614 V9") echo "chk U12H094T00_NETGEAR"; return;; + "Netgear WGR614 V10") echo "chk U12H139T01_NETGEAR"; return;; + "Netgear WN2500RP V1") echo "chk U12H197T00_NETGEAR"; return;; + "Netgear WN2500RP V2") echo "chk U12H294T00_NETGEAR"; return;; + "Netgear WNDR3300") echo "chk U12H093T00_NETGEAR"; return;; + "Netgear WNDR3400 V1") echo "chk U12H155T00_NETGEAR"; return;; + "Netgear WNDR3400 V2") echo "chk U12H187T00_NETGEAR"; return;; + "Netgear WNDR3400 V3") echo "chk U12H208T00_NETGEAR"; return;; + "Netgear WNDR3400 Vcna") echo "chk U12H155T01_NETGEAR"; return;; + "Netgear WNDR3700 V3") echo "chk U12H194T00_NETGEAR"; return;; + "Netgear WNDR4000") echo "chk U12H181T00_NETGEAR"; return;; + "Netgear WNDR4500 V1") echo "chk U12H189T00_NETGEAR"; return;; + "Netgear WNDR4500 V2") echo "chk U12H224T00_NETGEAR"; return;; + "Netgear WNR2000 V2") echo "chk U12H114T00_NETGEAR"; return;; + "Netgear WNR3500L") echo "chk U12H136T99_NETGEAR"; return;; + "Netgear WNR3500U") echo "chk U12H136T00_NETGEAR"; return;; + "Netgear WNR3500 V2") echo "chk U12H127T00_NETGEAR"; return;; + "Netgear WNR3500 V2vc") echo "chk U12H127T70_NETGEAR"; return;; + "Netgear WNR834B V2") echo "chk U12H081T00_NETGEAR"; return;; + "Linksys E900 V1") echo "cybertan E900"; return;; + "Linksys E1000 V1") echo "cybertan E100"; return;; + "Linksys E1000 V2") echo "cybertan E100"; return;; + "Linksys E1000 V2.1") echo "cybertan E100"; return;; + "Linksys E1200 V2") echo "cybertan E122"; return;; + "Linksys E2000 V1") echo "cybertan 32XN"; return;; + "Linksys E3000 V1") echo "cybertan 61XN"; return;; + "Linksys E3200 V1") echo "cybertan 3200"; return;; + "Linksys E4200 V1") echo "cybertan 4200"; return;; + "Linksys WRT150N V1.1") echo "cybertan N150"; return;; + "Linksys WRT150N V1") echo "cybertan N150"; return;; + "Linksys WRT160N V1") echo "cybertan N150"; return;; + "Linksys WRT160N V3") echo "cybertan N150"; return;; + "Linksys WRT300N V1") echo "cybertan EWCB"; return;; + "Linksys WRT300N V1.1") echo "cybertan EWC2"; return;; + "Linksys WRT310N V1") echo "cybertan 310N"; return;; + "Linksys WRT310N V2") echo "cybertan 310N"; return;; + "Linksys WRT610N V1") echo "cybertan 610N"; return;; + "Linksys WRT610N V2") echo "cybertan 610N"; return;; + "Luxul XAP-310 V1") echo "lxl XAP-310"; return;; + "Luxul XAP-1210 V1") echo "lxl XAP-1210"; return;; + "Luxul XAP-1230 V1") echo "lxl XAP-1230"; return;; + "Luxul XAP-1240 V1") echo "lxl XAP-1240"; return;; + "Luxul XAP-1500 V1") echo "lxl XAP-1500"; return;; + "Luxul ABR-4400 V1") echo "lxl ABR-4400"; return;; + "Luxul XBR-4400 V1") echo "lxl XBR-4400"; return;; + "Luxul XVW-P30 V1") echo "lxl XVW-P30"; return;; + "Luxul XWR-600 V1") echo "lxl XWR-600"; return;; + "Luxul XWR-1750 V1") echo "lxl XWR-1750"; return;; + esac +} + +bcm47xx_identify() { + local magic + + magic=$(get_magic_long "$1") + case "$magic" in + "48445230") + echo "trx" + return + ;; + "2a23245e") + echo "chk" + return + ;; + "4c584c23") + echo "lxl" + return + ;; + esac + + magic=$(get_magic_long_at "$1" 14) + [ "$magic" = "55324e44" ] && { + echo "cybertan" + return + } + + magic=$(get_magic_long_at "$1" 60) + [ "$magic" = "4c584c23" ] && { + echo "lxlold" + return + } + + echo "unknown" +} + +platform_check_image() { + [ "$#" -gt 1 ] && return 1 + + local file_type=$(bcm47xx_identify "$1") + local magic + local error=0 + + case "$file_type" in + "chk") + local header_len=$((0x$(get_magic_long_at "$1" 4))) + local board_id_len=$(($header_len - 40)) + local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"') + local dev_board_id=$(platform_expected_image) + echo "Found CHK image with device board_id $board_id" + + [ -n "$dev_board_id" -a "chk $board_id" != "$dev_board_id" ] && { + echo "Firmware board_id doesn't match device board_id ($dev_board_id)" + error=1 + } + + if ! otrx check "$1" -o "$header_len"; then + echo "No valid TRX firmware in the CHK image" + notify_firmware_test_result "trx_valid" 0 + error=1 + else + notify_firmware_test_result "trx_valid" 1 + fi + ;; + "cybertan") + local pattern=$(dd if="$1" bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%c"') + local dev_pattern=$(platform_expected_image) + echo "Found CyberTAN image with device pattern: $pattern" + + [ -n "$dev_pattern" -a "cybertan $pattern" != "$dev_pattern" ] && { + echo "Firmware pattern doesn't match device pattern ($dev_pattern)" + error=1 + } + + if ! otrx check "$1" -o 32; then + echo "No valid TRX firmware in the CyberTAN image" + notify_firmware_test_result "trx_valid" 0 + error=1 + else + notify_firmware_test_result "trx_valid" 1 + fi + ;; + "lxl") + local hdr_len=$(get_le_long_at "$1" 8) + local flags=$(get_le_long_at "$1" 12) + local board=$(dd if="$1" skip=16 bs=1 count=16 2>/dev/null | hexdump -v -e '1/1 "%c"') + local dev_board=$(platform_expected_image) + echo "Found Luxul image for board $board" + + [ -n "$dev_board" -a "lxl $board" != "$dev_board" ] && { + echo "Firmware ($board) doesn't match device ($dev_board)" + error=1 + } + + [ $((flags & LXL_FLAGS_VENDOR_LUXUL)) -gt 0 ] && notify_firmware_no_backup + + if ! otrx check "$1" -o "$hdr_len"; then + echo "No valid TRX firmware in the Luxul image" + notify_firmware_test_result "trx_valid" 0 + error=1 + else + notify_firmware_test_result "trx_valid" 1 + fi + ;; + "lxlold") + local board_id=$(dd if="$1" skip=48 bs=1 count=12 2>/dev/null | hexdump -v -e '1/1 "%c"') + local dev_board_id=$(platform_expected_image) + echo "Found Luxul image with device board_id $board_id" + + [ -n "$dev_board_id" -a "lxl $board_id" != "$dev_board_id" ] && { + echo "Firmware board_id doesn't match device board_id ($dev_board_id)" + error=1 + } + + notify_firmware_no_backup + + if ! otrx check "$1" -o 64; then + echo "No valid TRX firmware in the Luxul image" + notify_firmware_test_result "trx_valid" 0 + error=1 + else + notify_firmware_test_result "trx_valid" 1 + fi + ;; + "trx") + if ! otrx check "$1"; then + echo "Invalid (corrupted?) TRX firmware" + notify_firmware_test_result "trx_valid" 0 + error=1 + else + notify_firmware_test_result "trx_valid" 1 + fi + ;; + *) + echo "Invalid image type. Please use firmware specific for this device." + notify_firmware_broken + error=1 + ;; + esac + + return $error +} + +platform_trx_from_chk_cmd() { + local header_len=$((0x$(get_magic_long_at "$1" 4))) + + echo -n dd bs=$header_len skip=1 +} + +platform_trx_from_cybertan_cmd() { + echo -n dd bs=32 skip=1 +} + +platform_trx_from_lxl_cmd() { + local hdr_len=$(get_le_long_at "$1" 8) + + echo -n dd skip=$hdr_len iflag=skip_bytes +} + +platform_trx_from_lxlold_cmd() { + echo -n dd bs=64 skip=1 +} + +platform_do_upgrade() { + local file_type=$(bcm47xx_identify "$1") + local trx="$1" + local cmd="" + + case "$file_type" in + "chk") cmd=$(platform_trx_from_chk_cmd "$trx");; + "cybertan") cmd=$(platform_trx_from_cybertan_cmd "$trx");; + "lxl") cmd=$(platform_trx_from_lxl_cmd "$trx");; + "lxlold") cmd=$(platform_trx_from_lxlold_cmd "$trx");; + esac + + default_do_upgrade "$trx" "$cmd" +} diff --git a/target/linux/bcm47xx/config-4.14 b/target/linux/bcm47xx/config-4.14 new file mode 100644 index 0000000000..d26ef6426f --- /dev/null +++ b/target/linux/bcm47xx/config-4.14 @@ -0,0 +1,215 @@ +CONFIG_ADM6996_PHY=y +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set +# CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_BCM47XX=y +CONFIG_BCM47XX_BCMA=y +CONFIG_BCM47XX_NVRAM=y +CONFIG_BCM47XX_SPROM=y +CONFIG_BCM47XX_SSB=y +CONFIG_BCM47XX_WDT=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_DEBUG=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +CONFIG_BCMA_DRIVER_MIPS=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_NFLASH=y +CONFIG_BCMA_PFLASH=y +CONFIG_BCMA_SFLASH=y +# CONFIG_BGMAC_BCMA is not set +CONFIG_BLK_MQ_PCI=y +CONFIG_CEVT_R4K=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="noinitrd console=ttyS0,115200" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +# CONFIG_CPU_BMIPS is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +CONFIG_CPU_MIPSR1=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_EARLY_PRINTK is not set +CONFIG_FIXED_PHY=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_WDT=y +# CONFIG_GRO_CELLS is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +# CONFIG_HAVE_ARCH_BITREVERSE is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CBPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_LEDS_GPIO_REGISTER=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CLOCK_VSYSCALL=y +# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set +CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_BCM47XXSFLASH=y +CONFIG_MTD_BCM47XX_PARTS=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BCM47XXNFLASH=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_PHYSMAP=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NO_EXCEPT_FILL=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +# CONFIG_OF is not set +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_RCU_NEED_SEGCBLIST is not set +# CONFIG_RCU_STALL_COMMON is not set +# CONFIG_SCHED_INFO is not set +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_FSL is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SRCU=y +CONFIG_SSB=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_DEBUG=y +CONFIG_SSB_DRIVER_EXTIF=y +CONFIG_SSB_DRIVER_GIGE=y +CONFIG_SSB_DRIVER_GPIO=y +CONFIG_SSB_DRIVER_MIPS=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_EMBEDDED=y +CONFIG_SSB_HOST_SOC=y +CONFIG_SSB_PCICORE_HOSTMODE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_SERIAL=y +CONFIG_SSB_SFLASH=y +CONFIG_SSB_SPROM=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_B53=y +# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set +CONFIG_SWCONFIG_B53_PHY_DRIVER=y +CONFIG_SWCONFIG_B53_PHY_FIXUP=y +# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_BMIPS=y +CONFIG_SYS_HAS_CPU_BMIPS32_3300=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/bcm47xx/config-4.19 b/target/linux/bcm47xx/config-4.19 new file mode 100644 index 0000000000..8f679b377f --- /dev/null +++ b/target/linux/bcm47xx/config-4.19 @@ -0,0 +1,209 @@ +CONFIG_ADM6996_PHY=y +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_BCM47XX=y +CONFIG_BCM47XX_BCMA=y +CONFIG_BCM47XX_NVRAM=y +CONFIG_BCM47XX_SPROM=y +CONFIG_BCM47XX_SSB=y +CONFIG_BCM47XX_WDT=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_DEBUG=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +CONFIG_BCMA_DRIVER_MIPS=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_DRIVER_PCI_HOSTMODE=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_NFLASH=y +CONFIG_BCMA_PFLASH=y +CONFIG_BCMA_SFLASH=y +# CONFIG_BGMAC_BCMA is not set +CONFIG_BLK_MQ_PCI=y +CONFIG_CEVT_R4K=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="noinitrd console=ttyS0,115200" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +# CONFIG_CPU_BMIPS is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +CONFIG_CPU_MIPSR1=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_DIRECT_OPS=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y +CONFIG_DMA_NONCOHERENT_MMAP=y +CONFIG_DMA_NONCOHERENT_OPS=y +# CONFIG_EARLY_PRINTK is not set +CONFIG_FIXED_PHY=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_WDT=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_ARCH_COMPILER_H=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CBPF_JIT=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_LEDS_GPIO_REGISTER=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MEMFD_CREATE=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CLOCK_VSYSCALL=y +# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set +CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_BCM47XXSFLASH=y +CONFIG_MTD_BCM47XX_PARTS=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_BCM47XXNFLASH=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_PHYSMAP=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NO_EXCEPT_FILL=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_OF is not set +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SRCU=y +CONFIG_SSB=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_DRIVER_EXTIF=y +CONFIG_SSB_DRIVER_GIGE=y +CONFIG_SSB_DRIVER_GPIO=y +CONFIG_SSB_DRIVER_MIPS=y +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_EMBEDDED=y +CONFIG_SSB_HOST_SOC=y +CONFIG_SSB_PCICORE_HOSTMODE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_SERIAL=y +CONFIG_SSB_SFLASH=y +CONFIG_SSB_SPROM=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_B53=y +# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set +CONFIG_SWCONFIG_B53_PHY_DRIVER=y +CONFIG_SWCONFIG_B53_PHY_FIXUP=y +# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_BMIPS=y +CONFIG_SYS_HAS_CPU_BMIPS32_3300=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y +CONFIG_WATCHDOG_CORE=y diff --git a/target/linux/bcm47xx/generic/profiles/100-Broadcom-b43.mk b/target/linux/bcm47xx/generic/profiles/100-Broadcom-b43.mk new file mode 100644 index 0000000000..4c420fb299 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/100-Broadcom-b43.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b43 + NAME:=Broadcom SoC, all Ethernet, BCM43xx WiFi (b43, default) + PACKAGES:=kmod-b44 kmod-tg3 kmod-bgmac kmod-b43 kmod-b43legacy +endef + +define Profile/Broadcom-b43/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the mac80211, b43 and + b43legacy drivers and b44, tg3 or bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-b43)) + diff --git a/target/linux/bcm47xx/generic/profiles/101-Broadcom-wl.mk b/target/linux/bcm47xx/generic/profiles/101-Broadcom-wl.mk new file mode 100644 index 0000000000..c3e9d20c13 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/101-Broadcom-wl.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-wl + NAME:=Broadcom SoC, all Ethernet, BCM43xx WiFi (wl, proprietary) + PACKAGES:=-wpad-basic kmod-b44 kmod-tg3 kmod-bgmac kmod-brcm-wl wlc nas +endef + +define Profile/Broadcom-wl/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the proprietary Broadcom + wireless "wl" driver and b44, tg3 or bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-wl)) + diff --git a/target/linux/bcm47xx/generic/profiles/104-Broadcom-ath5k.mk b/target/linux/bcm47xx/generic/profiles/104-Broadcom-ath5k.mk new file mode 100644 index 0000000000..ca5295f7e3 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/104-Broadcom-ath5k.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-ath5k + NAME:=Broadcom SoC, all Ethernet, Atheros WiFi (ath5k) + PACKAGES:=kmod-b44 kmod-tg3 kmod-bgmac kmod-ath5k +endef + +define Profile/Broadcom-ath5k/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC with Atheros Wifi cards using the mac80211 and ath5k drivers and + b44, tg3 or bgmac Ethernet driver. +endef +$(eval $(call Profile,Broadcom-ath5k)) + diff --git a/target/linux/bcm47xx/generic/profiles/105-Broadcom-none.mk b/target/linux/bcm47xx/generic/profiles/105-Broadcom-none.mk new file mode 100644 index 0000000000..4497124a2e --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/105-Broadcom-none.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-none + NAME:=Broadcom SoC, all Ethernet, No WiFi + PACKAGES:=-wpad-basic kmod-b44 kmod-tg3 kmod-bgmac +endef + +define Profile/Broadcom-none/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC without any Wifi cards and b44, tg3 or bgmac Ethernet driver. +endef +$(eval $(call Profile,Broadcom-none)) + diff --git a/target/linux/bcm47xx/generic/profiles/200-Broadcom-b44-b43.mk b/target/linux/bcm47xx/generic/profiles/200-Broadcom-b44-b43.mk new file mode 100644 index 0000000000..662a7c8e94 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/200-Broadcom-b44-b43.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b44-b43 + NAME:=Broadcom SoC, b44 Ethernet, BCM43xx WiFi (b43, default) + PACKAGES:=kmod-b44 kmod-b43 kmod-b43legacy +endef + +define Profile/Broadcom-b44-b43/Description + Package set compatible with hardware older Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the mac80211, b43 and + b43legacy drivers and b44 Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-b44-b43)) + diff --git a/target/linux/bcm47xx/generic/profiles/201-Broadcom-b44-wl.mk b/target/linux/bcm47xx/generic/profiles/201-Broadcom-b44-wl.mk new file mode 100644 index 0000000000..79b7c5c000 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/201-Broadcom-b44-wl.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b44-wl + NAME:=Broadcom SoC, b44 Ethernet, BCM43xx WiFi (wl, proprietary) + PACKAGES:=-wpad-basic kmod-b44 kmod-brcm-wl wlc nas +endef + +define Profile/Broadcom-b44-wl/Description + Package set compatible with hardware older Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the proprietary Broadcom + wireless "wl" driver and b44 Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-b44-wl)) + diff --git a/target/linux/bcm47xx/generic/profiles/204-Broadcom-b44-ath5k.mk b/target/linux/bcm47xx/generic/profiles/204-Broadcom-b44-ath5k.mk new file mode 100644 index 0000000000..e9dda49d66 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/204-Broadcom-b44-ath5k.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b44-ath5k + NAME:=Broadcom SoC, b44 Ethernet, Atheros WiFi (ath5k) + PACKAGES:=kmod-b44 kmod-ath5k +endef + +define Profile/Broadcom-b44-ath5k/Description + Package set compatible with hardware older Broadcom BCM47xx or BCM535x + SoC with Atheros Wifi cards using the mac80211 and ath5k drivers and + b44 Ethernet driver. +endef +$(eval $(call Profile,Broadcom-b44-ath5k)) + diff --git a/target/linux/bcm47xx/generic/profiles/205-Broadcom-b44-none.mk b/target/linux/bcm47xx/generic/profiles/205-Broadcom-b44-none.mk new file mode 100644 index 0000000000..0854b5041e --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/205-Broadcom-b44-none.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b44-none + NAME:=Broadcom SoC, b44 Ethernet, No WiFi + PACKAGES:=-wpad-basic kmod-b44 +endef + +define Profile/Broadcom-b44-none/Description + Package set compatible with hardware older Broadcom BCM47xx or BCM535x + SoC without any Wifi cards and b44 Ethernet driver. +endef +$(eval $(call Profile,Broadcom-b44-none)) + diff --git a/target/linux/bcm47xx/generic/profiles/210-Broadcom-tg3-b43.mk b/target/linux/bcm47xx/generic/profiles/210-Broadcom-tg3-b43.mk new file mode 100644 index 0000000000..a0bece914d --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/210-Broadcom-tg3-b43.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-tg3-b43 + NAME:=Broadcom SoC, tg3 Ethernet, BCM43xx WiFi (b43) + PACKAGES:=kmod-b43 kmod-tg3 +endef + +define Profile/Broadcom-tg3-b43/Description + Package set compatible with hardware Broadcom BCM4705/BCM4785 + SoCs with Broadcom BCM43xx Wifi cards using the mac80211 and b43 + driver and tg3 Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-tg3-b43)) + diff --git a/target/linux/bcm47xx/generic/profiles/211-Broadcom-tg3-wl.mk b/target/linux/bcm47xx/generic/profiles/211-Broadcom-tg3-wl.mk new file mode 100644 index 0000000000..6946668c91 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/211-Broadcom-tg3-wl.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-tg3-wl + NAME:=Broadcom SoC, tg3 Ethernet, BCM43xx WiFi (wl, proprietary) + PACKAGES:=-wpad-basic kmod-brcm-wl wlc nas kmod-tg3 +endef + +define Profile/Broadcom-tg3-wl/Description + Package set compatible with hardware Broadcom BCM4705/BCM4785 + SoC with Broadcom BCM43xx Wifi cards using the proprietary Broadcom + wireless "wl" driver and tg3 Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-tg3-wl)) + diff --git a/target/linux/bcm47xx/generic/profiles/215-Broadcom-tg3-none.mk b/target/linux/bcm47xx/generic/profiles/215-Broadcom-tg3-none.mk new file mode 100644 index 0000000000..a5a3b4a010 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/215-Broadcom-tg3-none.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-tg3-none + NAME:=Broadcom SoC, tg3 Ethernet, no WiFi + PACKAGES:=-wpad-basic kmod-tg3 +endef + +define Profile/Broadcom-tg3-none/Description + Package set compatible with hardware Broadcom BCM4705/BCM4785 + SoC without any Wifi cards and tg3 Ethernet driver. +endef +$(eval $(call Profile,Broadcom-tg3-none)) + diff --git a/target/linux/bcm47xx/generic/profiles/220-Broadcom-bgmac-b43.mk b/target/linux/bcm47xx/generic/profiles/220-Broadcom-bgmac-b43.mk new file mode 100644 index 0000000000..6ef0691a4c --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/220-Broadcom-bgmac-b43.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-bgmac-b43 + NAME:=Broadcom SoC, bgmac Ethernet, BCM43xx WiFi (b43) + PACKAGES:=kmod-bgmac kmod-b43 +endef + +define Profile/Broadcom-bgmac-b43/Description + Package set compatible with hardware newer Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the mac80211 and b43 + drivers and bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-bgmac-b43)) + diff --git a/target/linux/bcm47xx/generic/profiles/221-Broadcom-bgmac-wl.mk b/target/linux/bcm47xx/generic/profiles/221-Broadcom-bgmac-wl.mk new file mode 100644 index 0000000000..acdc20fb70 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/221-Broadcom-bgmac-wl.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-bgmac-wl + NAME:=Broadcom SoC, bgmac Ethernet, BCM43xx WiFi (wl, proprietary) + PACKAGES:=-wpad-basic kmod-bgmac kmod-brcm-wl wlc nas +endef + +define Profile/Broadcom-bgmac-wl/Description + Package set compatible with hardware newer Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the proprietary Broadcom + wireless "wl" driver and bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-bgmac-wl)) + diff --git a/target/linux/bcm47xx/generic/profiles/225-Broadcom-bgmac-none.mk b/target/linux/bcm47xx/generic/profiles/225-Broadcom-bgmac-none.mk new file mode 100644 index 0000000000..db2d1a264c --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/225-Broadcom-bgmac-none.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2006-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-bgmac-none + NAME:=Broadcom SoC, bgmac Ethernet, No WiFi + PACKAGES:=-wpad-basic kmod-bgmac +endef + +define Profile/Broadcom-bgmac-none/Description + Package set compatible with hardware newer Broadcom BCM47xx or BCM535x + SoC without any Wifi cards and bgmac Ethernet driver. +endef +$(eval $(call Profile,Broadcom-bgmac-none)) + diff --git a/target/linux/bcm47xx/generic/profiles/226-Broadcom-bgmac-brcsmac.mk b/target/linux/bcm47xx/generic/profiles/226-Broadcom-bgmac-brcsmac.mk new file mode 100644 index 0000000000..d9dc9e7a4a --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/226-Broadcom-bgmac-brcsmac.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-bgmac-brcmsmac + NAME:=Broadcom SoC, bgmac Ethernet, BCM43xx WiFi (brcmsmac) + PACKAGES:=kmod-bgmac kmod-brcmsmac +endef + +define Profile/Broadcom-bgmac-brcmsmac/Description + Package set compatable with newer gigabit + N based bcm47xx SoCs with + Broadcom BCM43xx Wifi cards using the mac80211 brcmsmac driver and + bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-bgmac-brcmsmac)) + diff --git a/target/linux/bcm47xx/generic/profiles/PS-1208MFG.mk b/target/linux/bcm47xx/generic/profiles/PS-1208MFG.mk new file mode 100644 index 0000000000..14ee46f200 --- /dev/null +++ b/target/linux/bcm47xx/generic/profiles/PS-1208MFG.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2007-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Ps1208mfg + NAME:=Edimax PS-1208MFG + PACKAGES:=-firewall -dropbear -dnsmasq -mtd -ppp -wpad-basic kmod-b44 block-mount kmod-usb-storage kmod-usb2 kmod-usb-ohci -iptables -swconfig kmod-fs-ext4 +endef + +define Profile/Ps1208mfg/Description + Package set optimize for edimax PS-1208MFG printserver +endef + +$(eval $(call Profile,Ps1208mfg)) + diff --git a/target/linux/bcm47xx/generic/target.mk b/target/linux/bcm47xx/generic/target.mk new file mode 100644 index 0000000000..2f93778b09 --- /dev/null +++ b/target/linux/bcm47xx/generic/target.mk @@ -0,0 +1,9 @@ +BOARDNAME:=Generic +FEATURES+=pcmcia + +DEFAULT_PACKAGES += wpad-basic + +define Target/Description + Build generic firmware for all Broadcom BCM47xx and BCM53xx MIPS + devices. It runs on both architectures BMIPS3300 and MIPS 74K. +endef diff --git a/target/linux/bcm47xx/image/Makefile b/target/linux/bcm47xx/image/Makefile new file mode 100644 index 0000000000..432e787cba --- /dev/null +++ b/target/linux/bcm47xx/image/Makefile @@ -0,0 +1,1070 @@ +# +# Copyright (C) 2006-2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +USB1_PACKAGES := kmod-usb-ohci +USB2_PACKAGES := $(USB1_PACKAGES) kmod-usb2 + +define Build/Clean + $(MAKE) -C lzma-loader clean +endef + +define Image/Prepare + # Optimized LZMA compression (with dictionary), handled by lzma-loader. + cat $(KDIR)/vmlinux | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux.lzma + + # Less optimal LZMA compression (no dictionary), handled by CFE. + $(STAGING_DIR_HOST)/bin/lzma e -so -d16 $(KDIR)/vmlinux > $(KDIR)/vmlinux-nodictionary.lzma + + gzip -nc9 $(KDIR)/vmlinux > $(KDIR)/vmlinux.gz +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + cat $(KDIR)/vmlinux-initramfs | $(STAGING_DIR_HOST)/bin/lzma e -si -so -eos -lc1 -lp2 -pb2 > $(KDIR)/vmlinux-initramfs.lzma + $(STAGING_DIR_HOST)/bin/lzma e -so -d16 $(KDIR)/vmlinux-initramfs > $(KDIR)/vmlinux-initramfs-nodictionary.lzma +endif + rm -f $(KDIR)/loader.gz + $(MAKE) -C lzma-loader \ + BUILD_DIR="$(KDIR)" \ + TARGET="$(KDIR)" \ + clean install + echo -ne "\\x00" >> $(KDIR)/loader.gz + rm -f $(KDIR)/fs_mark + echo -ne '\xde\xad\xc0\xde' > $(KDIR)/fs_mark + $(call prepare_generic_squashfs,$(KDIR)/fs_mark) +endef + +define trxalign/jffs2-128k +-a 0x20000 -f $(KDIR)/root.$(1) +endef +define trxalign/jffs2-64k +-a 0x10000 -f $(KDIR)/root.$(1) +endef +define trxalign/squashfs +-a 1024 -f $(1) $(if $(2),-f $(2)) -a 0x10000 -A $(KDIR)/fs_mark +endef + +################################################# +# Images +################################################# + +define Build/trx-with-loader + $(STAGING_DIR_HOST)/bin/trx \ + -m 33554432 \ + -o $@.new \ + -f $(KDIR)/loader.gz \ + -f $(IMAGE_KERNEL) \ + $(call trxalign/$(FILESYSTEM),$@) + mv $@.new $@ +endef + +define Build/trx-v2-with-loader + $(STAGING_DIR_HOST)/bin/trx \ + -2 \ + -m 33554432 \ + -o $@.new \ + -f $(KDIR)/loader.gz \ + -f $(KDIR)/vmlinux.lzma \ + $(call trxalign/$(FILESYSTEM),$@,$@.pattern) + mv $@.new $@ +endef + +define Build/trx-without-loader + $(STAGING_DIR_HOST)/bin/trx \ + -m 33554432 \ + -o $@.new \ + -f $(IMAGE_KERNEL) \ + $(call trxalign/$(FILESYSTEM),$@) + mv $@.new $@ +endef + +define Build/asus-trx + $(STAGING_DIR_HOST)/bin/asustrx -p $(PRODUCTID) -i $@ -o $@.new + mv $@.new $@ +endef + +define Build/edimax-bin + $(STAGING_DIR_HOST)/bin/trx2edips $@ $@.new + mv $@.new $@ +endef + +define Build/huawei-bin + dd if=/dev/zero of=$@.new bs=92 count=1 + echo -ne 'HDR0\x08\x00\x00\x00' >> $@.new + cat $@ >> $@.new + mv $@.new $@ +endef + +define Build/linksys-bin + $(STAGING_DIR_HOST)/bin/addpattern -4 -p $(DEVICE_ID) -v v$(VERSION) $(if $(SERIAL),-s $(SERIAL)) -i $@ -o $@.new + mv $@.new $@ +endef + +define Build/linksys-pattern-partition + $(STAGING_DIR_HOST)/bin/addpattern -5 -p $(DEVICE_ID) -v v$(VERSION) $(if $(SERIAL),-s $(SERIAL)) -i /dev/null -o $@.pattern +endef + +define Build/motorola-bin + $(STAGING_DIR_HOST)/bin/motorola-bin -$(MOTOROLA_DEVICE) $@ $@.new + mv $@.new $@ +endef + +define Build/prepend-with-elf + mv $@ $@.old + dd if=$(KDIR)/loader.elf of=$@ bs=131072 conv=sync + cat $@.old >> $@ +endef + +define Build/tailed-bin + echo $(BIN_TAIL) >> $@ +endef + +define Build/usrobotics-bin + $(STAGING_DIR_HOST)/bin/trx2usr $@ $@.new + mv $@.new $@ +endef + +################################################# +# Devices +################################################# + +DEVICE_VARS += PRODUCTID +DEVICE_VARS += DEVICE_ID VERSION SERIAL +DEVICE_VARS += NETGEAR_BOARD_ID NETGEAR_REGION +DEVICE_VARS += MOTOROLA_DEVICE +DEVICE_VARS += BIN_TAIL + +define Device/Default + KERNEL := kernel-bin + IMAGE_NAME = $$(IMAGE_PREFIX)-$$(1).$$(2) + KERNEL_NAME = vmlinux.lzma + KERNEL_INITRAMFS_NAME = vmlinux-initramfs.lzma + FILESYSTEMS := $(FS_64K) + IMAGES := trx + IMAGE/trx := append-rootfs | trx-with-loader +endef + +define Device/standard + DEVICE_TITLE := Image with LZMA loader and LZMA compressed kernel +endef + +define Device/standard-noloader-gz + DEVICE_TITLE := Image with gzipped kernel + KERNEL_NAME = vmlinux.gz + IMAGE/trx := append-rootfs | trx-without-loader +endef + +define Device/standard-noloader-nodictionarylzma + DEVICE_TITLE := Image with LZMA compressed kernel matching CFE decompressor + KERNEL_NAME = vmlinux-nodictionary.lzma + IMAGE/trx := append-rootfs | trx-without-loader +endef + +define Device/asus + DEVICE_VENDOR := ASUS + IMAGES := trx + IMAGE/trx := append-rootfs | trx-with-loader | asus-trx +endef + +define Device/linksys + DEVICE_VENDOR := Linksys + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | linksys-bin +endef + +define Device/motorola + DEVICE_VENDOR := Motorola + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | motorola-bin +endef + +define Device/netgear + DEVICE_VENDOR := NETGEAR + IMAGES := chk + IMAGE/chk := append-rootfs | trx-with-loader | netgear-chk +endef + +################################################# +# Subtarget generic +################################################# + +ifeq ($(SUBTARGET),generic) + # BCM4705 with tg3 +define Device/linksys-wrt300n-v1.1 + DEVICE_MODEL := WRT300N + DEVICE_VARIANT := v1.1 + DEVICE_PACKAGES := kmod-tg3 kmod-b43 + $(Device/linksys) + DEVICE_ID := EWC2 + VERSION := 1.51.2 +endef +TARGET_DEVICES += linksys-wrt300n-v1.1 + +define Device/linksys-wrt310n-v1 + DEVICE_MODEL := WRT310N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-tg3 kmod-b43 + $(Device/linksys) + DEVICE_ID := 310N + VERSION := 1.0.10 +endef +TARGET_DEVICES += linksys-wrt310n-v1 + +define Device/linksys-wrt350n-v1 + DEVICE_MODEL := WRT350N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-tg3 kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := EWCG + VERSION := 1.04.1 +endef +TARGET_DEVICES += linksys-wrt350n-v1 + +define Device/linksys-wrt610n-v1 + DEVICE_MODEL := WRT610N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-tg3 kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := 610N + VERSION := 1.0.1 +endef +TARGET_DEVICES += linksys-wrt610n-v1 + + # BCMA SoC with SSB WiFi +define Device/linksys-wrt610n-v2 + DEVICE_MODEL := WRT610N + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-bgmac kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := 610N + VERSION := 2.0.0 +endef +TARGET_DEVICES += linksys-wrt610n-v2 + +define Device/linksys-e3000-v1 + DEVICE_MODEL := E3000 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-bgmac kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := 61XN + VERSION := 1.0.3 +endef +TARGET_DEVICES += linksys-e3000-v1 + +# generic has Ethernet drivers as modules so overwrite standard image +define Device/standard + DEVICE_TITLE := Image with LZMA loader and LZMA compressed kernel + DEVICE_PACKAGES := kmod-b44 kmod-bgmac kmod-tg3 +endef +TARGET_DEVICES += standard +endif + +################################################# +# Subtarget legacy +################################################# + +ifeq ($(SUBTARGET),legacy) + +define Device/asus-wl-300g + DEVICE_MODEL := WL-300g + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy + $(Device/asus) + PRODUCTID := "WL300g " +endef +TARGET_DEVICES += asus-wl-300g + +define Device/asus-wl-320gp + DEVICE_MODEL := WL-320gP + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := "WL320gP " +endef +TARGET_DEVICES += asus-wl-320gp + +define Device/asus-wl-330ge + DEVICE_MODEL := WL-330gE + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := "WL-330gE " +endef +TARGET_DEVICES += asus-wl-330ge + +define Device/asus-wl-500gd + DEVICE_MODEL := WL-500g Deluxe + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := "WL500gx " +endef +TARGET_DEVICES += asus-wl-500gd + +define Device/asus-wl-500gp-v1 + DEVICE_MODEL := WL-500gP + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := "WL500gp " +endef +TARGET_DEVICES += asus-wl-500gp-v1 + +define Device/asus-wl-500gp-v2 + DEVICE_MODEL := WL-500gP + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := "WL500gpv2 " +endef +TARGET_DEVICES += asus-wl-500gp-v2 + +define Device/asus-wl-500w + DEVICE_MODEL := WL-500W + DEVICE_PACKAGES := kmod-b43 kmod-usb-uhci kmod-usb2-pci + $(Device/asus) + PRODUCTID := "WL500W " +endef +TARGET_DEVICES += asus-wl-500w + +define Device/asus-wl-520gu + DEVICE_MODEL := WL-520gU + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := "WL520gu " +endef +TARGET_DEVICES += asus-wl-520gu + +define Device/asus-wl-550ge + DEVICE_MODEL := WL-550gE + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := "WL550gE " +endef +TARGET_DEVICES += asus-wl-550ge + +define Device/asus-wl-hdd25 + DEVICE_MODEL := WL-HDD25 + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy $(USB1_PACKAGES) + $(Device/asus) + PRODUCTID := "WLHDD " +endef +TARGET_DEVICES += asus-wl-hdd25 + +define Device/dlink-dwl-3150 + DEVICE_VENDOR := D-Link + DEVICE_MODEL := DWL-3150 + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | tailed-bin + BIN_TAIL := BCM-5352-2050-0000000-01 +endef +TARGET_DEVICES += dlink-dwl-3150 + +define Device/edimax-ps1208-mfg + DEVICE_VENDOR := Edimax + DEVICE_MODEL := PS-1208MFg + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | edimax-bin +endef +TARGET_DEVICES += edimax-ps1208-mfg + +define Device/huawei-e970 + DEVICE_VENDOR := Huawei + DEVICE_MODEL := E970 + DEVICE_PACKAGES := kmod-b43 + KERNEL_NAME = vmlinux.gz + IMAGES := bin + IMAGE/bin := append-rootfs | trx-without-loader | huawei-bin +endef +TARGET_DEVICES += huawei-e970 + +define Device/linksys-wrt54g3g + DEVICE_MODEL := WRT54G3G + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := W54F + VERSION := 2.20.1 +endef +TARGET_DEVICES += linksys-wrt54g3g + +define Device/linksys-wrt54g3g-em + DEVICE_MODEL := WRT54G3G-EM + $(Device/linksys) + DEVICE_ID := W3GN + VERSION := 2.20.1 +endef +TARGET_DEVICES += linksys-wrt54g3g-em + +define Device/linksys-wrt54g3gv2-vf + DEVICE_VENDOR := Linksys + DEVICE_MODEL := WRT54G3GV2-VF + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + FILESYSTEMS := $(FS_128K) + IMAGES := noheader.bin bin + IMAGE/noheader.bin := linksys-pattern-partition | append-rootfs | trx-v2-with-loader + IMAGE/bin := linksys-pattern-partition | append-rootfs | trx-v2-with-loader | linksys-bin + DEVICE_ID := 3G2V + VERSION := 3.00.24 + SERIAL := 6 +endef +TARGET_DEVICES += linksys-wrt54g3gv2-vf + +define Device/linksys-wrt54g + DEVICE_MODEL := WRT54G + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy + $(Device/linksys) + DEVICE_ID := W54G + VERSION := 4.71.1 +endef +TARGET_DEVICES += linksys-wrt54g + +define Device/linksys-wrt54gs + DEVICE_MODEL := WRT54GS + DEVICE_VARIANT := v1/v2/v3 + DEVICE_ALT0_VENDOR := Linksys + DEVICE_ALT0_MODEL := WRT54G-TM + DEVICE_ALT0_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + FILESYSTEMS := $(FS_128K) + DEVICE_ID := W54S + VERSION := 4.80.1 +endef +TARGET_DEVICES += linksys-wrt54gs + +define Device/linksys-wrt54gs-v4 + DEVICE_MODEL := WRT54GS + DEVICE_VARIANT := v4 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := W54s + VERSION := 1.09.1 +endef +TARGET_DEVICES += linksys-wrt54gs-v4 + +define Device/linksys-wrtsl54gs + DEVICE_MODEL := WRTSL54GS + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + FILESYSTEMS := $(FS_128K) + DEVICE_ID := W54U + VERSION := 2.08.1 +endef +TARGET_DEVICES += linksys-wrtsl54gs + +define Device/linksys-wrt150n + DEVICE_MODEL := WRT150N + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := N150 + VERSION := 1.51.3 +endef +TARGET_DEVICES += linksys-wrt150n + +define Device/linksys-wrt160n-v1 + DEVICE_MODEL := WRT160N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := N150 + VERSION := 1.50.1 +endef +TARGET_DEVICES += linksys-wrt160n-v1 + +define Device/linksys-wrt300n-v1 + DEVICE_MODEL := WRT300N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + IMAGES := bin trx + DEVICE_ID := EWCB + VERSION := 1.03.6 +endef +TARGET_DEVICES += linksys-wrt300n-v1 + +define Device/motorola-wa840g + DEVICE_MODEL := WA840G + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy + $(Device/motorola) + MOTOROLA_DEVICE := 2 +endef +TARGET_DEVICES += motorola-wa840g + +define Device/motorola-we800g + DEVICE_MODEL := WE800G + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy + $(Device/motorola) + MOTOROLA_DEVICE := 3 +endef +TARGET_DEVICES += motorola-we800g + +define Device/motorola-wr850g + DEVICE_MODEL := WR850G + DEVICE_PACKAGES := kmod-b43 kmod-b43legacy + $(Device/motorola) + MOTOROLA_DEVICE := 1 +endef +TARGET_DEVICES += motorola-wr850g + +define Device/netgear-wgr614-v8 + DEVICE_MODEL := WGR614 + DEVICE_VARIANT := v8 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H072T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wgr614-v8 + +define Device/netgear-wgt634u + DEVICE_VENDOR := NETGEAR + DEVICE_MODEL := WGT634U + DEVICE_PACKAGES := kmod-ath5k $(USB2_PACKAGES) + FILESYSTEMS := $(FS_128K) + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | prepend-with-elf +endef +TARGET_DEVICES += netgear-wgt634u + +define Device/netgear-wndr3300-v1 + DEVICE_MODEL := WNDR3300 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H093T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wndr3300-v1 + +define Device/netgear-wnr834b-v2 + DEVICE_MODEL := WNR834B + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H081T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wnr834b-v2 + +define Device/usrobotics-usr5461 + DEVICE_VENDOR := US Robotics + DEVICE_MODEL := USR5461 + DEVICE_PACKAGES := kmod-b43 $(USB1_PACKAGES) + IMAGES := bin + IMAGE/bin := append-rootfs | trx-with-loader | usrobotics-bin +endef +TARGET_DEVICES += usrobotics-usr5461 + +TARGET_DEVICES += standard standard-noloader-gz +endif + +################################################# +# Subtarget mips74k +################################################# + +ifeq ($(SUBTARGET),mips74k) +define Device/asus-rt-ac53u + DEVICE_MODEL := RT-AC53U + DEVICE_PACKAGES := $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-AC53U +endef +TARGET_DEVICES += asus-rt-ac53u + +define Device/asus-rt-ac66u + DEVICE_MODEL := RT-AC66U + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-AC66U +endef +# TARGET_DEVICES += asus-rt-ac66u + +define Device/asus-rt-n10 + DEVICE_MODEL := RT-N10 + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := "RT-N10 " +endef +TARGET_DEVICES += asus-rt-n10 + +define Device/asus-rt-n10p + DEVICE_MODEL := RT-N10P + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := RT-N10P +endef +TARGET_DEVICES += asus-rt-n10p + +define Device/asus-rt-n10p-v2 + DEVICE_MODEL := RT-N10P + DEVICE_VARIANT := v2 + $(Device/asus) + PRODUCTID := RT-N10PV2 +endef +TARGET_DEVICES += asus-rt-n10p-v2 + +define Device/asus-rt-n10u + DEVICE_MODEL := RT-N10U + DEVICE_VARIANT := A + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N10U +endef +TARGET_DEVICES += asus-rt-n10u + +define Device/asus-rt-n10u-b + DEVICE_MODEL := RT-N10U + DEVICE_VARIANT := B + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N10U +endef +TARGET_DEVICES += asus-rt-n10u-b + +define Device/asus-rt-n12 + DEVICE_MODEL := RT-N12 + DEVICE_VARIANT := A1 + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := "RT-N12 " +endef +TARGET_DEVICES += asus-rt-n12 + +define Device/asus-rt-n12-b1 + DEVICE_MODEL := RT-N12 + DEVICE_VARIANT := B1 + $(Device/asus) + PRODUCTID := RT-N12B1 +endef +TARGET_DEVICES += asus-rt-n12-b1 + +define Device/asus-rt-n12-c1 + DEVICE_MODEL := RT-N12 + DEVICE_VARIANT := C1 + $(Device/asus) + PRODUCTID := RT-N12C1 +endef +TARGET_DEVICES += asus-rt-n12-c1 + +define Device/asus-rt-n12-d1 + DEVICE_MODEL := RT-N12 + DEVICE_VARIANT := D1 + $(Device/asus) + PRODUCTID := RT-N12D1 +endef +TARGET_DEVICES += asus-rt-n12-d1 + +define Device/asus-rt-n12hp + DEVICE_MODEL := RT-N12HP + $(Device/asus) + PRODUCTID := RT-N12HP +endef +TARGET_DEVICES += asus-rt-n12hp + +define Device/asus-rt-n14uhp + DEVICE_MODEL := RT-N14UHP + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N14UHP +endef +TARGET_DEVICES += asus-rt-n14uhp + +define Device/asus-rt-n15u + DEVICE_MODEL := RT-N15U + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N15U +endef +TARGET_DEVICES += asus-rt-n15u + +define Device/asus-rt-n16 + DEVICE_MODEL := RT-N16 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N16 +endef +TARGET_DEVICES += asus-rt-n16 + +define Device/asus-rt-n53 + DEVICE_MODEL := RT-N53 + DEVICE_PACKAGES := kmod-b43 + $(Device/asus) + PRODUCTID := RT-N53 +endef +TARGET_DEVICES += asus-rt-n53 + +define Device/asus-rt-n66u + DEVICE_MODEL := RT-N66U + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N66U +endef +TARGET_DEVICES += asus-rt-n66u + +define Device/asus-rt-n66w + DEVICE_MODEL := RT-N66W + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/asus) + PRODUCTID := RT-N66U +endef +TARGET_DEVICES += asus-rt-n66w + +define Device/linksys-wrt160n-v3 + DEVICE_MODEL := WRT160N + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := N150 + VERSION := 3.0.3 +endef +TARGET_DEVICES += linksys-wrt160n-v3 + +define Device/linksys-wrt310n-v2 + DEVICE_MODEL := WRT310N + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 310N + VERSION := 2.0.1 +endef +TARGET_DEVICES += linksys-wrt310n-v2 + +define Device/linksys-wrt320n-v1 + DEVICE_MODEL := WRT320N + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 320N + VERSION := 1.0.5 +endef +TARGET_DEVICES += linksys-wrt320n-v1 + +define Device/linksys-e900-v1 + DEVICE_MODEL := E900 + DEVICE_VARIANT := v1 + $(Device/linksys) + DEVICE_ID := E900 + VERSION := 1.0.4 +endef +TARGET_DEVICES += linksys-e900-v1 + +define Device/linksys-e1000 + DEVICE_MODEL := E1000 + DEVICE_VARIANT := v1/v2/v2.1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := E100 + VERSION := 1.1.3 +endef +TARGET_DEVICES += linksys-e1000 + +define Device/linksys-e1200-v1 + DEVICE_MODEL := E1200 + DEVICE_VARIANT := v1 + $(Device/linksys) + DEVICE_ID := E120 + VERSION := 1.0.3 +endef +TARGET_DEVICES += linksys-e1200-v1 + +define Device/linksys-e1200-v2 + DEVICE_MODEL := E1200 + DEVICE_VARIANT := v2 + $(Device/linksys) + DEVICE_ID := E122 + VERSION := 1.0.4 +endef +TARGET_DEVICES += linksys-e1200-v2 + +define Device/linksys-e1500-v1 + DEVICE_MODEL := E1500 + DEVICE_VARIANT := v1 + $(Device/linksys) + DEVICE_ID := E150 + VERSION := 1.0.5 +endef +TARGET_DEVICES += linksys-e1500-v1 + +define Device/linksys-e1550-v1 + DEVICE_MODEL := E1550 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := 1550 + VERSION := 1.0.3 +endef +TARGET_DEVICES += linksys-e1550-v1 + +define Device/linksys-e2000-v1 + DEVICE_MODEL := E2000 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 32XN + VERSION := 1.0.4 +endef +TARGET_DEVICES += linksys-e2000-v1 + +define Device/linksys-e2500-v1 + DEVICE_MODEL := E2500 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := E25X + VERSION := 1.0.7 +endef +TARGET_DEVICES += linksys-e2500-v1 + +define Device/linksys-e2500-v2 + DEVICE_MODEL := E2500 + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := E25X + VERSION := 2.0.0 +endef +TARGET_DEVICES += linksys-e2500-v2 + +define Device/linksys-e2500-v2.1 + DEVICE_MODEL := E2500 + DEVICE_VARIANT := v2.1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 25RU + VERSION := 2.1.0 +endef +TARGET_DEVICES += linksys-e2500-v2.1 + +define Device/linksys-e2500-v3 + DEVICE_MODEL := E2500 + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 25V3 + VERSION := 3.0.0 +endef +TARGET_DEVICES += linksys-e2500-v3 + +define Device/linksys-e3200-v1 + DEVICE_MODEL := E3200 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/linksys) + DEVICE_ID := 3200 + VERSION := 1.0.1 +endef +TARGET_DEVICES += linksys-e3200-v1 + +define Device/linksys-e4200-v1 + DEVICE_MODEL := E4200 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/linksys) + DEVICE_ID := 4200 + VERSION := 1.0.5 +endef +TARGET_DEVICES += linksys-e4200-v1 + +define Device/netgear-wgr614-v10-na + DEVICE_MODEL := WGR614 + DEVICE_VARIANT := v10 (NA) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H139T01_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wgr614-v10-na + +define Device/netgear-wgr614-v10 + DEVICE_MODEL := WGR614 + DEVICE_VARIANT := v10 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H139T01_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wgr614-v10 + +define Device/netgear-wn2500rp-v1 + DEVICE_MODEL := WN2500RP + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H197T00_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wn2500rp-v1 + +define Device/netgear-wn3000rp + DEVICE_MODEL := WN3000RP + $(Device/netgear) + NETGEAR_BOARD_ID := U12H163T01_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wn3000rp + +define Device/netgear-wndr3400-v1 + DEVICE_MODEL := WNDR3400 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H155T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wndr3400-v1 + +define Device/netgear-wndr3400-v2 + DEVICE_MODEL := WNDR3400 + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H187T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wndr3400-v2 + +define Device/netgear-wndr3400-v3 + DEVICE_MODEL := WNDR3400 + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H208T00_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wndr3400-v3 + +define Device/netgear-wndr3700-v3 + DEVICE_MODEL := WNDR3700 + DEVICE_VARIANT := v3 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H194T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wndr3700-v3 + +define Device/netgear-wndr3400-vcna + DEVICE_MODEL := WNDR3400 + DEVICE_VARIANT := vcna + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H155T01_NETGEAR + NETGEAR_REGION := 2 +endef +# TARGET_DEVICES += netgear-wndr3400-vcna + +define Device/netgear-wndr4000 + DEVICE_MODEL := WNDR4000 + DEVICE_VARIANT := v1 + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H181T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wndr4000 + +define Device/netgear-wnr1000-v3 + DEVICE_MODEL := WNR1000 + DEVICE_VARIANT := v3 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H139T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wnr1000-v3 + +define Device/netgear-wnr2000v2 + DEVICE_MODEL := WNR2000 + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H114T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wnr2000v2 + +define Device/netgear-wnr3500l-v1-na + DEVICE_MODEL := WNR3500L + DEVICE_VARIANT := v1 (NA) + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H136T99_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wnr3500l-v1-na + +define Device/netgear-wnr3500l-v1 + DEVICE_MODEL := WNR3500L + DEVICE_VARIANT := v1 (ROW) + DEVICE_PACKAGES := kmod-b43 $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H136T99_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wnr3500l-v1 + +define Device/netgear-wnr3500l-v2 + DEVICE_MODEL := WNR3500L + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H172T00_NETGEAR + NETGEAR_REGION := 1 +endef +TARGET_DEVICES += netgear-wnr3500l-v2 + +define Device/netgear-wnr3500u + DEVICE_MODEL := WNR3500U + DEVICE_PACKAGES := $(USB2_PACKAGES) + $(Device/netgear) + NETGEAR_BOARD_ID := U12H136T00_NETGEAR + NETGEAR_REGION := 2 +endef +# TARGET_DEVICES += netgear-wnr3500u + +define Device/netgear-wnr3500-v2 + DEVICE_MODEL := WNR3500 + DEVICE_VARIANT := v2 + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H127T00_NETGEAR + NETGEAR_REGION := 2 +endef +TARGET_DEVICES += netgear-wnr3500-v2 + +define Device/netgear-wnr3500-v2-vc + DEVICE_MODEL := WNR3500 + DEVICE_VARIANT := v2 (VC) + DEVICE_PACKAGES := kmod-b43 + $(Device/netgear) + NETGEAR_BOARD_ID := U12H127T70_NETGEAR + NETGEAR_REGION := 2 +endef +# TARGET_DEVICES += netgear-wnr3500-v2-vc + +TARGET_DEVICES += standard standard-noloader-nodictionarylzma +endif + +################################################# +# Shared BuildImage defines +################################################# + +define Image/Build/Initramfs + $(STAGING_DIR_HOST)/bin/trx \ + -m 33554432 \ + -o $(BIN_DIR)/$(IMG_PREFIX)-initramfs.trx \ + -f $(KDIR)/loader.gz \ + -f $(KDIR)/vmlinux-initramfs.lzma + $(STAGING_DIR_HOST)/bin/trx \ + -m 33554432 \ + -o $(BIN_DIR)/$(IMG_PREFIX)-initramfs-noloader-nodictionary.trx \ + -f $(KDIR)/vmlinux-initramfs-nodictionary.lzma +endef + +# $(1): filesystem type. +define Image/Build + # TODO: Move it to Device/* +ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),) + $(call Image/Build/Initramfs) +endif +endef + +$(eval $(call BuildImage)) diff --git a/target/linux/bcm47xx/image/lzma-loader/Makefile b/target/linux/bcm47xx/image/lzma-loader/Makefile new file mode 100644 index 0000000000..5dd6f50977 --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME := lzma-loader +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +$(PKG_BUILD_DIR)/.prepared: + mkdir $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ + touch $@ + +$(PKG_BUILD_DIR)/loader.gz: $(PKG_BUILD_DIR)/.prepared + $(MAKE) -C $(PKG_BUILD_DIR) CC="$(TARGET_CC)" \ + LD="$(TARGET_CROSS)ld" CROSS_COMPILE="$(TARGET_CROSS)" + +download: +prepare: $(PKG_BUILD_DIR)/.prepared +compile: $(PKG_BUILD_DIR)/loader.gz +install: + +ifneq ($(TARGET),) +install: compile + $(CP) $(PKG_BUILD_DIR)/loader.gz $(PKG_BUILD_DIR)/loader.elf $(TARGET)/ +endif + +clean: + rm -rf $(PKG_BUILD_DIR) diff --git a/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.c b/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.c new file mode 100644 index 0000000000..951700bddf --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.c @@ -0,0 +1,663 @@ +/* + LzmaDecode.c + LZMA Decoder + + LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#ifndef Byte +#define Byte unsigned char +#endif + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +typedef struct _CRangeDecoder +{ + Byte *Buffer; + Byte *BufferLim; + UInt32 Range; + UInt32 Code; + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback; + int Result; + #endif + int ExtraBytes; +} CRangeDecoder; + +Byte RangeDecoderReadByte(CRangeDecoder *rd) +{ + if (rd->Buffer == rd->BufferLim) + { + #ifdef _LZMA_IN_CB + UInt32 size; + rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); + rd->BufferLim = rd->Buffer + size; + if (size == 0) + #endif + { + rd->ExtraBytes = 1; + return 0xFF; + } + } + return (*rd->Buffer++); +} + +/* #define ReadByte (*rd->Buffer++) */ +#define ReadByte (RangeDecoderReadByte(rd)) + +void RangeDecoderInit(CRangeDecoder *rd, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback + #else + Byte *stream, UInt32 bufferSize + #endif + ) +{ + int i; + #ifdef _LZMA_IN_CB + rd->InCallback = inCallback; + rd->Buffer = rd->BufferLim = 0; + #else + rd->Buffer = stream; + rd->BufferLim = stream + bufferSize; + #endif + rd->ExtraBytes = 0; + rd->Code = 0; + rd->Range = (0xFFFFFFFF); + for(i = 0; i < 5; i++) + rd->Code = (rd->Code << 8) | ReadByte; +} + +#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; +#define RC_FLUSH_VAR rd->Range = range; rd->Code = code; +#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } + +UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) +{ + RC_INIT_VAR + UInt32 result = 0; + int i; + for (i = numTotalBits; i > 0; i--) + { + /* UInt32 t; */ + range >>= 1; + + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + /* + t = (code - range) >> 31; + t &= 1; + code -= range & (t - 1); + result = (result + result) | (1 - t); + */ + RC_NORMALIZE + } + RC_FLUSH_VAR + return result; +} + +int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) +{ + UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; + if (rd->Code < bound) + { + rd->Range = bound; + *prob += (kBitModelTotal - *prob) >> kNumMoveBits; + if (rd->Range < kTopValue) + { + rd->Code = (rd->Code << 8) | ReadByte; + rd->Range <<= 8; + } + return 0; + } + else + { + rd->Range -= bound; + rd->Code -= bound; + *prob -= (*prob) >> kNumMoveBits; + if (rd->Range < kTopValue) + { + rd->Code = (rd->Code << 8) | ReadByte; + rd->Range <<= 8; + } + return 1; + } +} + +#define RC_GET_BIT2(prob, mi, A0, A1) \ + UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ + if (code < bound) \ + { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ + else \ + { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ + RC_NORMALIZE + +#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) + +int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +{ + int mi = 1; + int i; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + for(i = numLevels; i > 0; i--) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + mi; + RC_GET_BIT(prob, mi) + #else + mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); + #endif + } + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return mi - (1 << numLevels); +} + +int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +{ + int mi = 1; + int i; + int symbol = 0; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + for(i = 0; i < numLevels; i++) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + mi; + RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) + #else + int bit = RangeDecoderBitDecode(probs + mi, rd); + mi = mi + mi + bit; + symbol |= (bit << i); + #endif + } + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) +{ + int symbol = 1; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + do + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + symbol; + RC_GET_BIT(prob, symbol) + #else + symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); + #endif + } + while (symbol < 0x100); + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) +{ + int symbol = 1; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + do + { + int bit; + int matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + #ifdef _LZMA_LOC_OPT + { + CProb *prob = probs + ((1 + matchBit) << 8) + symbol; + RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) + } + #else + bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd); + symbol = (symbol << 1) | bit; + #endif + if (matchBit != bit) + { + while (symbol < 0x100) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + symbol; + RC_GET_BIT(prob, symbol) + #else + symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); + #endif + } + break; + } + } + while (symbol < 0x100); + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) +{ + if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) + return RangeDecoderBitTreeDecode(p + LenLow + + (posState << kLenNumLowBits), kLenNumLowBits, rd); + if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) + return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + + (posState << kLenNumMidBits), kLenNumMidBits, rd); + return kLenNumLowSymbols + kLenNumMidSymbols + + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); +} + +#define kNumStates 12 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +#ifdef _LZMA_OUT_READ + +typedef struct _LzmaVarState +{ + CRangeDecoder RangeDecoder; + Byte *Dictionary; + UInt32 DictionarySize; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 Reps[4]; + int lc; + int lp; + int pb; + int State; + int PreviousIsMatch; + int RemainLen; +} LzmaVarState; + +int LzmaDecoderInit( + unsigned char *buffer, UInt32 bufferSize, + int lc, int lp, int pb, + unsigned char *dictionary, UInt32 dictionarySize, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback + #else + unsigned char *inStream, UInt32 inSize + #endif + ) +{ + LzmaVarState *vs = (LzmaVarState *)buffer; + CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); + UInt32 i; + if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState)) + return LZMA_RESULT_NOT_ENOUGH_MEM; + vs->Dictionary = dictionary; + vs->DictionarySize = dictionarySize; + vs->DictionaryPos = 0; + vs->GlobalPos = 0; + vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1; + vs->lc = lc; + vs->lp = lp; + vs->pb = pb; + vs->State = 0; + vs->PreviousIsMatch = 0; + vs->RemainLen = 0; + dictionary[dictionarySize - 1] = 0; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + RangeDecoderInit(&vs->RangeDecoder, + #ifdef _LZMA_IN_CB + inCallback + #else + inStream, inSize + #endif + ); + return LZMA_RESULT_OK; +} + +int LzmaDecode(unsigned char *buffer, + unsigned char *outStream, UInt32 outSize, + UInt32 *outSizeProcessed) +{ + LzmaVarState *vs = (LzmaVarState *)buffer; + CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); + CRangeDecoder rd = vs->RangeDecoder; + int state = vs->State; + int previousIsMatch = vs->PreviousIsMatch; + Byte previousByte; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + UInt32 nowPos = 0; + UInt32 posStateMask = (1 << (vs->pb)) - 1; + UInt32 literalPosMask = (1 << (vs->lp)) - 1; + int lc = vs->lc; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + if (len == -1) + { + *outSizeProcessed = 0; + return LZMA_RESULT_OK; + } + + while(len > 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; +#else + +int LzmaDecode( + Byte *buffer, UInt32 bufferSize, + int lc, int lp, int pb, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + unsigned char *inStream, UInt32 inSize, + #endif + unsigned char *outStream, UInt32 outSize, + UInt32 *outSizeProcessed) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); + CProb *p = (CProb *)buffer; + CRangeDecoder rd; + UInt32 i; + int state = 0; + int previousIsMatch = 0; + Byte previousByte = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + UInt32 nowPos = 0; + UInt32 posStateMask = (1 << pb) - 1; + UInt32 literalPosMask = (1 << lp) - 1; + int len = 0; + if (bufferSize < numProbs * sizeof(CProb)) + return LZMA_RESULT_NOT_ENOUGH_MEM; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + RangeDecoderInit(&rd, + #ifdef _LZMA_IN_CB + inCallback + #else + inStream, inSize + #endif + ); +#endif + + *outSizeProcessed = 0; + while(nowPos < outSize) + { + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + #ifdef _LZMA_IN_CB + if (rd.Result != LZMA_RESULT_OK) + return rd.Result; + #endif + if (rd.ExtraBytes != 0) + return LZMA_RESULT_DATA_ERROR; + if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) + { + CProb *probs = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + if (previousIsMatch) + { + Byte matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); + previousIsMatch = 0; + } + else + previousByte = LzmaLiteralDecode(probs, &rd); + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + } + else + { + previousIsMatch = 1; + if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) + { + if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) + { + if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + if ( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + == 0) + return LZMA_RESULT_DATA_ERROR; + state = state < 7 ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + continue; + } + } + else + { + UInt32 distance; + if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) + distance = rep1; + else + { + if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = LzmaLenDecode(p + RepLenCoder, &rd, posState); + state = state < 7 ? 8 : 11; + } + else + { + int posSlot; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < 7 ? 7 : 10; + len = LzmaLenDecode(p + LenCoder, &rd, posState); + posSlot = RangeDecoderBitTreeDecode(p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits), kNumPosSlotBits, &rd); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + { + rep0 += RangeDecoderReverseBitTreeDecode( + p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); + } + else + { + rep0 += RangeDecoderDecodeDirectBits(&rd, + numDirectBits - kNumAlignBits) << kNumAlignBits; + rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); + } + } + else + rep0 = posSlot; + rep0++; + } + if (rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = -1; + break; + } + if (rep0 > nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + { + return LZMA_RESULT_DATA_ERROR; + } + len += kMatchMinLen; + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + len--; + } + while(len > 0 && nowPos < outSize); + } + } + + #ifdef _LZMA_OUT_READ + vs->RangeDecoder = rd; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + nowPos; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->PreviousIsMatch = previousIsMatch; + vs->RemainLen = len; + #endif + + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff --git a/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.h b/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.h new file mode 100644 index 0000000000..f58944e3c3 --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/LzmaDecode.h @@ -0,0 +1,100 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifndef UInt32 +#ifdef _LZMA_UINT32_IS_ULONG +#define UInt32 unsigned long +#else +#define UInt32 unsigned int +#endif +#endif + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb unsigned short +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 +#define LZMA_RESULT_NOT_ENOUGH_MEM 2 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +/* +bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb) +bufferSize += 100 in case of _LZMA_OUT_READ +by default CProb is unsigned short, +but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int) +*/ + +#ifdef _LZMA_OUT_READ +int LzmaDecoderInit( + unsigned char *buffer, UInt32 bufferSize, + int lc, int lp, int pb, + unsigned char *dictionary, UInt32 dictionarySize, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback + #else + unsigned char *inStream, UInt32 inSize + #endif +); +#endif + +int LzmaDecode( + unsigned char *buffer, + #ifndef _LZMA_OUT_READ + UInt32 bufferSize, + int lc, int lp, int pb, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + unsigned char *inStream, UInt32 inSize, + #endif + #endif + unsigned char *outStream, UInt32 outSize, + UInt32 *outSizeProcessed); + +#endif diff --git a/target/linux/bcm47xx/image/lzma-loader/src/Makefile b/target/linux/bcm47xx/image/lzma-loader/src/Makefile new file mode 100644 index 0000000000..a08fc05b9f --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/Makefile @@ -0,0 +1,78 @@ +# +# Makefile for Broadcom BCM947XX boards +# +# Copyright 2001-2003, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# Copyright 2004 Manuel Novoa III <mjn3@codepoet.org> +# Modified to support bzip'd kernels. +# Of course, it would be better to integrate bunzip capability into CFE. +# +# Copyright 2005 Oleg I. Vdovikin <oleg@cs.msu.su> +# Cleaned up, modified for lzma support, removed from kernel +# + +TEXT_START := 0x80001000 +BZ_TEXT_START := 0x80600000 +BZ_STACK_START := 0x80700000 + +OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S + +CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \ + -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \ + -ffunction-sections -pipe -mlong-calls -fno-common \ + -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap +CFLAGS += -DLOADADDR=$(TEXT_START) -D_LZMA_IN_CB + +ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ -DBZ_TEXT_START=$(BZ_TEXT_START) -DBZ_STACK_START=$(BZ_STACK_START) + +SEDFLAGS := s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/BZ_STACK_START/$(BZ_STACK_START)/;s/TEXT_START/$(TEXT_START)/ + +OBJECTS := head.o data.o + +all: loader.gz loader.elf + +# Don't build dependencies, this may die if $(CC) isn't gcc +dep: + +install: + +loader.gz: loader + gzip -nc9 $< > $@ + +loader.elf: loader.o + cp $< $@ + +loader: loader.o + $(OBJCOPY) $< $@ + +loader.o: loader.lds $(OBJECTS) + $(LD) -static --gc-sections -no-warn-mismatch -T loader.lds -o $@ $(OBJECTS) + +loader.lds: loader.lds.in Makefile + @sed "$(SEDFLAGS)" < $< > $@ + +data.o: data.lds decompress.image + $(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary decompress.image -b elf32-tradlittlemips + +data.lds: + @echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@ + +decompress.image: decompress + $(OBJCOPY) $< $@ + +decompress: decompress.lds decompress.o LzmaDecode.o + $(LD) -static --gc-sections -no-warn-mismatch -T decompress.lds -o $@ decompress.o LzmaDecode.o + +decompress.lds: decompress.lds.in Makefile + @sed "$(SEDFLAGS)" < $< > $@ + +mrproper: clean + +clean: + rm -f loader.gz loader decompress *.lds *.o *.image diff --git a/target/linux/bcm47xx/image/lzma-loader/src/README b/target/linux/bcm47xx/image/lzma-loader/src/README new file mode 100644 index 0000000000..16649e9500 --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/README @@ -0,0 +1,55 @@ +/* + * LZMA compressed kernel decompressor for bcm947xx boards + * + * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +The code is intended to decompress kernel, being compressed using lzma utility +build using 7zip LZMA SDK. This utility is located in the LZMA_Alone directory + +decompressor code expects that your .trx file consist of three partitions: + +1) decompressor itself (this is gziped code which pmon/cfe will extract and run +on boot-up instead of real kernel) +2) LZMA compressed kernel (both streamed and regular modes are supported now) +3) Root filesystem + +Please be sure to apply the following patch for use this new trx layout (it will +allow using both new and old trx files for root filesystem lookup code) + +--- linuz/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:24:27.503322896 +0300 ++++ linux/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:29:05.237100944 +0300 +@@ -221,7 +221,9 @@ + /* Try looking at TRX header for rootfs offset */ + if (le32_to_cpu(trx->magic) == TRX_MAGIC) { + bcm947xx_parts[1].offset = off; +- if (le32_to_cpu(trx->offsets[1]) > off) ++ if (le32_to_cpu(trx->offsets[2]) > off) ++ off = le32_to_cpu(trx->offsets[2]); ++ else if (le32_to_cpu(trx->offsets[1]) > off) + off = le32_to_cpu(trx->offsets[1]); + continue; + } + + +Revision history: + 0.02 Initial release + 0.03 Added Mineharu Takahara <mtakahar@yahoo.com> patch to pass actual + output size to decoder (stream mode compressed input is not + a requirement anymore) + 0.04 Reordered functions using lds script diff --git a/target/linux/bcm47xx/image/lzma-loader/src/decompress.c b/target/linux/bcm47xx/image/lzma-loader/src/decompress.c new file mode 100644 index 0000000000..05681b152d --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/decompress.c @@ -0,0 +1,186 @@ +/* + * LZMA compressed kernel decompressor for bcm947xx boards + * + * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Please note, this was code based on the bunzip2 decompressor code + * by Manuel Novoa III (mjn3@codepoet.org), although the only thing left + * is an idea and part of original vendor code + * + * + * 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com> + * pass actual output size to decoder (stream mode + * compressed input is not a requirement anymore) + * + * 24-Apr-2005 Oleg I. Vdovikin + * reordered functions using lds script, removed forward decl + * + */ + +#include "LzmaDecode.h" + +#define BCM4710_FLASH 0x1fc00000 /* Flash */ + +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 + +#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1) + +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 + +#define cache_unroll(base,op) \ + __asm__ __volatile__( \ + ".set noreorder;\n" \ + ".set mips3;\n" \ + "cache %1, (%0);\n" \ + ".set mips0;\n" \ + ".set reorder\n" \ + : \ + : "r" (base), \ + "i" (op)); + +static __inline__ void blast_icache(unsigned long size, unsigned long lsize) +{ + unsigned long start = KSEG0; + unsigned long end = (start + size); + + while(start < end) { + cache_unroll(start,Index_Invalidate_I); + start += lsize; + } +} + +static __inline__ void blast_dcache(unsigned long size, unsigned long lsize) +{ + unsigned long start = KSEG0; + unsigned long end = (start + size); + + while(start < end) { + cache_unroll(start,Index_Writeback_Inv_D); + start += lsize; + } +} + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ + +struct trx_header { + unsigned int magic; /* "HDR0" */ + unsigned int len; /* Length of file including header */ + unsigned int crc32; /* 32-bit CRC from flag_version to end of file */ + unsigned int flag_version; /* 0:15 flags, 16:31 version */ + unsigned int offsets[3]; /* Offsets of partitions from start of header */ +}; + +#define EDIMAX_PS_HEADER_MAGIC 0x36315350 /* "PS16" */ +#define EDIMAX_PS_HEADER_LEN 0xc /* 12 bytes long for edimax header */ + +/* beyound the image end, size not known in advance */ +extern unsigned char workspace[]; + +unsigned int offset; +unsigned char *data; + +/* flash access should be aligned, so wrapper is used */ +/* read byte from the flash, all accesses are 32-bit aligned */ +static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize) +{ + static unsigned int val; + + if (((unsigned int)offset % 4) == 0) { + val = *(unsigned int *)data; + data += 4; + } + + *bufferSize = 1; + *buffer = ((unsigned char *)&val) + (offset++ & 3); + + return LZMA_RESULT_OK; +} + +static __inline__ unsigned char get_byte(void) +{ + unsigned char *buffer; + UInt32 fake; + + return read_byte(0, &buffer, &fake), *buffer; +} + +/* should be the first function */ +void entry(unsigned long icache_size, unsigned long icache_lsize, + unsigned long dcache_size, unsigned long dcache_lsize, + unsigned long fw_arg0, unsigned long fw_arg1, + unsigned long fw_arg2, unsigned long fw_arg3) +{ + unsigned int i; /* temp value */ + unsigned int lc; /* literal context bits */ + unsigned int lp; /* literal pos state bits */ + unsigned int pb; /* pos state bits */ + unsigned int osize; /* uncompressed size */ + + ILzmaInCallback callback; + callback.Read = read_byte; + + /* look for trx header, 32-bit data access */ + for (data = ((unsigned char *) KSEG1ADDR(BCM4710_FLASH)); + ((struct trx_header *)data)->magic != TRX_MAGIC && + ((struct trx_header *)data)->magic != EDIMAX_PS_HEADER_MAGIC; + data += 65536); + + if (((struct trx_header *)data)->magic == EDIMAX_PS_HEADER_MAGIC) + data += EDIMAX_PS_HEADER_LEN; + /* compressed kernel is in the partition 0 or 1 */ + if (((struct trx_header *)data)->offsets[1] > 65536) + data += ((struct trx_header *)data)->offsets[0]; + else + data += ((struct trx_header *)data)->offsets[1]; + + offset = 0; + + /* lzma args */ + i = get_byte(); + lc = i % 9, i = i / 9; + lp = i % 5, pb = i / 5; + + /* skip rest of the LZMA coder property */ + for (i = 0; i < 4; i++) + get_byte(); + + /* read the lower half of uncompressed size in the header */ + osize = ((unsigned int)get_byte()) + + ((unsigned int)get_byte() << 8) + + ((unsigned int)get_byte() << 16) + + ((unsigned int)get_byte() << 24); + + /* skip rest of the header (upper half of uncompressed size) */ + for (i = 0; i < 4; i++) + get_byte(); + + /* decompress kernel */ + if (LzmaDecode(workspace, ~0, lc, lp, pb, &callback, + (unsigned char*)LOADADDR, osize, &i) == LZMA_RESULT_OK) + { + blast_dcache(dcache_size, dcache_lsize); + blast_icache(icache_size, icache_lsize); + + /* Jump to load address */ + ((void (*)(unsigned long, unsigned long, unsigned long, + unsigned long)) LOADADDR)(fw_arg0, fw_arg1, fw_arg2, + fw_arg3); + } +} diff --git a/target/linux/bcm47xx/image/lzma-loader/src/decompress.lds.in b/target/linux/bcm47xx/image/lzma-loader/src/decompress.lds.in new file mode 100644 index 0000000000..33f56f8a09 --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/decompress.lds.in @@ -0,0 +1,20 @@ +OUTPUT_ARCH(mips) +ENTRY(entry) +SECTIONS { + . = BZ_TEXT_START; + .text : { + *(.text.entry) + *(.text) + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } + + workspace = .; +} diff --git a/target/linux/bcm47xx/image/lzma-loader/src/head.S b/target/linux/bcm47xx/image/lzma-loader/src/head.S new file mode 100644 index 0000000000..50c159ce57 --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/head.S @@ -0,0 +1,161 @@ +/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su) */ +/* cache manipulation adapted from Broadcom code */ +/* idea taken from original bunzip2 decompressor code */ +/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */ +/* Licensed under the linux kernel's version of the GPL.*/ + +#include <asm/asm.h> +#include <asm/regdef.h> + +#define KSEG0 0x80000000 + +#define C0_CONFIG $16 +#define C0_TAGLO $28 +#define C0_TAGHI $29 + +#define CONF1_DA_SHIFT 7 /* D$ associativity */ +#define CONF1_DA_MASK 0x00000380 +#define CONF1_DA_BASE 1 +#define CONF1_DL_SHIFT 10 /* D$ line size */ +#define CONF1_DL_MASK 0x00001c00 +#define CONF1_DL_BASE 2 +#define CONF1_DS_SHIFT 13 /* D$ sets/way */ +#define CONF1_DS_MASK 0x0000e000 +#define CONF1_DS_BASE 64 +#define CONF1_IA_SHIFT 16 /* I$ associativity */ +#define CONF1_IA_MASK 0x00070000 +#define CONF1_IA_BASE 1 +#define CONF1_IL_SHIFT 19 /* I$ line size */ +#define CONF1_IL_MASK 0x00380000 +#define CONF1_IL_BASE 2 +#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */ +#define CONF1_IS_MASK 0x01c00000 +#define CONF1_IS_BASE 64 + +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 + + .text + LEAF(startup) + .set noreorder + li sp, BZ_STACK_START + addi sp, -48 + sw a0, 16(sp) + sw a1, 20(sp) + sw a2, 24(sp) + sw a3, 28(sp) + + /* Copy decompressor code to the right place */ + li t2, BZ_TEXT_START + add a0, t2, 0 + la a1, code_start + la a2, code_stop +$L1: + lw t0, 0(a1) + sw t0, 0(a0) + add a1, 4 + add a0, 4 + blt a1, a2, $L1 + nop + + /* At this point we need to invalidate dcache and */ + /* icache before jumping to new code */ + +1: /* Get cache sizes */ + .set mips32 + mfc0 s0,C0_CONFIG,1 + .set mips0 + + li s1,CONF1_DL_MASK + and s1,s0 + beq s1,zero,nodc + nop + + srl s1,CONF1_DL_SHIFT + li t0,CONF1_DL_BASE + sll s1,t0,s1 /* s1 has D$ cache line size */ + + li s2,CONF1_DA_MASK + and s2,s0 + srl s2,CONF1_DA_SHIFT + addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */ + + li t0,CONF1_DS_MASK + and t0,s0 + srl t0,CONF1_DS_SHIFT + li s3,CONF1_DS_BASE + sll s3,s3,t0 /* s3 has D$ sets per way */ + + multu s2,s3 /* sets/way * associativity */ + mflo t0 /* total cache lines */ + + multu s1,t0 /* D$ linesize * lines */ + mflo s2 /* s2 is now D$ size in bytes */ + + /* Initilize the D$: */ + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + li t0,KSEG0 /* Just an address for the first $ line */ + addu t1,t0,s2 /* + size of cache == end */ + + .set mips3 +1: cache Index_Writeback_Inv_D,0(t0) + .set mips0 + bne t0,t1,1b + addu t0,s1 + +nodc: + /* Now we get to do it all again for the I$ */ + + move s3,zero /* just in case there is no icache */ + move s4,zero + + li t0,CONF1_IL_MASK + and t0,s0 + beq t0,zero,noic + nop + + srl t0,CONF1_IL_SHIFT + li s3,CONF1_IL_BASE + sll s3,t0 /* s3 has I$ cache line size */ + + li t0,CONF1_IA_MASK + and t0,s0 + srl t0,CONF1_IA_SHIFT + addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */ + + li t0,CONF1_IS_MASK + and t0,s0 + srl t0,CONF1_IS_SHIFT + li s5,CONF1_IS_BASE + sll s5,t0 /* s5 has I$ sets per way */ + + multu s4,s5 /* sets/way * associativity */ + mflo t0 /* s4 is now total cache lines */ + + multu s3,t0 /* I$ linesize * lines */ + mflo s4 /* s4 is cache size in bytes */ + + /* Initilize the I$: */ + mtc0 zero,C0_TAGLO + mtc0 zero,C0_TAGHI + + li t0,KSEG0 /* Just an address for the first $ line */ + addu t1,t0,s4 /* + size of cache == end */ + + .set mips3 +1: cache Index_Invalidate_I,0(t0) + .set mips0 + bne t0,t1,1b + addu t0,s3 + +noic: + move a0,s4 /* icache size */ + move a1,s3 /* icache line size */ + move a2,s2 /* dcache size */ + jal t2 + move a3,s1 /* dcache line size */ + + .set reorder + END(startup) diff --git a/target/linux/bcm47xx/image/lzma-loader/src/loader.lds.in b/target/linux/bcm47xx/image/lzma-loader/src/loader.lds.in new file mode 100644 index 0000000000..20f2ea98ec --- /dev/null +++ b/target/linux/bcm47xx/image/lzma-loader/src/loader.lds.in @@ -0,0 +1,17 @@ +OUTPUT_ARCH(mips) +ENTRY(startup) +SECTIONS { + . = TEXT_START; + .text : { + *(.text) + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + } +} diff --git a/target/linux/bcm47xx/legacy/config-default b/target/linux/bcm47xx/legacy/config-default new file mode 100644 index 0000000000..8a52e475c7 --- /dev/null +++ b/target/linux/bcm47xx/legacy/config-default @@ -0,0 +1,8 @@ +CONFIG_B44=y +CONFIG_B44_PCI=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI_AUTOSELECT=y +# CONFIG_BCM47XX_BCMA is not set +# CONFIG_BCMA is not set +# CONFIG_MTD_NAND is not set +# CONFIG_SSB_DRIVER_GIGE is not set diff --git a/target/linux/bcm47xx/legacy/profiles/100-Broadcom-b43.mk b/target/linux/bcm47xx/legacy/profiles/100-Broadcom-b43.mk new file mode 100644 index 0000000000..50d777010b --- /dev/null +++ b/target/linux/bcm47xx/legacy/profiles/100-Broadcom-b43.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2007-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-b43 + NAME:=Broadcom SoC, all Ethernet, BCM43xx WiFi (b43, default) + PACKAGES:=kmod-b43 kmod-b43legacy +endef + +define Profile/Broadcom-b43/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the mac80211, b43 and + b43legacy drivers and b44, tg3 or bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-b43)) + diff --git a/target/linux/bcm47xx/legacy/profiles/101-Broadcom-wl.mk b/target/linux/bcm47xx/legacy/profiles/101-Broadcom-wl.mk new file mode 100644 index 0000000000..6a4c5b0394 --- /dev/null +++ b/target/linux/bcm47xx/legacy/profiles/101-Broadcom-wl.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2010-2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-wl + NAME:=Broadcom SoC, all Ethernet, BCM43xx WiFi (wl, proprietary) + PACKAGES:=-wpad-mini kmod-brcm-wl-mini wlc nas +endef + +define Profile/Broadcom-wl/Description + Package set compatible with hardware any Broadcom BCM47xx or BCM535x + SoC with Broadcom BCM43xx Wifi cards using the proprietary Broadcom + wireless "wl" driver and b44, tg3 or bgmac Ethernet driver. +endef + +$(eval $(call Profile,Broadcom-wl)) + diff --git a/target/linux/bcm47xx/legacy/target.mk b/target/linux/bcm47xx/legacy/target.mk new file mode 100644 index 0000000000..fca6128558 --- /dev/null +++ b/target/linux/bcm47xx/legacy/target.mk @@ -0,0 +1,10 @@ +FEATURES += low_mem pcmcia small_flash +BOARDNAME:=Legacy (BMIPS3300) + +DEFAULT_PACKAGES += wpad-mini + +define Target/Description + Build firmware for Broadcom BCM47xx and BCM53xx devices with + BMIPS3300 CPU except for BCM4705 SoC. + Supported SoCs: BCM5352E, BCM5354, BCM5365?, BCM4712, BCM4704. +endef diff --git a/target/linux/bcm47xx/mips74k/config-default b/target/linux/bcm47xx/mips74k/config-default new file mode 100644 index 0000000000..2c3c40377a --- /dev/null +++ b/target/linux/bcm47xx/mips74k/config-default @@ -0,0 +1,20 @@ +# CONFIG_ADM6996_PHY is not set +# CONFIG_BCM47XX_SSB is not set +CONFIG_BGMAC=y +CONFIG_BGMAC_BCMA=y +CONFIG_BOUNCE=y +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPSR1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +# CONFIG_FIXED_PHY is not set +# CONFIG_GPIO_WDT is not set +CONFIG_HIGHMEM=y +# CONFIG_SSB is not set +# CONFIG_SSB_DRIVER_EXTIF is not set +# CONFIG_SSB_DRIVER_GIGE is not set +# CONFIG_SSB_DRIVER_MIPS is not set +# CONFIG_SSB_EMBEDDED is not set +# CONFIG_SSB_PCICORE_HOSTMODE is not set +# CONFIG_SSB_SERIAL is not set +# CONFIG_SSB_SFLASH is not set diff --git a/target/linux/bcm47xx/mips74k/profiles/100-Broadcom-b43.mk b/target/linux/bcm47xx/mips74k/profiles/100-Broadcom-b43.mk new file mode 100644 index 0000000000..bd3b010f69 --- /dev/null +++ b/target/linux/bcm47xx/mips74k/profiles/100-Broadcom-b43.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-mips74k-b43 + NAME:=Broadcom SoC, BCM43xx WiFi (b43) + PACKAGES:=kmod-b43 +endef + +define Profile/Broadcom-mips74k-b43/Description + Package set for devices with BCM43xx WiFi including mac80211 and b43 + driver. +endef + +$(eval $(call Profile,Broadcom-mips74k-b43)) + diff --git a/target/linux/bcm47xx/mips74k/profiles/101-Broadcom-brcsmac.mk b/target/linux/bcm47xx/mips74k/profiles/101-Broadcom-brcsmac.mk new file mode 100644 index 0000000000..a138ef93b0 --- /dev/null +++ b/target/linux/bcm47xx/mips74k/profiles/101-Broadcom-brcsmac.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-mips74k-brcmsmac + NAME:=Broadcom SoC, BCM43xx WiFi (brcmsmac) + PACKAGES:=kmod-brcmsmac +endef + +define Profile/Broadcom-mips74k-brcmsmac/Description + Package set for devices with BCM43xx WiFi including mac80211 and + brcmsmac driver. +endef + +$(eval $(call Profile,Broadcom-mips74k-brcmsmac)) + diff --git a/target/linux/bcm47xx/mips74k/profiles/102-Broadcom-wl.mk b/target/linux/bcm47xx/mips74k/profiles/102-Broadcom-wl.mk new file mode 100644 index 0000000000..66b13bf879 --- /dev/null +++ b/target/linux/bcm47xx/mips74k/profiles/102-Broadcom-wl.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-mips74k-wl + NAME:=Broadcom SoC, BCM43xx WiFi (proprietary wl) + PACKAGES:=-wpad-basic kmod-brcm-wl wlc nas +endef + +define Profile/Broadcom-mips74k-wl/Description + Package set for devices with BCM43xx WiFi including proprietary (and + closed source) driver "wl". +endef + +$(eval $(call Profile,Broadcom-mips74k-wl)) + diff --git a/target/linux/bcm47xx/mips74k/profiles/103-Broadcom-none.mk b/target/linux/bcm47xx/mips74k/profiles/103-Broadcom-none.mk new file mode 100644 index 0000000000..cc4668de52 --- /dev/null +++ b/target/linux/bcm47xx/mips74k/profiles/103-Broadcom-none.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Broadcom-mips74k-none + NAME:=Broadcom SoC, No WiFi + PACKAGES:=-wpad-basic +endef + +define Profile/Broadcom-mips74k-none/Description + Package set for devices without a WiFi. +endef + +$(eval $(call Profile,Broadcom-mips74k-none)) + diff --git a/target/linux/bcm47xx/mips74k/target.mk b/target/linux/bcm47xx/mips74k/target.mk new file mode 100644 index 0000000000..1e2e8436d5 --- /dev/null +++ b/target/linux/bcm47xx/mips74k/target.mk @@ -0,0 +1,9 @@ +BOARDNAME:=MIPS 74K +CPU_TYPE:=74kc + +DEFAULT_PACKAGES += wpad-basic + +define Target/Description + Build firmware for Broadcom BCM47xx and BCM53xx devices with + MIPS 74K CPU. +endef diff --git a/target/linux/bcm47xx/modules.mk b/target/linux/bcm47xx/modules.mk new file mode 100644 index 0000000000..cd46901a3b --- /dev/null +++ b/target/linux/bcm47xx/modules.mk @@ -0,0 +1,24 @@ +# +# Copyright (C) 2006-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define KernelPackage/bgmac + TITLE:=Broadcom bgmac driver + KCONFIG:=CONFIG_BGMAC CONFIG_BGMAC_BCMA + DEPENDS:=@TARGET_bcm47xx @!TARGET_bcm47xx_legacy + SUBMENU:=$(NETWORK_DEVICES_MENU) + FILES:= \ + $(LINUX_DIR)/drivers/net/ethernet/broadcom/bgmac-bcma.ko \ + $(LINUX_DIR)/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.ko \ + $(LINUX_DIR)/drivers/net/ethernet/broadcom/bgmac.ko + AUTOLOAD:=$(call AutoProbe,bgmac-bcma) +endef + +define KernelPackage/bgmac/description + Kernel modules for Broadcom bgmac Ethernet adapters. +endef + +$(eval $(call KernelPackage,bgmac)) diff --git a/target/linux/bcm47xx/patches-4.14/031-MIPS-BCM47XX-Add-Luxul-XAP1500-XWR1750-WiFi-LEDs.patch b/target/linux/bcm47xx/patches-4.14/031-MIPS-BCM47XX-Add-Luxul-XAP1500-XWR1750-WiFi-LEDs.patch new file mode 100644 index 0000000000..e8b426f866 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/031-MIPS-BCM47XX-Add-Luxul-XAP1500-XWR1750-WiFi-LEDs.patch @@ -0,0 +1,86 @@ +From 272641206100e89656038180da12eff4f03d79d1 Mon Sep 17 00:00:00 2001 +From: Dan Haab <dan.haab@luxul.com> +Date: Tue, 27 Mar 2018 11:24:34 -0600 +Subject: [PATCH] MIPS: BCM47XX: Add Luxul XAP1500/XWR1750 WiFi LEDs + +Some Luxul devices use PCIe connected GPIO LEDs that are not available +until the PCI subsytem and its drivers load. Using the same array for +these LEDs would block registering any LEDs until all GPIOs become +available. This may be undesired behavior as some LEDs should be +available as early as possible (e.g. system status LED). This patch will +allow registering available LEDs while deferring these PCIe GPIO +connected 'extra' LEDs until they become available. + +Signed-off-by: Dan Haab <dan.haab@luxul.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: Hauke Mehrtens <hauke@hauke-m.de> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/18952/ +Signed-off-by: James Hogan <jhogan@kernel.org> +--- + arch/mips/bcm47xx/leds.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +--- a/arch/mips/bcm47xx/leds.c ++++ b/arch/mips/bcm47xx/leds.c +@@ -409,6 +409,12 @@ bcm47xx_leds_luxul_xap_1500_v1[] __initc + }; + + static const struct gpio_led ++bcm47xx_leds_luxul_xap1500_v1_extra[] __initconst = { ++ BCM47XX_GPIO_LED(44, "green", "5ghz", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(76, "green", "2ghz", 0, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_luxul_xbr_4400_v1[] __initconst = { + BCM47XX_GPIO_LED(12, "green", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED_TRIGGER(15, "green", "status", 0, "timer"), +@@ -435,6 +441,11 @@ bcm47xx_leds_luxul_xwr_1750_v1[] __initc + BCM47XX_GPIO_LED(15, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), + }; + ++static const struct gpio_led ++bcm47xx_leds_luxul_xwr1750_v1_extra[] __initconst = { ++ BCM47XX_GPIO_LED(76, "green", "2ghz", 0, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ + /* Microsoft */ + + static const struct gpio_led +@@ -528,6 +539,12 @@ static struct gpio_led_platform_data bcm + bcm47xx_leds_pdata.num_leds = ARRAY_SIZE(dev_leds); \ + } while (0) + ++static struct gpio_led_platform_data bcm47xx_leds_pdata_extra __initdata = {}; ++#define bcm47xx_set_pdata_extra(dev_leds) do { \ ++ bcm47xx_leds_pdata_extra.leds = dev_leds; \ ++ bcm47xx_leds_pdata_extra.num_leds = ARRAY_SIZE(dev_leds); \ ++} while (0) ++ + void __init bcm47xx_leds_register(void) + { + enum bcm47xx_board board = bcm47xx_board_get(); +@@ -705,6 +722,7 @@ void __init bcm47xx_leds_register(void) + break; + case BCM47XX_BOARD_LUXUL_XAP_1500_V1: + bcm47xx_set_pdata(bcm47xx_leds_luxul_xap_1500_v1); ++ bcm47xx_set_pdata_extra(bcm47xx_leds_luxul_xap1500_v1_extra); + break; + case BCM47XX_BOARD_LUXUL_XBR_4400_V1: + bcm47xx_set_pdata(bcm47xx_leds_luxul_xbr_4400_v1); +@@ -717,6 +735,7 @@ void __init bcm47xx_leds_register(void) + break; + case BCM47XX_BOARD_LUXUL_XWR_1750_V1: + bcm47xx_set_pdata(bcm47xx_leds_luxul_xwr_1750_v1); ++ bcm47xx_set_pdata_extra(bcm47xx_leds_luxul_xwr1750_v1_extra); + break; + + case BCM47XX_BOARD_MICROSOFT_MN700: +@@ -760,4 +779,6 @@ void __init bcm47xx_leds_register(void) + } + + gpio_led_register_device(-1, &bcm47xx_leds_pdata); ++ if (bcm47xx_leds_pdata_extra.num_leds) ++ gpio_led_register_device(0, &bcm47xx_leds_pdata_extra); + } diff --git a/target/linux/bcm47xx/patches-4.14/032-MIPS-BCM47XX-Add-support-for-Netgear-WNR1000-V3.patch b/target/linux/bcm47xx/patches-4.14/032-MIPS-BCM47XX-Add-support-for-Netgear-WNR1000-V3.patch new file mode 100644 index 0000000000..2f85e86553 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/032-MIPS-BCM47XX-Add-support-for-Netgear-WNR1000-V3.patch @@ -0,0 +1,96 @@ +From 88b882ba0b0b7439d16d2c9df7f111cdf793443b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> +Date: Sun, 8 Apr 2018 22:39:15 +0200 +Subject: [PATCH] MIPS: BCM47XX: Add support for Netgear WNR1000 V3 + +This adds support for detecting this model board and registers some LEDs +and buttons. + +There are two uncommon things regarding this device: +1) It can use two different "board_id" ID values. + Unit I have uses "U12H139T00_NETGEAR" value. This magic is also used + in firmware file header. There are two reports (one from an OpenWrt + user) of a different "U12H139T50_NETGEAR" magic though. +2) Power LEDs share GPIOs with buttons. + Amber one seems to share GPIO 2 with WPS button and green one seems + to share GPIO 3 with reset button. It remains unknown how to support + them and handle buttons at the same time. For that reason they aren't + added to the list of supported LEDs. +--- + arch/mips/bcm47xx/board.c | 2 ++ + arch/mips/bcm47xx/buttons.c | 9 +++++++++ + arch/mips/bcm47xx/leds.c | 9 +++++++++ + arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h | 1 + + 4 files changed, 21 insertions(+) + +--- a/arch/mips/bcm47xx/board.c ++++ b/arch/mips/bcm47xx/board.c +@@ -172,6 +172,8 @@ struct bcm47xx_board_type_list1 bcm47xx_ + {{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR4500V1, "Netgear WNDR4500 V1"}, "U12H189T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR4500V2, "Netgear WNDR4500 V2"}, "U12H224T00_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WNR1000_V3, "Netgear WNR1000 V3"}, "U12H139T00_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WNR1000_V3, "Netgear WNR1000 V3"}, "U12H139T50_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNR2000, "Netgear WNR2000"}, "U12H114T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "U12H136T99_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNR3500U, "Netgear WNR3500U"}, "U12H136T00_NETGEAR"}, +--- a/arch/mips/bcm47xx/buttons.c ++++ b/arch/mips/bcm47xx/buttons.c +@@ -412,6 +412,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __i + }; + + static const struct gpio_keys_button ++bcm47xx_buttons_netgear_wnr1000_v3[] __initconst = { ++ BCM47XX_GPIO_KEY(2, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(3, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON), +@@ -670,6 +676,9 @@ int __init bcm47xx_buttons_register(void + case BCM47XX_BOARD_NETGEAR_WNDR4500V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1); + break; ++ case BCM47XX_BOARD_NETGEAR_WNR1000_V3: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr1000_v3); ++ break; + case BCM47XX_BOARD_NETGEAR_WNR3500L: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1); + break; +--- a/arch/mips/bcm47xx/leds.c ++++ b/arch/mips/bcm47xx/leds.c +@@ -498,6 +498,12 @@ bcm47xx_leds_netgear_wndr4500v1[] __init + }; + + static const struct gpio_led ++bcm47xx_leds_netgear_wnr1000_v3[] __initconst = { ++ BCM47XX_GPIO_LED(0, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(1, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_netgear_wnr3500lv1[] __initconst = { + BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), +@@ -758,6 +764,9 @@ void __init bcm47xx_leds_register(void) + case BCM47XX_BOARD_NETGEAR_WNDR4500V1: + bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1); + break; ++ case BCM47XX_BOARD_NETGEAR_WNR1000_V3: ++ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr1000_v3); ++ break; + case BCM47XX_BOARD_NETGEAR_WNR3500L: + bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1); + break; +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +@@ -110,6 +110,7 @@ enum bcm47xx_board { + BCM47XX_BOARD_NETGEAR_WNDR4000, + BCM47XX_BOARD_NETGEAR_WNDR4500V1, + BCM47XX_BOARD_NETGEAR_WNDR4500V2, ++ BCM47XX_BOARD_NETGEAR_WNR1000_V3, + BCM47XX_BOARD_NETGEAR_WNR2000, + BCM47XX_BOARD_NETGEAR_WNR3500L, + BCM47XX_BOARD_NETGEAR_WNR3500U, diff --git a/target/linux/bcm47xx/patches-4.14/033-firmware-bcm47xx_nvram-support-small-0x6000-B-NVRAM-.patch b/target/linux/bcm47xx/patches-4.14/033-firmware-bcm47xx_nvram-support-small-0x6000-B-NVRAM-.patch new file mode 100644 index 0000000000..7c860bb7ed --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/033-firmware-bcm47xx_nvram-support-small-0x6000-B-NVRAM-.patch @@ -0,0 +1,24 @@ +From 663beaeacf2552ed07405e69e96a18775e069eab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> +Date: Sun, 8 Apr 2018 22:51:08 +0200 +Subject: [PATCH] firmware: bcm47xx_nvram: support small (0x6000 B) NVRAM + partitions + +Some old devices with 4 MiB flashes were using 0x1000 block size and +could use smaller (0x6000 bytes) flash partition for storing NVRAM +content. This adds support for reading NVRAM on Netgear WNR1000 V3. +--- + drivers/firmware/broadcom/bcm47xx_nvram.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -36,7 +36,7 @@ struct nvram_header { + + static char nvram_buf[NVRAM_SPACE]; + static size_t nvram_len; +-static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; ++static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; + + static u32 find_nvram_size(void __iomem *end) + { diff --git a/target/linux/bcm47xx/patches-4.14/035-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch b/target/linux/bcm47xx/patches-4.14/035-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch new file mode 100644 index 0000000000..34a79f9d5b --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/035-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch @@ -0,0 +1,34 @@ +From cdb8faa00e3fcdd0ad10add743516d616dc7d38e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz> +Date: Mon, 11 Mar 2019 22:08:22 +0100 +Subject: [PATCH] mips: bcm47xx: Enable USB power on Netgear WNDR3400v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Eric has reported on OpenWrt's bug tracking system[1], that he's not +able to use USB devices on his WNDR3400v2 device after the boot, until +he turns on GPIO #21 manually through sysfs. + +1. https://bugs.openwrt.org/index.php?do=details&task_id=2170 + +Cc: Rafał Miłecki <zajec5@gmail.com> +Cc: Hauke Mehrtens <hauke@hauke-m.de> +Reported-by: Eric Bohlman <ericbohlman@gmail.com> +Tested-by: Eric Bohlman <ericbohlman@gmail.com> +Signed-off-by: Petr Štetiar <ynezz@true.cz> +Signed-off-by: Paul Burton <paul.burton@mips.com> +--- + arch/mips/bcm47xx/workarounds.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/bcm47xx/workarounds.c ++++ b/arch/mips/bcm47xx/workarounds.c +@@ -24,6 +24,7 @@ void __init bcm47xx_workarounds(void) + case BCM47XX_BOARD_NETGEAR_WNR3500L: + bcm47xx_workarounds_enable_usb_power(12); + break; ++ case BCM47XX_BOARD_NETGEAR_WNDR3400V2: + case BCM47XX_BOARD_NETGEAR_WNDR3400_V3: + bcm47xx_workarounds_enable_usb_power(21); + break; diff --git a/target/linux/bcm47xx/patches-4.14/159-cpu_fixes.patch b/target/linux/bcm47xx/patches-4.14/159-cpu_fixes.patch new file mode 100644 index 0000000000..e015610269 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/159-cpu_fixes.patch @@ -0,0 +1,510 @@ +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -26,6 +26,38 @@ + extern void (*r4k_blast_dcache)(void); + extern void (*r4k_blast_icache)(void); + ++#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) ++#include <asm/paccess.h> ++#include <linux/ssb/ssb.h> ++#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg() ++ ++static inline unsigned long bcm4710_dummy_rreg(void) ++{ ++ return *(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE)); ++} ++ ++#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void *)(addr)) ++ ++static inline unsigned long bcm4710_fill_tlb(void *addr) ++{ ++ return *(unsigned long *)addr; ++} ++ ++#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void *)(addr)) ++ ++static inline void bcm4710_protected_fill_tlb(void *addr) ++{ ++ unsigned long x; ++ get_dbe(x, (unsigned long *)addr);; ++} ++ ++#else ++#define BCM4710_DUMMY_RREG() ++ ++#define BCM4710_FILL_TLB(addr) ++#define BCM4710_PROTECTED_FILL_TLB(addr) ++#endif ++ + /* + * This macro return a properly sign-extended address suitable as base address + * for indexed cache operations. Two issues here: +@@ -99,6 +131,7 @@ static inline void flush_icache_line_ind + static inline void flush_dcache_line_indexed(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Index_Writeback_Inv_D, addr); + __dflush_epilogue + } +@@ -126,6 +159,7 @@ static inline void flush_icache_line(uns + static inline void flush_dcache_line(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Hit_Writeback_Inv_D, addr); + __dflush_epilogue + } +@@ -133,6 +167,7 @@ static inline void flush_dcache_line(uns + static inline void invalidate_dcache_line(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Hit_Invalidate_D, addr); + __dflush_epilogue + } +@@ -206,6 +241,7 @@ static inline int protected_flush_icache + #ifdef CONFIG_EVA + return protected_cachee_op(Hit_Invalidate_I, addr); + #else ++ BCM4710_DUMMY_RREG(); + return protected_cache_op(Hit_Invalidate_I, addr); + #endif + } +@@ -219,6 +255,7 @@ static inline int protected_flush_icache + */ + static inline int protected_writeback_dcache_line(unsigned long addr) + { ++ BCM4710_DUMMY_RREG(); + #ifdef CONFIG_EVA + return protected_cachee_op(Hit_Writeback_Inv_D, addr); + #else +@@ -576,8 +613,51 @@ static inline void invalidate_tcache_pag + : "r" (base), \ + "i" (op)); + ++static inline void blast_dcache(void) ++{ ++ unsigned long start = KSEG0; ++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways; ++ unsigned long end = (start + dcache_size); ++ ++ do { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Index_Writeback_Inv_D, start); ++ start += current_cpu_data.dcache.linesz; ++ } while(start < end); ++} ++ ++static inline void blast_dcache_page(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ ++ BCM4710_FILL_TLB(start); ++ do { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Hit_Writeback_Inv_D, start); ++ start += current_cpu_data.dcache.linesz; ++ } while(start < end); ++} ++ ++static inline void blast_dcache_page_indexed(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; ++ unsigned long ws_end = current_cpu_data.dcache.ways << ++ current_cpu_data.dcache.waybit; ++ unsigned long ws, addr; ++ for (ws = 0; ws < ws_end; ws += ws_inc) { ++ start = page + ws; ++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Index_Writeback_Inv_D, addr); ++ } ++ } ++} ++ + /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ +-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ ++#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \ + static inline void extra##blast_##pfx##cache##lsize(void) \ + { \ + unsigned long start = INDEX_BASE; \ +@@ -589,6 +669,7 @@ static inline void extra##blast_##pfx##c + \ + __##pfx##flush_prologue \ + \ ++ war \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ +@@ -603,6 +684,7 @@ static inline void extra##blast_##pfx##c + \ + __##pfx##flush_prologue \ + \ ++ war \ + do { \ + cache##lsize##_unroll32(start, hitop); \ + start += lsize * 32; \ +@@ -621,6 +703,8 @@ static inline void extra##blast_##pfx##c + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ ++ war \ ++ \ + __##pfx##flush_prologue \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ +@@ -630,26 +714,26 @@ static inline void extra##blast_##pfx##c + __##pfx##flush_epilogue \ + } + +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) +- +-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) +-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, , ) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , ) ++ ++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , ) ++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , ) + + #define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \ + static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \ +@@ -678,53 +762,23 @@ __BUILD_BLAST_USER_CACHE(d, dcache, Inde + __BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) + + /* build blast_xxx_range, protected_blast_xxx_range */ +-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ ++#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2) \ + static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \ + unsigned long end) \ + { \ + unsigned long lsize = cpu_##desc##_line_size(); \ +- unsigned long lsize_2 = lsize * 2; \ +- unsigned long lsize_3 = lsize * 3; \ +- unsigned long lsize_4 = lsize * 4; \ +- unsigned long lsize_5 = lsize * 5; \ +- unsigned long lsize_6 = lsize * 6; \ +- unsigned long lsize_7 = lsize * 7; \ +- unsigned long lsize_8 = lsize * 8; \ + unsigned long addr = start & ~(lsize - 1); \ +- unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ +- int lines = (aend - addr) / lsize; \ ++ unsigned long aend = (end - 1) & ~(lsize - 1); \ ++ war \ + \ + __##pfx##flush_prologue \ + \ +- while (lines >= 8) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- prot##cache_op(hitop, addr + lsize_2); \ +- prot##cache_op(hitop, addr + lsize_3); \ +- prot##cache_op(hitop, addr + lsize_4); \ +- prot##cache_op(hitop, addr + lsize_5); \ +- prot##cache_op(hitop, addr + lsize_6); \ +- prot##cache_op(hitop, addr + lsize_7); \ +- addr += lsize_8; \ +- lines -= 8; \ +- } \ +- \ +- if (lines & 0x4) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- prot##cache_op(hitop, addr + lsize_2); \ +- prot##cache_op(hitop, addr + lsize_3); \ +- addr += lsize_4; \ +- } \ +- \ +- if (lines & 0x2) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- addr += lsize_2; \ +- } \ +- \ +- if (lines & 0x1) { \ ++ while (1) { \ ++ war2 \ + prot##cache_op(hitop, addr); \ ++ if (addr == aend) \ ++ break; \ ++ addr += lsize; \ + } \ + \ + __##pfx##flush_epilogue \ +@@ -732,8 +786,8 @@ static inline void prot##extra##blast_## + + #ifndef CONFIG_EVA + +-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) +-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) ++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , ) + + #else + +@@ -770,15 +824,15 @@ __BUILD_PROT_BLAST_CACHE_RANGE(d, dcache + __BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I) + + #endif +-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) ++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , ) + __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ +- protected_, loongson2_) +-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) +-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , ) +-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) ++ protected_, loongson2_, , ) ++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , , , ) ++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , ) + /* blast_inv_dcache_range */ +-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) +-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) ++__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , ) + + /* Currently, this is very specific to Loongson-3 */ + #define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ +--- a/arch/mips/include/asm/stackframe.h ++++ b/arch/mips/include/asm/stackframe.h +@@ -428,6 +428,10 @@ + eretnc + #else + .set arch=r4000 ++#ifdef CONFIG_BCM47XX ++ nop ++ nop ++#endif + eret + .set mips0 + #endif +--- a/arch/mips/kernel/genex.S ++++ b/arch/mips/kernel/genex.S +@@ -21,6 +21,19 @@ + #include <asm/war.h> + #include <asm/thread_info.h> + ++#ifdef CONFIG_BCM47XX ++# ifdef eret ++# undef eret ++# endif ++# define eret \ ++ .set push; \ ++ .set noreorder; \ ++ nop; \ ++ nop; \ ++ eret; \ ++ .set pop; ++#endif ++ + __INIT + + /* +@@ -32,6 +45,9 @@ + NESTED(except_vec3_generic, 0, sp) + .set push + .set noat ++#ifdef CONFIG_BCM47XX ++ nop ++#endif + #if R5432_CP0_INTERRUPT_WAR + mfc0 k0, CP0_INDEX + #endif +@@ -55,6 +71,9 @@ NESTED(except_vec3_r4000, 0, sp) + .set push + .set arch=r4000 + .set noat ++#ifdef CONFIG_BCM47XX ++ nop ++#endif + mfc0 k1, CP0_CAUSE + li k0, 31<<2 + andi k1, k1, 0x7c +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -39,6 +39,9 @@ + #include <asm/dma-coherence.h> + #include <asm/mips-cps.h> + ++/* For enabling BCM4710 cache workarounds */ ++static int bcm4710 = 0; ++ + /* + * Bits describing what cache ops an SMP callback function may perform. + * +@@ -190,6 +193,9 @@ static void r4k_blast_dcache_user_page_s + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache_page = blast_dcache_page; ++ else + if (dc_lsize == 0) + r4k_blast_dcache_user_page = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -208,6 +214,9 @@ static void r4k_blast_dcache_page_indexe + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed; ++ else + if (dc_lsize == 0) + r4k_blast_dcache_page_indexed = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -227,6 +236,9 @@ static void r4k_blast_dcache_setup(void) + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache = blast_dcache; ++ else + if (dc_lsize == 0) + r4k_blast_dcache = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -986,6 +998,8 @@ static void local_r4k_flush_cache_sigtra + } + + R4600_HIT_CACHEOP_WAR_IMPL; ++ BCM4710_PROTECTED_FILL_TLB(addr); ++ BCM4710_PROTECTED_FILL_TLB(addr + 4); + if (!cpu_has_ic_fills_f_dc) { + if (dc_lsize) + vaddr ? flush_dcache_line(addr & ~(dc_lsize - 1)) +@@ -1880,6 +1894,17 @@ static void coherency_setup(void) + * silly idea of putting something else there ... + */ + switch (current_cpu_type()) { ++ case CPU_BMIPS3300: ++ { ++ u32 cm; ++ cm = read_c0_diag(); ++ /* Enable icache */ ++ cm |= (1 << 31); ++ /* Enable dcache */ ++ cm |= (1 << 30); ++ write_c0_diag(cm); ++ } ++ break; + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: +@@ -1926,6 +1951,15 @@ void r4k_cache_init(void) + extern void build_copy_page(void); + struct cpuinfo_mips *c = ¤t_cpu_data; + ++ /* Check if special workarounds are required */ ++#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) ++ if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) { ++ printk("Enabling BCM4710A0 cache workarounds.\n"); ++ bcm4710 = 1; ++ } else ++#endif ++ bcm4710 = 0; ++ + probe_pcache(); + probe_vcache(); + setup_scache(); +@@ -2004,7 +2038,15 @@ void r4k_cache_init(void) + */ + local_r4k___flush_cache_all(NULL); + ++#ifdef CONFIG_BCM47XX ++ { ++ static void (*_coherency_setup)(void); ++ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup); ++ _coherency_setup(); ++ } ++#else + coherency_setup(); ++#endif + board_cache_error_setup = r4k_cache_error_setup; + + /* +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -983,6 +983,9 @@ void build_get_pgde32(u32 **p, unsigned + uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT); + uasm_i_addu(p, ptr, tmp, ptr); + #else ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++#endif + UASM_i_LA_mostly(p, ptr, pgdc); + #endif + uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ +@@ -1344,6 +1347,9 @@ static void build_r4000_tlb_refill_handl + #ifdef CONFIG_64BIT + build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ + #else ++# ifdef CONFIG_BCM47XX ++ uasm_i_nop(&p); ++# endif + build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ + #endif + +@@ -1355,6 +1361,9 @@ static void build_r4000_tlb_refill_handl + build_update_entries(&p, K0, K1); + build_tlb_write_entry(&p, &l, &r, tlb_random); + uasm_l_leave(&l, p); ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(&p); ++#endif + uasm_i_eret(&p); /* return from trap */ + } + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT +@@ -2064,6 +2073,9 @@ build_r4000_tlbchange_handler_head(u32 * + #ifdef CONFIG_64BIT + build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */ + #else ++# ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++# endif + build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */ + #endif + +@@ -2110,6 +2122,9 @@ build_r4000_tlbchange_handler_tail(u32 * + build_tlb_write_entry(p, l, r, tlb_indexed); + uasm_l_leave(l, *p); + build_restore_work_registers(p); ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++#endif + uasm_i_eret(p); /* return from trap */ + + #ifdef CONFIG_64BIT diff --git a/target/linux/bcm47xx/patches-4.14/160-kmap_coherent.patch b/target/linux/bcm47xx/patches-4.14/160-kmap_coherent.patch new file mode 100644 index 0000000000..5cdb545e55 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/160-kmap_coherent.patch @@ -0,0 +1,78 @@ +From: Jeff Hansen <jhansen@cardaccess-inc.com> +Subject: [PATCH] kmap_coherent + +On ASUS WL-500gP there are some "Data bus error"s when executing simple +commands liks "ps" or "cat /proc/1/cmdline". + +This fixes OpenWrt ticket #1485: https://dev.openwrt.org/ticket/1485 +--- +--- a/arch/mips/include/asm/cpu-features.h ++++ b/arch/mips/include/asm/cpu-features.h +@@ -187,6 +187,9 @@ + #ifndef cpu_has_local_ebase + #define cpu_has_local_ebase 1 + #endif ++#ifndef cpu_use_kmap_coherent ++#define cpu_use_kmap_coherent 1 ++#endif + + /* + * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors +--- a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h ++++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h +@@ -80,4 +80,6 @@ + #define cpu_scache_line_size() 0 + #define cpu_has_vz 0 + ++#define cpu_use_kmap_coherent 0 ++ + #endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */ +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -694,7 +694,7 @@ static inline void local_r4k_flush_cache + map_coherent = (cpu_has_dc_aliases && + page_mapcount(page) && + !Page_dcache_dirty(page)); +- if (map_coherent) ++ if (map_coherent && cpu_use_kmap_coherent) + vaddr = kmap_coherent(page, addr); + else + vaddr = kmap_atomic(page); +@@ -719,7 +719,7 @@ static inline void local_r4k_flush_cache + } + + if (vaddr) { +- if (map_coherent) ++ if (map_coherent && cpu_use_kmap_coherent) + kunmap_coherent(); + else + kunmap_atomic(vaddr); +--- a/arch/mips/mm/init.c ++++ b/arch/mips/mm/init.c +@@ -170,7 +170,7 @@ void copy_user_highpage(struct page *to, + void *vfrom, *vto; + + vto = kmap_atomic(to); +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(from) && !Page_dcache_dirty(from)) { + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); +@@ -192,7 +192,7 @@ void copy_to_user_page(struct vm_area_st + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) + { +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(page) && !Page_dcache_dirty(page)) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); +@@ -210,7 +210,7 @@ void copy_from_user_page(struct vm_area_ + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) + { +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(page) && !Page_dcache_dirty(page)) { + void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); diff --git a/target/linux/bcm47xx/patches-4.14/209-b44-register-adm-switch.patch b/target/linux/bcm47xx/patches-4.14/209-b44-register-adm-switch.patch new file mode 100644 index 0000000000..6e655ac802 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/209-b44-register-adm-switch.patch @@ -0,0 +1,121 @@ +From b36f694256f41bc71571f467646d015dda128d14 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Sat, 9 Nov 2013 17:03:59 +0100 +Subject: [PATCH 210/210] b44: register adm switch + +--- + drivers/net/ethernet/broadcom/b44.c | 57 +++++++++++++++++++++++++++++++++++ + drivers/net/ethernet/broadcom/b44.h | 3 ++ + 2 files changed, 60 insertions(+) + +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -31,6 +31,8 @@ + #include <linux/ssb/ssb.h> + #include <linux/slab.h> + #include <linux/phy.h> ++#include <linux/platform_device.h> ++#include <linux/platform_data/adm6996-gpio.h> + + #include <linux/uaccess.h> + #include <asm/io.h> +@@ -2248,6 +2250,69 @@ static void b44_adjust_link(struct net_d + } + } + ++#ifdef CONFIG_BCM47XX ++static int b44_register_adm_switch(struct b44 *bp) ++{ ++ int gpio; ++ struct platform_device *pdev; ++ struct adm6996_gpio_platform_data adm_data = {0}; ++ struct platform_device_info info = {0}; ++ ++ adm_data.model = ADM6996L; ++ gpio = bcm47xx_nvram_gpio_pin("adm_eecs"); ++ if (gpio >= 0) ++ adm_data.eecs = gpio; ++ else ++ adm_data.eecs = 2; ++ ++ gpio = bcm47xx_nvram_gpio_pin("adm_eesk"); ++ if (gpio >= 0) ++ adm_data.eesk = gpio; ++ else ++ adm_data.eesk = 3; ++ ++ gpio = bcm47xx_nvram_gpio_pin("adm_eedi"); ++ if (gpio >= 0) ++ adm_data.eedi = gpio; ++ else ++ adm_data.eedi = 4; ++ ++ /* ++ * We ignore the "adm_rc" GPIO here. The driver does not use it, ++ * and it conflicts with the Reset button GPIO on the Linksys WRT54GSv1. ++ */ ++ ++ info.parent = bp->sdev->dev; ++ info.name = "adm6996_gpio"; ++ info.id = -1; ++ info.data = &adm_data; ++ info.size_data = sizeof(adm_data); ++ ++ if (!bp->adm_switch) { ++ pdev = platform_device_register_full(&info); ++ if (IS_ERR(pdev)) ++ return PTR_ERR(pdev); ++ ++ bp->adm_switch = pdev; ++ } ++ return 0; ++} ++static void b44_unregister_adm_switch(struct b44 *bp) ++{ ++ if (bp->adm_switch) ++ platform_device_unregister(bp->adm_switch); ++} ++#else ++static int b44_register_adm_switch(struct b44 *bp) ++{ ++ return 0; ++} ++static void b44_unregister_adm_switch(struct b44 *bp) ++{ ++ ++} ++#endif /* CONFIG_BCM47XX */ ++ + static int b44_register_phy_one(struct b44 *bp) + { + struct mii_bus *mii_bus; +@@ -2283,6 +2348,9 @@ static int b44_register_phy_one(struct b + if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && + (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { + ++ if (sprom->boardflags_lo & B44_BOARDFLAG_ADM) ++ b44_register_adm_switch(bp); ++ + dev_info(sdev->dev, + "could not find PHY at %i, use fixed one\n", + bp->phy_addr); +@@ -2477,6 +2545,7 @@ static void b44_remove_one(struct ssb_de + unregister_netdev(dev); + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + b44_unregister_phy_one(bp); ++ b44_unregister_adm_switch(bp); + ssb_device_disable(sdev, 0); + ssb_bus_may_powerdown(sdev->bus); + netif_napi_del(&bp->napi); +--- a/drivers/net/ethernet/broadcom/b44.h ++++ b/drivers/net/ethernet/broadcom/b44.h +@@ -408,6 +408,9 @@ struct b44 { + struct mii_bus *mii_bus; + int old_link; + struct mii_if_info mii_if; ++ ++ /* platform device for associated switch */ ++ struct platform_device *adm_switch; + }; + + #endif /* _B44_H */ diff --git a/target/linux/bcm47xx/patches-4.14/210-b44_phy_fix.patch b/target/linux/bcm47xx/patches-4.14/210-b44_phy_fix.patch new file mode 100644 index 0000000000..5620d5cd5f --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/210-b44_phy_fix.patch @@ -0,0 +1,54 @@ +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -431,10 +431,34 @@ static void b44_wap54g10_workaround(stru + error: + pr_warn("PHY: cannot reset MII transceiver isolate bit\n"); + } ++ ++static void b44_bcm47xx_workarounds(struct b44 *bp) ++{ ++ char buf[20]; ++ struct ssb_device *sdev = bp->sdev; ++ ++ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */ ++ if (sdev->bus->sprom.board_num == 100) { ++ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY; ++ } else { ++ /* WL-HDD */ ++ if (bcm47xx_nvram_getenv("hardware_version", buf, sizeof(buf)) >= 0 && ++ !strncmp(buf, "WL300-", strlen("WL300-"))) { ++ if (sdev->bus->sprom.et0phyaddr == 0 && ++ sdev->bus->sprom.et1phyaddr == 1) ++ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY; ++ } ++ } ++ return; ++} + #else + static inline void b44_wap54g10_workaround(struct b44 *bp) + { + } ++ ++static inline void b44_bcm47xx_workarounds(struct b44 *bp) ++{ ++} + #endif + + static int b44_setup_phy(struct b44 *bp) +@@ -443,6 +467,7 @@ static int b44_setup_phy(struct b44 *bp) + int err; + + b44_wap54g10_workaround(bp); ++ b44_bcm47xx_workarounds(bp); + + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + return 0; +@@ -2178,6 +2203,8 @@ static int b44_get_invariants(struct b44 + * valid PHY address. */ + bp->phy_addr &= 0x1F; + ++ b44_bcm47xx_workarounds(bp); ++ + memcpy(bp->dev->dev_addr, addr, ETH_ALEN); + + if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ diff --git a/target/linux/bcm47xx/patches-4.14/280-activate_ssb_support_in_usb.patch b/target/linux/bcm47xx/patches-4.14/280-activate_ssb_support_in_usb.patch new file mode 100644 index 0000000000..0df8ec17f2 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/280-activate_ssb_support_in_usb.patch @@ -0,0 +1,25 @@ +This prevents the options from being delete with make kernel_oldconfig. +--- + drivers/ssb/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -31,6 +31,7 @@ config BCMA_HOST_PCI + config BCMA_HOST_SOC + bool "Support for BCMA in a SoC" + depends on BCMA ++ select USB_HCD_BCMA if USB_EHCI_HCD || USB_OHCI_HCD + help + Host interface for a Broadcom AIX bus directly mapped into + the memory. This only works with the Broadcom SoCs from the +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -157,6 +157,7 @@ config SSB_SFLASH + config SSB_EMBEDDED + bool + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE ++ select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD + default y + + config SSB_DRIVER_EXTIF diff --git a/target/linux/bcm47xx/patches-4.14/300-fork_cacheflush.patch b/target/linux/bcm47xx/patches-4.14/300-fork_cacheflush.patch new file mode 100644 index 0000000000..b5efaaf03c --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/300-fork_cacheflush.patch @@ -0,0 +1,21 @@ +From: Wolfram Joost <dbox2@frokaschwei.de> +Subject: [PATCH] fork_cacheflush + +On ASUS WL-500gP there are many unexpected "Segmentation fault"s that +seem to be caused by a kernel. They can be avoided by: +1) Disabling highpage +2) Using flush_cache_mm in flush_cache_dup_mm + +For details see OpenWrt ticket #2035 https://dev.openwrt.org/ticket/2035 +--- +--- a/arch/mips/include/asm/cacheflush.h ++++ b/arch/mips/include/asm/cacheflush.h +@@ -47,7 +47,7 @@ + extern void (*flush_cache_all)(void); + extern void (*__flush_cache_all)(void); + extern void (*flush_cache_mm)(struct mm_struct *mm); +-#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0) ++#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + extern void (*flush_cache_range)(struct vm_area_struct *vma, + unsigned long start, unsigned long end); + extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); diff --git a/target/linux/bcm47xx/patches-4.14/310-no_highpage.patch b/target/linux/bcm47xx/patches-4.14/310-no_highpage.patch new file mode 100644 index 0000000000..646f352e34 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/310-no_highpage.patch @@ -0,0 +1,74 @@ +From: Jeff Hansen <jhansen@cardaccess-inc.com> +Subject: [PATCH] no highpage + +On ASUS WL-500gP there are many unexpected "Segmentation fault"s that +seem to be caused by a kernel. They can be avoided by: +1) Disabling highpage +2) Using flush_cache_mm in flush_cache_dup_mm + +For details see OpenWrt ticket #2035 https://dev.openwrt.org/ticket/2035 +--- +--- a/arch/mips/include/asm/page.h ++++ b/arch/mips/include/asm/page.h +@@ -71,6 +71,7 @@ static inline unsigned int page_size_ftl + #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ + + #include <linux/pfn.h> ++#include <asm/cpu-features.h> + + extern void build_clear_page(void); + extern void build_copy_page(void); +@@ -105,11 +106,16 @@ static inline void clear_user_page(void + flush_data_cache_page((unsigned long)addr); + } + +-struct vm_area_struct; +-extern void copy_user_highpage(struct page *to, struct page *from, +- unsigned long vaddr, struct vm_area_struct *vma); ++static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, ++ struct page *to) ++{ ++ extern void (*flush_data_cache_page)(unsigned long addr); + +-#define __HAVE_ARCH_COPY_USER_HIGHPAGE ++ copy_page(vto, vfrom); ++ if (!cpu_has_ic_fills_f_dc || ++ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) ++ flush_data_cache_page((unsigned long)vto); ++} + + /* + * These are used to make use of C type-checking.. +--- a/arch/mips/mm/init.c ++++ b/arch/mips/mm/init.c +@@ -164,30 +164,6 @@ void kunmap_coherent(void) + preempt_enable(); + } + +-void copy_user_highpage(struct page *to, struct page *from, +- unsigned long vaddr, struct vm_area_struct *vma) +-{ +- void *vfrom, *vto; +- +- vto = kmap_atomic(to); +- if (cpu_has_dc_aliases && cpu_use_kmap_coherent && +- page_mapcount(from) && !Page_dcache_dirty(from)) { +- vfrom = kmap_coherent(from, vaddr); +- copy_page(vto, vfrom); +- kunmap_coherent(); +- } else { +- vfrom = kmap_atomic(from); +- copy_page(vto, vfrom); +- kunmap_atomic(vfrom); +- } +- if ((!cpu_has_ic_fills_f_dc) || +- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) +- flush_data_cache_page((unsigned long)vto); +- kunmap_atomic(vto); +- /* Make sure this page is cleared on other CPU's too before using it */ +- smp_wmb(); +-} +- + void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) diff --git a/target/linux/bcm47xx/patches-4.14/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch b/target/linux/bcm47xx/patches-4.14/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch new file mode 100644 index 0000000000..74060e2181 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch @@ -0,0 +1,185 @@ +--- a/arch/mips/bcm47xx/board.c ++++ b/arch/mips/bcm47xx/board.c +@@ -141,6 +141,7 @@ struct bcm47xx_board_type_list2 bcm47xx_ + {{BCM47XX_BOARD_LINKSYS_WRT300NV11, "Linksys WRT300N V1.1"}, "WRT300N", "1.1"}, + {{BCM47XX_BOARD_LINKSYS_WRT310NV1, "Linksys WRT310N V1"}, "WRT310N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT310NV2, "Linksys WRT310N V2"}, "WRT310N", "2.0"}, ++ {{BCM47XX_BOARD_LINKSYS_WRT320N_V1, "Linksys WRT320N V1"}, "WRT320N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"}, +@@ -160,9 +161,12 @@ struct bcm47xx_board_type_list1 bcm47xx_ + {{BCM47XX_BOARD_LUXUL_XVW_P30_V1, "Luxul XVW-P30 V1"}, "luxul_xvwp30_v1"}, + {{BCM47XX_BOARD_LUXUL_XWR_600_V1, "Luxul XWR-600 V1"}, "luxul_xwr600_v1"}, + {{BCM47XX_BOARD_LUXUL_XWR_1750_V1, "Luxul XWR-1750 V1"}, "luxul_xwr1750_v1"}, ++ {{BCM47XX_BOARD_NETGEAR_R6300_V1, "Netgear R6300 V1"}, "U12H218T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614_V10, "Netgear WGR614 V10"}, "U12H139T01_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WN2500RP_V1, "Netgear WN2500RP V1"}, "U12H197T00_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WN2500RP_V2, "Netgear WN2500RP V2"}, "U12H294T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"}, +--- a/arch/mips/bcm47xx/buttons.c ++++ b/arch/mips/bcm47xx/buttons.c +@@ -27,6 +27,12 @@ + /* Asus */ + + static const struct gpio_keys_button ++bcm47xx_buttons_asus_rtn10u[] __initconst = { ++ BCM47XX_GPIO_KEY(20, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(21, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_asus_rtn12[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(1, KEY_RESTART), +@@ -277,6 +283,18 @@ bcm47xx_buttons_linksys_wrt310nv1[] __in + }; + + static const struct gpio_keys_button ++bcm47xx_buttons_linksys_wrt310n_v2[] __initconst = { ++ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(6, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button ++bcm47xx_buttons_linksys_wrt320n_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(8, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_WIMAX), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +@@ -385,6 +403,17 @@ bcm47xx_buttons_motorola_wr850gv2v3[] __ + /* Netgear */ + + static const struct gpio_keys_button ++bcm47xx_buttons_netgear_r6300_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(6, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button ++bcm47xx_buttons_netgear_wn2500rp_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(12, KEY_RESTART), ++ BCM47XX_GPIO_KEY(31, KEY_WPS_BUTTON), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_netgear_wndr3400v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON), +@@ -471,6 +500,9 @@ int __init bcm47xx_buttons_register(void + int err; + + switch (board) { ++ case BCM47XX_BOARD_ASUS_RTN10U: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn10u); ++ break; + case BCM47XX_BOARD_ASUS_RTN12: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn12); + break; +@@ -601,6 +633,12 @@ int __init bcm47xx_buttons_register(void + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1); + break; ++ case BCM47XX_BOARD_LINKSYS_WRT310NV2: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310n_v2); ++ break; ++ case BCM47XX_BOARD_LINKSYS_WRT320N_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt320n_v1); ++ break; + case BCM47XX_BOARD_LINKSYS_WRT54G3GV2: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2); + break; +@@ -664,6 +702,12 @@ int __init bcm47xx_buttons_register(void + err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gv2v3); + break; + ++ case BCM47XX_BOARD_NETGEAR_R6300_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_r6300_v1); ++ break; ++ case BCM47XX_BOARD_NETGEAR_WN2500RP_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wn2500rp_v1); ++ break; + case BCM47XX_BOARD_NETGEAR_WNDR3400V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1); + break; +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +@@ -72,6 +72,7 @@ enum bcm47xx_board { + BCM47XX_BOARD_LINKSYS_WRT300NV11, + BCM47XX_BOARD_LINKSYS_WRT310NV1, + BCM47XX_BOARD_LINKSYS_WRT310NV2, ++ BCM47XX_BOARD_LINKSYS_WRT320N_V1, + BCM47XX_BOARD_LINKSYS_WRT54G3GV2, + BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, + BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, +@@ -98,9 +99,12 @@ enum bcm47xx_board { + BCM47XX_BOARD_MOTOROLA_WR850GP, + BCM47XX_BOARD_MOTOROLA_WR850GV2V3, + ++ BCM47XX_BOARD_NETGEAR_R6300_V1, + BCM47XX_BOARD_NETGEAR_WGR614V8, + BCM47XX_BOARD_NETGEAR_WGR614V9, + BCM47XX_BOARD_NETGEAR_WGR614_V10, ++ BCM47XX_BOARD_NETGEAR_WN2500RP_V1, ++ BCM47XX_BOARD_NETGEAR_WN2500RP_V2, + BCM47XX_BOARD_NETGEAR_WNDR3300, + BCM47XX_BOARD_NETGEAR_WNDR3400V1, + BCM47XX_BOARD_NETGEAR_WNDR3400V2, +--- a/arch/mips/bcm47xx/leds.c ++++ b/arch/mips/bcm47xx/leds.c +@@ -30,6 +30,14 @@ + /* Asus */ + + static const struct gpio_led ++bcm47xx_leds_asus_rtn10u[] __initconst = { ++ BCM47XX_GPIO_LED(5, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(6, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON), ++ BCM47XX_GPIO_LED(7, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(8, "green", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_asus_rtn12[] __initconst = { + BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), +@@ -314,6 +322,13 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc + }; + + static const struct gpio_led ++bcm47xx_leds_linksys_wrt320n_v1[] __initconst = { ++ BCM47XX_GPIO_LED(1, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(2, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON), ++ BCM47XX_GPIO_LED(4, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_linksys_wrt54g_generic[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), +@@ -556,6 +571,9 @@ void __init bcm47xx_leds_register(void) + enum bcm47xx_board board = bcm47xx_board_get(); + + switch (board) { ++ case BCM47XX_BOARD_ASUS_RTN10U: ++ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn10u); ++ break; + case BCM47XX_BOARD_ASUS_RTN12: + bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12); + break; +@@ -689,6 +707,9 @@ void __init bcm47xx_leds_register(void) + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1); + break; ++ case BCM47XX_BOARD_LINKSYS_WRT320N_V1: ++ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt320n_v1); ++ break; + case BCM47XX_BOARD_LINKSYS_WRT54G3GV2: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2); + break; diff --git a/target/linux/bcm47xx/patches-4.14/400-mtd-bcm47xxpart-get-nvram.patch b/target/linux/bcm47xx/patches-4.14/400-mtd-bcm47xxpart-get-nvram.patch new file mode 100644 index 0000000000..df9d434c9f --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/400-mtd-bcm47xxpart-get-nvram.patch @@ -0,0 +1,34 @@ +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -102,6 +102,7 @@ static int bcm47xxpart_parse(struct mtd_ + int trx_num = 0; /* Number of found TRX partitions */ + int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; + int err; ++ bool found_nvram = false; + + /* + * Some really old flashes (like AT45DB*) had smaller erasesize-s, but +@@ -283,12 +284,23 @@ static int bcm47xxpart_parse(struct mtd_ + if (buf[0] == NVRAM_HEADER) { + bcm47xxpart_add_part(&parts[curr_part++], "nvram", + master->size - blocksize, 0); ++ found_nvram = true; + break; + } + } + + kfree(buf); + ++ if (!found_nvram) { ++ pr_err("can not find a nvram partition reserve last block\n"); ++ bcm47xxpart_add_part(&parts[curr_part++], "nvram_guess", ++ master->size - blocksize * 2, MTD_WRITEABLE); ++ for (i = 0; i < curr_part; i++) { ++ if (parts[i].size + parts[i].offset == master->size) ++ parts[i].offset -= blocksize * 2; ++ } ++ } ++ + /* + * Assume that partitions end at the beginning of the one they are + * followed by. diff --git a/target/linux/bcm47xx/patches-4.14/610-pci_ide_fix.patch b/target/linux/bcm47xx/patches-4.14/610-pci_ide_fix.patch new file mode 100644 index 0000000000..ccae6a5988 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/610-pci_ide_fix.patch @@ -0,0 +1,41 @@ +From: b.sander +Subject: [PATCH] pci: IDE fix + +These are standard probing messages when using pdc202xx_old: +pdc202xx_old 0000:00:01.0: IDE controller (0x105a:0x0d30 rev 0x02) +PCI: Enabling device 0000:00:01.0 (0004 -> 0007) +PCI: Fixing up device 0000:00:01.0 +0000:00:01.0: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode. +0000:00:01.0: FORCING BURST BIT 0x00->0x01 ACTIVE +pdc202xx_old 0000:00:01.0: 100% native mode on irq 6 + +With the default MAX_HWIFS value after above we get: + ide2: BM-DMA at 0x0400-0x0407 + ide3: BM-DMA at 0x0408-0x040f +Probing IDE interface ide2... +hde: CF500, CFA DISK drive + +As you can see it's ide2 + ide3 and hde. + +With this patch applied we get: + ide0: BM-DMA at 0x0400-0x0407 + ide1: BM-DMA at 0x0408-0x040f +Probing IDE interface ide0... +hda: CF500, CFA DISK drive + +This fixes OpenWrt ticket #7061: https://dev.openwrt.org/ticket/7061 +--- +--- a/include/linux/ide.h ++++ b/include/linux/ide.h +@@ -241,7 +241,11 @@ static inline void ide_std_init_ports(st + hw->io_ports.ctl_addr = ctl_addr; + } + ++#if defined CONFIG_BCM47XX ++# define MAX_HWIFS 2 ++#else + #define MAX_HWIFS 10 ++#endif + + /* + * Now for the data we need to maintain per-drive: ide_drive_t diff --git a/target/linux/bcm47xx/patches-4.14/791-tg3-no-pci-sleep.patch b/target/linux/bcm47xx/patches-4.14/791-tg3-no-pci-sleep.patch new file mode 100644 index 0000000000..85bac98a26 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/791-tg3-no-pci-sleep.patch @@ -0,0 +1,17 @@ +When the Ethernet controller is powered down and someone wants to +access the mdio bus like the witch driver (b53) the system crashed if +PCI_D3hot was set before. This patch deactivates this power sawing mode +when a switch driver is in use. + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -4264,7 +4264,8 @@ static int tg3_power_down_prepare(struct + static void tg3_power_down(struct tg3 *tp) + { + pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE)); +- pci_set_power_state(tp->pdev, PCI_D3hot); ++ if (!tg3_flag(tp, ROBOSWITCH)) ++ pci_set_power_state(tp->pdev, PCI_D3hot); + } + + static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) diff --git a/target/linux/bcm47xx/patches-4.14/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch b/target/linux/bcm47xx/patches-4.14/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch new file mode 100644 index 0000000000..318dc55810 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch @@ -0,0 +1,73 @@ +From 597715c61ae75a05ab3310a34ff3857a006f0f63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Thu, 20 Nov 2014 21:32:42 +0100 +Subject: [PATCH] bcma: add table of serial flashes with smaller blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/bcma/driver_chipcommon_sflash.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/drivers/bcma/driver_chipcommon_sflash.c ++++ b/drivers/bcma/driver_chipcommon_sflash.c +@@ -9,6 +9,7 @@ + + #include <linux/platform_device.h> + #include <linux/bcma/bcma.h> ++#include <bcm47xx_board.h> + + static struct resource bcma_sflash_resource = { + .name = "bcma_sflash", +@@ -42,6 +43,13 @@ static const struct bcma_sflash_tbl_e bc + { NULL }, + }; + ++/* Some devices use smaller blocks (and have more of them) */ ++static const struct bcma_sflash_tbl_e bcma_sflash_st_shrink_tbl[] = { ++ { "M25P16", 0x14, 0x1000, 512, }, ++ { "M25P32", 0x15, 0x1000, 1024, }, ++ { NULL }, ++}; ++ + static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, +@@ -85,6 +93,24 @@ static void bcma_sflash_cmd(struct bcma_ + bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); + } + ++const struct bcma_sflash_tbl_e *bcma_sflash_shrink_flash(u32 id) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ const struct bcma_sflash_tbl_e *e; ++ ++ switch (board) { ++ case BCM47XX_BOARD_NETGEAR_WGR614_V10: ++ case BCM47XX_BOARD_NETGEAR_WNR1000_V3: ++ for (e = bcma_sflash_st_shrink_tbl; e->name; e++) { ++ if (e->id == id) ++ return e; ++ } ++ return NULL; ++ default: ++ return NULL; ++ } ++} ++ + /* Initialize serial flash access */ + int bcma_sflash_init(struct bcma_drv_cc *cc) + { +@@ -115,6 +141,10 @@ int bcma_sflash_init(struct bcma_drv_cc + case 0x13: + return -ENOTSUPP; + default: ++ e = bcma_sflash_shrink_flash(id); ++ if (e) ++ break; ++ + for (e = bcma_sflash_st_tbl; e->name; e++) { + if (e->id == id) + break; diff --git a/target/linux/bcm47xx/patches-4.14/820-wgt634u-nvram-fix.patch b/target/linux/bcm47xx/patches-4.14/820-wgt634u-nvram-fix.patch new file mode 100644 index 0000000000..aaab39ae41 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/820-wgt634u-nvram-fix.patch @@ -0,0 +1,304 @@ +The Netgear wgt634u uses a different format for storing the +configuration. This patch is needed to read out the correct +configuration. The cfe_env.c file uses a different method way to read +out the configuration than the in kernel cfe config reader. + +--- a/drivers/firmware/broadcom/Makefile ++++ b/drivers/firmware/broadcom/Makefile +@@ -1,2 +1,2 @@ +-obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o ++obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o cfe_env.o + obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx_sprom.o +--- /dev/null ++++ b/drivers/firmware/broadcom/cfe_env.c +@@ -0,0 +1,228 @@ ++/* ++ * CFE environment variable access ++ * ++ * Copyright 2001-2003, Broadcom Corporation ++ * Copyright 2006, Felix Fietkau <nbd@nbd.name> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/string.h> ++#include <asm/io.h> ++#include <linux/uaccess.h> ++ ++#define NVRAM_SIZE (0x1ff0) ++static char _nvdata[NVRAM_SIZE]; ++static char _valuestr[256]; ++ ++/* ++ * TLV types. These codes are used in the "type-length-value" ++ * encoding of the items stored in the NVRAM device (flash or EEPROM) ++ * ++ * The layout of the flash/nvram is as follows: ++ * ++ * <type> <length> <data ...> <type> <length> <data ...> <type_end> ++ * ++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list. ++ * The "length" field marks the length of the data section, not ++ * including the type and length fields. ++ * ++ * Environment variables are stored as follows: ++ * ++ * <type_env> <length> <flags> <name> = <value> ++ * ++ * If bit 0 (low bit) is set, the length is an 8-bit value. ++ * If bit 0 (low bit) is clear, the length is a 16-bit value ++ * ++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still ++ * indicates the size of the length field. ++ * ++ * Flags are from the constants below: ++ * ++ */ ++#define ENV_LENGTH_16BITS 0x00 /* for low bit */ ++#define ENV_LENGTH_8BITS 0x01 ++ ++#define ENV_TYPE_USER 0x80 ++ ++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) ++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) ++ ++/* ++ * The actual TLV types we support ++ */ ++ ++#define ENV_TLV_TYPE_END 0x00 ++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS) ++ ++/* ++ * Environment variable flags ++ */ ++ ++#define ENV_FLG_NORMAL 0x00 /* normal read/write */ ++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */ ++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */ ++ ++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */ ++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */ ++ ++ ++/* ********************************************************************* ++ * _nvram_read(buffer,offset,length) ++ * ++ * Read data from the NVRAM device ++ * ++ * Input parameters: ++ * buffer - destination buffer ++ * offset - offset of data to read ++ * length - number of bytes to read ++ * ++ * Return value: ++ * number of bytes read, or <0 if error occured ++ ********************************************************************* */ ++static int ++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) ++{ ++ int i; ++ if (offset > NVRAM_SIZE) ++ return -1; ++ ++ for ( i = 0; i < length; i++) { ++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; ++ } ++ return length; ++} ++ ++ ++static char* ++_strnchr(const char *dest,int c,size_t cnt) ++{ ++ while (*dest && (cnt > 0)) { ++ if (*dest == c) return (char *) dest; ++ dest++; ++ cnt--; ++ } ++ return NULL; ++} ++ ++ ++ ++/* ++ * Core support API: Externally visible. ++ */ ++ ++/* ++ * Get the value of an NVRAM variable ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++ ++char *cfe_env_get(unsigned char *nv_buf, const char *name) ++{ ++ int size; ++ unsigned char *buffer; ++ unsigned char *ptr; ++ unsigned char *envval; ++ unsigned int reclen; ++ unsigned int rectype; ++ int offset; ++ int flg; ++ ++ if (!strcmp(name, "nvram_type")) ++ return "cfe"; ++ ++ size = NVRAM_SIZE; ++ buffer = &_nvdata[0]; ++ ++ ptr = buffer; ++ offset = 0; ++ ++ /* Read the record type and length */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ ++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { ++ ++ /* Adjust pointer for TLV type */ ++ rectype = *(ptr); ++ offset++; ++ size--; ++ ++ /* ++ * Read the length. It can be either 1 or 2 bytes ++ * depending on the code ++ */ ++ if (rectype & ENV_LENGTH_8BITS) { ++ /* Read the record type and length - 8 bits */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ reclen = *(ptr); ++ size--; ++ offset++; ++ } ++ else { ++ /* Read the record type and length - 16 bits, MSB first */ ++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) { ++ goto error; ++ } ++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); ++ size -= 2; ++ offset += 2; ++ } ++ ++ if (reclen > size) ++ break; /* should not happen, bad NVRAM */ ++ ++ switch (rectype) { ++ case ENV_TLV_TYPE_ENV: ++ /* Read the TLV data */ ++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) ++ goto error; ++ flg = *ptr++; ++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); ++ if (envval) { ++ *envval++ = '\0'; ++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); ++ _valuestr[(reclen-1)-(envval-ptr)] = '\0'; ++#if 0 ++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); ++#endif ++ if(!strcmp(ptr, name)){ ++ return _valuestr; ++ } ++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) ++ return _valuestr; ++ } ++ break; ++ ++ default: ++ /* Unknown TLV type, skip it. */ ++ break; ++ } ++ ++ /* ++ * Advance to next TLV ++ */ ++ ++ size -= (int)reclen; ++ offset += reclen; ++ ++ /* Read the next record type */ ++ ptr = buffer; ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) ++ goto error; ++ } ++ ++error: ++ return NULL; ++ ++} ++ +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -37,6 +37,8 @@ struct nvram_header { + static char nvram_buf[NVRAM_SPACE]; + static size_t nvram_len; + static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; ++static int cfe_env; ++extern char *cfe_env_get(char *nv_buf, const char *name); + + static u32 find_nvram_size(void __iomem *end) + { +@@ -56,7 +58,9 @@ static u32 find_nvram_size(void __iomem + static int nvram_find_and_copy(void __iomem *iobase, u32 lim) + { + struct nvram_header __iomem *header; ++ int i; + u32 off; ++ u32 *src, *dst; + u32 size; + + if (nvram_len) { +@@ -64,6 +68,26 @@ static int nvram_find_and_copy(void __io + return -EEXIST; + } + ++ cfe_env = 0; ++ ++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */ ++ if (lim >= 8 * 1024 * 1024) { ++ src = (u32 *)(iobase + 8 * 1024 * 1024 - 0x2000); ++ dst = (u32 *)nvram_buf; ++ ++ if ((*src & 0xff00ff) == 0x000001) { ++ printk("early_nvram_init: WGT634U NVRAM found.\n"); ++ ++ for (i = 0; i < 0x1ff0; i++) { ++ if (*src == 0xFFFFFFFF) ++ break; ++ *dst++ = *src++; ++ } ++ cfe_env = 1; ++ return 0; ++ } ++ } ++ + /* TODO: when nvram is on nand flash check for bad blocks first. */ + off = FLASH_MIN; + while (off <= lim) { +@@ -174,6 +198,13 @@ int bcm47xx_nvram_getenv(const char *nam + if (!name) + return -EINVAL; + ++ if (cfe_env) { ++ value = cfe_env_get(nvram_buf, name); ++ if (!value) ++ return -ENOENT; ++ return snprintf(val, val_len, "%s", value); ++ } ++ + if (!nvram_len) { + err = nvram_init(); + if (err) diff --git a/target/linux/bcm47xx/patches-4.14/830-huawei_e970_support.patch b/target/linux/bcm47xx/patches-4.14/830-huawei_e970_support.patch new file mode 100644 index 0000000000..b6150ed8fd --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/830-huawei_e970_support.patch @@ -0,0 +1,101 @@ +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -37,6 +37,7 @@ + #include <linux/ssb/ssb.h> + #include <linux/ssb/ssb_embedded.h> + #include <linux/bcma/bcma_soc.h> ++#include <linux/old_gpio_wdt.h> + #include <asm/bootinfo.h> + #include <asm/idle.h> + #include <asm/prom.h> +@@ -225,6 +226,33 @@ static struct fixed_phy_status bcm47xx_f + .duplex = DUPLEX_FULL, + }; + ++static struct gpio_wdt_platform_data gpio_wdt_data; ++ ++static struct platform_device gpio_wdt_device = { ++ .name = "gpio-wdt", ++ .id = 0, ++ .dev = { ++ .platform_data = &gpio_wdt_data, ++ }, ++}; ++ ++static int __init bcm47xx_register_gpio_watchdog(void) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ ++ switch (board) { ++ case BCM47XX_BOARD_HUAWEI_E970: ++ pr_info("bcm47xx: detected Huawei E970 or similar, starting early gpio_wdt timer\n"); ++ gpio_wdt_data.gpio = 7; ++ gpio_wdt_data.interval = HZ; ++ gpio_wdt_data.first_interval = HZ / 5; ++ return platform_device_register(&gpio_wdt_device); ++ default: ++ /* Nothing to do */ ++ return 0; ++ } ++} ++ + static int __init bcm47xx_register_bus_complete(void) + { + switch (bcm47xx_bus_type) { +@@ -244,6 +272,7 @@ static int __init bcm47xx_register_bus_c + bcm47xx_workarounds(); + + fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status, -1); ++ bcm47xx_register_gpio_watchdog(); + return 0; + } + device_initcall(bcm47xx_register_bus_complete); +--- a/arch/mips/configs/bcm47xx_defconfig ++++ b/arch/mips/configs/bcm47xx_defconfig +@@ -66,6 +66,7 @@ CONFIG_HW_RANDOM=y + CONFIG_GPIO_SYSFS=y + CONFIG_WATCHDOG=y + CONFIG_BCM47XX_WDT=y ++CONFIG_GPIO_WDT=y + CONFIG_SSB_DEBUG=y + CONFIG_SSB_DRIVER_GIGE=y + CONFIG_BCMA_DRIVER_GMAC_CMN=y +--- a/drivers/ssb/embedded.c ++++ b/drivers/ssb/embedded.c +@@ -34,11 +34,36 @@ int ssb_watchdog_timer_set(struct ssb_bu + } + EXPORT_SYMBOL(ssb_watchdog_timer_set); + ++#ifdef CONFIG_BCM47XX ++#include <bcm47xx_board.h> ++ ++static bool ssb_watchdog_supported(void) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ ++ /* The Huawei E970 has a hardware watchdog using a GPIO */ ++ switch (board) { ++ case BCM47XX_BOARD_HUAWEI_E970: ++ return false; ++ default: ++ return true; ++ } ++} ++#else ++static bool ssb_watchdog_supported(void) ++{ ++ return true; ++} ++#endif ++ + int ssb_watchdog_register(struct ssb_bus *bus) + { + struct bcm47xx_wdt wdt = {}; + struct platform_device *pdev; + ++ if (!ssb_watchdog_supported()) ++ return 0; ++ + if (ssb_chipco_available(&bus->chipco)) { + wdt.driver_data = &bus->chipco; + wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt; diff --git a/target/linux/bcm47xx/patches-4.14/831-old_gpio_wdt.patch b/target/linux/bcm47xx/patches-4.14/831-old_gpio_wdt.patch new file mode 100644 index 0000000000..c2becac712 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/831-old_gpio_wdt.patch @@ -0,0 +1,360 @@ +This generic GPIO watchdog is used on Huawei E970 (bcm47xx) + +Signed-off-by: Mathias Adam <m.adam--openwrt@adamis.de> + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1472,6 +1472,15 @@ config WDT_MTX1 + Hardware driver for the MTX-1 boards. This is a watchdog timer that + will reboot the machine after a 100 seconds timer expired. + ++config GPIO_WDT ++ tristate "GPIO Hardware Watchdog" ++ help ++ Hardware driver for GPIO-controlled watchdogs. GPIO pin and ++ toggle interval settings are platform-specific. The driver ++ will stop toggling the GPIO (i.e. machine reboots) after a ++ 100 second timer expired and no process has written to ++ /dev/watchdog during that time. ++ + config PNX833X_WDT + tristate "PNX833x Hardware Watchdog" + depends on SOC_PNX8335 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -163,6 +163,7 @@ obj-$(CONFIG_RC32434_WDT) += rc32434_wdt + obj-$(CONFIG_INDYDOG) += indydog.o + obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o + obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o ++obj-$(CONFIG_GPIO_WDT) += old_gpio_wdt.o + obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o +--- /dev/null ++++ b/drivers/watchdog/old_gpio_wdt.c +@@ -0,0 +1,301 @@ ++/* ++ * Driver for GPIO-controlled Hardware Watchdogs. ++ * ++ * Copyright (C) 2013 Mathias Adam <m.adam--linux@adamis.de> ++ * ++ * Replaces mtx1_wdt (driver for the MTX-1 Watchdog): ++ * ++ * (C) Copyright 2005 4G Systems <info@4g-systems.biz>, ++ * All Rights Reserved. ++ * http://www.4g-systems.biz ++ * ++ * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Neither Michael Stickel nor 4G Systems admit liability nor provide ++ * warranty for any of this software. This material is provided ++ * "AS-IS" and at no charge. ++ * ++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz> ++ * ++ * Release 0.01. ++ * Author: Michael Stickel michael.stickel@4g-systems.biz ++ * ++ * Release 0.02. ++ * Author: Florian Fainelli florian@openwrt.org ++ * use the Linux watchdog/timer APIs ++ * ++ * Release 0.03. ++ * Author: Mathias Adam <m.adam--linux@adamis.de> ++ * make it a generic gpio watchdog driver ++ * ++ * The Watchdog is configured to reset the MTX-1 ++ * if it is not triggered for 100 seconds. ++ * It should not be triggered more often than 1.6 seconds. ++ * ++ * A timer triggers the watchdog every 5 seconds, until ++ * it is opened for the first time. After the first open ++ * it MUST be triggered every 2..95 seconds. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/miscdevice.h> ++#include <linux/fs.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/timer.h> ++#include <linux/completion.h> ++#include <linux/jiffies.h> ++#include <linux/watchdog.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/uaccess.h> ++#include <linux/gpio.h> ++#include <linux/old_gpio_wdt.h> ++ ++static int ticks = 100 * HZ; ++ ++static struct { ++ struct completion stop; ++ spinlock_t lock; ++ int running; ++ struct timer_list timer; ++ int queue; ++ int default_ticks; ++ unsigned long inuse; ++ unsigned gpio; ++ unsigned int gstate; ++ int interval; ++ int first_interval; ++} gpio_wdt_device; ++ ++static void gpio_wdt_trigger(unsigned long unused) ++{ ++ spin_lock(&gpio_wdt_device.lock); ++ if (gpio_wdt_device.running && ticks > 0) ++ ticks -= gpio_wdt_device.interval; ++ ++ /* toggle wdt gpio */ ++ gpio_wdt_device.gstate = !gpio_wdt_device.gstate; ++ gpio_set_value(gpio_wdt_device.gpio, gpio_wdt_device.gstate); ++ ++ if (gpio_wdt_device.queue && ticks > 0) ++ mod_timer(&gpio_wdt_device.timer, jiffies + gpio_wdt_device.interval); ++ else ++ complete(&gpio_wdt_device.stop); ++ spin_unlock(&gpio_wdt_device.lock); ++} ++ ++static void gpio_wdt_reset(void) ++{ ++ ticks = gpio_wdt_device.default_ticks; ++} ++ ++ ++static void gpio_wdt_start(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gpio_wdt_device.lock, flags); ++ if (!gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 1; ++ gpio_wdt_device.gstate = 1; ++ gpio_set_value(gpio_wdt_device.gpio, 1); ++ mod_timer(&gpio_wdt_device.timer, jiffies + gpio_wdt_device.first_interval); ++ } ++ gpio_wdt_device.running++; ++ spin_unlock_irqrestore(&gpio_wdt_device.lock, flags); ++} ++ ++static int gpio_wdt_stop(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gpio_wdt_device.lock, flags); ++ if (gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 0; ++ gpio_wdt_device.gstate = 0; ++ gpio_set_value(gpio_wdt_device.gpio, 0); ++ } ++ ticks = gpio_wdt_device.default_ticks; ++ spin_unlock_irqrestore(&gpio_wdt_device.lock, flags); ++ return 0; ++} ++ ++/* Filesystem functions */ ++ ++static int gpio_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(0, &gpio_wdt_device.inuse)) ++ return -EBUSY; ++ return nonseekable_open(inode, file); ++} ++ ++ ++static int gpio_wdt_release(struct inode *inode, struct file *file) ++{ ++ clear_bit(0, &gpio_wdt_device.inuse); ++ return 0; ++} ++ ++static long gpio_wdt_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ void __user *argp = (void __user *)arg; ++ int __user *p = (int __user *)argp; ++ unsigned int value; ++ static const struct watchdog_info ident = { ++ .options = WDIOF_CARDRESET, ++ .identity = "GPIO WDT", ++ }; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ if (copy_to_user(argp, &ident, sizeof(ident))) ++ return -EFAULT; ++ break; ++ case WDIOC_GETSTATUS: ++ case WDIOC_GETBOOTSTATUS: ++ put_user(0, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ if (get_user(value, p)) ++ return -EFAULT; ++ if (value & WDIOS_ENABLECARD) ++ gpio_wdt_start(); ++ else if (value & WDIOS_DISABLECARD) ++ gpio_wdt_stop(); ++ else ++ return -EINVAL; ++ return 0; ++ case WDIOC_KEEPALIVE: ++ gpio_wdt_reset(); ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++ ++static ssize_t gpio_wdt_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) ++{ ++ if (!count) ++ return -EIO; ++ gpio_wdt_reset(); ++ return count; ++} ++ ++static const struct file_operations gpio_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = gpio_wdt_ioctl, ++ .open = gpio_wdt_open, ++ .write = gpio_wdt_write, ++ .release = gpio_wdt_release, ++}; ++ ++ ++static struct miscdevice gpio_wdt_misc = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &gpio_wdt_fops, ++}; ++ ++ ++static int gpio_wdt_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct gpio_wdt_platform_data *gpio_wdt_data = pdev->dev.platform_data; ++ ++ gpio_wdt_device.gpio = gpio_wdt_data->gpio; ++ gpio_wdt_device.interval = gpio_wdt_data->interval; ++ gpio_wdt_device.first_interval = gpio_wdt_data->first_interval; ++ if (gpio_wdt_device.first_interval <= 0) { ++ gpio_wdt_device.first_interval = gpio_wdt_device.interval; ++ } ++ ++ ret = gpio_request(gpio_wdt_device.gpio, "gpio-wdt"); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request gpio"); ++ return ret; ++ } ++ ++ spin_lock_init(&gpio_wdt_device.lock); ++ init_completion(&gpio_wdt_device.stop); ++ gpio_wdt_device.queue = 0; ++ clear_bit(0, &gpio_wdt_device.inuse); ++ setup_timer(&gpio_wdt_device.timer, gpio_wdt_trigger, 0L); ++ gpio_wdt_device.default_ticks = ticks; ++ ++ gpio_wdt_start(); ++ dev_info(&pdev->dev, "GPIO Hardware Watchdog driver (gpio=%i interval=%i/%i)\n", ++ gpio_wdt_data->gpio, gpio_wdt_data->first_interval, gpio_wdt_data->interval); ++ return 0; ++} ++ ++static int gpio_wdt_remove(struct platform_device *pdev) ++{ ++ /* FIXME: do we need to lock this test ? */ ++ if (gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 0; ++ wait_for_completion(&gpio_wdt_device.stop); ++ } ++ ++ gpio_free(gpio_wdt_device.gpio); ++ misc_deregister(&gpio_wdt_misc); ++ return 0; ++} ++ ++static struct platform_driver gpio_wdt_driver = { ++ .probe = gpio_wdt_probe, ++ .remove = gpio_wdt_remove, ++ .driver.name = "gpio-wdt", ++ .driver.owner = THIS_MODULE, ++}; ++ ++static int __init gpio_wdt_init(void) ++{ ++ return platform_driver_register(&gpio_wdt_driver); ++} ++arch_initcall(gpio_wdt_init); ++ ++/* ++ * We do wdt initialization in two steps: arch_initcall probes the wdt ++ * very early to start pinging the watchdog (misc devices are not yet ++ * available), and later module_init() just registers the misc device. ++ */ ++static int gpio_wdt_init_late(void) ++{ ++ int ret; ++ ++ ret = misc_register(&gpio_wdt_misc); ++ if (ret < 0) { ++ pr_err("GPIO_WDT: failed to register misc device\n"); ++ return ret; ++ } ++ return 0; ++} ++#ifndef MODULE ++module_init(gpio_wdt_init_late); ++#endif ++ ++static void __exit gpio_wdt_exit(void) ++{ ++ platform_driver_unregister(&gpio_wdt_driver); ++} ++module_exit(gpio_wdt_exit); ++ ++MODULE_AUTHOR("Michael Stickel, Florian Fainelli, Mathias Adam"); ++MODULE_DESCRIPTION("Driver for GPIO hardware watchdogs"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); ++MODULE_ALIAS("platform:gpio-wdt"); +--- /dev/null ++++ b/include/linux/old_gpio_wdt.h +@@ -0,0 +1,21 @@ ++/* ++ * Definitions for the GPIO watchdog driver ++ * ++ * Copyright (C) 2013 Mathias Adam <m.adam--linux@adamis.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _GPIO_WDT_H_ ++#define _GPIO_WDT_H_ ++ ++struct gpio_wdt_platform_data { ++ int gpio; /* GPIO line number */ ++ int interval; /* watchdog reset interval in system ticks */ ++ int first_interval; /* first wd reset interval in system ticks */ ++}; ++ ++#endif /* _GPIO_WDT_H_ */ diff --git a/target/linux/bcm47xx/patches-4.14/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch b/target/linux/bcm47xx/patches-4.14/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch new file mode 100644 index 0000000000..d7d2d7e59a --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch @@ -0,0 +1,30 @@ +From 5c81397a0147ea59c778d1de14ef54e2268221f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 8 Apr 2015 06:58:11 +0200 +Subject: [PATCH] ssb: reject PCI writes setting CardBus bridge resources +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If SoC has a CardBus we can set resources of device at slot 1 only. It's +impossigle to set bridge resources as it simply overwrites device 1 +configuration and usually results in Data bus error-s. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/ssb/driver_pcicore.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -164,6 +164,10 @@ static int ssb_extpci_write_config(struc + SSB_WARN_ON(!pc->hostmode); + if (unlikely(len != 1 && len != 2 && len != 4)) + goto out; ++ /* CardBus SoCs allow configuring dev 1 resources only */ ++ if (extpci_core->cardbusmode && dev != 1 && ++ off >= PCI_BASE_ADDRESS_0 && off <= PCI_BASE_ADDRESS_5) ++ goto out; + addr = get_cfgspace_addr(pc, bus, dev, func, off); + if (unlikely(!addr)) + goto out; diff --git a/target/linux/bcm47xx/patches-4.14/901-Revert-bcma-switch-GPIO-portions-to-use-GPIOLIB_IRQC.patch b/target/linux/bcm47xx/patches-4.14/901-Revert-bcma-switch-GPIO-portions-to-use-GPIOLIB_IRQC.patch new file mode 100644 index 0000000000..3ec853951f --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/901-Revert-bcma-switch-GPIO-portions-to-use-GPIOLIB_IRQC.patch @@ -0,0 +1,233 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Fri, 18 Dec 2015 07:51:08 +0100 +Subject: [PATCH] Revert "bcma: switch GPIO portions to use GPIOLIB_IRQCHIP" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit 74f4e0cc61080f63f28e8d519bdf437957e64217. + +On BCM47XX (MIPS) bcma_bus_get_host_dev returns NULL which results in: +[ 0.157054] missing gpiochip .dev parent pointer +[ 0.157287] bcma: bus0: Error registering GPIO driver: -22 + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/bcma/Kconfig | 2 +- + drivers/bcma/driver_gpio.c | 92 +++++++++++++++++++---------- + include/linux/bcma/bcma_driver_chipcommon.h | 1 + + 3 files changed, 64 insertions(+), 31 deletions(-) + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -104,7 +104,7 @@ config BCMA_DRIVER_GMAC_CMN + config BCMA_DRIVER_GPIO + bool "BCMA GPIO driver" + depends on BCMA && GPIOLIB +- select GPIOLIB_IRQCHIP if BCMA_HOST_SOC ++ select IRQ_DOMAIN if BCMA_HOST_SOC + help + Driver to provide access to the GPIO pins of the bcma bus. + +--- a/drivers/bcma/driver_gpio.c ++++ b/drivers/bcma/driver_gpio.c +@@ -8,8 +8,10 @@ + * Licensed under the GNU/GPL. See COPYING for details. + */ + +-#include <linux/gpio/driver.h> ++#include <linux/gpio.h> ++#include <linux/irq.h> + #include <linux/interrupt.h> ++#include <linux/irqdomain.h> + #include <linux/export.h> + #include <linux/bcma/bcma.h> + +@@ -72,11 +74,19 @@ static void bcma_gpio_free(struct gpio_c + } + + #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X) ++static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) ++{ ++ struct bcma_drv_cc *cc = gpiochip_get_data(chip); ++ ++ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) ++ return irq_find_mapping(cc->irq_domain, gpio); ++ else ++ return -EINVAL; ++} + + static void bcma_gpio_irq_unmask(struct irq_data *d) + { +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- struct bcma_drv_cc *cc = gpiochip_get_data(gc); ++ struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + u32 val = bcma_chipco_gpio_in(cc, BIT(gpio)); + +@@ -86,8 +96,7 @@ static void bcma_gpio_irq_unmask(struct + + static void bcma_gpio_irq_mask(struct irq_data *d) + { +- struct gpio_chip *gc = irq_data_get_irq_chip_data(d); +- struct bcma_drv_cc *cc = gpiochip_get_data(gc); ++ struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d); + int gpio = irqd_to_hwirq(d); + + bcma_chipco_gpio_intmask(cc, BIT(gpio), 0); +@@ -102,7 +111,6 @@ static struct irq_chip bcma_gpio_irq_chi + static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id) + { + struct bcma_drv_cc *cc = dev_id; +- struct gpio_chip *gc = &cc->gpio; + u32 val = bcma_cc_read32(cc, BCMA_CC_GPIOIN); + u32 mask = bcma_cc_read32(cc, BCMA_CC_GPIOIRQ); + u32 pol = bcma_cc_read32(cc, BCMA_CC_GPIOPOL); +@@ -112,58 +120,81 @@ static irqreturn_t bcma_gpio_irq_handler + if (!irqs) + return IRQ_NONE; + +- for_each_set_bit(gpio, &irqs, gc->ngpio) +- generic_handle_irq(irq_find_mapping(gc->irqdomain, gpio)); ++ for_each_set_bit(gpio, &irqs, cc->gpio.ngpio) ++ generic_handle_irq(bcma_gpio_to_irq(&cc->gpio, gpio)); + bcma_chipco_gpio_polarity(cc, irqs, val & irqs); + + return IRQ_HANDLED; + } + +-static int bcma_gpio_irq_init(struct bcma_drv_cc *cc) ++static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc) + { + struct gpio_chip *chip = &cc->gpio; +- int hwirq, err; ++ int gpio, hwirq, err; + + if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) + return 0; + ++ cc->irq_domain = irq_domain_add_linear(NULL, chip->ngpio, ++ &irq_domain_simple_ops, cc); ++ if (!cc->irq_domain) { ++ err = -ENODEV; ++ goto err_irq_domain; ++ } ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_create_mapping(cc->irq_domain, gpio); ++ ++ irq_set_chip_data(irq, cc); ++ irq_set_chip_and_handler(irq, &bcma_gpio_irq_chip, ++ handle_simple_irq); ++ } ++ + hwirq = bcma_core_irq(cc->core, 0); + err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio", + cc); + if (err) +- return err; ++ goto err_req_irq; + + bcma_chipco_gpio_intmask(cc, ~0, 0); + bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO); + +- err = gpiochip_irqchip_add(chip, +- &bcma_gpio_irq_chip, +- 0, +- handle_simple_irq, +- IRQ_TYPE_NONE); +- if (err) { +- free_irq(hwirq, cc); +- return err; +- } +- + return 0; ++ ++err_req_irq: ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(cc->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(cc->irq_domain); ++err_irq_domain: ++ return err; + } + +-static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc) ++static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc) + { ++ struct gpio_chip *chip = &cc->gpio; ++ int gpio; ++ + if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) + return; + + bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO); + free_irq(bcma_core_irq(cc->core, 0), cc); ++ for (gpio = 0; gpio < chip->ngpio; gpio++) { ++ int irq = irq_find_mapping(cc->irq_domain, gpio); ++ ++ irq_dispose_mapping(irq); ++ } ++ irq_domain_remove(cc->irq_domain); + } + #else +-static int bcma_gpio_irq_init(struct bcma_drv_cc *cc) ++static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc) + { + return 0; + } + +-static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc) ++static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc) + { + } + #endif +@@ -182,8 +213,9 @@ int bcma_gpio_init(struct bcma_drv_cc *c + chip->set = bcma_gpio_set_value; + chip->direction_input = bcma_gpio_direction_input; + chip->direction_output = bcma_gpio_direction_output; +- chip->owner = THIS_MODULE; +- chip->parent = bus->dev; ++#if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X) ++ chip->to_irq = bcma_gpio_to_irq; ++#endif + #if IS_BUILTIN(CONFIG_OF) + chip->of_node = cc->core->dev.of_node; + #endif +@@ -212,13 +244,13 @@ int bcma_gpio_init(struct bcma_drv_cc *c + else + chip->base = -1; + +- err = gpiochip_add_data(chip, cc); ++ err = bcma_gpio_irq_domain_init(cc); + if (err) + return err; + +- err = bcma_gpio_irq_init(cc); ++ err = gpiochip_add_data(chip, cc); + if (err) { +- gpiochip_remove(chip); ++ bcma_gpio_irq_domain_exit(cc); + return err; + } + +@@ -227,7 +259,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c + + int bcma_gpio_unregister(struct bcma_drv_cc *cc) + { +- bcma_gpio_irq_exit(cc); ++ bcma_gpio_irq_domain_exit(cc); + gpiochip_remove(&cc->gpio); + return 0; + } +--- a/include/linux/bcma/bcma_driver_chipcommon.h ++++ b/include/linux/bcma/bcma_driver_chipcommon.h +@@ -645,6 +645,7 @@ struct bcma_drv_cc { + spinlock_t gpio_lock; + #ifdef CONFIG_BCMA_DRIVER_GPIO + struct gpio_chip gpio; ++ struct irq_domain *irq_domain; + #endif + }; + diff --git a/target/linux/bcm47xx/patches-4.14/940-bcm47xx-yenta.patch b/target/linux/bcm47xx/patches-4.14/940-bcm47xx-yenta.patch new file mode 100644 index 0000000000..bda27d16c4 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/940-bcm47xx-yenta.patch @@ -0,0 +1,46 @@ +--- a/drivers/pcmcia/yenta_socket.c ++++ b/drivers/pcmcia/yenta_socket.c +@@ -920,6 +920,8 @@ static unsigned int yenta_probe_irq(stru + * Probe for usable interrupts using the force + * register to generate bogus card status events. + */ ++#ifndef CONFIG_BCM47XX ++ /* WRT54G3G does not like this */ + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + reg = exca_readb(socket, I365_CSCINT); +@@ -935,6 +937,7 @@ static unsigned int yenta_probe_irq(stru + } + cb_writel(socket, CB_SOCKET_MASK, 0); + exca_writeb(socket, I365_CSCINT, reg); ++#endif + + mask = probe_irq_mask(val) & 0xffff; + +@@ -1019,6 +1022,10 @@ static void yenta_get_socket_capabilitie + else + socket->socket.irq_mask = 0; + ++ /* irq mask probing is broken for the WRT54G3G */ ++ if (socket->socket.irq_mask == 0) ++ socket->socket.irq_mask = 0x6f8; ++ + dev_info(&socket->dev->dev, "ISA IRQ mask 0x%04x, PCI irq %d\n", + socket->socket.irq_mask, socket->cb_irq); + } +@@ -1251,6 +1258,15 @@ static int yenta_probe(struct pci_dev *d + dev_info(&dev->dev, "Socket status: %08x\n", + cb_readl(socket, CB_SOCKET_STATE)); + ++ /* Generate an interrupt on card insert/remove */ ++ config_writew(socket, CB_SOCKET_MASK, CB_CSTSMASK | CB_CDMASK); ++ ++ /* Set up Multifunction Routing Status Register */ ++ config_writew(socket, 0x8C, 0x1000 /* MFUNC3 to GPIO3 */ | 0x2 /* MFUNC0 to INTA */); ++ ++ /* Switch interrupts to parallelized */ ++ config_writeb(socket, 0x92, 0x64); ++ + yenta_fixup_parent_bridge(dev->subordinate); + + /* Register it with the pcmcia layer.. */ diff --git a/target/linux/bcm47xx/patches-4.14/976-ssb_increase_pci_delay.patch b/target/linux/bcm47xx/patches-4.14/976-ssb_increase_pci_delay.patch new file mode 100644 index 0000000000..90bda515eb --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/976-ssb_increase_pci_delay.patch @@ -0,0 +1,11 @@ +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -389,7 +389,7 @@ static void ssb_pcicore_init_hostmode(st + set_io_port_base(ssb_pcicore_controller.io_map_base); + /* Give some time to the PCI controller to configure itself with the new + * values. Not waiting at this point causes crashes of the machine. */ +- mdelay(10); ++ mdelay(300); + register_pci_controller(&ssb_pcicore_controller); + } + diff --git a/target/linux/bcm47xx/patches-4.14/999-wl_exports.patch b/target/linux/bcm47xx/patches-4.14/999-wl_exports.patch new file mode 100644 index 0000000000..2ecf651472 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.14/999-wl_exports.patch @@ -0,0 +1,22 @@ +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -34,7 +34,8 @@ struct nvram_header { + u32 config_ncdl; /* ncdl values for memc */ + }; + +-static char nvram_buf[NVRAM_SPACE]; ++char nvram_buf[NVRAM_SPACE]; ++EXPORT_SYMBOL(nvram_buf); + static size_t nvram_len; + static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; + static int cfe_env; +--- a/arch/mips/mm/cache.c ++++ b/arch/mips/mm/cache.c +@@ -64,6 +64,7 @@ void (*_dma_cache_wback)(unsigned long s + void (*_dma_cache_inv)(unsigned long start, unsigned long size); + + EXPORT_SYMBOL(_dma_cache_wback_inv); ++EXPORT_SYMBOL(_dma_cache_inv); + + #endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */ + diff --git a/target/linux/bcm47xx/patches-4.19/031-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch b/target/linux/bcm47xx/patches-4.19/031-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch new file mode 100644 index 0000000000..34a79f9d5b --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/031-v5.1-mips-bcm47xx-Enable-USB-power-on-Netgear-WNDR3400v2.patch @@ -0,0 +1,34 @@ +From cdb8faa00e3fcdd0ad10add743516d616dc7d38e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C5=A0tetiar?= <ynezz@true.cz> +Date: Mon, 11 Mar 2019 22:08:22 +0100 +Subject: [PATCH] mips: bcm47xx: Enable USB power on Netgear WNDR3400v2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Eric has reported on OpenWrt's bug tracking system[1], that he's not +able to use USB devices on his WNDR3400v2 device after the boot, until +he turns on GPIO #21 manually through sysfs. + +1. https://bugs.openwrt.org/index.php?do=details&task_id=2170 + +Cc: Rafał Miłecki <zajec5@gmail.com> +Cc: Hauke Mehrtens <hauke@hauke-m.de> +Reported-by: Eric Bohlman <ericbohlman@gmail.com> +Tested-by: Eric Bohlman <ericbohlman@gmail.com> +Signed-off-by: Petr Štetiar <ynezz@true.cz> +Signed-off-by: Paul Burton <paul.burton@mips.com> +--- + arch/mips/bcm47xx/workarounds.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/bcm47xx/workarounds.c ++++ b/arch/mips/bcm47xx/workarounds.c +@@ -24,6 +24,7 @@ void __init bcm47xx_workarounds(void) + case BCM47XX_BOARD_NETGEAR_WNR3500L: + bcm47xx_workarounds_enable_usb_power(12); + break; ++ case BCM47XX_BOARD_NETGEAR_WNDR3400V2: + case BCM47XX_BOARD_NETGEAR_WNDR3400_V3: + bcm47xx_workarounds_enable_usb_power(21); + break; diff --git a/target/linux/bcm47xx/patches-4.19/159-cpu_fixes.patch b/target/linux/bcm47xx/patches-4.19/159-cpu_fixes.patch new file mode 100644 index 0000000000..75e493b2dd --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/159-cpu_fixes.patch @@ -0,0 +1,510 @@ +--- a/arch/mips/include/asm/r4kcache.h ++++ b/arch/mips/include/asm/r4kcache.h +@@ -26,6 +26,38 @@ + extern void (*r4k_blast_dcache)(void); + extern void (*r4k_blast_icache)(void); + ++#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) ++#include <asm/paccess.h> ++#include <linux/ssb/ssb.h> ++#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg() ++ ++static inline unsigned long bcm4710_dummy_rreg(void) ++{ ++ return *(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE)); ++} ++ ++#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void *)(addr)) ++ ++static inline unsigned long bcm4710_fill_tlb(void *addr) ++{ ++ return *(unsigned long *)addr; ++} ++ ++#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void *)(addr)) ++ ++static inline void bcm4710_protected_fill_tlb(void *addr) ++{ ++ unsigned long x; ++ get_dbe(x, (unsigned long *)addr);; ++} ++ ++#else ++#define BCM4710_DUMMY_RREG() ++ ++#define BCM4710_FILL_TLB(addr) ++#define BCM4710_PROTECTED_FILL_TLB(addr) ++#endif ++ + /* + * This macro return a properly sign-extended address suitable as base address + * for indexed cache operations. Two issues here: +@@ -99,6 +131,7 @@ static inline void flush_icache_line_ind + static inline void flush_dcache_line_indexed(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Index_Writeback_Inv_D, addr); + __dflush_epilogue + } +@@ -126,6 +159,7 @@ static inline void flush_icache_line(uns + static inline void flush_dcache_line(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Hit_Writeback_Inv_D, addr); + __dflush_epilogue + } +@@ -133,6 +167,7 @@ static inline void flush_dcache_line(uns + static inline void invalidate_dcache_line(unsigned long addr) + { + __dflush_prologue ++ BCM4710_DUMMY_RREG(); + cache_op(Hit_Invalidate_D, addr); + __dflush_epilogue + } +@@ -206,6 +241,7 @@ static inline int protected_flush_icache + #ifdef CONFIG_EVA + return protected_cachee_op(Hit_Invalidate_I, addr); + #else ++ BCM4710_DUMMY_RREG(); + return protected_cache_op(Hit_Invalidate_I, addr); + #endif + } +@@ -219,6 +255,7 @@ static inline int protected_flush_icache + */ + static inline int protected_writeback_dcache_line(unsigned long addr) + { ++ BCM4710_DUMMY_RREG(); + #ifdef CONFIG_EVA + return protected_cachee_op(Hit_Writeback_Inv_D, addr); + #else +@@ -576,8 +613,51 @@ static inline void invalidate_tcache_pag + : "r" (base), \ + "i" (op)); + ++static inline void blast_dcache(void) ++{ ++ unsigned long start = KSEG0; ++ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways; ++ unsigned long end = (start + dcache_size); ++ ++ do { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Index_Writeback_Inv_D, start); ++ start += current_cpu_data.dcache.linesz; ++ } while(start < end); ++} ++ ++static inline void blast_dcache_page(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ ++ BCM4710_FILL_TLB(start); ++ do { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Hit_Writeback_Inv_D, start); ++ start += current_cpu_data.dcache.linesz; ++ } while(start < end); ++} ++ ++static inline void blast_dcache_page_indexed(unsigned long page) ++{ ++ unsigned long start = page; ++ unsigned long end = start + PAGE_SIZE; ++ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; ++ unsigned long ws_end = current_cpu_data.dcache.ways << ++ current_cpu_data.dcache.waybit; ++ unsigned long ws, addr; ++ for (ws = 0; ws < ws_end; ws += ws_inc) { ++ start = page + ws; ++ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) { ++ BCM4710_DUMMY_RREG(); ++ cache_op(Index_Writeback_Inv_D, addr); ++ } ++ } ++} ++ + /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ +-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ ++#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \ + static inline void extra##blast_##pfx##cache##lsize(void) \ + { \ + unsigned long start = INDEX_BASE; \ +@@ -589,6 +669,7 @@ static inline void extra##blast_##pfx##c + \ + __##pfx##flush_prologue \ + \ ++ war \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ + for (addr = start; addr < end; addr += lsize * 32) \ + cache##lsize##_unroll32(addr|ws, indexop); \ +@@ -603,6 +684,7 @@ static inline void extra##blast_##pfx##c + \ + __##pfx##flush_prologue \ + \ ++ war \ + do { \ + cache##lsize##_unroll32(start, hitop); \ + start += lsize * 32; \ +@@ -621,6 +703,8 @@ static inline void extra##blast_##pfx##c + current_cpu_data.desc.waybit; \ + unsigned long ws, addr; \ + \ ++ war \ ++ \ + __##pfx##flush_prologue \ + \ + for (ws = 0; ws < ws_end; ws += ws_inc) \ +@@ -630,26 +714,26 @@ static inline void extra##blast_##pfx##c + __##pfx##flush_epilogue \ + } + +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, ) +-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, ) +-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) +- +-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) +-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) +-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, , ) ++__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, , ) ++__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , ) ++ ++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , ) ++__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , ) ++__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , ) + + #define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \ + static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \ +@@ -678,53 +762,23 @@ __BUILD_BLAST_USER_CACHE(d, dcache, Inde + __BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) + + /* build blast_xxx_range, protected_blast_xxx_range */ +-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ ++#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2) \ + static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \ + unsigned long end) \ + { \ + unsigned long lsize = cpu_##desc##_line_size(); \ +- unsigned long lsize_2 = lsize * 2; \ +- unsigned long lsize_3 = lsize * 3; \ +- unsigned long lsize_4 = lsize * 4; \ +- unsigned long lsize_5 = lsize * 5; \ +- unsigned long lsize_6 = lsize * 6; \ +- unsigned long lsize_7 = lsize * 7; \ +- unsigned long lsize_8 = lsize * 8; \ + unsigned long addr = start & ~(lsize - 1); \ +- unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ +- int lines = (aend - addr) / lsize; \ ++ unsigned long aend = (end - 1) & ~(lsize - 1); \ ++ war \ + \ + __##pfx##flush_prologue \ + \ +- while (lines >= 8) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- prot##cache_op(hitop, addr + lsize_2); \ +- prot##cache_op(hitop, addr + lsize_3); \ +- prot##cache_op(hitop, addr + lsize_4); \ +- prot##cache_op(hitop, addr + lsize_5); \ +- prot##cache_op(hitop, addr + lsize_6); \ +- prot##cache_op(hitop, addr + lsize_7); \ +- addr += lsize_8; \ +- lines -= 8; \ +- } \ +- \ +- if (lines & 0x4) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- prot##cache_op(hitop, addr + lsize_2); \ +- prot##cache_op(hitop, addr + lsize_3); \ +- addr += lsize_4; \ +- } \ +- \ +- if (lines & 0x2) { \ +- prot##cache_op(hitop, addr); \ +- prot##cache_op(hitop, addr + lsize); \ +- addr += lsize_2; \ +- } \ +- \ +- if (lines & 0x1) { \ ++ while (1) { \ ++ war2 \ + prot##cache_op(hitop, addr); \ ++ if (addr == aend) \ ++ break; \ ++ addr += lsize; \ + } \ + \ + __##pfx##flush_epilogue \ +@@ -732,8 +786,8 @@ static inline void prot##extra##blast_## + + #ifndef CONFIG_EVA + +-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) +-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) ++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , ) + + #else + +@@ -770,15 +824,15 @@ __BUILD_PROT_BLAST_CACHE_RANGE(d, dcache + __BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I) + + #endif +-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) ++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , ) + __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ +- protected_, loongson2_) +-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) +-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , ) +-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) ++ protected_, loongson2_, , ) ++__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , , , ) ++__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , ) + /* blast_inv_dcache_range */ +-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) +-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) ++__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();) ++__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , ) + + /* Currently, this is very specific to Loongson-3 */ + #define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ +--- a/arch/mips/include/asm/stackframe.h ++++ b/arch/mips/include/asm/stackframe.h +@@ -428,6 +428,10 @@ + eretnc + #else + .set arch=r4000 ++#ifdef CONFIG_BCM47XX ++ nop ++ nop ++#endif + eret + .set mips0 + #endif +--- a/arch/mips/kernel/genex.S ++++ b/arch/mips/kernel/genex.S +@@ -21,6 +21,19 @@ + #include <asm/war.h> + #include <asm/thread_info.h> + ++#ifdef CONFIG_BCM47XX ++# ifdef eret ++# undef eret ++# endif ++# define eret \ ++ .set push; \ ++ .set noreorder; \ ++ nop; \ ++ nop; \ ++ eret; \ ++ .set pop; ++#endif ++ + __INIT + + /* +@@ -32,6 +45,9 @@ + NESTED(except_vec3_generic, 0, sp) + .set push + .set noat ++#ifdef CONFIG_BCM47XX ++ nop ++#endif + #if R5432_CP0_INTERRUPT_WAR + mfc0 k0, CP0_INDEX + #endif +@@ -55,6 +71,9 @@ NESTED(except_vec3_r4000, 0, sp) + .set push + .set arch=r4000 + .set noat ++#ifdef CONFIG_BCM47XX ++ nop ++#endif + mfc0 k1, CP0_CAUSE + li k0, 31<<2 + andi k1, k1, 0x7c +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -39,6 +39,9 @@ + #include <asm/dma-coherence.h> + #include <asm/mips-cps.h> + ++/* For enabling BCM4710 cache workarounds */ ++static int bcm4710 = 0; ++ + /* + * Bits describing what cache ops an SMP callback function may perform. + * +@@ -190,6 +193,9 @@ static void r4k_blast_dcache_user_page_s + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache_page = blast_dcache_page; ++ else + if (dc_lsize == 0) + r4k_blast_dcache_user_page = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -208,6 +214,9 @@ static void r4k_blast_dcache_page_indexe + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed; ++ else + if (dc_lsize == 0) + r4k_blast_dcache_page_indexed = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -227,6 +236,9 @@ static void r4k_blast_dcache_setup(void) + { + unsigned long dc_lsize = cpu_dcache_line_size(); + ++ if (bcm4710) ++ r4k_blast_dcache = blast_dcache; ++ else + if (dc_lsize == 0) + r4k_blast_dcache = (void *)cache_noop; + else if (dc_lsize == 16) +@@ -986,6 +998,8 @@ static void local_r4k_flush_cache_sigtra + } + + R4600_HIT_CACHEOP_WAR_IMPL; ++ BCM4710_PROTECTED_FILL_TLB(addr); ++ BCM4710_PROTECTED_FILL_TLB(addr + 4); + if (!cpu_has_ic_fills_f_dc) { + if (dc_lsize) + vaddr ? flush_dcache_line(addr & ~(dc_lsize - 1)) +@@ -1888,6 +1902,17 @@ static void coherency_setup(void) + * silly idea of putting something else there ... + */ + switch (current_cpu_type()) { ++ case CPU_BMIPS3300: ++ { ++ u32 cm; ++ cm = read_c0_diag(); ++ /* Enable icache */ ++ cm |= (1 << 31); ++ /* Enable dcache */ ++ cm |= (1 << 30); ++ write_c0_diag(cm); ++ } ++ break; + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: +@@ -1934,6 +1959,15 @@ void r4k_cache_init(void) + extern void build_copy_page(void); + struct cpuinfo_mips *c = ¤t_cpu_data; + ++ /* Check if special workarounds are required */ ++#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) ++ if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) { ++ printk("Enabling BCM4710A0 cache workarounds.\n"); ++ bcm4710 = 1; ++ } else ++#endif ++ bcm4710 = 0; ++ + probe_pcache(); + probe_vcache(); + setup_scache(); +@@ -2012,7 +2046,15 @@ void r4k_cache_init(void) + */ + local_r4k___flush_cache_all(NULL); + ++#ifdef CONFIG_BCM47XX ++ { ++ static void (*_coherency_setup)(void); ++ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup); ++ _coherency_setup(); ++ } ++#else + coherency_setup(); ++#endif + board_cache_error_setup = r4k_cache_error_setup; + + /* +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -979,6 +979,9 @@ void build_get_pgde32(u32 **p, unsigned + uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT); + uasm_i_addu(p, ptr, tmp, ptr); + #else ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++#endif + UASM_i_LA_mostly(p, ptr, pgdc); + #endif + uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ +@@ -1340,6 +1343,9 @@ static void build_r4000_tlb_refill_handl + #ifdef CONFIG_64BIT + build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ + #else ++# ifdef CONFIG_BCM47XX ++ uasm_i_nop(&p); ++# endif + build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ + #endif + +@@ -1351,6 +1357,9 @@ static void build_r4000_tlb_refill_handl + build_update_entries(&p, K0, K1); + build_tlb_write_entry(&p, &l, &r, tlb_random); + uasm_l_leave(&l, p); ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(&p); ++#endif + uasm_i_eret(&p); /* return from trap */ + } + #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT +@@ -2046,6 +2055,9 @@ build_r4000_tlbchange_handler_head(u32 * + #ifdef CONFIG_64BIT + build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */ + #else ++# ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++# endif + build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */ + #endif + +@@ -2092,6 +2104,9 @@ build_r4000_tlbchange_handler_tail(u32 * + build_tlb_write_entry(p, l, r, tlb_indexed); + uasm_l_leave(l, *p); + build_restore_work_registers(p); ++#ifdef CONFIG_BCM47XX ++ uasm_i_nop(p); ++#endif + uasm_i_eret(p); /* return from trap */ + + #ifdef CONFIG_64BIT diff --git a/target/linux/bcm47xx/patches-4.19/160-kmap_coherent.patch b/target/linux/bcm47xx/patches-4.19/160-kmap_coherent.patch new file mode 100644 index 0000000000..db5660bc32 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/160-kmap_coherent.patch @@ -0,0 +1,78 @@ +From: Jeff Hansen <jhansen@cardaccess-inc.com> +Subject: [PATCH] kmap_coherent + +On ASUS WL-500gP there are some "Data bus error"s when executing simple +commands liks "ps" or "cat /proc/1/cmdline". + +This fixes OpenWrt ticket #1485: https://dev.openwrt.org/ticket/1485 +--- +--- a/arch/mips/include/asm/cpu-features.h ++++ b/arch/mips/include/asm/cpu-features.h +@@ -226,6 +226,9 @@ + #ifndef cpu_has_local_ebase + #define cpu_has_local_ebase 1 + #endif ++#ifndef cpu_use_kmap_coherent ++#define cpu_use_kmap_coherent 1 ++#endif + + /* + * I-Cache snoops remote store. This only matters on SMP. Some multiprocessors +--- a/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h ++++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h +@@ -80,4 +80,6 @@ + #define cpu_scache_line_size() 0 + #define cpu_has_vz 0 + ++#define cpu_use_kmap_coherent 0 ++ + #endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */ +--- a/arch/mips/mm/c-r4k.c ++++ b/arch/mips/mm/c-r4k.c +@@ -694,7 +694,7 @@ static inline void local_r4k_flush_cache + map_coherent = (cpu_has_dc_aliases && + page_mapcount(page) && + !Page_dcache_dirty(page)); +- if (map_coherent) ++ if (map_coherent && cpu_use_kmap_coherent) + vaddr = kmap_coherent(page, addr); + else + vaddr = kmap_atomic(page); +@@ -719,7 +719,7 @@ static inline void local_r4k_flush_cache + } + + if (vaddr) { +- if (map_coherent) ++ if (map_coherent && cpu_use_kmap_coherent) + kunmap_coherent(); + else + kunmap_atomic(vaddr); +--- a/arch/mips/mm/init.c ++++ b/arch/mips/mm/init.c +@@ -168,7 +168,7 @@ void copy_user_highpage(struct page *to, + void *vfrom, *vto; + + vto = kmap_atomic(to); +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(from) && !Page_dcache_dirty(from)) { + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); +@@ -190,7 +190,7 @@ void copy_to_user_page(struct vm_area_st + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) + { +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(page) && !Page_dcache_dirty(page)) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); +@@ -208,7 +208,7 @@ void copy_from_user_page(struct vm_area_ + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) + { +- if (cpu_has_dc_aliases && ++ if (cpu_has_dc_aliases && cpu_use_kmap_coherent && + page_mapcount(page) && !Page_dcache_dirty(page)) { + void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); diff --git a/target/linux/bcm47xx/patches-4.19/209-b44-register-adm-switch.patch b/target/linux/bcm47xx/patches-4.19/209-b44-register-adm-switch.patch new file mode 100644 index 0000000000..bc2d2ab90a --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/209-b44-register-adm-switch.patch @@ -0,0 +1,121 @@ +From b36f694256f41bc71571f467646d015dda128d14 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Sat, 9 Nov 2013 17:03:59 +0100 +Subject: [PATCH 210/210] b44: register adm switch + +--- + drivers/net/ethernet/broadcom/b44.c | 57 +++++++++++++++++++++++++++++++++++ + drivers/net/ethernet/broadcom/b44.h | 3 ++ + 2 files changed, 60 insertions(+) + +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -31,6 +31,8 @@ + #include <linux/ssb/ssb.h> + #include <linux/slab.h> + #include <linux/phy.h> ++#include <linux/platform_device.h> ++#include <linux/platform_data/adm6996-gpio.h> + + #include <linux/uaccess.h> + #include <asm/io.h> +@@ -2249,6 +2251,69 @@ static void b44_adjust_link(struct net_d + } + } + ++#ifdef CONFIG_BCM47XX ++static int b44_register_adm_switch(struct b44 *bp) ++{ ++ int gpio; ++ struct platform_device *pdev; ++ struct adm6996_gpio_platform_data adm_data = {0}; ++ struct platform_device_info info = {0}; ++ ++ adm_data.model = ADM6996L; ++ gpio = bcm47xx_nvram_gpio_pin("adm_eecs"); ++ if (gpio >= 0) ++ adm_data.eecs = gpio; ++ else ++ adm_data.eecs = 2; ++ ++ gpio = bcm47xx_nvram_gpio_pin("adm_eesk"); ++ if (gpio >= 0) ++ adm_data.eesk = gpio; ++ else ++ adm_data.eesk = 3; ++ ++ gpio = bcm47xx_nvram_gpio_pin("adm_eedi"); ++ if (gpio >= 0) ++ adm_data.eedi = gpio; ++ else ++ adm_data.eedi = 4; ++ ++ /* ++ * We ignore the "adm_rc" GPIO here. The driver does not use it, ++ * and it conflicts with the Reset button GPIO on the Linksys WRT54GSv1. ++ */ ++ ++ info.parent = bp->sdev->dev; ++ info.name = "adm6996_gpio"; ++ info.id = -1; ++ info.data = &adm_data; ++ info.size_data = sizeof(adm_data); ++ ++ if (!bp->adm_switch) { ++ pdev = platform_device_register_full(&info); ++ if (IS_ERR(pdev)) ++ return PTR_ERR(pdev); ++ ++ bp->adm_switch = pdev; ++ } ++ return 0; ++} ++static void b44_unregister_adm_switch(struct b44 *bp) ++{ ++ if (bp->adm_switch) ++ platform_device_unregister(bp->adm_switch); ++} ++#else ++static int b44_register_adm_switch(struct b44 *bp) ++{ ++ return 0; ++} ++static void b44_unregister_adm_switch(struct b44 *bp) ++{ ++ ++} ++#endif /* CONFIG_BCM47XX */ ++ + static int b44_register_phy_one(struct b44 *bp) + { + struct mii_bus *mii_bus; +@@ -2284,6 +2349,9 @@ static int b44_register_phy_one(struct b + if (!mdiobus_is_registered_device(bp->mii_bus, bp->phy_addr) && + (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) { + ++ if (sprom->boardflags_lo & B44_BOARDFLAG_ADM) ++ b44_register_adm_switch(bp); ++ + dev_info(sdev->dev, + "could not find PHY at %i, use fixed one\n", + bp->phy_addr); +@@ -2478,6 +2546,7 @@ static void b44_remove_one(struct ssb_de + unregister_netdev(dev); + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + b44_unregister_phy_one(bp); ++ b44_unregister_adm_switch(bp); + ssb_device_disable(sdev, 0); + ssb_bus_may_powerdown(sdev->bus); + netif_napi_del(&bp->napi); +--- a/drivers/net/ethernet/broadcom/b44.h ++++ b/drivers/net/ethernet/broadcom/b44.h +@@ -408,6 +408,9 @@ struct b44 { + struct mii_bus *mii_bus; + int old_link; + struct mii_if_info mii_if; ++ ++ /* platform device for associated switch */ ++ struct platform_device *adm_switch; + }; + + #endif /* _B44_H */ diff --git a/target/linux/bcm47xx/patches-4.19/210-b44_phy_fix.patch b/target/linux/bcm47xx/patches-4.19/210-b44_phy_fix.patch new file mode 100644 index 0000000000..8c7a73ac0f --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/210-b44_phy_fix.patch @@ -0,0 +1,54 @@ +--- a/drivers/net/ethernet/broadcom/b44.c ++++ b/drivers/net/ethernet/broadcom/b44.c +@@ -431,10 +431,34 @@ static void b44_wap54g10_workaround(stru + error: + pr_warn("PHY: cannot reset MII transceiver isolate bit\n"); + } ++ ++static void b44_bcm47xx_workarounds(struct b44 *bp) ++{ ++ char buf[20]; ++ struct ssb_device *sdev = bp->sdev; ++ ++ /* Toshiba WRC-1000, Siemens SE505 v1, Askey RT-210W, RT-220W */ ++ if (sdev->bus->sprom.board_num == 100) { ++ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY; ++ } else { ++ /* WL-HDD */ ++ if (bcm47xx_nvram_getenv("hardware_version", buf, sizeof(buf)) >= 0 && ++ !strncmp(buf, "WL300-", strlen("WL300-"))) { ++ if (sdev->bus->sprom.et0phyaddr == 0 && ++ sdev->bus->sprom.et1phyaddr == 1) ++ bp->phy_addr = B44_PHY_ADDR_NO_LOCAL_PHY; ++ } ++ } ++ return; ++} + #else + static inline void b44_wap54g10_workaround(struct b44 *bp) + { + } ++ ++static inline void b44_bcm47xx_workarounds(struct b44 *bp) ++{ ++} + #endif + + static int b44_setup_phy(struct b44 *bp) +@@ -443,6 +467,7 @@ static int b44_setup_phy(struct b44 *bp) + int err; + + b44_wap54g10_workaround(bp); ++ b44_bcm47xx_workarounds(bp); + + if (bp->flags & B44_FLAG_EXTERNAL_PHY) + return 0; +@@ -2179,6 +2204,8 @@ static int b44_get_invariants(struct b44 + * valid PHY address. */ + bp->phy_addr &= 0x1F; + ++ b44_bcm47xx_workarounds(bp); ++ + memcpy(bp->dev->dev_addr, addr, ETH_ALEN); + + if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){ diff --git a/target/linux/bcm47xx/patches-4.19/280-activate_ssb_support_in_usb.patch b/target/linux/bcm47xx/patches-4.19/280-activate_ssb_support_in_usb.patch new file mode 100644 index 0000000000..a1c988bb59 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/280-activate_ssb_support_in_usb.patch @@ -0,0 +1,25 @@ +This prevents the options from being delete with make kernel_oldconfig. +--- + drivers/ssb/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/bcma/Kconfig ++++ b/drivers/bcma/Kconfig +@@ -32,6 +32,7 @@ config BCMA_HOST_PCI + config BCMA_HOST_SOC + bool "Support for BCMA in a SoC" + depends on HAS_IOMEM ++ select USB_HCD_BCMA if USB_EHCI_HCD || USB_OHCI_HCD + help + Host interface for a Broadcom AIX bus directly mapped into + the memory. This only works with the Broadcom SoCs from the +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -135,6 +135,7 @@ config SSB_SFLASH + config SSB_EMBEDDED + bool + depends on SSB_DRIVER_MIPS && SSB_PCICORE_HOSTMODE ++ select USB_HCD_SSB if USB_EHCI_HCD || USB_OHCI_HCD + default y + + config SSB_DRIVER_EXTIF diff --git a/target/linux/bcm47xx/patches-4.19/300-fork_cacheflush.patch b/target/linux/bcm47xx/patches-4.19/300-fork_cacheflush.patch new file mode 100644 index 0000000000..b5efaaf03c --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/300-fork_cacheflush.patch @@ -0,0 +1,21 @@ +From: Wolfram Joost <dbox2@frokaschwei.de> +Subject: [PATCH] fork_cacheflush + +On ASUS WL-500gP there are many unexpected "Segmentation fault"s that +seem to be caused by a kernel. They can be avoided by: +1) Disabling highpage +2) Using flush_cache_mm in flush_cache_dup_mm + +For details see OpenWrt ticket #2035 https://dev.openwrt.org/ticket/2035 +--- +--- a/arch/mips/include/asm/cacheflush.h ++++ b/arch/mips/include/asm/cacheflush.h +@@ -47,7 +47,7 @@ + extern void (*flush_cache_all)(void); + extern void (*__flush_cache_all)(void); + extern void (*flush_cache_mm)(struct mm_struct *mm); +-#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0) ++#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + extern void (*flush_cache_range)(struct vm_area_struct *vma, + unsigned long start, unsigned long end); + extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); diff --git a/target/linux/bcm47xx/patches-4.19/310-no_highpage.patch b/target/linux/bcm47xx/patches-4.19/310-no_highpage.patch new file mode 100644 index 0000000000..09bfc64552 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/310-no_highpage.patch @@ -0,0 +1,74 @@ +From: Jeff Hansen <jhansen@cardaccess-inc.com> +Subject: [PATCH] no highpage + +On ASUS WL-500gP there are many unexpected "Segmentation fault"s that +seem to be caused by a kernel. They can be avoided by: +1) Disabling highpage +2) Using flush_cache_mm in flush_cache_dup_mm + +For details see OpenWrt ticket #2035 https://dev.openwrt.org/ticket/2035 +--- +--- a/arch/mips/include/asm/page.h ++++ b/arch/mips/include/asm/page.h +@@ -71,6 +71,7 @@ static inline unsigned int page_size_ftl + #endif /* CONFIG_MIPS_HUGE_TLB_SUPPORT */ + + #include <linux/pfn.h> ++#include <asm/cpu-features.h> + + extern void build_clear_page(void); + extern void build_copy_page(void); +@@ -110,11 +111,16 @@ static inline void clear_user_page(void + flush_data_cache_page((unsigned long)addr); + } + +-struct vm_area_struct; +-extern void copy_user_highpage(struct page *to, struct page *from, +- unsigned long vaddr, struct vm_area_struct *vma); ++static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, ++ struct page *to) ++{ ++ extern void (*flush_data_cache_page)(unsigned long addr); + +-#define __HAVE_ARCH_COPY_USER_HIGHPAGE ++ copy_page(vto, vfrom); ++ if (!cpu_has_ic_fills_f_dc || ++ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) ++ flush_data_cache_page((unsigned long)vto); ++} + + /* + * These are used to make use of C type-checking.. +--- a/arch/mips/mm/init.c ++++ b/arch/mips/mm/init.c +@@ -162,30 +162,6 @@ void kunmap_coherent(void) + preempt_enable(); + } + +-void copy_user_highpage(struct page *to, struct page *from, +- unsigned long vaddr, struct vm_area_struct *vma) +-{ +- void *vfrom, *vto; +- +- vto = kmap_atomic(to); +- if (cpu_has_dc_aliases && cpu_use_kmap_coherent && +- page_mapcount(from) && !Page_dcache_dirty(from)) { +- vfrom = kmap_coherent(from, vaddr); +- copy_page(vto, vfrom); +- kunmap_coherent(); +- } else { +- vfrom = kmap_atomic(from); +- copy_page(vto, vfrom); +- kunmap_atomic(vfrom); +- } +- if ((!cpu_has_ic_fills_f_dc) || +- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) +- flush_data_cache_page((unsigned long)vto); +- kunmap_atomic(vto); +- /* Make sure this page is cleared on other CPU's too before using it */ +- smp_wmb(); +-} +- + void copy_to_user_page(struct vm_area_struct *vma, + struct page *page, unsigned long vaddr, void *dst, const void *src, + unsigned long len) diff --git a/target/linux/bcm47xx/patches-4.19/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch b/target/linux/bcm47xx/patches-4.19/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch new file mode 100644 index 0000000000..74060e2181 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/320-MIPS-BCM47XX-Devices-database-update-for-4.x.patch @@ -0,0 +1,185 @@ +--- a/arch/mips/bcm47xx/board.c ++++ b/arch/mips/bcm47xx/board.c +@@ -141,6 +141,7 @@ struct bcm47xx_board_type_list2 bcm47xx_ + {{BCM47XX_BOARD_LINKSYS_WRT300NV11, "Linksys WRT300N V1.1"}, "WRT300N", "1.1"}, + {{BCM47XX_BOARD_LINKSYS_WRT310NV1, "Linksys WRT310N V1"}, "WRT310N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT310NV2, "Linksys WRT310N V2"}, "WRT310N", "2.0"}, ++ {{BCM47XX_BOARD_LINKSYS_WRT320N_V1, "Linksys WRT320N V1"}, "WRT320N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT54G3GV2, "Linksys WRT54G3GV2-VF"}, "WRT54G3GV2-VF", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT610NV1, "Linksys WRT610N V1"}, "WRT610N", "1.0"}, + {{BCM47XX_BOARD_LINKSYS_WRT610NV2, "Linksys WRT610N V2"}, "WRT610N", "2.0"}, +@@ -160,9 +161,12 @@ struct bcm47xx_board_type_list1 bcm47xx_ + {{BCM47XX_BOARD_LUXUL_XVW_P30_V1, "Luxul XVW-P30 V1"}, "luxul_xvwp30_v1"}, + {{BCM47XX_BOARD_LUXUL_XWR_600_V1, "Luxul XWR-600 V1"}, "luxul_xwr600_v1"}, + {{BCM47XX_BOARD_LUXUL_XWR_1750_V1, "Luxul XWR-1750 V1"}, "luxul_xwr1750_v1"}, ++ {{BCM47XX_BOARD_NETGEAR_R6300_V1, "Netgear R6300 V1"}, "U12H218T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614V8, "Netgear WGR614 V8"}, "U12H072T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614V9, "Netgear WGR614 V9"}, "U12H094T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WGR614_V10, "Netgear WGR614 V10"}, "U12H139T01_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WN2500RP_V1, "Netgear WN2500RP V1"}, "U12H197T00_NETGEAR"}, ++ {{BCM47XX_BOARD_NETGEAR_WN2500RP_V2, "Netgear WN2500RP V2"}, "U12H294T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3300, "Netgear WNDR3300"}, "U12H093T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3400V1, "Netgear WNDR3400 V1"}, "U12H155T00_NETGEAR"}, + {{BCM47XX_BOARD_NETGEAR_WNDR3400V2, "Netgear WNDR3400 V2"}, "U12H187T00_NETGEAR"}, +--- a/arch/mips/bcm47xx/buttons.c ++++ b/arch/mips/bcm47xx/buttons.c +@@ -27,6 +27,12 @@ + /* Asus */ + + static const struct gpio_keys_button ++bcm47xx_buttons_asus_rtn10u[] __initconst = { ++ BCM47XX_GPIO_KEY(20, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(21, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_asus_rtn12[] __initconst = { + BCM47XX_GPIO_KEY(0, KEY_WPS_BUTTON), + BCM47XX_GPIO_KEY(1, KEY_RESTART), +@@ -277,6 +283,18 @@ bcm47xx_buttons_linksys_wrt310nv1[] __in + }; + + static const struct gpio_keys_button ++bcm47xx_buttons_linksys_wrt310n_v2[] __initconst = { ++ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(6, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button ++bcm47xx_buttons_linksys_wrt320n_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(5, KEY_WPS_BUTTON), ++ BCM47XX_GPIO_KEY(8, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_linksys_wrt54g3gv2[] __initconst = { + BCM47XX_GPIO_KEY(5, KEY_WIMAX), + BCM47XX_GPIO_KEY(6, KEY_RESTART), +@@ -385,6 +403,17 @@ bcm47xx_buttons_motorola_wr850gv2v3[] __ + /* Netgear */ + + static const struct gpio_keys_button ++bcm47xx_buttons_netgear_r6300_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(6, KEY_RESTART), ++}; ++ ++static const struct gpio_keys_button ++bcm47xx_buttons_netgear_wn2500rp_v1[] __initconst = { ++ BCM47XX_GPIO_KEY(12, KEY_RESTART), ++ BCM47XX_GPIO_KEY(31, KEY_WPS_BUTTON), ++}; ++ ++static const struct gpio_keys_button + bcm47xx_buttons_netgear_wndr3400v1[] __initconst = { + BCM47XX_GPIO_KEY(4, KEY_RESTART), + BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON), +@@ -471,6 +500,9 @@ int __init bcm47xx_buttons_register(void + int err; + + switch (board) { ++ case BCM47XX_BOARD_ASUS_RTN10U: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn10u); ++ break; + case BCM47XX_BOARD_ASUS_RTN12: + err = bcm47xx_copy_bdata(bcm47xx_buttons_asus_rtn12); + break; +@@ -601,6 +633,12 @@ int __init bcm47xx_buttons_register(void + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310nv1); + break; ++ case BCM47XX_BOARD_LINKSYS_WRT310NV2: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt310n_v2); ++ break; ++ case BCM47XX_BOARD_LINKSYS_WRT320N_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt320n_v1); ++ break; + case BCM47XX_BOARD_LINKSYS_WRT54G3GV2: + err = bcm47xx_copy_bdata(bcm47xx_buttons_linksys_wrt54g3gv2); + break; +@@ -664,6 +702,12 @@ int __init bcm47xx_buttons_register(void + err = bcm47xx_copy_bdata(bcm47xx_buttons_motorola_wr850gv2v3); + break; + ++ case BCM47XX_BOARD_NETGEAR_R6300_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_r6300_v1); ++ break; ++ case BCM47XX_BOARD_NETGEAR_WN2500RP_V1: ++ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wn2500rp_v1); ++ break; + case BCM47XX_BOARD_NETGEAR_WNDR3400V1: + err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr3400v1); + break; +--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h ++++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h +@@ -72,6 +72,7 @@ enum bcm47xx_board { + BCM47XX_BOARD_LINKSYS_WRT300NV11, + BCM47XX_BOARD_LINKSYS_WRT310NV1, + BCM47XX_BOARD_LINKSYS_WRT310NV2, ++ BCM47XX_BOARD_LINKSYS_WRT320N_V1, + BCM47XX_BOARD_LINKSYS_WRT54G3GV2, + BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0101, + BCM47XX_BOARD_LINKSYS_WRT54G_TYPE_0467, +@@ -98,9 +99,12 @@ enum bcm47xx_board { + BCM47XX_BOARD_MOTOROLA_WR850GP, + BCM47XX_BOARD_MOTOROLA_WR850GV2V3, + ++ BCM47XX_BOARD_NETGEAR_R6300_V1, + BCM47XX_BOARD_NETGEAR_WGR614V8, + BCM47XX_BOARD_NETGEAR_WGR614V9, + BCM47XX_BOARD_NETGEAR_WGR614_V10, ++ BCM47XX_BOARD_NETGEAR_WN2500RP_V1, ++ BCM47XX_BOARD_NETGEAR_WN2500RP_V2, + BCM47XX_BOARD_NETGEAR_WNDR3300, + BCM47XX_BOARD_NETGEAR_WNDR3400V1, + BCM47XX_BOARD_NETGEAR_WNDR3400V2, +--- a/arch/mips/bcm47xx/leds.c ++++ b/arch/mips/bcm47xx/leds.c +@@ -30,6 +30,14 @@ + /* Asus */ + + static const struct gpio_led ++bcm47xx_leds_asus_rtn10u[] __initconst = { ++ BCM47XX_GPIO_LED(5, "green", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(6, "green", "power", 1, LEDS_GPIO_DEFSTATE_ON), ++ BCM47XX_GPIO_LED(7, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(8, "green", "usb", 0, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_asus_rtn12[] __initconst = { + BCM47XX_GPIO_LED(2, "unk", "power", 1, LEDS_GPIO_DEFSTATE_ON), + BCM47XX_GPIO_LED(7, "unk", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF), +@@ -314,6 +322,13 @@ bcm47xx_leds_linksys_wrt310nv1[] __initc + }; + + static const struct gpio_led ++bcm47xx_leds_linksys_wrt320n_v1[] __initconst = { ++ BCM47XX_GPIO_LED(1, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF), ++ BCM47XX_GPIO_LED(2, "blue", "power", 0, LEDS_GPIO_DEFSTATE_ON), ++ BCM47XX_GPIO_LED(4, "amber", "wps", 1, LEDS_GPIO_DEFSTATE_OFF), ++}; ++ ++static const struct gpio_led + bcm47xx_leds_linksys_wrt54g_generic[] __initconst = { + BCM47XX_GPIO_LED(0, "unk", "dmz", 1, LEDS_GPIO_DEFSTATE_OFF), + BCM47XX_GPIO_LED(1, "unk", "power", 0, LEDS_GPIO_DEFSTATE_ON), +@@ -556,6 +571,9 @@ void __init bcm47xx_leds_register(void) + enum bcm47xx_board board = bcm47xx_board_get(); + + switch (board) { ++ case BCM47XX_BOARD_ASUS_RTN10U: ++ bcm47xx_set_pdata(bcm47xx_leds_asus_rtn10u); ++ break; + case BCM47XX_BOARD_ASUS_RTN12: + bcm47xx_set_pdata(bcm47xx_leds_asus_rtn12); + break; +@@ -689,6 +707,9 @@ void __init bcm47xx_leds_register(void) + case BCM47XX_BOARD_LINKSYS_WRT310NV1: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt310nv1); + break; ++ case BCM47XX_BOARD_LINKSYS_WRT320N_V1: ++ bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt320n_v1); ++ break; + case BCM47XX_BOARD_LINKSYS_WRT54G3GV2: + bcm47xx_set_pdata(bcm47xx_leds_linksys_wrt54g3gv2); + break; diff --git a/target/linux/bcm47xx/patches-4.19/400-mtd-bcm47xxpart-get-nvram.patch b/target/linux/bcm47xx/patches-4.19/400-mtd-bcm47xxpart-get-nvram.patch new file mode 100644 index 0000000000..df9d434c9f --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/400-mtd-bcm47xxpart-get-nvram.patch @@ -0,0 +1,34 @@ +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -102,6 +102,7 @@ static int bcm47xxpart_parse(struct mtd_ + int trx_num = 0; /* Number of found TRX partitions */ + int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; + int err; ++ bool found_nvram = false; + + /* + * Some really old flashes (like AT45DB*) had smaller erasesize-s, but +@@ -283,12 +284,23 @@ static int bcm47xxpart_parse(struct mtd_ + if (buf[0] == NVRAM_HEADER) { + bcm47xxpart_add_part(&parts[curr_part++], "nvram", + master->size - blocksize, 0); ++ found_nvram = true; + break; + } + } + + kfree(buf); + ++ if (!found_nvram) { ++ pr_err("can not find a nvram partition reserve last block\n"); ++ bcm47xxpart_add_part(&parts[curr_part++], "nvram_guess", ++ master->size - blocksize * 2, MTD_WRITEABLE); ++ for (i = 0; i < curr_part; i++) { ++ if (parts[i].size + parts[i].offset == master->size) ++ parts[i].offset -= blocksize * 2; ++ } ++ } ++ + /* + * Assume that partitions end at the beginning of the one they are + * followed by. diff --git a/target/linux/bcm47xx/patches-4.19/610-pci_ide_fix.patch b/target/linux/bcm47xx/patches-4.19/610-pci_ide_fix.patch new file mode 100644 index 0000000000..a353eec08c --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/610-pci_ide_fix.patch @@ -0,0 +1,41 @@ +From: b.sander +Subject: [PATCH] pci: IDE fix + +These are standard probing messages when using pdc202xx_old: +pdc202xx_old 0000:00:01.0: IDE controller (0x105a:0x0d30 rev 0x02) +PCI: Enabling device 0000:00:01.0 (0004 -> 0007) +PCI: Fixing up device 0000:00:01.0 +0000:00:01.0: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode. +0000:00:01.0: FORCING BURST BIT 0x00->0x01 ACTIVE +pdc202xx_old 0000:00:01.0: 100% native mode on irq 6 + +With the default MAX_HWIFS value after above we get: + ide2: BM-DMA at 0x0400-0x0407 + ide3: BM-DMA at 0x0408-0x040f +Probing IDE interface ide2... +hde: CF500, CFA DISK drive + +As you can see it's ide2 + ide3 and hde. + +With this patch applied we get: + ide0: BM-DMA at 0x0400-0x0407 + ide1: BM-DMA at 0x0408-0x040f +Probing IDE interface ide0... +hda: CF500, CFA DISK drive + +This fixes OpenWrt ticket #7061: https://dev.openwrt.org/ticket/7061 +--- +--- a/include/linux/ide.h ++++ b/include/linux/ide.h +@@ -235,7 +235,11 @@ static inline void ide_std_init_ports(st + hw->io_ports.ctl_addr = ctl_addr; + } + ++#if defined CONFIG_BCM47XX ++# define MAX_HWIFS 2 ++#else + #define MAX_HWIFS 10 ++#endif + + /* + * Now for the data we need to maintain per-drive: ide_drive_t diff --git a/target/linux/bcm47xx/patches-4.19/791-tg3-no-pci-sleep.patch b/target/linux/bcm47xx/patches-4.19/791-tg3-no-pci-sleep.patch new file mode 100644 index 0000000000..31c87b38c5 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/791-tg3-no-pci-sleep.patch @@ -0,0 +1,17 @@ +When the Ethernet controller is powered down and someone wants to +access the mdio bus like the witch driver (b53) the system crashed if +PCI_D3hot was set before. This patch deactivates this power sawing mode +when a switch driver is in use. + +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -4279,7 +4279,8 @@ static int tg3_power_down_prepare(struct + static void tg3_power_down(struct tg3 *tp) + { + pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE)); +- pci_set_power_state(tp->pdev, PCI_D3hot); ++ if (!tg3_flag(tp, ROBOSWITCH)) ++ pci_set_power_state(tp->pdev, PCI_D3hot); + } + + static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) diff --git a/target/linux/bcm47xx/patches-4.19/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch b/target/linux/bcm47xx/patches-4.19/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch new file mode 100644 index 0000000000..318dc55810 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/800-bcma-add-table-of-serial-flashes-with-smaller-blocks.patch @@ -0,0 +1,73 @@ +From 597715c61ae75a05ab3310a34ff3857a006f0f63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Thu, 20 Nov 2014 21:32:42 +0100 +Subject: [PATCH] bcma: add table of serial flashes with smaller blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/bcma/driver_chipcommon_sflash.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/drivers/bcma/driver_chipcommon_sflash.c ++++ b/drivers/bcma/driver_chipcommon_sflash.c +@@ -9,6 +9,7 @@ + + #include <linux/platform_device.h> + #include <linux/bcma/bcma.h> ++#include <bcm47xx_board.h> + + static struct resource bcma_sflash_resource = { + .name = "bcma_sflash", +@@ -42,6 +43,13 @@ static const struct bcma_sflash_tbl_e bc + { NULL }, + }; + ++/* Some devices use smaller blocks (and have more of them) */ ++static const struct bcma_sflash_tbl_e bcma_sflash_st_shrink_tbl[] = { ++ { "M25P16", 0x14, 0x1000, 512, }, ++ { "M25P32", 0x15, 0x1000, 1024, }, ++ { NULL }, ++}; ++ + static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { + { "SST25WF512", 1, 0x1000, 16, }, + { "SST25VF512", 0x48, 0x1000, 16, }, +@@ -85,6 +93,24 @@ static void bcma_sflash_cmd(struct bcma_ + bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); + } + ++const struct bcma_sflash_tbl_e *bcma_sflash_shrink_flash(u32 id) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ const struct bcma_sflash_tbl_e *e; ++ ++ switch (board) { ++ case BCM47XX_BOARD_NETGEAR_WGR614_V10: ++ case BCM47XX_BOARD_NETGEAR_WNR1000_V3: ++ for (e = bcma_sflash_st_shrink_tbl; e->name; e++) { ++ if (e->id == id) ++ return e; ++ } ++ return NULL; ++ default: ++ return NULL; ++ } ++} ++ + /* Initialize serial flash access */ + int bcma_sflash_init(struct bcma_drv_cc *cc) + { +@@ -115,6 +141,10 @@ int bcma_sflash_init(struct bcma_drv_cc + case 0x13: + return -ENOTSUPP; + default: ++ e = bcma_sflash_shrink_flash(id); ++ if (e) ++ break; ++ + for (e = bcma_sflash_st_tbl; e->name; e++) { + if (e->id == id) + break; diff --git a/target/linux/bcm47xx/patches-4.19/820-wgt634u-nvram-fix.patch b/target/linux/bcm47xx/patches-4.19/820-wgt634u-nvram-fix.patch new file mode 100644 index 0000000000..aaab39ae41 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/820-wgt634u-nvram-fix.patch @@ -0,0 +1,304 @@ +The Netgear wgt634u uses a different format for storing the +configuration. This patch is needed to read out the correct +configuration. The cfe_env.c file uses a different method way to read +out the configuration than the in kernel cfe config reader. + +--- a/drivers/firmware/broadcom/Makefile ++++ b/drivers/firmware/broadcom/Makefile +@@ -1,2 +1,2 @@ +-obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o ++obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o cfe_env.o + obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx_sprom.o +--- /dev/null ++++ b/drivers/firmware/broadcom/cfe_env.c +@@ -0,0 +1,228 @@ ++/* ++ * CFE environment variable access ++ * ++ * Copyright 2001-2003, Broadcom Corporation ++ * Copyright 2006, Felix Fietkau <nbd@nbd.name> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/string.h> ++#include <asm/io.h> ++#include <linux/uaccess.h> ++ ++#define NVRAM_SIZE (0x1ff0) ++static char _nvdata[NVRAM_SIZE]; ++static char _valuestr[256]; ++ ++/* ++ * TLV types. These codes are used in the "type-length-value" ++ * encoding of the items stored in the NVRAM device (flash or EEPROM) ++ * ++ * The layout of the flash/nvram is as follows: ++ * ++ * <type> <length> <data ...> <type> <length> <data ...> <type_end> ++ * ++ * The type code of "ENV_TLV_TYPE_END" marks the end of the list. ++ * The "length" field marks the length of the data section, not ++ * including the type and length fields. ++ * ++ * Environment variables are stored as follows: ++ * ++ * <type_env> <length> <flags> <name> = <value> ++ * ++ * If bit 0 (low bit) is set, the length is an 8-bit value. ++ * If bit 0 (low bit) is clear, the length is a 16-bit value ++ * ++ * Bit 7 set indicates "user" TLVs. In this case, bit 0 still ++ * indicates the size of the length field. ++ * ++ * Flags are from the constants below: ++ * ++ */ ++#define ENV_LENGTH_16BITS 0x00 /* for low bit */ ++#define ENV_LENGTH_8BITS 0x01 ++ ++#define ENV_TYPE_USER 0x80 ++ ++#define ENV_CODE_SYS(n,l) (((n)<<1)|(l)) ++#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER) ++ ++/* ++ * The actual TLV types we support ++ */ ++ ++#define ENV_TLV_TYPE_END 0x00 ++#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS) ++ ++/* ++ * Environment variable flags ++ */ ++ ++#define ENV_FLG_NORMAL 0x00 /* normal read/write */ ++#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */ ++#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */ ++ ++#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */ ++#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */ ++ ++ ++/* ********************************************************************* ++ * _nvram_read(buffer,offset,length) ++ * ++ * Read data from the NVRAM device ++ * ++ * Input parameters: ++ * buffer - destination buffer ++ * offset - offset of data to read ++ * length - number of bytes to read ++ * ++ * Return value: ++ * number of bytes read, or <0 if error occured ++ ********************************************************************* */ ++static int ++_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length) ++{ ++ int i; ++ if (offset > NVRAM_SIZE) ++ return -1; ++ ++ for ( i = 0; i < length; i++) { ++ buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i]; ++ } ++ return length; ++} ++ ++ ++static char* ++_strnchr(const char *dest,int c,size_t cnt) ++{ ++ while (*dest && (cnt > 0)) { ++ if (*dest == c) return (char *) dest; ++ dest++; ++ cnt--; ++ } ++ return NULL; ++} ++ ++ ++ ++/* ++ * Core support API: Externally visible. ++ */ ++ ++/* ++ * Get the value of an NVRAM variable ++ * @param name name of variable to get ++ * @return value of variable or NULL if undefined ++ */ ++ ++char *cfe_env_get(unsigned char *nv_buf, const char *name) ++{ ++ int size; ++ unsigned char *buffer; ++ unsigned char *ptr; ++ unsigned char *envval; ++ unsigned int reclen; ++ unsigned int rectype; ++ int offset; ++ int flg; ++ ++ if (!strcmp(name, "nvram_type")) ++ return "cfe"; ++ ++ size = NVRAM_SIZE; ++ buffer = &_nvdata[0]; ++ ++ ptr = buffer; ++ offset = 0; ++ ++ /* Read the record type and length */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ ++ while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) { ++ ++ /* Adjust pointer for TLV type */ ++ rectype = *(ptr); ++ offset++; ++ size--; ++ ++ /* ++ * Read the length. It can be either 1 or 2 bytes ++ * depending on the code ++ */ ++ if (rectype & ENV_LENGTH_8BITS) { ++ /* Read the record type and length - 8 bits */ ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) { ++ goto error; ++ } ++ reclen = *(ptr); ++ size--; ++ offset++; ++ } ++ else { ++ /* Read the record type and length - 16 bits, MSB first */ ++ if (_nvram_read(nv_buf, ptr,offset,2) != 2) { ++ goto error; ++ } ++ reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1); ++ size -= 2; ++ offset += 2; ++ } ++ ++ if (reclen > size) ++ break; /* should not happen, bad NVRAM */ ++ ++ switch (rectype) { ++ case ENV_TLV_TYPE_ENV: ++ /* Read the TLV data */ ++ if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen) ++ goto error; ++ flg = *ptr++; ++ envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1)); ++ if (envval) { ++ *envval++ = '\0'; ++ memcpy(_valuestr,envval,(reclen-1)-(envval-ptr)); ++ _valuestr[(reclen-1)-(envval-ptr)] = '\0'; ++#if 0 ++ printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr); ++#endif ++ if(!strcmp(ptr, name)){ ++ return _valuestr; ++ } ++ if((strlen(ptr) > 1) && !strcmp(&ptr[1], name)) ++ return _valuestr; ++ } ++ break; ++ ++ default: ++ /* Unknown TLV type, skip it. */ ++ break; ++ } ++ ++ /* ++ * Advance to next TLV ++ */ ++ ++ size -= (int)reclen; ++ offset += reclen; ++ ++ /* Read the next record type */ ++ ptr = buffer; ++ if (_nvram_read(nv_buf, ptr,offset,1) != 1) ++ goto error; ++ } ++ ++error: ++ return NULL; ++ ++} ++ +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -37,6 +37,8 @@ struct nvram_header { + static char nvram_buf[NVRAM_SPACE]; + static size_t nvram_len; + static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; ++static int cfe_env; ++extern char *cfe_env_get(char *nv_buf, const char *name); + + static u32 find_nvram_size(void __iomem *end) + { +@@ -56,7 +58,9 @@ static u32 find_nvram_size(void __iomem + static int nvram_find_and_copy(void __iomem *iobase, u32 lim) + { + struct nvram_header __iomem *header; ++ int i; + u32 off; ++ u32 *src, *dst; + u32 size; + + if (nvram_len) { +@@ -64,6 +68,26 @@ static int nvram_find_and_copy(void __io + return -EEXIST; + } + ++ cfe_env = 0; ++ ++ /* XXX: hack for supporting the CFE environment stuff on WGT634U */ ++ if (lim >= 8 * 1024 * 1024) { ++ src = (u32 *)(iobase + 8 * 1024 * 1024 - 0x2000); ++ dst = (u32 *)nvram_buf; ++ ++ if ((*src & 0xff00ff) == 0x000001) { ++ printk("early_nvram_init: WGT634U NVRAM found.\n"); ++ ++ for (i = 0; i < 0x1ff0; i++) { ++ if (*src == 0xFFFFFFFF) ++ break; ++ *dst++ = *src++; ++ } ++ cfe_env = 1; ++ return 0; ++ } ++ } ++ + /* TODO: when nvram is on nand flash check for bad blocks first. */ + off = FLASH_MIN; + while (off <= lim) { +@@ -174,6 +198,13 @@ int bcm47xx_nvram_getenv(const char *nam + if (!name) + return -EINVAL; + ++ if (cfe_env) { ++ value = cfe_env_get(nvram_buf, name); ++ if (!value) ++ return -ENOENT; ++ return snprintf(val, val_len, "%s", value); ++ } ++ + if (!nvram_len) { + err = nvram_init(); + if (err) diff --git a/target/linux/bcm47xx/patches-4.19/830-huawei_e970_support.patch b/target/linux/bcm47xx/patches-4.19/830-huawei_e970_support.patch new file mode 100644 index 0000000000..4d43b9960b --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/830-huawei_e970_support.patch @@ -0,0 +1,101 @@ +--- a/arch/mips/bcm47xx/setup.c ++++ b/arch/mips/bcm47xx/setup.c +@@ -37,6 +37,7 @@ + #include <linux/ssb/ssb.h> + #include <linux/ssb/ssb_embedded.h> + #include <linux/bcma/bcma_soc.h> ++#include <linux/old_gpio_wdt.h> + #include <asm/bootinfo.h> + #include <asm/idle.h> + #include <asm/prom.h> +@@ -254,6 +255,33 @@ static struct fixed_phy_status bcm47xx_f + .duplex = DUPLEX_FULL, + }; + ++static struct gpio_wdt_platform_data gpio_wdt_data; ++ ++static struct platform_device gpio_wdt_device = { ++ .name = "gpio-wdt", ++ .id = 0, ++ .dev = { ++ .platform_data = &gpio_wdt_data, ++ }, ++}; ++ ++static int __init bcm47xx_register_gpio_watchdog(void) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ ++ switch (board) { ++ case BCM47XX_BOARD_HUAWEI_E970: ++ pr_info("bcm47xx: detected Huawei E970 or similar, starting early gpio_wdt timer\n"); ++ gpio_wdt_data.gpio = 7; ++ gpio_wdt_data.interval = HZ; ++ gpio_wdt_data.first_interval = HZ / 5; ++ return platform_device_register(&gpio_wdt_device); ++ default: ++ /* Nothing to do */ ++ return 0; ++ } ++} ++ + static int __init bcm47xx_register_bus_complete(void) + { + switch (bcm47xx_bus_type) { +@@ -275,6 +303,7 @@ static int __init bcm47xx_register_bus_c + bcm47xx_workarounds(); + + fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status, -1); ++ bcm47xx_register_gpio_watchdog(); + return 0; + } + device_initcall(bcm47xx_register_bus_complete); +--- a/arch/mips/configs/bcm47xx_defconfig ++++ b/arch/mips/configs/bcm47xx_defconfig +@@ -66,6 +66,7 @@ CONFIG_HW_RANDOM=y + CONFIG_GPIO_SYSFS=y + CONFIG_WATCHDOG=y + CONFIG_BCM47XX_WDT=y ++CONFIG_GPIO_WDT=y + CONFIG_SSB_DRIVER_GIGE=y + CONFIG_BCMA_DRIVER_GMAC_CMN=y + CONFIG_USB=y +--- a/drivers/ssb/embedded.c ++++ b/drivers/ssb/embedded.c +@@ -34,11 +34,36 @@ int ssb_watchdog_timer_set(struct ssb_bu + } + EXPORT_SYMBOL(ssb_watchdog_timer_set); + ++#ifdef CONFIG_BCM47XX ++#include <bcm47xx_board.h> ++ ++static bool ssb_watchdog_supported(void) ++{ ++ enum bcm47xx_board board = bcm47xx_board_get(); ++ ++ /* The Huawei E970 has a hardware watchdog using a GPIO */ ++ switch (board) { ++ case BCM47XX_BOARD_HUAWEI_E970: ++ return false; ++ default: ++ return true; ++ } ++} ++#else ++static bool ssb_watchdog_supported(void) ++{ ++ return true; ++} ++#endif ++ + int ssb_watchdog_register(struct ssb_bus *bus) + { + struct bcm47xx_wdt wdt = {}; + struct platform_device *pdev; + ++ if (!ssb_watchdog_supported()) ++ return 0; ++ + if (ssb_chipco_available(&bus->chipco)) { + wdt.driver_data = &bus->chipco; + wdt.timer_set = ssb_chipco_watchdog_timer_set_wdt; diff --git a/target/linux/bcm47xx/patches-4.19/831-old_gpio_wdt.patch b/target/linux/bcm47xx/patches-4.19/831-old_gpio_wdt.patch new file mode 100644 index 0000000000..e88f08b53c --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/831-old_gpio_wdt.patch @@ -0,0 +1,360 @@ +This generic GPIO watchdog is used on Huawei E970 (bcm47xx) + +Signed-off-by: Mathias Adam <m.adam--openwrt@adamis.de> + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1498,6 +1498,15 @@ config WDT_MTX1 + Hardware driver for the MTX-1 boards. This is a watchdog timer that + will reboot the machine after a 100 seconds timer expired. + ++config GPIO_WDT ++ tristate "GPIO Hardware Watchdog" ++ help ++ Hardware driver for GPIO-controlled watchdogs. GPIO pin and ++ toggle interval settings are platform-specific. The driver ++ will stop toggling the GPIO (i.e. machine reboots) after a ++ 100 second timer expired and no process has written to ++ /dev/watchdog during that time. ++ + config PNX833X_WDT + tristate "PNX833x Hardware Watchdog" + depends on SOC_PNX8335 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -154,6 +154,7 @@ obj-$(CONFIG_RC32434_WDT) += rc32434_wdt + obj-$(CONFIG_INDYDOG) += indydog.o + obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o + obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o ++obj-$(CONFIG_GPIO_WDT) += old_gpio_wdt.o + obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o +--- /dev/null ++++ b/drivers/watchdog/old_gpio_wdt.c +@@ -0,0 +1,301 @@ ++/* ++ * Driver for GPIO-controlled Hardware Watchdogs. ++ * ++ * Copyright (C) 2013 Mathias Adam <m.adam--linux@adamis.de> ++ * ++ * Replaces mtx1_wdt (driver for the MTX-1 Watchdog): ++ * ++ * (C) Copyright 2005 4G Systems <info@4g-systems.biz>, ++ * All Rights Reserved. ++ * http://www.4g-systems.biz ++ * ++ * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ * ++ * Neither Michael Stickel nor 4G Systems admit liability nor provide ++ * warranty for any of this software. This material is provided ++ * "AS-IS" and at no charge. ++ * ++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz> ++ * ++ * Release 0.01. ++ * Author: Michael Stickel michael.stickel@4g-systems.biz ++ * ++ * Release 0.02. ++ * Author: Florian Fainelli florian@openwrt.org ++ * use the Linux watchdog/timer APIs ++ * ++ * Release 0.03. ++ * Author: Mathias Adam <m.adam--linux@adamis.de> ++ * make it a generic gpio watchdog driver ++ * ++ * The Watchdog is configured to reset the MTX-1 ++ * if it is not triggered for 100 seconds. ++ * It should not be triggered more often than 1.6 seconds. ++ * ++ * A timer triggers the watchdog every 5 seconds, until ++ * it is opened for the first time. After the first open ++ * it MUST be triggered every 2..95 seconds. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/miscdevice.h> ++#include <linux/fs.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/timer.h> ++#include <linux/completion.h> ++#include <linux/jiffies.h> ++#include <linux/watchdog.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/uaccess.h> ++#include <linux/gpio.h> ++#include <linux/old_gpio_wdt.h> ++ ++static int ticks = 100 * HZ; ++ ++static struct { ++ struct completion stop; ++ spinlock_t lock; ++ int running; ++ struct timer_list timer; ++ int queue; ++ int default_ticks; ++ unsigned long inuse; ++ unsigned gpio; ++ unsigned int gstate; ++ int interval; ++ int first_interval; ++} gpio_wdt_device; ++ ++static void gpio_wdt_trigger(struct timer_list *unused) ++{ ++ spin_lock(&gpio_wdt_device.lock); ++ if (gpio_wdt_device.running && ticks > 0) ++ ticks -= gpio_wdt_device.interval; ++ ++ /* toggle wdt gpio */ ++ gpio_wdt_device.gstate = !gpio_wdt_device.gstate; ++ gpio_set_value(gpio_wdt_device.gpio, gpio_wdt_device.gstate); ++ ++ if (gpio_wdt_device.queue && ticks > 0) ++ mod_timer(&gpio_wdt_device.timer, jiffies + gpio_wdt_device.interval); ++ else ++ complete(&gpio_wdt_device.stop); ++ spin_unlock(&gpio_wdt_device.lock); ++} ++ ++static void gpio_wdt_reset(void) ++{ ++ ticks = gpio_wdt_device.default_ticks; ++} ++ ++ ++static void gpio_wdt_start(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gpio_wdt_device.lock, flags); ++ if (!gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 1; ++ gpio_wdt_device.gstate = 1; ++ gpio_set_value(gpio_wdt_device.gpio, 1); ++ mod_timer(&gpio_wdt_device.timer, jiffies + gpio_wdt_device.first_interval); ++ } ++ gpio_wdt_device.running++; ++ spin_unlock_irqrestore(&gpio_wdt_device.lock, flags); ++} ++ ++static int gpio_wdt_stop(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&gpio_wdt_device.lock, flags); ++ if (gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 0; ++ gpio_wdt_device.gstate = 0; ++ gpio_set_value(gpio_wdt_device.gpio, 0); ++ } ++ ticks = gpio_wdt_device.default_ticks; ++ spin_unlock_irqrestore(&gpio_wdt_device.lock, flags); ++ return 0; ++} ++ ++/* Filesystem functions */ ++ ++static int gpio_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(0, &gpio_wdt_device.inuse)) ++ return -EBUSY; ++ return nonseekable_open(inode, file); ++} ++ ++ ++static int gpio_wdt_release(struct inode *inode, struct file *file) ++{ ++ clear_bit(0, &gpio_wdt_device.inuse); ++ return 0; ++} ++ ++static long gpio_wdt_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ void __user *argp = (void __user *)arg; ++ int __user *p = (int __user *)argp; ++ unsigned int value; ++ static const struct watchdog_info ident = { ++ .options = WDIOF_CARDRESET, ++ .identity = "GPIO WDT", ++ }; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ if (copy_to_user(argp, &ident, sizeof(ident))) ++ return -EFAULT; ++ break; ++ case WDIOC_GETSTATUS: ++ case WDIOC_GETBOOTSTATUS: ++ put_user(0, p); ++ break; ++ case WDIOC_SETOPTIONS: ++ if (get_user(value, p)) ++ return -EFAULT; ++ if (value & WDIOS_ENABLECARD) ++ gpio_wdt_start(); ++ else if (value & WDIOS_DISABLECARD) ++ gpio_wdt_stop(); ++ else ++ return -EINVAL; ++ return 0; ++ case WDIOC_KEEPALIVE: ++ gpio_wdt_reset(); ++ break; ++ default: ++ return -ENOTTY; ++ } ++ return 0; ++} ++ ++ ++static ssize_t gpio_wdt_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) ++{ ++ if (!count) ++ return -EIO; ++ gpio_wdt_reset(); ++ return count; ++} ++ ++static const struct file_operations gpio_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .unlocked_ioctl = gpio_wdt_ioctl, ++ .open = gpio_wdt_open, ++ .write = gpio_wdt_write, ++ .release = gpio_wdt_release, ++}; ++ ++ ++static struct miscdevice gpio_wdt_misc = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &gpio_wdt_fops, ++}; ++ ++ ++static int gpio_wdt_probe(struct platform_device *pdev) ++{ ++ int ret; ++ struct gpio_wdt_platform_data *gpio_wdt_data = pdev->dev.platform_data; ++ ++ gpio_wdt_device.gpio = gpio_wdt_data->gpio; ++ gpio_wdt_device.interval = gpio_wdt_data->interval; ++ gpio_wdt_device.first_interval = gpio_wdt_data->first_interval; ++ if (gpio_wdt_device.first_interval <= 0) { ++ gpio_wdt_device.first_interval = gpio_wdt_device.interval; ++ } ++ ++ ret = gpio_request(gpio_wdt_device.gpio, "gpio-wdt"); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request gpio"); ++ return ret; ++ } ++ ++ spin_lock_init(&gpio_wdt_device.lock); ++ init_completion(&gpio_wdt_device.stop); ++ gpio_wdt_device.queue = 0; ++ clear_bit(0, &gpio_wdt_device.inuse); ++ timer_setup(&gpio_wdt_device.timer, gpio_wdt_trigger, 0L); ++ gpio_wdt_device.default_ticks = ticks; ++ ++ gpio_wdt_start(); ++ dev_info(&pdev->dev, "GPIO Hardware Watchdog driver (gpio=%i interval=%i/%i)\n", ++ gpio_wdt_data->gpio, gpio_wdt_data->first_interval, gpio_wdt_data->interval); ++ return 0; ++} ++ ++static int gpio_wdt_remove(struct platform_device *pdev) ++{ ++ /* FIXME: do we need to lock this test ? */ ++ if (gpio_wdt_device.queue) { ++ gpio_wdt_device.queue = 0; ++ wait_for_completion(&gpio_wdt_device.stop); ++ } ++ ++ gpio_free(gpio_wdt_device.gpio); ++ misc_deregister(&gpio_wdt_misc); ++ return 0; ++} ++ ++static struct platform_driver gpio_wdt_driver = { ++ .probe = gpio_wdt_probe, ++ .remove = gpio_wdt_remove, ++ .driver.name = "gpio-wdt", ++ .driver.owner = THIS_MODULE, ++}; ++ ++static int __init gpio_wdt_init(void) ++{ ++ return platform_driver_register(&gpio_wdt_driver); ++} ++arch_initcall(gpio_wdt_init); ++ ++/* ++ * We do wdt initialization in two steps: arch_initcall probes the wdt ++ * very early to start pinging the watchdog (misc devices are not yet ++ * available), and later module_init() just registers the misc device. ++ */ ++static int gpio_wdt_init_late(void) ++{ ++ int ret; ++ ++ ret = misc_register(&gpio_wdt_misc); ++ if (ret < 0) { ++ pr_err("GPIO_WDT: failed to register misc device\n"); ++ return ret; ++ } ++ return 0; ++} ++#ifndef MODULE ++module_init(gpio_wdt_init_late); ++#endif ++ ++static void __exit gpio_wdt_exit(void) ++{ ++ platform_driver_unregister(&gpio_wdt_driver); ++} ++module_exit(gpio_wdt_exit); ++ ++MODULE_AUTHOR("Michael Stickel, Florian Fainelli, Mathias Adam"); ++MODULE_DESCRIPTION("Driver for GPIO hardware watchdogs"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); ++MODULE_ALIAS("platform:gpio-wdt"); +--- /dev/null ++++ b/include/linux/old_gpio_wdt.h +@@ -0,0 +1,21 @@ ++/* ++ * Definitions for the GPIO watchdog driver ++ * ++ * Copyright (C) 2013 Mathias Adam <m.adam--linux@adamis.de> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _GPIO_WDT_H_ ++#define _GPIO_WDT_H_ ++ ++struct gpio_wdt_platform_data { ++ int gpio; /* GPIO line number */ ++ int interval; /* watchdog reset interval in system ticks */ ++ int first_interval; /* first wd reset interval in system ticks */ ++}; ++ ++#endif /* _GPIO_WDT_H_ */ diff --git a/target/linux/bcm47xx/patches-4.19/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch b/target/linux/bcm47xx/patches-4.19/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch new file mode 100644 index 0000000000..6b7ee06e50 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/900-ssb-reject-PCI-writes-setting-CardBus-bridge-resourc.patch @@ -0,0 +1,30 @@ +From 5c81397a0147ea59c778d1de14ef54e2268221f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 8 Apr 2015 06:58:11 +0200 +Subject: [PATCH] ssb: reject PCI writes setting CardBus bridge resources +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If SoC has a CardBus we can set resources of device at slot 1 only. It's +impossigle to set bridge resources as it simply overwrites device 1 +configuration and usually results in Data bus error-s. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/ssb/driver_pcicore.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -164,6 +164,10 @@ static int ssb_extpci_write_config(struc + WARN_ON(!pc->hostmode); + if (unlikely(len != 1 && len != 2 && len != 4)) + goto out; ++ /* CardBus SoCs allow configuring dev 1 resources only */ ++ if (extpci_core->cardbusmode && dev != 1 && ++ off >= PCI_BASE_ADDRESS_0 && off <= PCI_BASE_ADDRESS_5) ++ goto out; + addr = get_cfgspace_addr(pc, bus, dev, func, off); + if (unlikely(!addr)) + goto out; diff --git a/target/linux/bcm47xx/patches-4.19/940-bcm47xx-yenta.patch b/target/linux/bcm47xx/patches-4.19/940-bcm47xx-yenta.patch new file mode 100644 index 0000000000..f5b7bda4e6 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/940-bcm47xx-yenta.patch @@ -0,0 +1,46 @@ +--- a/drivers/pcmcia/yenta_socket.c ++++ b/drivers/pcmcia/yenta_socket.c +@@ -920,6 +920,8 @@ static unsigned int yenta_probe_irq(stru + * Probe for usable interrupts using the force + * register to generate bogus card status events. + */ ++#ifndef CONFIG_BCM47XX ++ /* WRT54G3G does not like this */ + cb_writel(socket, CB_SOCKET_EVENT, -1); + cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); + reg = exca_readb(socket, I365_CSCINT); +@@ -935,6 +937,7 @@ static unsigned int yenta_probe_irq(stru + } + cb_writel(socket, CB_SOCKET_MASK, 0); + exca_writeb(socket, I365_CSCINT, reg); ++#endif + + mask = probe_irq_mask(val) & 0xffff; + +@@ -1019,6 +1022,10 @@ static void yenta_get_socket_capabilitie + else + socket->socket.irq_mask = 0; + ++ /* irq mask probing is broken for the WRT54G3G */ ++ if (socket->socket.irq_mask == 0) ++ socket->socket.irq_mask = 0x6f8; ++ + dev_info(&socket->dev->dev, "ISA IRQ mask 0x%04x, PCI irq %d\n", + socket->socket.irq_mask, socket->cb_irq); + } +@@ -1250,6 +1257,15 @@ static int yenta_probe(struct pci_dev *d + dev_info(&dev->dev, "Socket status: %08x\n", + cb_readl(socket, CB_SOCKET_STATE)); + ++ /* Generate an interrupt on card insert/remove */ ++ config_writew(socket, CB_SOCKET_MASK, CB_CSTSMASK | CB_CDMASK); ++ ++ /* Set up Multifunction Routing Status Register */ ++ config_writew(socket, 0x8C, 0x1000 /* MFUNC3 to GPIO3 */ | 0x2 /* MFUNC0 to INTA */); ++ ++ /* Switch interrupts to parallelized */ ++ config_writeb(socket, 0x92, 0x64); ++ + yenta_fixup_parent_bridge(dev->subordinate); + + /* Register it with the pcmcia layer.. */ diff --git a/target/linux/bcm47xx/patches-4.19/976-ssb_increase_pci_delay.patch b/target/linux/bcm47xx/patches-4.19/976-ssb_increase_pci_delay.patch new file mode 100644 index 0000000000..99aa188374 --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/976-ssb_increase_pci_delay.patch @@ -0,0 +1,11 @@ +--- a/drivers/ssb/driver_pcicore.c ++++ b/drivers/ssb/driver_pcicore.c +@@ -390,7 +390,7 @@ static void ssb_pcicore_init_hostmode(st + set_io_port_base(ssb_pcicore_controller.io_map_base); + /* Give some time to the PCI controller to configure itself with the new + * values. Not waiting at this point causes crashes of the machine. */ +- mdelay(10); ++ mdelay(300); + register_pci_controller(&ssb_pcicore_controller); + } + diff --git a/target/linux/bcm47xx/patches-4.19/999-wl_exports.patch b/target/linux/bcm47xx/patches-4.19/999-wl_exports.patch new file mode 100644 index 0000000000..2936421aff --- /dev/null +++ b/target/linux/bcm47xx/patches-4.19/999-wl_exports.patch @@ -0,0 +1,22 @@ +--- a/drivers/firmware/broadcom/bcm47xx_nvram.c ++++ b/drivers/firmware/broadcom/bcm47xx_nvram.c +@@ -34,7 +34,8 @@ struct nvram_header { + u32 config_ncdl; /* ncdl values for memc */ + }; + +-static char nvram_buf[NVRAM_SPACE]; ++char nvram_buf[NVRAM_SPACE]; ++EXPORT_SYMBOL(nvram_buf); + static size_t nvram_len; + static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000}; + static int cfe_env; +--- a/arch/mips/mm/cache.c ++++ b/arch/mips/mm/cache.c +@@ -64,6 +64,7 @@ void (*_dma_cache_wback)(unsigned long s + void (*_dma_cache_inv)(unsigned long start, unsigned long size); + + EXPORT_SYMBOL(_dma_cache_wback_inv); ++EXPORT_SYMBOL(_dma_cache_inv); + + #endif /* CONFIG_DMA_NONCOHERENT */ + |