diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-4.1')
43 files changed, 5782 insertions, 0 deletions
diff --git a/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch new file mode 100644 index 0000000000..290ea0aea9 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/058-ARM-BCM5301X-Add-USB-LED-for-Buffalo-WZR-1750DHP.patch @@ -0,0 +1,26 @@ +From 35ad0e50bd6683c6699586e3bd5045f0695586d9 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Wed, 13 May 2015 09:10:51 +0200 +Subject: [PATCH] ARM: BCM5301X: Add USB LED for Buffalo WZR-1750DHP + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -47,6 +47,12 @@ + leds { + compatible = "gpio-leds"; + ++ usb { ++ label = "bcm53xx:blue:usb"; ++ gpios = <&hc595 0 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ + power0 { + label = "bcm53xx:red:power"; + gpios = <&hc595 1 GPIO_ACTIVE_HIGH>; diff --git a/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch b/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch new file mode 100644 index 0000000000..e16d39b423 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/059-ARM-BCM5301X-Add-DT-for-Buffalo-WXR-1900DHP.patch @@ -0,0 +1,157 @@ +From 35eecd10ee57b9d4f31e12598296b235ed2b34ae Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Wed, 13 May 2015 09:10:52 +0200 +Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WXR-1900DHP +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 127 ++++++++++++++++++++++ + 2 files changed, 128 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -63,6 +63,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm47081-asus-rt-n18u.dtb \ + bcm47081-buffalo-wzr-600dhp2.dtb \ + bcm47081-buffalo-wzr-900dhp.dtb \ ++ bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-netgear-r8000.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ + bcm963138dvt.dtb +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -0,0 +1,127 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Buffalo WXR-1900DHP ++ * ++ * Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++ ++/ { ++ compatible = "buffalo,wxr-1900dhp", "brcm,bcm4709", "brcm,bcm4708"; ++ model = "Buffalo WXR-1900DHP"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ usb { ++ label = "bcm53xx:green:usb"; ++ gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ power-amber { ++ label = "bcm53xx:amber:power"; ++ gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ power-white { ++ label = "bcm53xx:white:power"; ++ gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ router-amber { ++ label = "bcm53xx:amber:router"; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ router-white { ++ label = "bcm53xx:white:router"; ++ gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wan-amber { ++ label = "bcm53xx:amber:wan"; ++ gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wan-white { ++ label = "bcm53xx:white:wan"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wireless-amber { ++ label = "bcm53xx:amber:wireless"; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wireless-white { ++ label = "bcm53xx:white:wireless"; ++ gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ power { ++ label = "Power"; ++ linux,code = <KEY_POWER>; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>; ++ }; ++ ++ restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>; ++ }; ++ ++ aoss { ++ label = "AOSS"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>; ++ }; ++ ++ /* Commit mode set by switch? */ ++ mode { ++ label = "Mode"; ++ linux,code = <KEY_SETUP>; ++ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>; ++ }; ++ ++ /* Switch: AP mode */ ++ sw_ap { ++ label = "AP"; ++ linux,code = <BTN_0>; ++ gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>; ++ }; ++ ++ eject { ++ label = "USB eject"; ++ linux,code = <KEY_EJECTCD>; ++ gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch b/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch new file mode 100644 index 0000000000..dafae7b170 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/060-ARM-BCM5301X-Add-DT-for-SmartRG-SR400ac.patch @@ -0,0 +1,148 @@ +From 691917f20cae813d242f7123a4dc97e7d48e6ff1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 13 May 2015 09:10:53 +0200 +Subject: [PATCH] ARM: BCM5301X: Add DT for SmartRG SR400ac +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts | 119 ++++++++++++++++++++++++++ + 2 files changed, 120 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -60,6 +60,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4708-luxul-xwc-1000.dtb \ + bcm4708-netgear-r6250.dtb \ + bcm4708-netgear-r6300-v2.dtb \ ++ bcm4708-smartrg-sr400ac.dtb \ + bcm47081-asus-rt-n18u.dtb \ + bcm47081-buffalo-wzr-600dhp2.dtb \ + bcm47081-buffalo-wzr-900dhp.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +@@ -0,0 +1,119 @@ ++/* ++ * Broadcom BCM470X / BCM5301X arm platform code. ++ * DTS for SmartRG SR400ac ++ * ++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++ ++/ { ++ compatible = "smartrg,sr400ac", "brcm,bcm4708"; ++ model = "SmartRG SR400ac"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power-white { ++ label = "bcm53xx:white:power"; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ power-amber { ++ label = "bcm53xx:amber:power"; ++ gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ usb2 { ++ label = "bcm53xx:white:usb2"; ++ gpios = <&chipcommon 3 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ usb3-white { ++ label = "bcm53xx:white:usb3"; ++ gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ usb3-green { ++ label = "bcm53xx:green:usb3"; ++ gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wps { ++ label = "bcm53xx:white:wps"; ++ gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ status-red { ++ label = "bcm53xx:red:status"; ++ gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ status-green { ++ label = "bcm53xx:green:status"; ++ gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ status-blue { ++ label = "bcm53xx:blue:status"; ++ gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wan-white { ++ label = "bcm53xx:white:wan"; ++ gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wan-red { ++ label = "bcm53xx:red:wan"; ++ gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rfkill { ++ label = "WiFi"; ++ linux,code = <KEY_RFKILL>; ++ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wps { ++ label = "WPS"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ ++ restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch b/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch new file mode 100644 index 0000000000..02e644e7c0 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/061-ARM-BCM5301X-Add-DT-for-Asus-RT-AC68U.patch @@ -0,0 +1,112 @@ +From b5f350c790ae6aaf3dda5a825d7e3fdeed731164 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sat, 28 Mar 2015 15:01:38 +0100 +Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC68U +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts | 83 +++++++++++++++++++++++++++++ + 2 files changed, 84 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2835-rpi-b.dtb \ + bcm2835-rpi-b-plus.dtb + dtb-$(CONFIG_ARCH_BCM_5301X) += \ ++ bcm4708-asus-rt-ac68u.dtb \ + bcm4708-buffalo-wzr-1750dhp.dtb \ + bcm4708-luxul-xwc-1000.dtb \ + bcm4708-netgear-r6250.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts +@@ -0,0 +1,83 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Asus RT-AC68U ++ * ++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++ ++/ { ++ compatible = "asus,rt-ac68u", "brcm,bcm4708"; ++ model = "Asus RT-AC68U (BCM4708)"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ usb2 { ++ label = "bcm53xx:blue:usb2"; ++ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ power { ++ label = "bcm53xx:blue:power"; ++ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ logo { ++ label = "bcm53xx:white:logo"; ++ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ usb3 { ++ label = "bcm53xx:blue:usb3"; ++ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brightness { ++ label = "Backlight"; ++ linux,code = <KEY_BRIGHTNESS_ZERO>; ++ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wps { ++ label = "WPS"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ ++ restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ rfkill { ++ label = "WiFi"; ++ linux,code = <KEY_RFKILL>; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch b/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch new file mode 100644 index 0000000000..e72835b186 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/062-ARM-BCM5301X-Add-DT-for-Asus-RT-AC56U.patch @@ -0,0 +1,125 @@ +From 16dc3bac722252a10e396546f44135ae1b6a7ff3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Tue, 31 Mar 2015 17:29:18 +0200 +Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC56U +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts | 96 +++++++++++++++++++++++++++++ + 2 files changed, 97 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -56,6 +56,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2835-rpi-b.dtb \ + bcm2835-rpi-b-plus.dtb + dtb-$(CONFIG_ARCH_BCM_5301X) += \ ++ bcm4708-asus-rt-ac56u.dtb \ + bcm4708-asus-rt-ac68u.dtb \ + bcm4708-buffalo-wzr-1750dhp.dtb \ + bcm4708-luxul-xwc-1000.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts +@@ -0,0 +1,96 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Asus RT-AC56U ++ * ++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++ ++/ { ++ compatible = "asus,rt-ac56u", "brcm,bcm4708"; ++ model = "Asus RT-AC56U (BCM4708)"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ usb3 { ++ label = "bcm53xx:blue:usb3"; ++ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ wan { ++ label = "bcm53xx:blue:wan"; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ lan { ++ label = "bcm53xx:blue:lan"; ++ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ power { ++ label = "bcm53xx:blue:power"; ++ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ all { ++ label = "bcm53xx:blue:all"; ++ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ 2ghz { ++ label = "bcm53xx:blue:2ghz"; ++ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ ++ usb2 { ++ label = "bcm53xx:blue:usb2"; ++ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rfkill { ++ label = "WiFi"; ++ linux,code = <KEY_RFKILL>; ++ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; ++ }; ++ ++ restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ ++ wps { ++ label = "WPS"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch b/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch new file mode 100644 index 0000000000..8716a0d5c6 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/063-ARM-BCM5301X-Ignore-another-BCM4709-specific-fault-c.patch @@ -0,0 +1,41 @@ +From 7eb68a2a0519a77b93184c695d4d293c92dc2286 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 11 Feb 2015 16:40:58 +0100 +Subject: [PATCH] ARM: BCM5301X: Ignore another (BCM4709 specific) fault code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom ARM devices seem to generate some fault once per boot. We +already have an ignoring handler for BCM4707/BCM4708, but BCM4709 +generates different code. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/mach-bcm/bcm_5301x.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/arch/arm/mach-bcm/bcm_5301x.c ++++ b/arch/arm/mach-bcm/bcm_5301x.c +@@ -18,15 +18,16 @@ static bool first_fault = true; + static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, + struct pt_regs *regs) + { +- if (fsr == 0x1c06 && first_fault) { ++ if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) { + first_fault = false; + + /* +- * These faults with code 0x1c06 happens for no good reason, +- * possibly left over from the CFE boot loader. ++ * These faults with codes 0x1406 (BCM4709) or 0x1c06 happens ++ * for no good reason, possibly left over from the CFE boot ++ * loader. + */ + pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", +- addr, fsr); ++ addr, fsr); + + /* Returning non-zero causes fault display and panic */ + return 0; diff --git a/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch b/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch new file mode 100644 index 0000000000..aa99f3758c --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/064-ARM-BCM5301X-add-NAND-flash-chip-description.patch @@ -0,0 +1,210 @@ +From 9faa5960eef3204cae6637b530f5e23e53b5a9ef Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Fri, 29 May 2015 23:39:47 +0200 +Subject: [PATCH] ARM: BCM5301X: add NAND flash chip description + +This adds the NAND flash chip description for a standard chip found +connected to this SoC. This makes use of generic Broadcom NAND driver +with the iProc interface. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts | 1 + + arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts | 1 + + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 1 + + arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 9 +++----- + arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 1 + + arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 1 + + arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts | 1 + + arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 1 + + arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 1 + + arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts | 1 + + arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 1 + + arch/arm/boot/dts/bcm4709-netgear-r8000.dts | 1 + + arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi | 24 ++++++++++++++++++++++ + arch/arm/boot/dts/bcm5301x.dtsi | 12 +++++++++++ + 14 files changed, 50 insertions(+), 6 deletions(-) + create mode 100644 arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi + +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "asus,rt-ac56u", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "asus,rt-ac68u", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "buffalo,wzr-1750dhp", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts ++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "luxul,xwc-1000", "brcm,bcm4708"; +@@ -23,12 +24,8 @@ + reg = <0x00000000 0x08000000>; + }; + +- axi@18000000 { +- nand@28000 { +- reg = <0x00028000 0x1000>; +- #address-cells = <1>; +- #size-cells = <1>; +- ++ nand: nand@18028000 { ++ nandcs@0 { + partition@0 { + label = "ubi"; + reg = <0x00000000 0x08000000>; +--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "netgear,r6250v1", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "netgear,r6300v2", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts ++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "smartrg,sr400ac", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts ++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm47081.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "asus,rt-n18u", "brcm,bcm47081", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm47081.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "buffalo,wzr-600dhp2", "brcm,bcm47081", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm47081.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "buffalo,wzr-900dhp", "brcm,bcm47081", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "buffalo,wxr-1900dhp", "brcm,bcm4709", "brcm,bcm4708"; +--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +@@ -10,6 +10,7 @@ + /dts-v1/; + + #include "bcm4708.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" + + / { + compatible = "netgear,r8000", "brcm,bcm4709", "brcm,bcm4708"; +--- /dev/null ++++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi +@@ -0,0 +1,24 @@ ++/* ++ * Broadcom BCM470X / BCM5301X Nand chip defaults. ++ * ++ * This should be included if the NAND controller is on chip select 0 ++ * and uses 8 bit ECC. ++ * ++ * Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/ { ++ nand@18028000 { ++ nandcs@0 { ++ compatible = "brcm,nandcs"; ++ reg = <0>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ nand-ecc-strength = <8>; ++ nand-ecc-step-size = <512>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -143,4 +143,16 @@ + #gpio-cells = <2>; + }; + }; ++ ++ nand: nand@18028000 { ++ compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1", "brcm,brcmnand"; ++ reg = <0x18028000 0x600>, <0x1811a408 0x600>, <0x18028f00 0x20>; ++ reg-names = "nand", "iproc-idm", "iproc-ext"; ++ interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ brcm,nand-has-wp; ++ }; + }; diff --git a/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch b/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch new file mode 100644 index 0000000000..142211520e --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/065-ARM-BCM5301X-add-IRQ-numbers-for-PCIe-controller.patch @@ -0,0 +1,48 @@ +From 1f80de6863ca0e36cabc622e858168fe5beb1e92 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Sun, 24 May 2015 21:08:14 +0200 +Subject: [PATCH] ARM: BCM5301X: add IRQ numbers for PCIe controller + +The driver for the PCIe controller was just added, this adds the +missing definition of the IRQ numbers to device tree. The driver itself +will be automatically detected by bcma. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/bcm5301x.dtsi | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -108,6 +108,30 @@ + /* ChipCommon */ + <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, + ++ /* PCIe Controller 0 */ ++ <0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, ++ ++ /* PCIe Controller 1 */ ++ <0x00013000 0 &gic GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00013000 1 &gic GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00013000 2 &gic GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00013000 3 &gic GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00013000 4 &gic GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00013000 5 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, ++ ++ /* PCIe Controller 2 */ ++ <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, ++ <0x00014000 5 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, ++ + /* USB 2.0 Controller */ + <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, + diff --git a/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch b/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch new file mode 100644 index 0000000000..5790c9aaaf --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/066-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch @@ -0,0 +1,95 @@ +From 26343bdacfcdbf6ee3303d6078a015b908f90193 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sat, 16 May 2015 16:55:39 +0200 +Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC87U +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com> +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +--- + arch/arm/boot/dts/Makefile | 1 + + arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts | 65 +++++++++++++++++++++++++++++ + 2 files changed, 66 insertions(+) + create mode 100644 arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts + +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -66,6 +66,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm47081-asus-rt-n18u.dtb \ + bcm47081-buffalo-wzr-600dhp2.dtb \ + bcm47081-buffalo-wzr-900dhp.dtb \ ++ bcm4709-asus-rt-ac87u.dtb \ + bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-netgear-r8000.dtb + dtb-$(CONFIG_ARCH_BCM_63XX) += \ +--- /dev/null ++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +@@ -0,0 +1,65 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Asus RT-AC87U ++ * ++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4708.dtsi" ++ ++/ { ++ compatible = "asus,rt-ac87u", "brcm,bcm4709", "brcm,bcm4708"; ++ model = "Asus RT-AC87U"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000>; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ wps { ++ label = "bcm53xx:blue:wps"; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ ++ power { ++ label = "bcm53xx:blue:power"; ++ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-on"; ++ }; ++ ++ wan { ++ label = "bcm53xx:red:wan"; ++ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>; ++ linux,default-trigger = "default-off"; ++ }; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ wps { ++ label = "WPS"; ++ linux,code = <KEY_WPS_BUTTON>; ++ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; ++ }; ++ ++ restart { ++ label = "Reset"; ++ linux,code = <KEY_RESTART>; ++ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; diff --git a/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch b/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch new file mode 100644 index 0000000000..5e944b0513 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/110-firmware-backport-NVRAM-driver.patch @@ -0,0 +1,49 @@ +From 0509f6dcc46d10ea4bb8c70494dc7ae11bcb3f01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 10 Dec 2014 21:14:10 +0100 +Subject: [PATCH] firmware: backport NVRAM driver +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/Kconfig | 2 ++ + drivers/firmware/Kconfig | 1 + + drivers/firmware/Makefile | 1 + + drivers/net/ethernet/broadcom/b44.c | 2 +- + drivers/net/ethernet/broadcom/bgmac.c | 2 +- + drivers/ssb/driver_chipcommon_pmu.c | 2 +- + 6 files changed, 7 insertions(+), 3 deletions(-) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -2105,6 +2105,8 @@ source "drivers/Kconfig" + + source "drivers/firmware/Kconfig" + ++source "drivers/firmware/Kconfig" ++ + source "fs/Kconfig" + + source "arch/arm/Kconfig.debug" +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -136,6 +136,7 @@ config QCOM_SCM + bool + depends on ARM || ARM64 + ++source "drivers/firmware/broadcom/Kconfig" + source "drivers/firmware/google/Kconfig" + source "drivers/firmware/efi/Kconfig" + +--- a/drivers/firmware/Makefile ++++ b/drivers/firmware/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap. + obj-$(CONFIG_QCOM_SCM) += qcom_scm.o + CFLAGS_qcom_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) + ++obj-y += broadcom/ + obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ + obj-$(CONFIG_EFI) += efi/ + obj-$(CONFIG_UEFI_CPER) += efi/ diff --git a/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch b/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch new file mode 100644 index 0000000000..b914fd995f --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/112-bcm53xx-sprom-add-sprom-driver.patch @@ -0,0 +1,69 @@ +From 4e0ab3269a6d260a41a3673157753147f5f71341 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Sun, 4 May 2014 13:19:20 +0200 +Subject: [PATCH 03/17] bcm47xx-sprom: add Broadcom sprom parser driver + +This driver needs an nvram driver and fetches the sprom values from the +nvram and provides it to any other driver. The calibration data for the +wifi chip the mac address and some more board description data is +stores in the sprom. + +This is based on a copy of arch/mips/bcm47xx/sprom.c and my plan is to +make the bcm47xx MIPS SoCs also use this driver some time later. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + .../devicetree/bindings/misc/bcm47xx-sprom.txt | 16 + + drivers/misc/Kconfig | 11 + + drivers/misc/Makefile | 1 + + drivers/misc/bcm47xx-sprom.c | 690 +++++++++++++++++++++ + 4 files changed, 718 insertions(+) + create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt + create mode 100644 drivers/misc/bcm47xx-sprom.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt +@@ -0,0 +1,16 @@ ++Broadcom bcm47xx/bcm53xx sprom converter ++ ++This driver provbides an sprom based on a given nvram. ++ ++Required properties: ++ ++- compatible : brcm,bcm47xx-sprom ++ ++- nvram : reference to a nvram driver, e.g. bcm47xx-nvram ++ ++Example: ++ ++sprom0: sprom@0 { ++ compatible = "brcm,bcm47xx-sprom"; ++ nvram = <&nvram0>; ++}; +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -515,6 +515,17 @@ config VEXPRESS_SYSCFG + bus. System Configuration interface is one of the possible means + of generating transactions on this bus. + ++config BCM47XX_SPROM ++ tristate "BCM47XX sprom driver" ++ help ++ This driver parses the sprom from a given nvram which is found on ++ Broadcom bcm47xx and bcm53xx SoCs. ++ ++ The sprom contains board configuration data like the ++ calibration data fro the wifi chips, the mac addresses used ++ by the board and many other board configuration data. This ++ driver will provide the sprom to bcma. ++ + source "drivers/misc/c2port/Kconfig" + source "drivers/misc/eeprom/Kconfig" + source "drivers/misc/cb710/Kconfig" +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/ + obj-$(CONFIG_ECHO) += echo/ + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o + obj-$(CONFIG_CXL_BASE) += cxl/ ++obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx-sprom.o diff --git a/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch b/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch new file mode 100644 index 0000000000..bdc7dea9e1 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/131-ARM-BCM5301X-Implement-SMP-support.patch @@ -0,0 +1,314 @@ +From 707ab07695ea8953a5bb56512e7bb38ca79c5c38 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Thu, 19 Feb 2015 23:27:59 +0100 +Subject: [PATCH V2] ARM: BCM5301X: Implement SMP support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- +V2: Change code after receiving Florian's comments: + 1) Use "mmio-sram" + 2) Remove commented out ASM call + 3) Fix coding style in ASM + 4) Simplify finding OF node +--- + Documentation/devicetree/bindings/arm/bcm4708.txt | 24 ++++ + Documentation/devicetree/bindings/arm/cpus.txt | 1 + + arch/arm/boot/dts/bcm4708.dtsi | 13 ++ + arch/arm/mach-bcm/Makefile | 3 + + arch/arm/mach-bcm/bcm5301x_headsmp.S | 45 ++++++ + arch/arm/mach-bcm/bcm5301x_smp.c | 158 ++++++++++++++++++++++ + 6 files changed, 244 insertions(+) + create mode 100644 arch/arm/mach-bcm/bcm5301x_headsmp.S + create mode 100644 arch/arm/mach-bcm/bcm5301x_smp.c + +--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt ++++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.txt +@@ -6,3 +6,27 @@ Boards with the BCM4708 SoC shall have t + Required root node property: + + compatible = "brcm,bcm4708"; ++ ++Optional sub-node properties: ++ ++compatible = "mmio-sram" for SRAM access with IO memory region ++ This is needed for SMP-capable SoCs which use part of ++ SRAM for storing location of code to be executed by the ++ extra cores. ++ SMP support requires another sub-node with compatible ++ property "brcm,bcm4708-sysram". ++ ++Example: ++ ++ sysram@ffff0000 { ++ compatible = "mmio-sram"; ++ reg = <0xffff0000 0x10000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0xffff0000 0x10000>; ++ ++ smp-sysram@0 { ++ compatible = "brcm,bcm4708-sysram"; ++ reg = <0x0 0x1000>; ++ }; ++ }; +--- a/Documentation/devicetree/bindings/arm/cpus.txt ++++ b/Documentation/devicetree/bindings/arm/cpus.txt +@@ -189,6 +189,7 @@ nodes to be present and contain the prop + can be one of: + "allwinner,sun6i-a31" + "arm,psci" ++ "brcm,bcm4708-smp" + "brcm,brahma-b15" + "marvell,armada-375-smp" + "marvell,armada-380-smp" +--- a/arch/arm/boot/dts/bcm4708.dtsi ++++ b/arch/arm/boot/dts/bcm4708.dtsi +@@ -15,6 +15,7 @@ + cpus { + #address-cells = <1>; + #size-cells = <0>; ++ enable-method = "brcm,bcm4708-smp"; + + cpu@0 { + device_type = "cpu"; +@@ -31,4 +32,16 @@ + }; + }; + ++ sysram@ffff0000 { ++ compatible = "mmio-sram"; ++ reg = <0xffff0000 0x10000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0xffff0000 0x10000>; ++ ++ smp-sysram@0 { ++ compatible = "brcm,bcm4708-sysram"; ++ reg = <0x0 0x1000>; ++ }; ++ }; + }; +--- a/arch/arm/mach-bcm/Makefile ++++ b/arch/arm/mach-bcm/Makefile +@@ -36,6 +36,9 @@ obj-$(CONFIG_ARCH_BCM2835) += board_bcm2 + + # BCM5301X + obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o ++ifeq ($(CONFIG_SMP),y) ++obj-$(CONFIG_ARCH_BCM_5301X) += bcm5301x_smp.o bcm5301x_headsmp.o ++endif + + # BCM63XXx + obj-$(CONFIG_ARCH_BCM_63XX) := bcm63xx.o +--- /dev/null ++++ b/arch/arm/mach-bcm/bcm5301x_headsmp.S +@@ -0,0 +1,45 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * ++ * Copyright (c) 2003 ARM Limited ++ * All Rights Reserved ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++#include <linux/linkage.h> ++ ++/* ++ * BCM5301X specific entry point for secondary CPUs. ++ */ ++ENTRY(bcm5301x_secondary_startup) ++ mrc p15, 0, r0, c0, c0, 5 ++ and r0, r0, #15 ++ adr r4, 1f ++ ldmia r4, {r5, r6} ++ sub r4, r4, r5 ++ add r6, r6, r4 ++pen: ldr r7, [r6] ++ cmp r7, r0 ++ bne pen ++ ++ /* ++ * In case L1 cache has unpredictable contents at power-up ++ * clean its contents without flushing. ++ */ ++ bl v7_invalidate_l1 ++ ++ mov r0, #0 ++ mcr p15, 0, r0, c7, c5, 0 /* Invalidate icache */ ++ dsb ++ isb ++ ++ /* ++ * we've been released from the holding pen: secondary_stack ++ * should now contain the SVC stack for this core ++ */ ++ b secondary_startup ++ENDPROC(bcm5301x_secondary_startup) ++ ++ .align 2 ++1: .long . ++ .long pen_release +--- /dev/null ++++ b/arch/arm/mach-bcm/bcm5301x_smp.c +@@ -0,0 +1,158 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * ++ * Copyright (C) 2002 ARM Ltd. ++ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include <asm/cacheflush.h> ++#include <asm/delay.h> ++#include <asm/smp_plat.h> ++#include <asm/smp_scu.h> ++ ++#include <linux/clockchips.h> ++#include <linux/of.h> ++#include <linux/of_address.h> ++ ++#define SOC_ROM_LUT_OFF 0x400 ++ ++extern void bcm5301x_secondary_startup(void); ++ ++static void __cpuinit write_pen_release(int val) ++{ ++ pen_release = val; ++ smp_wmb(); ++ sync_cache_w(&pen_release); ++} ++ ++static DEFINE_SPINLOCK(boot_lock); ++ ++static void __init bcm5301x_smp_secondary_set_entry(void (*entry_point)(void)) ++{ ++ void __iomem *sysram_base_addr = NULL; ++ struct device_node *node; ++ ++ node = of_find_compatible_node(NULL, NULL, "brcm,bcm4708-sysram"); ++ if (!of_device_is_available(node)) ++ return; ++ ++ sysram_base_addr = of_iomap(node, 0); ++ if (!sysram_base_addr) { ++ pr_warn("Failed to map sysram\n"); ++ return; ++ } ++ ++ writel(virt_to_phys(entry_point), sysram_base_addr + SOC_ROM_LUT_OFF); ++ ++ dsb_sev(); /* Exit WFI */ ++ mb(); /* make sure write buffer is drained */ ++ ++ iounmap(sysram_base_addr); ++} ++ ++static void __init bcm5301x_smp_prepare_cpus(unsigned int max_cpus) ++{ ++ void __iomem *scu_base; ++ ++ if (!scu_a9_has_base()) { ++ pr_warn("Unknown SCU base\n"); ++ return; ++ } ++ ++ scu_base = ioremap((phys_addr_t)scu_a9_get_base(), SZ_256); ++ if (!scu_base) { ++ pr_err("Failed to remap SCU\n"); ++ return; ++ } ++ ++ /* Initialise the SCU */ ++ scu_enable(scu_base); ++ ++ /* Let CPUs know where to start */ ++ bcm5301x_smp_secondary_set_entry(bcm5301x_secondary_startup); ++ ++ iounmap(scu_base); ++} ++ ++static void __cpuinit bcm5301x_smp_secondary_init(unsigned int cpu) ++{ ++ trace_hardirqs_off(); ++ ++ /* ++ * let the primary processor know we're out of the ++ * pen, then head off into the C entry point ++ */ ++ write_pen_release(-1); ++ ++ /* ++ * Synchronise with the boot thread. ++ */ ++ spin_lock(&boot_lock); ++ spin_unlock(&boot_lock); ++} ++ ++static int __cpuinit bcm5301x_smp_boot_secondary(unsigned int cpu, ++ struct task_struct *idle) ++{ ++ unsigned long timeout; ++ ++ /* ++ * set synchronisation state between this boot processor ++ * and the secondary one ++ */ ++ spin_lock(&boot_lock); ++ ++ /* ++ * The secondary processor is waiting to be released from ++ * the holding pen - release it, then wait for it to flag ++ * that it has been released by resetting pen_release. ++ * ++ * Note that "pen_release" is the hardware CPU ID, whereas ++ * "cpu" is Linux's internal ID. ++ */ ++ write_pen_release(cpu_logical_map(cpu)); ++ ++ /* Send the secondary CPU SEV */ ++ dsb_sev(); ++ ++ udelay(100); ++ ++ /* ++ * Send the secondary CPU a soft interrupt, thereby causing ++ * the boot monitor to read the system wide flags register, ++ * and branch to the address found there. ++ */ ++ arch_send_wakeup_ipi_mask(cpumask_of(cpu)); ++ ++ /* ++ * Timeout set on purpose in jiffies so that on slow processors ++ * that must also have low HZ it will wait longer. ++ */ ++ timeout = jiffies + (HZ * 10); ++ while (time_before(jiffies, timeout)) { ++ smp_rmb(); ++ if (pen_release == -1) ++ break; ++ ++ udelay(10); ++ } ++ ++ /* ++ * now the secondary core is starting up let it run its ++ * calibrations, then wait for it to finish ++ */ ++ spin_unlock(&boot_lock); ++ ++ return pen_release != -1 ? -ENOSYS : 0; ++} ++ ++static struct smp_operations bcm5301x_smp_ops __initdata = { ++ .smp_prepare_cpus = bcm5301x_smp_prepare_cpus, ++ .smp_secondary_init = bcm5301x_smp_secondary_init, ++ .smp_boot_secondary = bcm5301x_smp_boot_secondary, ++}; ++ ++CPU_METHOD_OF_DECLARE(bcm5301x_smp, "brcm,bcm4708-smp", ++ &bcm5301x_smp_ops); diff --git a/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch new file mode 100644 index 0000000000..d4dedc0365 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch @@ -0,0 +1,534 @@ +From cf067bf8bb993d6cfdc42d750ae241c43f88403f Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Mon, 12 May 2014 11:55:20 +0200 +Subject: [PATCH 1/2] PCI: BCM5301X: add PCIe2 driver for BCM5301X SoCs + +This driver supports the PCIe controller found on the BCM4708 and +similar SoCs. The controller itself is automatically detected by bcma. + +This controller is found on SoCs usually used in SOHO routers to +connect the wifi cards to the SoC. All the of the BCM5301X SoCs I know +of have 2 or 3 of these controllers in the SoC. + +I had to use PCI domains otherwise the pci_create_root_bus() function +in drivers/pci/probe.c would fail for the second controller being +registered because pci_find_bus() would find the same PCIe bus again +and assume it is already registered, which ends up in a kernel panic in +pcibios_init_hw() in arch/arm/kernel/bios32.c + +The ARM PCI code assumes that every controller has an I/O space and +adds a dummy area if the driver does not specify one. This will work +for the first controller, but when we register the second one this will +result in an error. To prevent this problem we add an empty I/O space. + +Currently I have problems with probing the devices on the bus, because +pci_bus_add_devices() is called too early in pci_scan_root_bus() in +drivers/pci/probe.c, before pci_bus_assign_resources() was called in +pci_common_init_dev() in arch/arm/kernel/bios32.c. When the devices are +added too early they do not have any resources and adding fails. I have +to remove the call to pci_bus_add_devices() in pci_scan_root_bus() to +make registration work, calling pci_bus_add_devices() later again does +not fix this problem. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + arch/arm/mach-bcm/Kconfig | 1 + + drivers/pci/host/Kconfig | 7 + + drivers/pci/host/Makefile | 1 + + drivers/pci/host/pci-host-bcm5301x.c | 428 +++++++++++++++++++++++++++++++++++ + 4 files changed, 437 insertions(+) + create mode 100644 drivers/pci/host/pci-host-bcm5301x.c + +--- a/arch/arm/mach-bcm/Kconfig ++++ b/arch/arm/mach-bcm/Kconfig +@@ -38,6 +38,7 @@ config ARCH_BCM_CYGNUS + config ARCH_BCM_5301X + bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 + select ARCH_BCM_IPROC ++ select PCI_DOMAINS if PCI + help + Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. + +--- a/drivers/pci/host/Kconfig ++++ b/drivers/pci/host/Kconfig +@@ -125,4 +125,11 @@ config PCIE_IPROC_PLATFORM + Say Y here if you want to use the Broadcom iProc PCIe controller + through the generic platform bus interface + ++config PCI_BCM5301X ++ bool "BCM5301X PCIe2 host controller" ++ depends on BCMA && OF && ARM && PCI_DOMAINS ++ help ++ Say Y here if you want to support the PCIe host controller found ++ on Broadcom BCM5301X and BCM470X (Northstar) SoCs. ++ + endmenu +--- a/drivers/pci/host/Makefile ++++ b/drivers/pci/host/Makefile +@@ -15,3 +15,4 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-laye + obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o + obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o + obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o ++obj-$(CONFIG_PCI_BCM5301X) += pci-host-bcm5301x.o +--- /dev/null ++++ b/drivers/pci/host/pci-host-bcm5301x.c +@@ -0,0 +1,459 @@ ++/* ++ * Northstar PCI-Express driver ++ * Only supports Root-Complex (RC) mode ++ * ++ * Notes: ++ * PCI Domains are being used to identify the PCIe port 1:1. ++ * ++ * Only MEM access is supported, PAX does not support IO. ++ * ++ * Copyright 2012-2014, Broadcom Corporation ++ * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/pci.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/bcma/bcma.h> ++#include <linux/bcma/bcma_driver_pcie2.h> ++ ++#define SOC_PCIE_HDR_OFF 0x400 /* 256 bytes per function */ ++ ++#define PCI_LINK_STATUS_CTRL_2_OFFSET 0xDC ++#define PCI_TARGET_LINK_SPEED_MASK 0xF ++#define PCI_TARGET_LINK_SPEED_GEN2 0x2 ++#define PCI_TARGET_LINK_SPEED_GEN1 0x1 ++ ++static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) ++{ ++ struct pci_sys_data *sys = pdev->sysdata; ++ struct bcma_device *bdev = sys->private_data; ++ ++ return bcma_core_irq(bdev, 5); ++} ++ ++static u32 bcma_pcie2_cfg_base(struct bcma_device *bdev, int busno, ++ unsigned int devfn, int where) ++{ ++ int slot = PCI_SLOT(devfn); ++ int fn = PCI_FUNC(devfn); ++ u32 addr_reg; ++ ++ if (busno == 0) { ++ if (slot >= 1) ++ return 0; ++ bcma_write32(bdev, BCMA_CORE_PCIE2_CONFIGINDADDR, ++ where & 0xffc); ++ return BCMA_CORE_PCIE2_CONFIGINDDATA; ++ } ++ if (fn > 1) ++ return 0; ++ addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) | ++ (where & 0xffc) | (1 & 0x3); ++ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_CFG_ADDR, addr_reg); ++ return BCMA_CORE_PCIE2_CFG_DATA; ++} ++ ++static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno, ++ unsigned int devfn, int where, int size) ++{ ++ u32 base; ++ u32 data_reg; ++ u32 mask; ++ int shift; ++ ++ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); ++ ++ if (!base) ++ return ~0UL; ++ ++ data_reg = bcma_read32(bdev, base); ++ ++ if (size == 4) ++ return data_reg; ++ ++ mask = (1 << (size * 8)) - 1; ++ shift = (where % 4) * 8; ++ return (data_reg >> shift) & mask; ++} ++ ++static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno, ++ unsigned int devfn, int where, int size, ++ u32 val) ++{ ++ u32 base; ++ u32 data_reg; ++ ++ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); ++ ++ if (!base) ++ return; ++ ++ if (size < 4) { ++ u32 mask = (1 << (size * 8)) - 1; ++ int shift = (where % 4) * 8; ++ ++ data_reg = bcma_read32(bdev, base); ++ data_reg &= ~(mask << shift); ++ data_reg |= (val & mask) << shift; ++ } else { ++ data_reg = val; ++ } ++ ++ bcma_write32(bdev, base, data_reg); ++} ++ ++static int bcma_pcie2_read_config_pci(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *val) ++{ ++ struct pci_sys_data *sys = bus->sysdata; ++ struct bcma_device *bdev = sys->private_data; ++ ++ *val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int bcma_pcie2_write_config_pci(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 val) ++{ ++ struct pci_sys_data *sys = bus->sysdata; ++ struct bcma_device *bdev = sys->private_data; ++ ++ bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++/* ++ * Methods for accessing configuration registers ++ */ ++static struct pci_ops bcma_pcie2_ops = { ++ .read = bcma_pcie2_read_config_pci, ++ .write = bcma_pcie2_write_config_pci, ++}; ++ ++/* NS: CLASS field is R/O, and set to wrong 0x200 value */ ++static void bcma_pcie2_fixup_class(struct pci_dev *dev) ++{ ++ dev->class = PCI_CLASS_BRIDGE_PCI << 8; ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class); ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class); ++ ++/* ++ * Check link status, return 0 if link is up in RC mode, ++ * otherwise return non-zero ++ */ ++static int bcma_pcie2_check_link(struct bcma_device *bdev, struct pci_sys_data *sys) ++{ ++ u32 tmp32; ++ u16 tmp16; ++ u16 pos; ++ u8 nlw; ++ /* ++ * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before ++ * creating bus root, so we don't have it here yet. On the other hand ++ * we really want to use pci_bus_find_capability helper to check NLW. ++ * Let's fake simple pci_bus just to query for capabilities. ++ */ ++ struct pci_bus bus = { ++ .number = 0, ++ .ops = &bcma_pcie2_ops, ++ .sysdata = sys, ++ }; ++ ++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_LINK_STATUS); ++ dev_dbg(&bdev->dev, "link status: 0x%08x\n", tmp32); ++ ++ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_STRAP_STATUS); ++ dev_dbg(&bdev->dev, "strap status: 0x%08x\n", tmp32); ++ ++ /* check link status to see if link is active */ ++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP); ++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, &tmp16); ++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT; ++ ++ if (nlw == 0) { ++ /* try GEN 1 link speed */ ++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, ++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4); ++ if ((tmp32 & PCI_TARGET_LINK_SPEED_MASK) == ++ PCI_TARGET_LINK_SPEED_GEN2) { ++ tmp32 &= ~PCI_TARGET_LINK_SPEED_MASK; ++ tmp32 |= PCI_TARGET_LINK_SPEED_GEN1; ++ bcma_pcie2_write_config(bdev, 0, 0, ++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4, tmp32); ++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, ++ PCI_LINK_STATUS_CTRL_2_OFFSET, 4); ++ msleep(100); ++ ++ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP); ++ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, ++ &tmp16); ++ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> ++ PCI_EXP_LNKSTA_NLW_SHIFT; ++ } ++ } ++ ++ dev_info(&bdev->dev, "link: %s\n", nlw ? "UP" : "DOWN"); ++ return nlw ? 0 : -ENODEV; ++} ++ ++/* ++ * Initializte the PCIe controller ++ */ ++static void bcma_pcie2_hw_init(struct bcma_device *bdev) ++{ ++ u32 tmp32; ++ u16 tmp16; ++ ++ /* Change MPS and MRRS to 512 */ ++ tmp16 = bcma_pcie2_read_config(bdev, 0, 0, 0x4d4, 2); ++ tmp16 &= ~7; ++ tmp16 |= 2; ++ bcma_pcie2_write_config(bdev, 0, 0, 0x4d4, 2, tmp16); ++ ++ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, 0xb4, 4); ++ tmp32 &= ~((7 << 12) | (7 << 5)); ++ tmp32 |= (2 << 12) | (2 << 5); ++ bcma_pcie2_write_config(bdev, 0, 0, 0xb4, 4, tmp32); ++ ++ /* ++ * Turn-on Root-Complex (RC) mode, from reset default of EP ++ * The mode is set by straps, can be overwritten via DMU ++ * register <cru_straps_control> bit 5, "1" means RC ++ */ ++ ++ /* Send a downstream reset */ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL, ++ PCIE2_CLKC_RST_OE | PCIE2_CLKC_RST); ++ usleep_range(250, 400); ++ bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL, PCIE2_CLKC_RST_OE); ++ msleep(250); ++ ++ /* TBD: take care of PM, check we're on */ ++} ++ ++/* ++ * Setup the address translation ++ * ++ * NOTE: All PCI-to-CPU address mapping are 1:1 for simplicity ++ */ ++static int bcma_pcie2_map_init(struct bcma_device *bdev, u32 addr) ++{ ++ /* 64MB alignment */ ++ if (!addr || (addr & (SZ_64M - 1))) ++ return -EINVAL; ++ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP0_LOWER, addr); ++ bcma_write32(bdev, BCMA_CORE_PCIE2_OARR0, addr | 0x01); ++ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP1_LOWER, addr + SZ_64M); ++ bcma_write32(bdev, BCMA_CORE_PCIE2_OARR1, (addr + SZ_64M) | 0x01); ++ ++ /* ++ * Inbound address translation setup ++ * Northstar only maps up to 128 MiB inbound, DRAM could be up to 1 GiB. ++ * ++ * For now allow access to entire DRAM, assuming it is less than 128MiB, ++ * otherwise DMA bouncing mechanism may be required. ++ * Also consider DMA mask to limit DMA physical address ++ */ ++ /* 64-bit LE regs, write low word, high is 0 at reset */ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_FUNC0_IMAP1, PHYS_OFFSET | 0x1); ++ bcma_write32(bdev, BCMA_CORE_PCIE2_IARR1_LOWER, ++ PHYS_OFFSET | ((SZ_128M >> 20) & 0xff)); ++ return 0; ++} ++ ++/* ++ * Setup PCIE Host bridge ++ */ ++static int bcma_pcie2_bridge_init(struct bcma_device *bdev, u32 addr, u32 size) ++{ ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1, 0); ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1, 1); ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1, 4); ++ ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1); ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1); ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1); ++ ++ /* MEM_BASE, MEM_LIM require 1MB alignment */ ++ if (((addr >> 16) & 0xf) || (((addr + size) >> 16) & 0xf)) ++ return -EINVAL; ++ ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_BASE, 2, addr >> 16); ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2, ++ (addr + size) >> 16); ++ ++ /* These registers are not supported on the NS */ ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_BASE_UPPER16, 2, 0); ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_LIMIT_UPPER16, 2, 0); ++ ++ /* Force class to that of a Bridge */ ++ bcma_pcie2_write_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2, ++ PCI_CLASS_BRIDGE_PCI); ++ ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2); ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_BASE, 2); ++ bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2); ++ return 0; ++} ++ ++static void bcma_pcie2_3rd_init(struct bcma_bus *bus) ++{ ++ /* PCIE PLL block register (base 0x8000) */ ++ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x57fe8000); ++ /* Check PCIE PLL lock status */ ++ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x67c60000); ++} ++ ++/* To improve PCIE phy jitter */ ++static void bcma_pcie2_improve_phy_jitter(struct bcma_bus *bus, int phyaddr) ++{ ++ u32 val; ++ ++ /* Change blkaddr */ ++ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x1f << 18) | ++ (2 << 16) | (0x863 << 4); ++ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); ++ ++ /* Write 0x0190 to 0x13 regaddr */ ++ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x13 << 18) | ++ (2 << 16) | 0x0190; ++ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); ++ ++ /* Write 0x0191 to 0x19 regaddr */ ++ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x19 << 18) | ++ (2 << 16) | 0x0191; ++ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); ++} ++ ++static int bcma_pcie2_setup(int nr, struct pci_sys_data *sys) ++{ ++ struct bcma_device *bdev = sys->private_data; ++ struct bcma_bus *bus = bdev->bus; ++ struct resource *res; ++ struct bcma_device *arm_core; ++ u32 cru_straps_ctrl; ++ int ret; ++ int phyaddr; ++ ++ if (bdev->core_unit == 2) { ++ arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9); ++ cru_straps_ctrl = bcma_read32(arm_core, 0x2a0); ++ ++ /* 3rd PCIE is not selected */ ++ if (cru_straps_ctrl & 0x10) ++ return -ENODEV; ++ ++ bcma_pcie2_3rd_init(bus); ++ phyaddr = 0xf; ++ } else { ++ phyaddr = bdev->core_unit; ++ } ++ bcma_pcie2_improve_phy_jitter(bus, phyaddr); ++ ++ /* create mem resource */ ++ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); ++ if (!res) ++ return -EINVAL; ++ ++ res->start = bdev->addr_s[0]; ++ res->end = bdev->addr_s[0] + SZ_128M -1; ++ res->name = "PCIe dummy IO space"; ++ res->flags = IORESOURCE_MEM; ++ ++ pci_add_resource(&sys->resources, res); ++ ++ /* This PCIe controller does not support IO Mem, so use a dummy one. */ ++ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); ++ if (!res) ++ return -EINVAL; ++ ++ res->start = 0; ++ res->end = 0; ++ res->name = "PCIe dummy IO space"; ++ res->flags = IORESOURCE_IO; ++ ++ pci_add_resource(&sys->resources, res); ++ ++ bcma_pcie2_hw_init(bdev); ++ ret = bcma_pcie2_map_init(bdev, bdev->addr_s[0]); ++ if (ret) ++ return ret; ++ ++ /* ++ * Skip inactive ports - ++ * will need to change this for hot-plugging ++ */ ++ ret = bcma_pcie2_check_link(bdev, sys); ++ if (ret) ++ return ret; ++ ++ ret = bcma_pcie2_bridge_init(bdev, bdev->addr_s[0], SZ_128M); ++ if (ret) ++ return ret; ++ ++ return 1; ++} ++ ++static int bcma_pcie2_probe(struct bcma_device *bdev) ++{ ++ struct hw_pci hw = { ++ .nr_controllers = 1, ++ .private_data = (void **)&bdev, ++ .setup = bcma_pcie2_setup, ++ .map_irq = bcma_pcie2_map_irq, ++ .ops = &bcma_pcie2_ops, ++ }; ++ ++ dev_info(&bdev->dev, "initializing PCIe controller\n"); ++ ++ /* Announce this port to ARM/PCI common code */ ++ pci_common_init_dev(&bdev->dev, &hw); ++ ++ /* Setup virtual-wire interrupts */ ++ bcma_write32(bdev, BCMA_CORE_PCIE2_SYS_RC_INTX_EN, 0xf); ++ ++ /* Enable memory and bus master */ ++ bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6); ++ ++ return 0; ++} ++ ++static const struct bcma_device_id bcma_pcie2_table[] = { ++ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS), ++ {}, ++}; ++MODULE_DEVICE_TABLE(bcma, bcma_pcie2_table); ++ ++static struct bcma_driver bcma_pcie2_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = bcma_pcie2_table, ++ .probe = bcma_pcie2_probe, ++}; ++ ++static int __init bcma_pcie2_init(void) ++{ ++ return bcma_driver_register(&bcma_pcie2_driver); ++} ++module_init(bcma_pcie2_init); ++ ++static void __exit bcma_pcie2_exit(void) ++{ ++ bcma_driver_unregister(&bcma_pcie2_driver); ++} ++module_exit(bcma_pcie2_exit); ++ ++MODULE_AUTHOR("Hauke Mehrtens"); ++MODULE_DESCRIPTION("BCM5301X PCIe host controller"); ++MODULE_LICENSE("GPLv2"); diff --git a/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch b/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch new file mode 100644 index 0000000000..e5e3010356 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/180-USB-bcma-remove-chip-id-check.patch @@ -0,0 +1,34 @@ +From baf3d128e5bdf9d322539609133a15b493b0c2ef Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:35 +0200 +Subject: [PATCH] USB: bcma: remove chip id check + +I have never seen any bcma device with an USB host core which was not a +SoC, the bcma devices have an USB device core with a different core id. +Some SoC have IDs with 47XX and 53XX in decimal form which would be +rejected by this check. Instead of fixing this check just remove it. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -214,16 +214,11 @@ err_alloc: + static int bcma_hcd_probe(struct bcma_device *dev) + { + int err; +- u16 chipid_top; + u32 ohci_addr; + struct bcma_hcd_device *usb_dev; + struct bcma_chipinfo *chipinfo; + + chipinfo = &dev->bus->chipinfo; +- /* USBcores are only connected on embedded devices. */ +- chipid_top = (chipinfo->id & 0xFF00); +- if (chipid_top != 0x4700 && chipid_top != 0x5300) +- return -ENODEV; + + /* TODO: Probably need checks here; is the core connected? */ + diff --git a/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch b/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch new file mode 100644 index 0000000000..5ae4e0d7aa --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/181-USB-bcma-replace-numbers-with-constants.patch @@ -0,0 +1,24 @@ +From f5bc834917a8b1b9487749bdfe8eda52a01967b4 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:36 +0200 +Subject: [PATCH] USB: bcma: replace numbers with constants + +The constants for these numbers were added long time ago, use them. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -233,7 +233,8 @@ static int bcma_hcd_probe(struct bcma_de + + /* In AI chips EHCI is addrspace 0, OHCI is 1 */ + ohci_addr = dev->addr_s[0]; +- if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749) ++ if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 || ++ chipinfo->id == BCMA_CHIP_ID_BCM4749) + && chipinfo->rev == 0) + ohci_addr = 0x18009000; + diff --git a/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch b/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch new file mode 100644 index 0000000000..700d354332 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/182-USB-bcma-use-devm_kzalloc.patch @@ -0,0 +1,47 @@ +From 93724affb195149df6f7630901d878f6e273fa02 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:37 +0200 +Subject: [PATCH] USB: bcma: use devm_kzalloc + +Instead of manually handling the frees use devm. There was also a free +missing in the unregister call which is not needed with devm. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -225,7 +225,8 @@ static int bcma_hcd_probe(struct bcma_de + if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) + return -EOPNOTSUPP; + +- usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL); ++ usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), ++ GFP_KERNEL); + if (!usb_dev) + return -ENOMEM; + +@@ -239,10 +240,8 @@ static int bcma_hcd_probe(struct bcma_de + ohci_addr = 0x18009000; + + usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); +- if (IS_ERR(usb_dev->ohci_dev)) { +- err = PTR_ERR(usb_dev->ohci_dev); +- goto err_free_usb_dev; +- } ++ if (IS_ERR(usb_dev->ohci_dev)) ++ return PTR_ERR(usb_dev->ohci_dev); + + usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); + if (IS_ERR(usb_dev->ehci_dev)) { +@@ -255,8 +254,6 @@ static int bcma_hcd_probe(struct bcma_de + + err_unregister_ohci_dev: + platform_device_unregister(usb_dev->ohci_dev); +-err_free_usb_dev: +- kfree(usb_dev); + return err; + } + diff --git a/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch b/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch new file mode 100644 index 0000000000..91cd0fa320 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/183-USB-bcma-fix-error-handling-in-bcma_hcd_create_pdev.patch @@ -0,0 +1,33 @@ +From 232996d1ba3002e7e80b18075e2838fc86f21412 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:38 +0200 +Subject: [PATCH] USB: bcma: fix error handling in bcma_hcd_create_pdev() + +This patch makes bcma_hcd_create_pdev() not return NULL, but a prober +error code in case of an error. + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -169,7 +169,7 @@ static struct platform_device *bcma_hcd_ + { + struct platform_device *hci_dev; + struct resource hci_res[2]; +- int ret = -ENOMEM; ++ int ret; + + memset(hci_res, 0, sizeof(hci_res)); + +@@ -183,7 +183,7 @@ static struct platform_device *bcma_hcd_ + hci_dev = platform_device_alloc(ohci ? "ohci-platform" : + "ehci-platform" , 0); + if (!hci_dev) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + hci_dev->dev.parent = &dev->dev; + hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask; diff --git a/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch b/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch new file mode 100644 index 0000000000..bca555cf6a --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/184-USB-bcma-add-bcm53xx-support.patch @@ -0,0 +1,133 @@ +From b65851f41c22b8c69b8fe9ca7782d19ed2155efc Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:39 +0200 +Subject: [PATCH] USB: bcma: add bcm53xx support + +The Broadcom ARM SoCs with this usb core need a different +initialization and they have a different core id. This patch adds +support for these USB 2.0 core. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 81 +++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 78 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -2,7 +2,8 @@ + * Broadcom specific Advanced Microcontroller Bus + * Broadcom USB-core driver (BCMA bus glue) + * +- * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de> ++ * Copyright 2015 Felix Fietkau <nbd@openwrt.org> + * + * Based on ssb-ohci driver + * Copyright 2007 Michael Buesch <m@bues.ch> +@@ -88,7 +89,7 @@ static void bcma_hcd_4716wa(struct bcma_ + } + + /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ +-static void bcma_hcd_init_chip(struct bcma_device *dev) ++static void bcma_hcd_init_chip_mips(struct bcma_device *dev) + { + u32 tmp; + +@@ -159,6 +160,70 @@ static void bcma_hcd_init_chip(struct bc + } + } + ++static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev) ++{ ++ struct bcma_device *arm_core; ++ void __iomem *dmu; ++ ++ arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9); ++ if (!arm_core) { ++ dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n"); ++ return; ++ } ++ ++ dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); ++ if (!dmu) { ++ dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n"); ++ return; ++ } ++ ++ /* Unlock DMU PLL settings */ ++ iowrite32(0x0000ea68, dmu + 0x180); ++ ++ /* Write USB 2.0 PLL control setting */ ++ iowrite32(0x00dd10c3, dmu + 0x164); ++ ++ /* Lock DMU PLL settings */ ++ iowrite32(0x00000000, dmu + 0x180); ++ ++ iounmap(dmu); ++} ++ ++static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev) ++{ ++ u32 val; ++ ++ /* ++ * Delay after PHY initialized to ensure HC is ready to be configured ++ */ ++ usleep_range(1000, 2000); ++ ++ /* Set packet buffer OUT threshold */ ++ val = bcma_read32(dev, 0x94); ++ val &= 0xffff; ++ val |= 0x80 << 16; ++ bcma_write32(dev, 0x94, val); ++ ++ /* Enable break memory transfer */ ++ val = bcma_read32(dev, 0x9c); ++ val |= 1; ++ bcma_write32(dev, 0x9c, val); ++} ++ ++static void bcma_hcd_init_chip_arm(struct bcma_device *dev) ++{ ++ bcma_core_enable(dev, 0); ++ ++ if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 || ++ dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) { ++ if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 || ++ dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708) ++ bcma_hcd_init_chip_arm_phy(dev); ++ ++ bcma_hcd_init_chip_arm_hc(dev); ++ } ++} ++ + static const struct usb_ehci_pdata ehci_pdata = { + }; + +@@ -230,7 +295,16 @@ static int bcma_hcd_probe(struct bcma_de + if (!usb_dev) + return -ENOMEM; + +- bcma_hcd_init_chip(dev); ++ switch (dev->id.id) { ++ case BCMA_CORE_NS_USB20: ++ bcma_hcd_init_chip_arm(dev); ++ break; ++ case BCMA_CORE_USB20_HOST: ++ bcma_hcd_init_chip_mips(dev); ++ break; ++ default: ++ return -ENODEV; ++ } + + /* In AI chips EHCI is addrspace 0, OHCI is 1 */ + ohci_addr = dev->addr_s[0]; +@@ -299,6 +373,7 @@ static int bcma_hcd_resume(struct bcma_d + + static const struct bcma_device_id bcma_hcd_table[] = { + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), ++ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), + {}, + }; + MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); diff --git a/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch b/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch new file mode 100644 index 0000000000..d9a8a1e621 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/185-USB-bcma-add-support-for-controlling-bus-power-throu.patch @@ -0,0 +1,82 @@ +From f3cf44a313b3687efd55ba091558e20a4d218c31 Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Thu, 11 Jun 2015 22:57:40 +0200 +Subject: [PATCH] USB: bcma: add support for controlling bus power through GPIO + +On some boards a GPIO is needed to activate USB controller. Make it +possible to specify such a GPIO in device tree. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + drivers/usb/host/bcma-hcd.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -24,6 +24,8 @@ + #include <linux/platform_device.h> + #include <linux/module.h> + #include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/of_gpio.h> + #include <linux/usb/ehci_pdriver.h> + #include <linux/usb/ohci_pdriver.h> + +@@ -224,6 +226,23 @@ static void bcma_hcd_init_chip_arm(struc + } + } + ++static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) ++{ ++ int gpio; ++ ++ gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0); ++ if (!gpio_is_valid(gpio)) ++ return; ++ ++ if (val) { ++ gpio_request(gpio, "bcma-hcd-gpio"); ++ gpio_set_value(gpio, 1); ++ } else { ++ gpio_set_value(gpio, 0); ++ gpio_free(gpio); ++ } ++} ++ + static const struct usb_ehci_pdata ehci_pdata = { + }; + +@@ -295,6 +314,8 @@ static int bcma_hcd_probe(struct bcma_de + if (!usb_dev) + return -ENOMEM; + ++ bcma_hci_platform_power_gpio(dev, true); ++ + switch (dev->id.id) { + case BCMA_CORE_NS_USB20: + bcma_hcd_init_chip_arm(dev); +@@ -347,6 +368,7 @@ static void bcma_hcd_remove(struct bcma_ + + static void bcma_hcd_shutdown(struct bcma_device *dev) + { ++ bcma_hci_platform_power_gpio(dev, false); + bcma_core_disable(dev, 0); + } + +@@ -354,6 +376,7 @@ static void bcma_hcd_shutdown(struct bcm + + static int bcma_hcd_suspend(struct bcma_device *dev) + { ++ bcma_hci_platform_power_gpio(dev, false); + bcma_core_disable(dev, 0); + + return 0; +@@ -361,6 +384,7 @@ static int bcma_hcd_suspend(struct bcma_ + + static int bcma_hcd_resume(struct bcma_device *dev) + { ++ bcma_hci_platform_power_gpio(dev, true); + bcma_core_enable(dev, 0); + + return 0; diff --git a/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch b/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch new file mode 100644 index 0000000000..bc5757fb11 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch @@ -0,0 +1,195 @@ +From 26023cdfacaf116545b1087b9d1fe50dc6fbda10 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 24 Sep 2014 22:14:07 +0200 +Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache for decompression +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without this fix kernel was randomly hanging in ~25% of tries during +early init. Hangs used to happen at random places in the start_kernel. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/compressed/Makefile | 5 + + arch/arm/boot/compressed/head-bcm_5301x-mpcore.S | 37 +++++++ + arch/arm/boot/compressed/mpcore_cache.S | 118 +++++++++++++++++++++++ + 3 files changed, 160 insertions(+) + create mode 100644 arch/arm/boot/compressed/head-bcm_5301x-mpcore.S + create mode 100644 arch/arm/boot/compressed/mpcore_cache.S + +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -31,6 +31,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y) + OBJS += ll_char_wr.o font.o + endif + ++ifeq ($(CONFIG_ARCH_BCM_5301X),y) ++OBJS += head-bcm_5301x-mpcore.o ++OBJS += mpcore_cache.o ++endif ++ + ifeq ($(CONFIG_ARCH_SA1100),y) + OBJS += head-sa1100.o + endif +--- /dev/null ++++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S +@@ -0,0 +1,37 @@ ++/* ++ * ++ * Platform specific tweaks. This is merged into head.S by the linker. ++ * ++ */ ++ ++#include <linux/linkage.h> ++#include <asm/assembler.h> ++#include <asm/cp15.h> ++ ++ .section ".start", "ax" ++ ++/* ++ * This code section is spliced into the head code by the linker ++ */ ++ ++__plat_uncompress_start: ++ ++ @ Preserve r8/r7 i.e. kernel entry values ++ mov r12, r8 ++ ++ @ Clear MMU enable and Dcache enable bits ++ mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR ++ bic r0, #CR_C|CR_M ++ mcr p15, 0, r0, c1, c0, 0 @ Write SCTLR ++ nop ++ ++ @ Call the cache invalidation routine ++ bl v7_all_dcache_invalidate ++ nop ++ mov r0,#0 ++ ldr r3, =0x19022000 @ L2 cache controller, control reg ++ str r0, [r3, #0x100] @ Disable L2 cache ++ nop ++ ++ @ Restore ++ mov r8, r12 +--- /dev/null ++++ b/arch/arm/boot/compressed/mpcore_cache.S +@@ -0,0 +1,118 @@ ++/***************************************************************************** ++* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include <linux/linkage.h> ++#include <linux/init.h> ++ ++ __INIT ++ ++/* ++ * v7_l1_cache_invalidate ++ * ++ * Invalidate contents of L1 cache without flushing its contents ++ * into outer cache and memory. This is needed when the contents ++ * of the cache are unpredictable after power-up. ++ * ++ * corrupts r0-r6 ++ */ ++ ++ENTRY(v7_l1_cache_invalidate) ++ mov r0, #0 ++ mcr p15, 2, r0, c0, c0, 0 @ set cache level to 1 ++ mrc p15, 1, r0, c0, c0, 0 @ read CLIDR ++ ++ ldr r1, =0x7fff ++ and r2, r1, r0, lsr #13 @ get max # of index size ++ ++ ldr r1, =0x3ff ++ and r3, r1, r0, lsr #3 @ NumWays - 1 ++ add r2, r2, #1 @ NumSets ++ ++ and r0, r0, #0x7 ++ add r0, r0, #4 @ SetShift ++ ++ clz r1, r3 @ WayShift ++ add r4, r3, #1 @ NumWays ++1: sub r2, r2, #1 @ NumSets-- ++ mov r3, r4 @ Temp = NumWays ++2: subs r3, r3, #1 @ Temp-- ++ mov r5, r3, lsl r1 ++ mov r6, r2, lsl r0 ++ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) ++ mcr p15, 0, r5, c7, c6, 2 @ Invalidate line ++ bgt 2b ++ cmp r2, #0 ++ bgt 1b ++ dsb ++ mov r0,#0 ++ mcr p15,0,r0,c7,c5,0 /* Invalidate icache */ ++ isb ++ mov pc, lr ++ENDPROC(v7_l1_cache_invalidate) ++ ++/* ++ * v7_all_dcache_invalidate ++ * ++ * Invalidate without flushing the contents of all cache levels ++ * accesible by the current processor core. ++ * This is useful when the contents of cache memory are undetermined ++ * at power-up. ++ * Corrupted registers: r0-r7, r9-r11 ++ * ++ * Based on cache-v7.S: v7_flush_dcache_all() ++ */ ++ ++ENTRY(v7_all_dcache_invalidate) ++ mrc p15, 1, r0, c0, c0, 1 @ read clidr ++ ands r3, r0, #0x7000000 @ extract loc from clidr ++ mov r3, r3, lsr #23 @ left align loc bit field ++ beq finished @ if loc is 0, then no need to clean ++ mov r10, #0 @ start clean at cache level 0 ++loop1: ++ add r2, r10, r10, lsr #1 @ work out 3x current cache level ++ mov r1, r0, lsr r2 @ extract cache type bits from clidr ++ and r1, r1, #7 @ mask of bits for current cache only ++ cmp r1, #2 @ see what cache we have at this level ++ blt skip @ skip if no cache, or just i-cache ++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr ++ isb @ isb to sych the new cssr&csidr ++ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr ++ and r2, r1, #7 @ extract the length of the cache lines ++ add r2, r2, #4 @ add 4 (line length offset) ++ ldr r4, =0x3ff ++ ands r4, r4, r1, lsr #3 @ find maximum number on the way size ++ clz r5, r4 @ find bit pos of way size increment ++ ldr r7, =0x7fff ++ ands r7, r7, r1, lsr #13 @ extract max number of the index size ++loop2: ++ mov r9, r4 @ create working copy of max way size ++loop3: ++ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 ++ orr r11, r11, r7, lsl r2 @ factor index number into r11 ++ mcr p15, 0, r11, c7, c6, 2 @ Invalidate line ++ subs r9, r9, #1 @ decrement the way ++ bge loop3 ++ subs r7, r7, #1 @ decrement the index ++ bge loop2 ++skip: ++ add r10, r10, #2 @ increment cache number ++ cmp r3, r10 ++ bgt loop1 ++finished: ++ mov r10, #0 @ swith back to cache level 0 ++ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr ++ dsb ++ isb ++ mov pc, lr ++ENDPROC(v7_all_dcache_invalidate) diff --git a/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch b/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch new file mode 100644 index 0000000000..ca6462e3c7 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/301-ARM-BCM5301X-Add-SPROM.patch @@ -0,0 +1,26 @@ +From d404e0b22356078a51719fa911f6e09cb1a72d80 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 7 Jun 2015 16:18:18 +0200 +Subject: [PATCH] ARM: BCM5301X: Add SPROM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm5301x.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -95,6 +95,10 @@ + }; + }; + ++ sprom0: sprom@0 { ++ compatible = "brcm,bcm47xx-sprom"; ++ }; ++ + axi@18000000 { + compatible = "brcm,bus-axi"; + reg = <0x18000000 0x1000>; diff --git a/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch b/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch new file mode 100644 index 0000000000..9b562ce1a9 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch @@ -0,0 +1,148 @@ +From eb1075cc48d3c315c7403822c33da9588ab76492 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 14 Jan 2015 08:33:25 +0100 +Subject: [PATCH] ARM: BCM5310X: Enable earlyprintk on tested devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 2 +- + arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 2 +- + arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 2 +- + arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 2 +- + 4 files changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -17,7 +17,7 @@ + model = "Buffalo WZR-1750DHP (BCM4708)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +@@ -17,7 +17,7 @@ + model = "Netgear R6250 V1 (BCM4708)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts ++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts +@@ -17,7 +17,7 @@ + model = "Asus RT-N18U (BCM47081)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +@@ -17,7 +17,7 @@ + model = "Buffalo WZR-600DHP2 (BCM47081)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -17,7 +17,7 @@ + model = "Buffalo WZR-900DHP (BCM47081)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +@@ -17,7 +17,7 @@ + model = "Netgear R8000 (BCM4709)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts +@@ -17,7 +17,7 @@ + model = "Asus RT-AC56U (BCM4708)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts +@@ -17,7 +17,7 @@ + model = "Asus RT-AC68U (BCM4708)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts ++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +@@ -17,7 +17,7 @@ + model = "Luxul XWC-1000 (BCM4708)"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -17,7 +17,7 @@ + model = "Buffalo WXR-1900DHP"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts ++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +@@ -17,7 +17,7 @@ + model = "SmartRG SR400ac"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { +--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +@@ -16,7 +16,7 @@ + model = "Asus RT-AC87U"; + + chosen { +- bootargs = "console=ttyS0,115200"; ++ bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { diff --git a/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch b/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch new file mode 100644 index 0000000000..a2bed2aeb7 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/305-ARM-BCM53XX-set-customized-AUXCTL.patch @@ -0,0 +1,30 @@ +From 4a658590f83c1e916ab63ed7fe6f0841924247db Mon Sep 17 00:00:00 2001 +From: Hauke Mehrtens <hauke@hauke-m.de> +Date: Fri, 3 Oct 2014 18:37:33 +0200 +Subject: [PATCH 2/2] ARM: BCM53XX: set customized AUXCTL + +This activated some more features in the l310 cache. + +This is based on some vendor code + +Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> +--- + arch/arm/mach-bcm/bcm_5301x.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/arm/mach-bcm/bcm_5301x.c ++++ b/arch/arm/mach-bcm/bcm_5301x.c +@@ -50,7 +50,12 @@ static const char __initconst *bcm5301x_ + }; + + DT_MACHINE_START(BCM5301X, "BCM5301X") +- .l2c_aux_val = 0, ++ .l2c_aux_val = L310_AUX_CTRL_CACHE_REPLACE_RR | ++ L310_AUX_CTRL_DATA_PREFETCH | ++ L310_AUX_CTRL_INSTR_PREFETCH | ++ L310_AUX_CTRL_EARLY_BRESP | ++ L2C_AUX_CTRL_SHARED_OVERRIDE | ++ L310_AUX_CTRL_FULL_LINE_ZERO, + .l2c_aux_mask = ~0, + .init_early = bcm5301x_init_early, + .dt_compat = bcm5301x_dt_compat, diff --git a/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch b/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch new file mode 100644 index 0000000000..6637a62adc --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch @@ -0,0 +1,161 @@ +From 36b2fbb3badf0e32b371e1f7579a95d4fe25c0e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 14 Jan 2015 09:13:58 +0100 +Subject: [PATCH] ARM: BCM5301X: Specify RAM on devices by including HIGHMEM +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 3 ++- + arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 3 ++- + arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 3 ++- + arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 3 ++- + arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 3 ++- + 5 files changed, 10 insertions(+), 5 deletions(-) + +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; + }; + + spi { +--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + chipcommonA { +--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts ++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + spi { +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + gpio-keys { +--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x18000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts ++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +@@ -21,7 +21,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { +--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +@@ -20,7 +20,8 @@ + }; + + memory { +- reg = <0x00000000 0x08000000>; ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; + }; + + leds { diff --git a/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch b/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch new file mode 100644 index 0000000000..f99460aa46 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/320-ARM-BCM5301X-Add-Buffalo-WXR-1900DHP-clock-and-USB-p.patch @@ -0,0 +1,41 @@ +From 504dba5b073a9009ae1e3f2fc53ea9c3aa10c38a Mon Sep 17 00:00:00 2001 +From: Felix Fietkau <nbd@openwrt.org> +Date: Wed, 13 May 2015 20:56:38 +0200 +Subject: [PATCH] ARM: BCM5301X: Add Buffalo WXR-1900DHP clock and USB power + control +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -25,6 +25,23 @@ + 0x88000000 0x18000000>; + }; + ++ clocks { ++ clk_periph: periph { ++ clock-frequency = <500000000>; ++ }; ++ }; ++ ++ axi@18000000 { ++ usb2@21000 { ++ reg = <0x00021000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + diff --git a/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch b/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch new file mode 100644 index 0000000000..7e5f018fd4 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/321-ARM-BCM5301X-Set-vcc-gpio-for-USB-controllers.patch @@ -0,0 +1,63 @@ +From f1ee1275f65e87e035260f4d09a0f0ba98c6854d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 21 Jun 2015 12:56:32 +0200 +Subject: [PATCH] ARM: BCM5301X: Set vcc-gpio for USB controllers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 20 ++++++++++++++++++++ + arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 11 +++++++++++ + 2 files changed, 31 insertions(+) + +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -25,6 +25,26 @@ + 0x88000000 0x18000000>; + }; + ++ axi@18000000 { ++ usb2@21000 { ++ reg = <0x00021000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ usb3@23000 { ++ reg = <0x00023000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 10 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ + spi { + compatible = "spi-gpio"; + num-chipselects = <1>; +--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts +@@ -35,6 +35,17 @@ + }; + }; + ++ axi@18000000 { ++ usb3@23000 { ++ reg = <0x00023000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + diff --git a/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch new file mode 100644 index 0000000000..f9ca7eb7c1 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/332-ARM-BCM5301X-Add-power-button-for-Buffalo-WZR-1750DHP.patch @@ -0,0 +1,20 @@ +From: Felix Fietkau <nbd@openwrt.org> +Subject: [PATCH] ARM: BCM5301X: Add power button for Buffalo WZR-1750DHP + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +--- +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -123,6 +123,12 @@ + #address-cells = <1>; + #size-cells = <0>; + ++ power { ++ label = "Power"; ++ linux,code = <KEY_POWER>; ++ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>; ++ }; ++ + restart { + label = "Reset"; + linux,code = <KEY_RESTART>; diff --git a/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch b/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch new file mode 100644 index 0000000000..291ec72f2c --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/340-ARM-BCM5301X-Add-profiling-support.patch @@ -0,0 +1,20 @@ +Subject: [PATCH] ARM: BCM5301X: Add profiling support + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +--- +--- a/arch/arm/boot/dts/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/bcm5301x.dtsi +@@ -82,6 +82,13 @@ + }; + }; + ++ pmu { ++ compatible = "arm,cortex-a9-pmu"; ++ interrupts = ++ <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, ++ <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>; ++ }; ++ + clocks { + #address-cells = <1>; + #size-cells = <0>; diff --git a/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch b/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch new file mode 100644 index 0000000000..87065de48a --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch @@ -0,0 +1,250 @@ +From 6c223da976a9225ba9fae8d6f891a8fffaae6092 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Fri, 5 Dec 2014 17:38:40 +0100 +Subject: [PATCH] ARM: BCM5301X: Enable ChipCommon UART (serial console) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 10 ++++++++++ + arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 10 ++++++++++ + arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 10 ++++++++++ + arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 10 ++++++++++ + 4 files changed, 40 insertions(+) + +--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x18000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + axi@18000000 { + usb2@21000 { + reg = <0x00021000 0x1000>; +--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts ++++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts ++++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + spi { + compatible = "spi-gpio"; + num-chipselects = <1>; +--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts ++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +@@ -23,6 +23,16 @@ + memory { + reg = <0x00000000 0x08000000>; + }; ++ ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; + + nand: nand@18028000 { + nandcs@0 { +--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; +--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts +@@ -46,6 +46,18 @@ + }; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ }; ++ + gpio-keys { + compatible = "gpio-keys"; + #address-cells = <1>; +--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts +@@ -25,6 +25,18 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts ++++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts +@@ -25,6 +25,18 @@ + 0x88000000 0x18000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ clock-frequency = <125000000>; ++ }; ++ }; ++ + clocks { + clk_periph: periph { + clock-frequency = <500000000>; +--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts ++++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts +@@ -25,6 +25,16 @@ + 0x88000000 0x08000000>; + }; + ++ chipcommonA { ++ uart0: serial@0300 { ++ status = "okay"; ++ }; ++ ++ uart1: serial@0400 { ++ status = "okay"; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + diff --git a/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch b/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch new file mode 100644 index 0000000000..df65e0d03d --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/352-ARM-BCM5301X-Add-back-Luxul-XWC-1000-NAND-flash-layo.patch @@ -0,0 +1,37 @@ +From b97e582cd05f6ba80bdb63d9f677a3395edc7ff1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 7 Jun 2015 15:37:43 +0200 +Subject: [PATCH] ARM: BCM5301X: Add back Luxul XWC-1000 NAND flash layout +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In OpenWrt we still use old NAND driver instead of "brcm,nandcs", so +we need to add this DT entry back. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts ++++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts +@@ -34,6 +34,18 @@ + }; + }; + ++ axi@18000000 { ++ nand@28000 { ++ reg = <0x00028000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ partition@0 { ++ label = "ubi"; ++ reg = <0x00000000 0x08000000>; ++ }; ++ }; ++ }; ++ + nand: nand@18028000 { + nandcs@0 { + partition@0 { diff --git a/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch b/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch new file mode 100644 index 0000000000..ccdb28b54d --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch @@ -0,0 +1,31 @@ +From d658c21d6697293a928434fd6ac19264b5a8948d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Fri, 30 Jan 2015 08:25:54 +0100 +Subject: [PATCH] mtd: bcm47xxpart: scan whole flash on ARCH_BCM_5301X +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/mtd/bcm47xxpart.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -120,9 +120,15 @@ static int bcm47xxpart_parse(struct mtd_ + /* Parse block by block looking for magics */ + for (offset = 0; offset <= master->size - blocksize; + offset += blocksize) { ++#ifndef CONFIG_ARCH_BCM_5301X ++ /* ++ * ARM routers may have partitions in higher memory. E.g. ++ * Netgear R8000 has board_data at 0x2600000. ++ */ + /* Nothing more in higher memory */ + if (offset >= 0x2000000) + break; ++#endif + + if (curr_part >= BCM47XXPART_MAX_PARTS) { + pr_warn("Reached maximum number of partitions, scanning stopped!\n"); diff --git a/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch b/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch new file mode 100644 index 0000000000..41ef3b300e --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch @@ -0,0 +1,19 @@ +--- a/drivers/mtd/spi-nor/Kconfig ++++ b/drivers/mtd/spi-nor/Kconfig +@@ -28,4 +28,10 @@ config SPI_FSL_QUADSPI + This enables support for the Quad SPI controller in master mode. + We only connect the NOR to this controller now. + ++config MTD_SPI_BCM53XXSPIFLASH ++ tristate "SPI-NOR flashes connected to the Broadcom ARM SoC" ++ depends on MTD_SPI_NOR ++ help ++ SPI driver for flashes used on Broadcom ARM SoCs. ++ + endif # MTD_SPI_NOR +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -1,2 +1,3 @@ + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o + obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o ++obj-$(CONFIG_MTD_SPI_BCM53XXSPIFLASH) += bcm53xxspiflash.o diff --git a/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch b/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch new file mode 100644 index 0000000000..07cde2114a --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/420-mtd-bcm5301x_nand.patch @@ -0,0 +1,1608 @@ +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -530,4 +530,10 @@ config MTD_NAND_HISI504 + help + Enables support for NAND controller on Hisilicon SoC Hip04. + ++config MTD_NAND_BCM ++ tristate "Support for NAND on some Broadcom SoC" ++ help ++ This driver is currently used for the NAND flash controller on the ++ Broadcom BCM5301X (NorthStar) SoCs. ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -52,5 +52,6 @@ obj-$(CONFIG_MTD_NAND_XWAY) += xway_nan + obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ + obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_nand.o + obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o ++obj-$(CONFIG_MTD_NAND_BCM) += bcm_nand.o + + nand-objs := nand_base.o nand_bbt.o nand_timings.o +--- /dev/null ++++ b/drivers/mtd/nand/bcm_nand.c +@@ -0,0 +1,1583 @@ ++/* ++ * Nortstar NAND controller driver ++ * ++ * (c) Broadcom, Inc. 2012 All Rights Reserved. ++ * Copyright 2014 Hauke Mehrtens <hauke@hauke-m.de> ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ * ++ * This module interfaces the NAND controller and hardware ECC capabilities ++ * tp the generic NAND chip support in the NAND library. ++ * ++ * Notes: ++ * This driver depends on generic NAND driver, but works at the ++ * page level for operations. ++ * ++ * When a page is written, the ECC calculated also protects the OOB ++ * bytes not taken by ECC, and so the OOB must be combined with any ++ * OOB data that preceded the page-write operation in order for the ++ * ECC to be calculated correctly. ++ * Also, when the page is erased, but OOB data is not, HW ECC will ++ * indicate an error, because it checks OOB too, which calls for some ++ * help from the software in this driver. ++ * ++ * TBD: ++ * Block locking/unlocking support, OTP support ++ */ ++ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/interrupt.h> ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/slab.h> ++#include <linux/bcma/bcma.h> ++#include <linux/of_irq.h> ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/partitions.h> ++ ++#define NANDC_MAX_CHIPS 2 /* Only 2 CSn supported in NorthStar */ ++ ++/* ++ * Driver private control structure ++ */ ++struct bcmnand_ctrl { ++ struct mtd_info mtd; ++ struct nand_chip nand; ++ struct bcma_device *core; ++ ++ struct completion op_completion; ++ ++ struct nand_ecclayout ecclayout; ++ int cmd_ret; /* saved error code */ ++ unsigned char oob_index; ++ unsigned char id_byte_index; ++ unsigned char chip_num; ++ unsigned char last_cmd; ++ unsigned char ecc_level; ++ unsigned char sector_size_shift; ++ unsigned char sec_per_page_shift; ++}; ++ ++ ++/* ++ * IRQ numbers - offset from first irq in nandc_irq resource ++ */ ++#define NANDC_IRQ_RD_MISS 0 ++#define NANDC_IRQ_ERASE_COMPLETE 1 ++#define NANDC_IRQ_COPYBACK_COMPLETE 2 ++#define NANDC_IRQ_PROGRAM_COMPLETE 3 ++#define NANDC_IRQ_CONTROLLER_RDY 4 ++#define NANDC_IRQ_RDBSY_RDY 5 ++#define NANDC_IRQ_ECC_UNCORRECTABLE 6 ++#define NANDC_IRQ_ECC_CORRECTABLE 7 ++#define NANDC_IRQ_NUM 8 ++ ++struct bcmnand_reg_field { ++ unsigned int reg; ++ unsigned int pos; ++ unsigned int width; ++}; ++ ++/* ++ * REGISTERS ++ * ++ * Individual bit-fields aof registers are specificed here ++ * for clarity, and the rest of the code will access each field ++ * as if it was its own register. ++ * ++ * Following registers are off <reg_base>: ++ */ ++#define REG_BIT_FIELD(r, p, w) ((struct bcmnand_reg_field){(r), (p), (w)}) ++ ++#define NANDC_8KB_PAGE_SUPPORT REG_BIT_FIELD(0x0, 31, 1) ++#define NANDC_REV_MAJOR REG_BIT_FIELD(0x0, 8, 8) ++#define NANDC_REV_MINOR REG_BIT_FIELD(0x0, 0, 8) ++ ++#define NANDC_CMD_START_OPCODE REG_BIT_FIELD(0x4, 24, 5) ++ ++#define NANDC_CMD_CS_SEL REG_BIT_FIELD(0x8, 16, 3) ++#define NANDC_CMD_EXT_ADDR REG_BIT_FIELD(0x8, 0, 16) ++ ++#define NANDC_CMD_ADDRESS REG_BIT_FIELD(0xc, 0, 32) ++#define NANDC_CMD_END_ADDRESS REG_BIT_FIELD(0x10, 0, 32) ++ ++#define NANDC_INT_STATUS REG_BIT_FIELD(0x14, 0, 32) ++#define NANDC_INT_STAT_CTLR_RDY REG_BIT_FIELD(0x14, 31, 1) ++#define NANDC_INT_STAT_FLASH_RDY REG_BIT_FIELD(0x14, 30, 1) ++#define NANDC_INT_STAT_CACHE_VALID REG_BIT_FIELD(0x14, 29, 1) ++#define NANDC_INT_STAT_SPARE_VALID REG_BIT_FIELD(0x14, 28, 1) ++#define NANDC_INT_STAT_ERASED REG_BIT_FIELD(0x14, 27, 1) ++#define NANDC_INT_STAT_PLANE_RDY REG_BIT_FIELD(0x14, 26, 1) ++#define NANDC_INT_STAT_FLASH_STATUS REG_BIT_FIELD(0x14, 0, 8) ++ ++#define NANDC_CS_LOCK REG_BIT_FIELD(0x18, 31, 1) ++#define NANDC_CS_AUTO_CONFIG REG_BIT_FIELD(0x18, 30, 1) ++#define NANDC_CS_NAND_WP REG_BIT_FIELD(0x18, 29, 1) ++#define NANDC_CS_BLK0_WP REG_BIT_FIELD(0x18, 28, 1) ++#define NANDC_CS_SW_USING_CS(n) REG_BIT_FIELD(0x18, 8+(n), 1) ++#define NANDC_CS_MAP_SEL_CS(n) REG_BIT_FIELD(0x18, 0+(n), 1) ++ ++#define NANDC_XOR_ADDR_BLK0_ONLY REG_BIT_FIELD(0x1c, 31, 1) ++#define NANDC_XOR_ADDR_CS(n) REG_BIT_FIELD(0x1c, 0+(n), 1) ++ ++#define NANDC_LL_OP_RET_IDLE REG_BIT_FIELD(0x20, 31, 1) ++#define NANDC_LL_OP_CLE REG_BIT_FIELD(0x20, 19, 1) ++#define NANDC_LL_OP_ALE REG_BIT_FIELD(0x20, 18, 1) ++#define NANDC_LL_OP_WE REG_BIT_FIELD(0x20, 17, 1) ++#define NANDC_LL_OP_RE REG_BIT_FIELD(0x20, 16, 1) ++#define NANDC_LL_OP_DATA REG_BIT_FIELD(0x20, 0, 16) ++ ++#define NANDC_MPLANE_ADDR_EXT REG_BIT_FIELD(0x24, 0, 16) ++#define NANDC_MPLANE_ADDR REG_BIT_FIELD(0x28, 0, 32) ++ ++#define NANDC_ACC_CTRL_CS(n) REG_BIT_FIELD(0x50+((n)<<4), 0, 32) ++#define NANDC_ACC_CTRL_RD_ECC(n) REG_BIT_FIELD(0x50+((n)<<4), 31, 1) ++#define NANDC_ACC_CTRL_WR_ECC(n) REG_BIT_FIELD(0x50+((n)<<4), 30, 1) ++#define NANDC_ACC_CTRL_CE_CARE(n) REG_BIT_FIELD(0x50+((n)<<4), 29, 1) ++#define NANDC_ACC_CTRL_PGM_RDIN(n) REG_BIT_FIELD(0x50+((n)<<4), 28, 1) ++#define NANDC_ACC_CTRL_ERA_ECC_ERR(n) REG_BIT_FIELD(0x50+((n)<<4), 27, 1) ++#define NANDC_ACC_CTRL_PGM_PARTIAL(n) REG_BIT_FIELD(0x50+((n)<<4), 26, 1) ++#define NANDC_ACC_CTRL_WR_PREEMPT(n) REG_BIT_FIELD(0x50+((n)<<4), 25, 1) ++#define NANDC_ACC_CTRL_PG_HIT(n) REG_BIT_FIELD(0x50+((n)<<4), 24, 1) ++#define NANDC_ACC_CTRL_PREFETCH(n) REG_BIT_FIELD(0x50+((n)<<4), 23, 1) ++#define NANDC_ACC_CTRL_CACHE_MODE(n) REG_BIT_FIELD(0x50+((n)<<4), 22, 1) ++#define NANDC_ACC_CTRL_CACHE_LASTPG(n) REG_BIT_FIELD(0x50+((n)<<4), 21, 1) ++#define NANDC_ACC_CTRL_ECC_LEVEL(n) REG_BIT_FIELD(0x50+((n)<<4), 16, 5) ++#define NANDC_ACC_CTRL_SECTOR_1K(n) REG_BIT_FIELD(0x50+((n)<<4), 7, 1) ++#define NANDC_ACC_CTRL_SPARE_SIZE(n) REG_BIT_FIELD(0x50+((n)<<4), 0, 7) ++ ++#define NANDC_CONFIG_CS(n) REG_BIT_FIELD(0x54+((n)<<4), 0, 32) ++#define NANDC_CONFIG_LOCK(n) REG_BIT_FIELD(0x54+((n)<<4), 31, 1) ++#define NANDC_CONFIG_BLK_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 28, 3) ++#define NANDC_CONFIG_CHIP_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 24, 4) ++#define NANDC_CONFIG_CHIP_WIDTH(n) REG_BIT_FIELD(0x54+((n)<<4), 23, 1) ++#define NANDC_CONFIG_PAGE_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 20, 2) ++#define NANDC_CONFIG_FUL_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 16, 3) ++#define NANDC_CONFIG_COL_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 12, 3) ++#define NANDC_CONFIG_BLK_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 8, 3) ++ ++#define NANDC_TIMING_1_CS(n) REG_BIT_FIELD(0x58+((n)<<4), 0, 32) ++#define NANDC_TIMING_2_CS(n) REG_BIT_FIELD(0x5c+((n)<<4), 0, 32) ++ /* Individual bits for Timing registers - TBD */ ++ ++#define NANDC_CORR_STAT_THRESH_CS(n) REG_BIT_FIELD(0xc0, 6*(n), 6) ++ ++#define NANDC_BLK_WP_END_ADDR REG_BIT_FIELD(0xc8, 0, 32) ++ ++#define NANDC_MPLANE_ERASE_CYC2_OPCODE REG_BIT_FIELD(0xcc, 24, 8) ++#define NANDC_MPLANE_READ_STAT_OPCODE REG_BIT_FIELD(0xcc, 16, 8) ++#define NANDC_MPLANE_PROG_ODD_OPCODE REG_BIT_FIELD(0xcc, 8, 8) ++#define NANDC_MPLANE_PROG_TRL_OPCODE REG_BIT_FIELD(0xcc, 0, 8) ++ ++#define NANDC_MPLANE_PGCACHE_TRL_OPCODE REG_BIT_FIELD(0xd0, 24, 8) ++#define NANDC_MPLANE_READ_STAT2_OPCODE REG_BIT_FIELD(0xd0, 16, 8) ++#define NANDC_MPLANE_READ_EVEN_OPCODE REG_BIT_FIELD(0xd0, 8, 8) ++#define NANDC_MPLANE_READ_ODD__OPCODE REG_BIT_FIELD(0xd0, 0, 8) ++ ++#define NANDC_MPLANE_CTRL_ERASE_CYC2_EN REG_BIT_FIELD(0xd4, 31, 1) ++#define NANDC_MPLANE_CTRL_RD_ADDR_SIZE REG_BIT_FIELD(0xd4, 30, 1) ++#define NANDC_MPLANE_CTRL_RD_CYC_ADDR REG_BIT_FIELD(0xd4, 29, 1) ++#define NANDC_MPLANE_CTRL_RD_COL_ADDR REG_BIT_FIELD(0xd4, 28, 1) ++ ++#define NANDC_UNCORR_ERR_COUNT REG_BIT_FIELD(0xfc, 0, 32) ++ ++#define NANDC_CORR_ERR_COUNT REG_BIT_FIELD(0x100, 0, 32) ++ ++#define NANDC_READ_CORR_BIT_COUNT REG_BIT_FIELD(0x104, 0, 32) ++ ++#define NANDC_BLOCK_LOCK_STATUS REG_BIT_FIELD(0x108, 0, 8) ++ ++#define NANDC_ECC_CORR_ADDR_CS REG_BIT_FIELD(0x10c, 16, 3) ++#define NANDC_ECC_CORR_ADDR_EXT REG_BIT_FIELD(0x10c, 0, 16) ++ ++#define NANDC_ECC_CORR_ADDR REG_BIT_FIELD(0x110, 0, 32) ++ ++#define NANDC_ECC_UNC_ADDR_CS REG_BIT_FIELD(0x114, 16, 3) ++#define NANDC_ECC_UNC_ADDR_EXT REG_BIT_FIELD(0x114, 0, 16) ++ ++#define NANDC_ECC_UNC_ADDR REG_BIT_FIELD(0x118, 0, 32) ++ ++#define NANDC_READ_ADDR_CS REG_BIT_FIELD(0x11c, 16, 3) ++#define NANDC_READ_ADDR_EXT REG_BIT_FIELD(0x11c, 0, 16) ++#define NANDC_READ_ADDR REG_BIT_FIELD(0x120, 0, 32) ++ ++#define NANDC_PROG_ADDR_CS REG_BIT_FIELD(0x124, 16, 3) ++#define NANDC_PROG_ADDR_EXT REG_BIT_FIELD(0x124, 0, 16) ++#define NANDC_PROG_ADDR REG_BIT_FIELD(0x128, 0, 32) ++ ++#define NANDC_CPYBK_ADDR_CS REG_BIT_FIELD(0x12c, 16, 3) ++#define NANDC_CPYBK_ADDR_EXT REG_BIT_FIELD(0x12c, 0, 16) ++#define NANDC_CPYBK_ADDR REG_BIT_FIELD(0x130, 0, 32) ++ ++#define NANDC_ERASE_ADDR_CS REG_BIT_FIELD(0x134, 16, 3) ++#define NANDC_ERASE_ADDR_EXT REG_BIT_FIELD(0x134, 0, 16) ++#define NANDC_ERASE_ADDR REG_BIT_FIELD(0x138, 0, 32) ++ ++#define NANDC_INV_READ_ADDR_CS REG_BIT_FIELD(0x13c, 16, 3) ++#define NANDC_INV_READ_ADDR_EXT REG_BIT_FIELD(0x13c, 0, 16) ++#define NANDC_INV_READ_ADDR REG_BIT_FIELD(0x140, 0, 32) ++ ++#define NANDC_INIT_STAT REG_BIT_FIELD(0x144, 0, 32) ++#define NANDC_INIT_ONFI_DONE REG_BIT_FIELD(0x144, 31, 1) ++#define NANDC_INIT_DEVID_DONE REG_BIT_FIELD(0x144, 30, 1) ++#define NANDC_INIT_SUCCESS REG_BIT_FIELD(0x144, 29, 1) ++#define NANDC_INIT_FAIL REG_BIT_FIELD(0x144, 28, 1) ++#define NANDC_INIT_BLANK REG_BIT_FIELD(0x144, 27, 1) ++#define NANDC_INIT_TIMEOUT REG_BIT_FIELD(0x144, 26, 1) ++#define NANDC_INIT_UNC_ERROR REG_BIT_FIELD(0x144, 25, 1) ++#define NANDC_INIT_CORR_ERROR REG_BIT_FIELD(0x144, 24, 1) ++#define NANDC_INIT_PARAM_RDY REG_BIT_FIELD(0x144, 23, 1) ++#define NANDC_INIT_AUTH_FAIL REG_BIT_FIELD(0x144, 22, 1) ++ ++#define NANDC_ONFI_STAT REG_BIT_FIELD(0x148, 0, 32) ++#define NANDC_ONFI_DEBUG REG_BIT_FIELD(0x148, 28, 4) ++#define NANDC_ONFI_PRESENT REG_BIT_FIELD(0x148, 27, 1) ++#define NANDC_ONFI_BADID_PG2 REG_BIT_FIELD(0x148, 5, 1) ++#define NANDC_ONFI_BADID_PG1 REG_BIT_FIELD(0x148, 4, 1) ++#define NANDC_ONFI_BADID_PG0 REG_BIT_FIELD(0x148, 3, 1) ++#define NANDC_ONFI_BADCRC_PG2 REG_BIT_FIELD(0x148, 2, 1) ++#define NANDC_ONFI_BADCRC_PG1 REG_BIT_FIELD(0x148, 1, 1) ++#define NANDC_ONFI_BADCRC_PG0 REG_BIT_FIELD(0x148, 0, 1) ++ ++#define NANDC_ONFI_DEBUG_DATA REG_BIT_FIELD(0x14c, 0, 32) ++ ++#define NANDC_SEMAPHORE REG_BIT_FIELD(0x150, 0, 8) ++ ++#define NANDC_DEVID_BYTE(b) REG_BIT_FIELD(0x194+((b)&0x4), \ ++ 24-(((b)&3)<<3), 8) ++ ++#define NANDC_LL_RDDATA REG_BIT_FIELD(0x19c, 0, 16) ++ ++#define NANDC_INT_N_REG(n) REG_BIT_FIELD(0xf00|((n)<<2), 0, 1) ++#define NANDC_INT_DIREC_READ_MISS REG_BIT_FIELD(0xf00, 0, 1) ++#define NANDC_INT_ERASE_DONE REG_BIT_FIELD(0xf04, 0, 1) ++#define NANDC_INT_CPYBK_DONE REG_BIT_FIELD(0xf08, 0, 1) ++#define NANDC_INT_PROGRAM_DONE REG_BIT_FIELD(0xf0c, 0, 1) ++#define NANDC_INT_CONTROLLER_RDY REG_BIT_FIELD(0xf10, 0, 1) ++#define NANDC_INT_RDBSY_RDY REG_BIT_FIELD(0xf14, 0, 1) ++#define NANDC_INT_ECC_UNCORRECTABLE REG_BIT_FIELD(0xf18, 0, 1) ++#define NANDC_INT_ECC_CORRECTABLE REG_BIT_FIELD(0xf1c, 0, 1) ++ ++/* ++ * Following registers are treated as contigous IO memory, offset is from ++ * <reg_base>, and the data is in big-endian byte order ++ */ ++#define NANDC_SPARE_AREA_READ_OFF 0x200 ++#define NANDC_SPARE_AREA_WRITE_OFF 0x280 ++#define NANDC_CACHE_OFF 0x400 ++#define NANDC_CACHE_SIZE (128*4) ++ ++struct bcmnand_areg_field { ++ unsigned int reg; ++ unsigned int pos; ++ unsigned int width; ++}; ++ ++/* ++ * Following are IDM (a.k.a. Slave Wrapper) registers are off <idm_base>: ++ */ ++#define IDMREG_BIT_FIELD(r, p, w) ((struct bcmnand_areg_field){(r), (p), (w)}) ++ ++#define NANDC_IDM_AXI_BIG_ENDIAN IDMREG_BIT_FIELD(0x408, 28, 1) ++#define NANDC_IDM_APB_LITTLE_ENDIAN IDMREG_BIT_FIELD(0x408, 24, 1) ++#define NANDC_IDM_TM IDMREG_BIT_FIELD(0x408, 16, 5) ++#define NANDC_IDM_IRQ_CORRECABLE_EN IDMREG_BIT_FIELD(0x408, 9, 1) ++#define NANDC_IDM_IRQ_UNCORRECABLE_EN IDMREG_BIT_FIELD(0x408, 8, 1) ++#define NANDC_IDM_IRQ_RDYBSY_RDY_EN IDMREG_BIT_FIELD(0x408, 7, 1) ++#define NANDC_IDM_IRQ_CONTROLLER_RDY_EN IDMREG_BIT_FIELD(0x408, 6, 1) ++#define NANDC_IDM_IRQ_PRPOGRAM_COMP_EN IDMREG_BIT_FIELD(0x408, 5, 1) ++#define NANDC_IDM_IRQ_COPYBK_COMP_EN IDMREG_BIT_FIELD(0x408, 4, 1) ++#define NANDC_IDM_IRQ_ERASE_COMP_EN IDMREG_BIT_FIELD(0x408, 3, 1) ++#define NANDC_IDM_IRQ_READ_MISS_EN IDMREG_BIT_FIELD(0x408, 2, 1) ++#define NANDC_IDM_IRQ_N_EN(n) IDMREG_BIT_FIELD(0x408, 2+(n), 1) ++ ++#define NANDC_IDM_CLOCK_EN IDMREG_BIT_FIELD(0x408, 0, 1) ++ ++#define NANDC_IDM_IO_ECC_CORR IDMREG_BIT_FIELD(0x500, 3, 1) ++#define NANDC_IDM_IO_ECC_UNCORR IDMREG_BIT_FIELD(0x500, 2, 1) ++#define NANDC_IDM_IO_RDYBSY IDMREG_BIT_FIELD(0x500, 1, 1) ++#define NANDC_IDM_IO_CTRL_RDY IDMREG_BIT_FIELD(0x500, 0, 1) ++ ++#define NANDC_IDM_RESET IDMREG_BIT_FIELD(0x800, 0, 1) ++ /* Remaining IDM registers do not seem to be useful, skipped */ ++ ++/* ++ * NAND Controller has its own command opcodes ++ * different from opcodes sent to the actual flash chip ++ */ ++#define NANDC_CMD_OPCODE_NULL 0 ++#define NANDC_CMD_OPCODE_PAGE_READ 1 ++#define NANDC_CMD_OPCODE_SPARE_READ 2 ++#define NANDC_CMD_OPCODE_STATUS_READ 3 ++#define NANDC_CMD_OPCODE_PAGE_PROG 4 ++#define NANDC_CMD_OPCODE_SPARE_PROG 5 ++#define NANDC_CMD_OPCODE_DEVID_READ 7 ++#define NANDC_CMD_OPCODE_BLOCK_ERASE 8 ++#define NANDC_CMD_OPCODE_FLASH_RESET 9 ++ ++/* ++ * NAND Controller hardware ECC data size ++ * ++ * The following table contains the number of bytes needed for ++ * each of the ECC levels, per "sector", which is either 512 or 1024 bytes. ++ * The actual layout is as follows: ++ * The entire spare area is equally divided into as many sections as there ++ * are sectors per page, and the ECC data is located at the end of each ++ * of these sections. ++ * For example, given a 2K per page and 64 bytes spare device, configured for ++ * sector size 1k and ECC level of 4, the spare area will be divided into 2 ++ * sections 32 bytes each, and the last 14 bytes of 32 in each section will ++ * be filled with ECC data. ++ * Note: the name of the algorythm and the number of error bits it can correct ++ * is of no consequence to this driver, therefore omitted. ++ */ ++struct bcmnand_ecc_size_s { ++ unsigned char sector_size_shift; ++ unsigned char ecc_level; ++ unsigned char ecc_bytes_per_sec; ++ unsigned char reserved; ++}; ++ ++static const struct bcmnand_ecc_size_s bcmnand_ecc_sizes[] = { ++ { 9, 0, 0 }, ++ { 10, 0, 0 }, ++ { 9, 1, 2 }, ++ { 10, 1, 4 }, ++ { 9, 2, 4 }, ++ { 10, 2, 7 }, ++ { 9, 3, 6 }, ++ { 10, 3, 11 }, ++ { 9, 4, 7 }, ++ { 10, 4, 14 }, ++ { 9, 5, 9 }, ++ { 10, 5, 18 }, ++ { 9, 6, 11 }, ++ { 10, 6, 21 }, ++ { 9, 7, 13 }, ++ { 10, 7, 25 }, ++ { 9, 8, 14 }, ++ { 10, 8, 28 }, ++ ++ { 9, 9, 16 }, ++ { 9, 10, 18 }, ++ { 9, 11, 20 }, ++ { 9, 12, 21 }, ++ ++ { 10, 9, 32 }, ++ { 10, 10, 35 }, ++ { 10, 11, 39 }, ++ { 10, 12, 42 }, ++}; ++ ++/* ++ * Populate the various fields that depend on how ++ * the hardware ECC data is located in the spare area ++ * ++ * For this controiller, it is easier to fill-in these ++ * structures at run time. ++ * ++ * The bad-block marker is assumed to occupy one byte ++ * at chip->badblockpos, which must be in the first ++ * sector of the spare area, namely it is either ++ * at offset 0 or 5. ++ * Some chips use both for manufacturer's bad block ++ * markers, but we ingore that issue here, and assume only ++ * one byte is used as bad-block marker always. ++ */ ++static int bcmnand_hw_ecc_layout(struct bcmnand_ctrl *ctrl) ++{ ++ struct nand_ecclayout *layout; ++ struct device *dev = &ctrl->core->dev; ++ unsigned int i, j, k; ++ unsigned int ecc_per_sec, oob_per_sec; ++ unsigned int bbm_pos = ctrl->nand.badblockpos; ++ ++ /* Caclculate spare area per sector size */ ++ oob_per_sec = ctrl->mtd.oobsize >> ctrl->sec_per_page_shift; ++ ++ /* Try to calculate the amount of ECC bytes per sector with a formula */ ++ if (ctrl->sector_size_shift == 9) ++ ecc_per_sec = ((ctrl->ecc_level * 14) + 7) >> 3; ++ else if (ctrl->sector_size_shift == 10) ++ ecc_per_sec = ((ctrl->ecc_level * 14) + 3) >> 2; ++ else ++ ecc_per_sec = oob_per_sec + 1; /* cause an error if not in table */ ++ ++ /* Now find out the answer according to the table */ ++ for (i = 0; i < ARRAY_SIZE(bcmnand_ecc_sizes); i++) { ++ if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level && ++ bcmnand_ecc_sizes[i].sector_size_shift == ++ ctrl->sector_size_shift) { ++ break; ++ } ++ } ++ ++ /* Table match overrides formula */ ++ if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level && ++ bcmnand_ecc_sizes[i].sector_size_shift == ctrl->sector_size_shift) ++ ecc_per_sec = bcmnand_ecc_sizes[i].ecc_bytes_per_sec; ++ ++ /* Return an error if calculated ECC leaves no room for OOB */ ++ if ((ctrl->sec_per_page_shift != 0 && ecc_per_sec >= oob_per_sec) || ++ (ctrl->sec_per_page_shift == 0 && ecc_per_sec >= (oob_per_sec - 1))) { ++ dev_err(dev, "ECC level %d too high, leaves no room for OOB data\n", ++ ctrl->ecc_level); ++ return -EINVAL; ++ } ++ ++ /* Fill in the needed fields */ ++ ctrl->nand.ecc.size = ctrl->mtd.writesize >> ctrl->sec_per_page_shift; ++ ctrl->nand.ecc.bytes = ecc_per_sec; ++ ctrl->nand.ecc.steps = 1 << ctrl->sec_per_page_shift; ++ ctrl->nand.ecc.total = ecc_per_sec << ctrl->sec_per_page_shift; ++ ctrl->nand.ecc.strength = ctrl->ecc_level; ++ ++ /* Build an ecc layout data structure */ ++ layout = &ctrl->ecclayout; ++ memset(layout, 0, sizeof(*layout)); ++ ++ /* Total number of bytes used by HW ECC */ ++ layout->eccbytes = ecc_per_sec << ctrl->sec_per_page_shift; ++ ++ /* Location for each of the HW ECC bytes */ ++ for (i = j = 0, k = 1; ++ i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes; ++ i++, j++) { ++ /* switch sector # */ ++ if (j == ecc_per_sec) { ++ j = 0; ++ k++; ++ } ++ /* save position of each HW-generated ECC byte */ ++ layout->eccpos[i] = (oob_per_sec * k) - ecc_per_sec + j; ++ ++ /* Check that HW ECC does not overlap bad-block marker */ ++ if (bbm_pos == layout->eccpos[i]) { ++ dev_err(dev, "ECC level %d too high, HW ECC collides with bad-block marker position\n", ++ ctrl->ecc_level); ++ return -EINVAL; ++ } ++ } ++ ++ /* Location of all user-available OOB byte-ranges */ ++ for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++) { ++ struct nand_oobfree *oobfree = &layout->oobfree[i]; ++ ++ if (i >= (1 << ctrl->sec_per_page_shift)) ++ break; ++ oobfree->offset = oob_per_sec * i; ++ oobfree->length = oob_per_sec - ecc_per_sec; ++ ++ /* Bad-block marker must be in the first sector spare area */ ++ if (WARN_ON(bbm_pos >= (oobfree->offset + oobfree->length))) ++ return -EINVAL; ++ ++ if (i != 0) ++ continue; ++ ++ /* Remove bad-block marker from available byte range */ ++ if (bbm_pos == oobfree->offset) { ++ oobfree->offset += 1; ++ oobfree->length -= 1; ++ } else if (bbm_pos == (oobfree->offset + oobfree->length - 1)) { ++ oobfree->length -= 1; ++ } else { ++ layout->oobfree[i + 1].offset = bbm_pos + 1; ++ layout->oobfree[i + 1].length = ++ oobfree->length - bbm_pos - 1; ++ oobfree->length = bbm_pos; ++ i++; ++ } ++ } ++ ++ layout->oobavail = ((oob_per_sec - ecc_per_sec) ++ << ctrl->sec_per_page_shift) - 1; ++ ++ ctrl->mtd.oobavail = layout->oobavail; ++ ctrl->nand.ecc.layout = layout; ++ ++ /* Output layout for debugging */ ++ dev_dbg(dev, "Spare area=%d eccbytes %d, ecc bytes located at:\n", ++ ctrl->mtd.oobsize, layout->eccbytes); ++ for (i = j = 0; ++ i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes; i++) ++ pr_debug(" %d", layout->eccpos[i]); ++ pr_debug("\n"); ++ ++ dev_dbg(dev, "Available %d bytes at (off,len):\n", layout->oobavail); ++ for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++) ++ pr_debug("(%d,%d) ", layout->oobfree[i].offset, ++ layout->oobfree[i].length); ++ pr_debug("\n"); ++ ++ return 0; ++} ++ ++/* ++ * Register bit-field manipulation routines ++ */ ++ ++static inline unsigned int bcmnand_reg_read(struct bcmnand_ctrl *ctrl, ++ struct bcmnand_reg_field rbf) ++{ ++ u32 val; ++ ++ val = bcma_read32(ctrl->core, rbf.reg); ++ val >>= rbf.pos; ++ val &= (1 << rbf.width) - 1; ++ ++ return val; ++} ++ ++static inline void bcmnand_reg_write(struct bcmnand_ctrl *ctrl, ++ struct bcmnand_reg_field rbf, ++ unsigned newval) ++{ ++ u32 val, msk; ++ ++ msk = (1 << rbf.width) - 1; ++ msk <<= rbf.pos; ++ newval <<= rbf.pos; ++ newval &= msk; ++ ++ val = bcma_read32(ctrl->core, rbf.reg); ++ val &= ~msk; ++ val |= newval; ++ bcma_write32(ctrl->core, rbf.reg, val); ++} ++ ++static inline unsigned int bcmnand_reg_aread(struct bcmnand_ctrl *ctrl, ++ struct bcmnand_areg_field rbf) ++{ ++ u32 val; ++ ++ val = bcma_aread32(ctrl->core, rbf.reg); ++ val >>= rbf.pos; ++ val &= (1 << rbf.width) - 1; ++ ++ return val; ++} ++ ++static inline void bcmnand_reg_awrite(struct bcmnand_ctrl *ctrl, ++ struct bcmnand_areg_field rbf, ++ unsigned int newval) ++{ ++ u32 val, msk; ++ ++ msk = (1 << rbf.width) - 1; ++ msk <<= rbf.pos; ++ newval <<= rbf.pos; ++ newval &= msk; ++ ++ val = bcma_aread32(ctrl->core, rbf.reg); ++ val &= ~msk; ++ val |= newval; ++ bcma_awrite32(ctrl->core, rbf.reg, val); ++} ++ ++/* ++ * NAND Interface - dev_ready ++ * ++ * Return 1 iff device is ready, 0 otherwise ++ */ ++static int bcmnand_dev_ready(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ ++ return bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY); ++} ++ ++/* ++ * Interrupt service routines ++ */ ++static irqreturn_t bcmnand_isr(int irq, void *dev_id) ++{ ++ struct bcmnand_ctrl *ctrl = dev_id; ++ int irq_off; ++ ++ irq_off = irq - ctrl->core->irq; ++ WARN_ON(irq_off < 0 || irq_off >= NANDC_IRQ_NUM); ++ ++ if (!bcmnand_reg_read(ctrl, NANDC_INT_N_REG(irq_off))) ++ return IRQ_NONE; ++ ++ /* Acknowledge interrupt */ ++ bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1); ++ ++ /* Wake up task */ ++ complete(&ctrl->op_completion); ++ ++ return IRQ_HANDLED; ++} ++ ++static int bcmnand_wait_interrupt(struct bcmnand_ctrl *ctrl, ++ unsigned int irq_off, ++ unsigned int timeout_usec) ++{ ++ long timeout_jiffies; ++ int ret = 0; ++ ++ reinit_completion(&ctrl->op_completion); ++ ++ /* Acknowledge interrupt */ ++ bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1); ++ ++ /* Enable IRQ to wait on */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 1); ++ ++ timeout_jiffies = 1 + usecs_to_jiffies(timeout_usec); ++ ++ if (irq_off != NANDC_IRQ_CONTROLLER_RDY || ++ 0 == bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)) { ++ ++ timeout_jiffies = wait_for_completion_timeout( ++ &ctrl->op_completion, timeout_jiffies); ++ ++ if (timeout_jiffies < 0) ++ ret = timeout_jiffies; ++ if (timeout_jiffies == 0) ++ ret = -ETIME; ++ } ++ ++ /* Disable IRQ, we're done waiting */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0); ++ ++ if (bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)) ++ ret = 0; ++ ++ return ret; ++} ++ ++/* ++ * wait for command completion ++ */ ++static int bcmnand_wait_cmd(struct bcmnand_ctrl *ctrl, unsigned int timeout_usec) ++{ ++ unsigned int retries; ++ ++ if (bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY)) ++ return 0; ++ ++ /* If the timeout is long, wait for interrupt */ ++ if (timeout_usec >= jiffies_to_usecs(1) >> 4) ++ return bcmnand_wait_interrupt( ++ ctrl, NANDC_IRQ_CONTROLLER_RDY, timeout_usec); ++ ++ /* Wait for completion of the prior command */ ++ retries = (timeout_usec >> 3) + 1; ++ ++ while (retries-- && ++ 0 == bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY)) { ++ cpu_relax(); ++ udelay(6); ++ } ++ ++ if (retries == 0) ++ return -ETIME; ++ ++ return 0; ++} ++ ++ ++/* ++ * NAND Interface - waitfunc ++ */ ++static int bcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) ++{ ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ unsigned int to; ++ int ret; ++ ++ /* figure out timeout based on what command is on */ ++ switch (ctrl->last_cmd) { ++ default: ++ case NAND_CMD_ERASE1: ++ case NAND_CMD_ERASE2: ++ to = 1 << 16; ++ break; ++ case NAND_CMD_STATUS: ++ case NAND_CMD_RESET: ++ to = 256; ++ break; ++ case NAND_CMD_READID: ++ to = 1024; ++ break; ++ case NAND_CMD_READ1: ++ case NAND_CMD_READ0: ++ to = 2048; ++ break; ++ case NAND_CMD_PAGEPROG: ++ to = 4096; ++ break; ++ case NAND_CMD_READOOB: ++ to = 512; ++ break; ++ } ++ ++ /* deliver deferred error code if any */ ++ ret = ctrl->cmd_ret; ++ if (ret < 0) ++ ctrl->cmd_ret = 0; ++ else ++ ret = bcmnand_wait_cmd(ctrl, to); ++ ++ /* Timeout */ ++ if (ret < 0) ++ return NAND_STATUS_FAIL; ++ ++ ret = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS); ++ ++ return ret; ++} ++ ++/* ++ * NAND Interface - read_oob ++ */ ++static int bcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, ++ int page) ++{ ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ unsigned int n = ctrl->chip_num; ++ void __iomem *ctrl_spare; ++ unsigned int spare_per_sec, sector; ++ u64 nand_addr; ++ ++ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF; ++ ++ /* Set the page address for the following commands */ ++ nand_addr = ((u64)page << chip->page_shift); ++ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); ++ ++ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; ++ ++ /* Disable ECC validation for spare area reads */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), 0); ++ ++ /* Loop all sectors in page */ ++ for (sector = 0; sector < (1<<ctrl->sec_per_page_shift); sector++) { ++ unsigned int col; ++ ++ col = (sector << ctrl->sector_size_shift); ++ ++ /* Issue command to read partial page */ ++ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col); ++ ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_SPARE_READ); ++ ++ /* Wait for the command to complete */ ++ if (bcmnand_wait_cmd(ctrl, (sector == 0) ? 10000 : 100)) ++ return -EIO; ++ ++ if (!bcmnand_reg_read(ctrl, NANDC_INT_STAT_SPARE_VALID)) ++ return -EIO; ++ ++ /* Set controller to Little Endian mode for copying */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); ++ ++ memcpy(chip->oob_poi + sector * spare_per_sec, ++ ctrl_spare, spare_per_sec); ++ ++ /* Return to Big Endian mode for commands etc */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); ++ } ++ ++ return 0; ++} ++ ++/* ++ * NAND Interface - write_oob ++ */ ++static int bcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, ++ int page) ++{ ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ unsigned int n = ctrl->chip_num; ++ void __iomem *ctrl_spare; ++ unsigned int spare_per_sec, sector, num_sec; ++ u64 nand_addr; ++ int to, status = 0; ++ ++ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF; ++ ++ /* Disable ECC generation for spare area writes */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), 0); ++ ++ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; ++ ++ /* Set the page address for the following commands */ ++ nand_addr = ((u64)page << chip->page_shift); ++ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); ++ ++ /* Must allow partial programming to change spare area only */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 1); ++ ++ num_sec = 1 << ctrl->sec_per_page_shift; ++ /* Loop all sectors in page */ ++ for (sector = 0; sector < num_sec; sector++) { ++ unsigned int col; ++ ++ /* Spare area accessed by the data sector offset */ ++ col = (sector << ctrl->sector_size_shift); ++ ++ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col); ++ ++ /* Set controller to Little Endian mode for copying */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); ++ ++ memcpy(ctrl_spare, chip->oob_poi + sector * spare_per_sec, ++ spare_per_sec); ++ ++ /* Return to Big Endian mode for commands etc */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); ++ ++ /* Push spare bytes into internal buffer, last goes to flash */ ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_SPARE_PROG); ++ ++ if (sector == (num_sec - 1)) ++ to = 1 << 16; ++ else ++ to = 1 << 10; ++ ++ if (bcmnand_wait_cmd(ctrl, to)) ++ return -EIO; ++ } ++ ++ /* Restore partial programming inhibition */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 0); ++ ++ status = bcmnand_waitfunc(mtd, chip); ++ return status & NAND_STATUS_FAIL ? -EIO : 0; ++} ++ ++/* ++ * verify that a buffer is all erased ++ */ ++static bool bcmnand_buf_erased(const void *buf, unsigned int len) ++{ ++ unsigned int i; ++ const u32 *p = buf; ++ ++ for (i = 0; i < (len >> 2); i++) { ++ if (p[i] != 0xffffffff) ++ return false; ++ } ++ return true; ++} ++ ++/* ++ * read a page, with or without ECC checking ++ */ ++static int bcmnand_read_page_do(struct mtd_info *mtd, struct nand_chip *chip, ++ uint8_t *buf, int page, bool ecc) ++{ ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ unsigned int n = ctrl->chip_num; ++ void __iomem *ctrl_cache; ++ void __iomem *ctrl_spare; ++ unsigned int data_bytes; ++ unsigned int spare_per_sec; ++ unsigned int sector, to = 1 << 16; ++ u32 err_soft_reg, err_hard_reg; ++ unsigned int hard_err_count = 0; ++ int ret; ++ u64 nand_addr; ++ ++ ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF; ++ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF; ++ ++ /* Reset ECC error stats */ ++ err_hard_reg = bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT); ++ err_soft_reg = bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT); ++ ++ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; ++ ++ /* Set the page address for the following commands */ ++ nand_addr = ((u64)page << chip->page_shift); ++ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); ++ ++ /* Enable ECC validation for ecc page reads */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), ecc); ++ ++ /* Loop all sectors in page */ ++ for (sector = 0; sector < (1 << ctrl->sec_per_page_shift); sector++) { ++ data_bytes = 0; ++ ++ /* Copy partial sectors sized by cache reg */ ++ while (data_bytes < (1<<ctrl->sector_size_shift)) { ++ unsigned int col; ++ ++ col = data_bytes + (sector << ctrl->sector_size_shift); ++ ++ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, ++ nand_addr + col); ++ ++ /* Issue command to read partial page */ ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_PAGE_READ); ++ ++ /* Wait for the command to complete */ ++ ret = bcmnand_wait_cmd(ctrl, to); ++ if (ret < 0) ++ return ret; ++ ++ /* Set controller to Little Endian mode for copying */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); ++ ++ if (data_bytes == 0) { ++ memcpy(chip->oob_poi + sector * spare_per_sec, ++ ctrl_spare, spare_per_sec); ++ } ++ ++ memcpy(buf + col, ctrl_cache, NANDC_CACHE_SIZE); ++ data_bytes += NANDC_CACHE_SIZE; ++ ++ /* Return to Big Endian mode for commands etc */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); ++ ++ /* Next iterations should go fast */ ++ to = 1 << 10; ++ ++ /* capture hard errors for each partial */ ++ if (err_hard_reg != bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT)) { ++ int era = bcmnand_reg_read(ctrl, NANDC_INT_STAT_ERASED); ++ ++ if (!era && ++ !bcmnand_buf_erased(buf + col, NANDC_CACHE_SIZE)) ++ hard_err_count++; ++ ++ err_hard_reg = bcmnand_reg_read(ctrl, ++ NANDC_UNCORR_ERR_COUNT); ++ } ++ } ++ } ++ ++ if (!ecc) ++ return 0; ++ ++ /* Report hard ECC errors */ ++ if (hard_err_count) ++ mtd->ecc_stats.failed++; ++ ++ /* Get ECC soft error stats */ ++ mtd->ecc_stats.corrected += err_soft_reg - ++ bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT); ++ ++ return 0; ++} ++ ++/* ++ * NAND Interface - read_page_ecc ++ */ ++static int bcmnand_read_page_ecc(struct mtd_info *mtd, struct nand_chip *chip, ++ uint8_t *buf, int oob_required, int page) ++{ ++ return bcmnand_read_page_do(mtd, chip, buf, page, true); ++} ++ ++/* ++ * NAND Interface - read_page_raw ++ */ ++static int bcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ++ uint8_t *buf, int oob_required, int page) ++{ ++ return bcmnand_read_page_do(mtd, chip, buf, page, true); ++} ++ ++/* ++ * do page write, with or without ECC generation enabled ++ */ ++static int bcmnand_write_page_do(struct mtd_info *mtd, struct nand_chip *chip, ++ const uint8_t *buf, bool ecc) ++{ ++ struct bcmnand_ctrl *ctrl = chip->priv; ++ unsigned int n = ctrl->chip_num; ++ void __iomem *ctrl_cache; ++ void __iomem *ctrl_spare; ++ unsigned int spare_per_sec, sector, num_sec; ++ unsigned int data_bytes, spare_bytes; ++ int i, to; ++ uint8_t *tmp_poi; ++ u32 nand_addr; ++ ++ ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF; ++ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF; ++ ++ /* Get start-of-page address */ ++ nand_addr = bcmnand_reg_read(ctrl, NANDC_CMD_ADDRESS); ++ ++ tmp_poi = kmalloc(mtd->oobsize, GFP_KERNEL); ++ if (!tmp_poi) ++ return -ENOMEM; ++ ++ /* Retreive pre-existing OOB values */ ++ memcpy(tmp_poi, chip->oob_poi, mtd->oobsize); ++ ctrl->cmd_ret = bcmnand_read_oob(mtd, chip, ++ nand_addr >> chip->page_shift); ++ if (ctrl->cmd_ret < 0) { ++ kfree(tmp_poi); ++ return ctrl->cmd_ret; ++ } ++ ++ /* Apply new OOB data bytes just like they would end up on the chip */ ++ for (i = 0; i < mtd->oobsize; i++) ++ chip->oob_poi[i] &= tmp_poi[i]; ++ kfree(tmp_poi); ++ ++ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; ++ ++ /* Enable ECC generation for ecc page write, if requested */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), ecc); ++ ++ spare_bytes = 0; ++ num_sec = 1 << ctrl->sec_per_page_shift; ++ ++ /* Loop all sectors in page */ ++ for (sector = 0; sector < num_sec; sector++) { ++ data_bytes = 0; ++ ++ /* Copy partial sectors sized by cache reg */ ++ while (data_bytes < (1<<ctrl->sector_size_shift)) { ++ unsigned int col; ++ ++ col = data_bytes + ++ (sector << ctrl->sector_size_shift); ++ ++ /* Set address of 512-byte sub-page */ ++ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, ++ nand_addr + col); ++ ++ /* Set controller to Little Endian mode for copying */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, ++ 1); ++ ++ /* Set spare area is written at each sector start */ ++ if (data_bytes == 0) { ++ memcpy(ctrl_spare, ++ chip->oob_poi + spare_bytes, ++ spare_per_sec); ++ spare_bytes += spare_per_sec; ++ } ++ ++ /* Copy sub-page data */ ++ memcpy(ctrl_cache, buf + col, NANDC_CACHE_SIZE); ++ data_bytes += NANDC_CACHE_SIZE; ++ ++ /* Return to Big Endian mode for commands etc */ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); ++ ++ /* Push data into internal cache */ ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_PAGE_PROG); ++ ++ /* Wait for the command to complete */ ++ if (sector == (num_sec - 1)) ++ to = 1 << 16; ++ else ++ to = 1 << 10; ++ ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to); ++ if (ctrl->cmd_ret < 0) ++ return ctrl->cmd_ret; ++ } ++ } ++ return 0; ++} ++ ++/* ++ * NAND Interface = write_page_ecc ++ */ ++static int bcmnand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip, ++ const uint8_t *buf, int oob_required) ++{ ++ return bcmnand_write_page_do(mtd, chip, buf, true); ++} ++ ++/* ++ * NAND Interface = write_page_raw ++ */ ++static int bcmnand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, ++ const uint8_t *buf, int oob_required) ++{ ++ return bcmnand_write_page_do(mtd, chip, buf, false); ++} ++ ++/* ++ * MTD Interface - read_byte ++ * ++ * This function emulates simple controllers behavior ++ * for just a few relevant commands ++ */ ++static uint8_t bcmnand_read_byte(struct mtd_info *mtd) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct bcmnand_ctrl *ctrl = nand->priv; ++ struct device *dev = &ctrl->core->dev; ++ uint8_t b = ~0; ++ ++ switch (ctrl->last_cmd) { ++ case NAND_CMD_READID: ++ if (ctrl->id_byte_index < 8) { ++ b = bcmnand_reg_read(ctrl, NANDC_DEVID_BYTE( ++ ctrl->id_byte_index)); ++ ctrl->id_byte_index++; ++ } ++ break; ++ case NAND_CMD_READOOB: ++ if (ctrl->oob_index < mtd->oobsize) ++ b = nand->oob_poi[ctrl->oob_index++]; ++ break; ++ case NAND_CMD_STATUS: ++ b = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS); ++ break; ++ default: ++ dev_err(dev, "got unkown command: 0x%x in read_byte\n", ++ ctrl->last_cmd); ++ } ++ return b; ++} ++ ++/* ++ * MTD Interface - read_word ++ * ++ * Can not be tested without x16 chip, but the SoC does not support x16 i/f. ++ */ ++static u16 bcmnand_read_word(struct mtd_info *mtd) ++{ ++ u16 w = ~0; ++ ++ w = bcmnand_read_byte(mtd); ++ barrier(); ++ w |= bcmnand_read_byte(mtd) << 8; ++ ++ return w; ++} ++ ++/* ++ * MTD Interface - select a chip from an array ++ */ ++static void bcmnand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct bcmnand_ctrl *ctrl = nand->priv; ++ ++ ctrl->chip_num = chip; ++ bcmnand_reg_write(ctrl, NANDC_CMD_CS_SEL, chip); ++} ++ ++/* ++ * NAND Interface - emulate low-level NAND commands ++ * ++ * Only a few low-level commands are really needed by generic NAND, ++ * and they do not call for CMD_LL operations the controller can support. ++ */ ++static void bcmnand_cmdfunc(struct mtd_info *mtd, unsigned int command, ++ int column, int page_addr) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct bcmnand_ctrl *ctrl = nand->priv; ++ struct device *dev = &ctrl->core->dev; ++ u64 nand_addr; ++ unsigned int to = 1; ++ ++ ctrl->last_cmd = command; ++ ++ /* Set address for some commands */ ++ switch (command) { ++ case NAND_CMD_ERASE1: ++ column = 0; ++ /*FALLTHROUGH*/ ++ case NAND_CMD_SEQIN: ++ case NAND_CMD_READ0: ++ case NAND_CMD_READ1: ++ WARN_ON(column >= mtd->writesize); ++ nand_addr = (u64) column | ++ ((u64)page_addr << nand->page_shift); ++ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); ++ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr); ++ break; ++ case NAND_CMD_ERASE2: ++ case NAND_CMD_RESET: ++ case NAND_CMD_READID: ++ case NAND_CMD_READOOB: ++ case NAND_CMD_PAGEPROG: ++ default: ++ /* Do nothing, address not used */ ++ break; ++ } ++ ++ /* Issue appropriate command to controller */ ++ switch (command) { ++ case NAND_CMD_SEQIN: ++ /* Only need to load command address, done */ ++ return; ++ ++ case NAND_CMD_RESET: ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_FLASH_RESET); ++ to = 1 << 8; ++ break; ++ ++ case NAND_CMD_READID: ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_DEVID_READ); ++ ctrl->id_byte_index = 0; ++ to = 1 << 8; ++ break; ++ ++ case NAND_CMD_READ0: ++ case NAND_CMD_READ1: ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_PAGE_READ); ++ to = 1 << 15; ++ break; ++ case NAND_CMD_STATUS: ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_STATUS_READ); ++ to = 1 << 8; ++ break; ++ case NAND_CMD_ERASE1: ++ return; ++ ++ case NAND_CMD_ERASE2: ++ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, ++ NANDC_CMD_OPCODE_BLOCK_ERASE); ++ to = 1 << 18; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ /* Cmd already set from write_page */ ++ return; ++ ++ case NAND_CMD_READOOB: ++ /* Emulate simple interface */ ++ bcmnand_read_oob(mtd, nand, page_addr); ++ ctrl->oob_index = 0; ++ return; ++ ++ default: ++ dev_err(dev, "got unkown command: 0x%x in cmdfunc\n", ++ ctrl->last_cmd); ++ } ++ ++ /* Wait for command to complete */ ++ ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to); ++ ++} ++ ++static int bcmnand_scan(struct mtd_info *mtd) ++{ ++ struct nand_chip *nand = mtd->priv; ++ struct bcmnand_ctrl *ctrl = nand->priv; ++ struct device *dev = &ctrl->core->dev; ++ bool sector_1k = false; ++ unsigned int chip_num = 0; ++ int ecc_level = 0; ++ int ret; ++ ++ ret = nand_scan_ident(mtd, NANDC_MAX_CHIPS, NULL); ++ if (ret) ++ return ret; ++ ++ /* Get configuration from first chip */ ++ sector_1k = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_SECTOR_1K(0)); ++ ecc_level = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(0)); ++ mtd->writesize_shift = nand->page_shift; ++ ++ ctrl->ecc_level = ecc_level; ++ ctrl->sector_size_shift = sector_1k ? 10 : 9; ++ ++ /* Configure spare area, tweak as needed */ ++ do { ++ ctrl->sec_per_page_shift = ++ mtd->writesize_shift - ctrl->sector_size_shift; ++ ++ /* will return -EINVAL if OOB space exhausted */ ++ ret = bcmnand_hw_ecc_layout(ctrl); ++ ++ /* First try to bump sector size to 1k, then decrease level */ ++ if (ret && nand->page_shift > 9 && ctrl->sector_size_shift < 10) ++ ctrl->sector_size_shift = 10; ++ else if (ret) ++ ctrl->ecc_level--; ++ ++ } while (ret && ctrl->ecc_level > 0); ++ ++ if (WARN_ON(ctrl->ecc_level == 0)) ++ return -ENOENT; ++ ++ if ((ctrl->sector_size_shift > 9) != (sector_1k == 1)) { ++ dev_info(dev, "sector size adjusted to 1k\n"); ++ sector_1k = 1; ++ } ++ ++ if (ecc_level != ctrl->ecc_level) { ++ dev_info(dev, "ECC level adjusted from %u to %u\n", ++ ecc_level, ctrl->ecc_level); ++ ecc_level = ctrl->ecc_level; ++ } ++ ++ /* handle the hardware chip config registers */ ++ for (chip_num = 0; chip_num < nand->numchips; chip_num++) { ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_SECTOR_1K(chip_num), ++ sector_1k); ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip_num), ++ ecc_level); ++ ++ /* Large pages: no partial page programming */ ++ if (mtd->writesize > 512) { ++ bcmnand_reg_write(ctrl, ++ NANDC_ACC_CTRL_PGM_RDIN(chip_num), 0); ++ bcmnand_reg_write(ctrl, ++ NANDC_ACC_CTRL_PGM_PARTIAL(chip_num), 0); ++ } ++ ++ /* Do not raise ECC error when reading erased pages */ ++ /* This bit has only partial effect, driver needs to help */ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ERA_ECC_ERR(chip_num), ++ 0); ++ ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PG_HIT(chip_num), 0); ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PREFETCH(chip_num), 0); ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_MODE(chip_num), 0); ++ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_LASTPG(chip_num), ++ 0); ++ ++ /* TBD: consolidate or at least verify the s/w and h/w geometries agree */ ++ } ++ ++ /* Allow writing on device */ ++ if (!(nand->options & NAND_ROM)) ++ bcmnand_reg_write(ctrl, NANDC_CS_NAND_WP, 0); ++ ++ dev_dbg(dev, "layout.oobavail=%d\n", nand->ecc.layout->oobavail); ++ ++ ret = nand_scan_tail(mtd); ++ ++ if (nand->badblockbits == 0) ++ nand->badblockbits = 8; ++ if (WARN_ON((1 << nand->page_shift) != mtd->writesize)) ++ return -EIO; ++ ++ /* Spit out some key chip parameters as detected by nand_base */ ++ dev_dbg(dev, "erasesize=%d writesize=%d oobsize=%d page_shift=%d badblockpos=%d badblockbits=%d\n", ++ mtd->erasesize, mtd->writesize, mtd->oobsize, ++ nand->page_shift, nand->badblockpos, nand->badblockbits); ++ ++ return ret; ++} ++ ++/* ++ * main intiailization function ++ */ ++static int bcmnand_ctrl_init(struct bcmnand_ctrl *ctrl) ++{ ++ unsigned int chip; ++ struct nand_chip *nand; ++ struct mtd_info *mtd; ++ struct device *dev = &ctrl->core->dev; ++ int ret; ++ ++ /* Software variables init */ ++ nand = &ctrl->nand; ++ mtd = &ctrl->mtd; ++ ++ init_completion(&ctrl->op_completion); ++ ++ mtd->priv = nand; ++ mtd->owner = THIS_MODULE; ++ mtd->name = KBUILD_MODNAME; ++ ++ nand->priv = ctrl; ++ ++ nand->chip_delay = 5; /* not used */ ++ nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)~0L; ++ ++ if (bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_WIDTH(0))) ++ nand->options |= NAND_BUSWIDTH_16; ++ nand->options |= NAND_SKIP_BBTSCAN; /* Dont need BBTs */ ++ ++ nand->options |= NAND_NO_SUBPAGE_WRITE; /* Subpages unsupported */ ++ ++ nand->dev_ready = bcmnand_dev_ready; ++ nand->read_byte = bcmnand_read_byte; ++ nand->read_word = bcmnand_read_word; ++ nand->select_chip = bcmnand_select_chip; ++ nand->cmdfunc = bcmnand_cmdfunc; ++ nand->waitfunc = bcmnand_waitfunc; ++ ++ nand->ecc.mode = NAND_ECC_HW; ++ nand->ecc.read_page_raw = bcmnand_read_page_raw; ++ nand->ecc.write_page_raw = bcmnand_write_page_raw; ++ nand->ecc.read_page = bcmnand_read_page_ecc; ++ nand->ecc.write_page = bcmnand_write_page_ecc; ++ nand->ecc.read_oob = bcmnand_read_oob; ++ nand->ecc.write_oob = bcmnand_write_oob; ++ ++ /* Set AUTO_CNFIG bit - try to auto-detect chips */ ++ bcmnand_reg_write(ctrl, NANDC_CS_AUTO_CONFIG, 1); ++ ++ usleep_range(1000, 1500); ++ ++ /* Print out current chip config */ ++ for (chip = 0; chip < NANDC_MAX_CHIPS; chip++) { ++ dev_dbg(dev, "chip[%d]: size=%#x block=%#x page=%#x ecc_level=%#x\n", ++ chip, ++ bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_SIZE(chip)), ++ bcmnand_reg_read(ctrl, NANDC_CONFIG_BLK_SIZE(chip)), ++ bcmnand_reg_read(ctrl, NANDC_CONFIG_PAGE_SIZE(chip)), ++ bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip))); ++ } ++ ++ dev_dbg(dev, "Nand controller is reads=%d\n", ++ bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)); ++ ++ ret = bcmnand_scan(mtd); ++ if (ret) { ++ dev_err(dev, "scanning the nand flash chip failed with %i\n", ++ ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int bcmnand_idm_init(struct bcmnand_ctrl *ctrl) ++{ ++ int irq_off; ++ unsigned int retries = 0x1000; ++ struct device *dev = &ctrl->core->dev; ++ ++ if (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) ++ dev_info(dev, "stuck in reset\n"); ++ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 1); ++ if (!bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) { ++ dev_err(dev, "reset of failed\n"); ++ return -EIO; ++ } ++ ++ while (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) { ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 0); ++ cpu_relax(); ++ usleep_range(100, 150); ++ if (!(retries--)) { ++ dev_err(dev, "did not came back from reset\n"); ++ return -ETIMEDOUT; ++ } ++ } ++ ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_CLOCK_EN, 1); ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); ++ udelay(10); ++ ++ dev_info(dev, "NAND Controller rev %d.%02d\n", ++ bcmnand_reg_read(ctrl, NANDC_REV_MAJOR), ++ bcmnand_reg_read(ctrl, NANDC_REV_MINOR)); ++ ++ usleep_range(250, 350); ++ ++ /* Disable all IRQs */ ++ for (irq_off = 0; irq_off < NANDC_IRQ_NUM; irq_off++) ++ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0); ++ ++ return 0; ++} ++ ++static const char * const part_probes[] = { "ofpart", "bcm47xxpart", NULL }; ++ ++/* ++ * Top-level init function ++ */ ++static int bcmnand_probe(struct bcma_device *core) ++{ ++ struct mtd_part_parser_data parser_data; ++ struct device *dev = &core->dev; ++ struct bcmnand_ctrl *ctrl; ++ int res, i, irq; ++ ++ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); ++ if (!ctrl) ++ return -ENOMEM; ++ ++ bcma_set_drvdata(core, ctrl); ++ ++ ctrl->mtd.dev.parent = &core->dev; ++ ctrl->core = core; ++ ++ /* Acquire all interrupt lines */ ++ for (i = 0; i < NANDC_IRQ_NUM; i++) { ++ irq = bcma_core_irq(core, i); ++ if (!irq) { ++ dev_err(dev, "IRQ idx %i not available\n", i); ++ return -ENOENT; ++ } ++ res = devm_request_irq(dev, irq, bcmnand_isr, 0, ++ KBUILD_MODNAME, ctrl); ++ if (res < 0) { ++ dev_err(dev, "problem requesting irq: %i (idx: %i)\n", ++ irq, i); ++ return res; ++ } ++ } ++ ++ res = bcmnand_idm_init(ctrl); ++ if (res) ++ return res; ++ ++ res = bcmnand_ctrl_init(ctrl); ++ if (res) ++ return res; ++ ++ parser_data.of_node = dev->of_node; ++ res = mtd_device_parse_register(&ctrl->mtd, part_probes, &parser_data, NULL, 0); ++ if (res) { ++ dev_err(dev, "Failed to register MTD device: %d\n", res); ++ return res; ++ } ++ return 0; ++} ++ ++static void bcmnand_remove(struct bcma_device *core) ++{ ++ struct bcmnand_ctrl *ctrl = bcma_get_drvdata(core); ++ ++ mtd_device_unregister(&ctrl->mtd); ++} ++ ++static const struct bcma_device_id bcmnand_bcma_tbl[] = { ++ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_NAND, BCMA_ANY_REV, BCMA_ANY_CLASS), ++ {}, ++}; ++MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); ++ ++static struct bcma_driver bcmnand_bcma_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = bcmnand_bcma_tbl, ++ .probe = bcmnand_probe, ++ .remove = bcmnand_remove, ++}; ++ ++static int __init bcmnand_init(void) ++{ ++ return bcma_driver_register(&bcmnand_bcma_driver); ++} ++ ++static void __exit bcmnand_exit(void) ++{ ++ bcma_driver_unregister(&bcmnand_bcma_driver); ++} ++ ++module_init(bcmnand_init) ++module_exit(bcmnand_exit) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Hauke Mehrtens"); ++MODULE_DESCRIPTION("Northstar on-chip NAND Flash Controller driver"); diff --git a/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch new file mode 100644 index 0000000000..a3d0f75b48 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch @@ -0,0 +1,59 @@ +From 2a2af518266a29323cf30c3f9ba9ef2ceb1dd84b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Thu, 16 Oct 2014 20:52:16 +0200 +Subject: [PATCH] UBI: Detect EOF mark and erase all remaining 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/mtd/ubi/attach.c | 5 +++++ + drivers/mtd/ubi/io.c | 4 ++++ + drivers/mtd/ubi/ubi.h | 1 + + 3 files changed, 10 insertions(+) + +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -95,6 +95,9 @@ static int self_check_ai(struct ubi_devi + static struct ubi_ec_hdr *ech; + static struct ubi_vid_hdr *vidh; + ++/* Set on finding block with 0xdeadc0de, indicates erasing all blocks behind */ ++bool erase_all_next; ++ + /** + * add_to_list - add physical eraseblock to a list. + * @ai: attaching information +@@ -1427,6 +1430,8 @@ int ubi_attach(struct ubi_device *ubi, i + if (!ai) + return -ENOMEM; + ++ erase_all_next = false; ++ + #ifdef CONFIG_MTD_UBI_FASTMAP + /* On small flash devices we disable fastmap in any case. */ + if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { +--- a/drivers/mtd/ubi/io.c ++++ b/drivers/mtd/ubi/io.c +@@ -755,6 +755,10 @@ int ubi_io_read_ec_hdr(struct ubi_device + } + + magic = be32_to_cpu(ec_hdr->magic); ++ if (magic == 0xdeadc0de) ++ erase_all_next = true; ++ if (erase_all_next) ++ return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF; + if (magic != UBI_EC_HDR_MAGIC) { + if (mtd_is_eccerr(read_err)) + return UBI_IO_BAD_HDR_EBADMSG; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -781,6 +781,7 @@ extern struct mutex ubi_devices_mutex; + extern struct blocking_notifier_head ubi_notifiers; + + /* attach.c */ ++extern bool erase_all_next; + int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, + int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); + struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, diff --git a/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch b/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch new file mode 100644 index 0000000000..6be75bb806 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/700-bgmac-add-support-for-the-3rd-bus-core-device.patch @@ -0,0 +1,63 @@ +From f5d5afc0b1402aae0f6a2350e43241603dbaff1e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 13 May 2015 10:46:47 +0200 +Subject: [PATCH] bgmac: add support for the 3rd bus core (device) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +So far we were supporting up to 2 cores but recent devices (e.g. Netgear +R8000) may use 3rd as well. Lower ones (1st, 2nd) are usually used for +some offloading then. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/net/ethernet/broadcom/bgmac.c | 28 +++++++++++++++++++++++----- + 1 file changed, 23 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bgmac.c ++++ b/drivers/net/ethernet/broadcom/bgmac.c +@@ -1561,11 +1561,20 @@ static int bgmac_probe(struct bcma_devic + struct net_device *net_dev; + struct bgmac *bgmac; + struct ssb_sprom *sprom = &core->bus->sprom; +- u8 *mac = core->core_unit ? sprom->et1mac : sprom->et0mac; ++ u8 *mac; + int err; + +- /* We don't support 2nd, 3rd, ... units, SPROM has to be adjusted */ +- if (core->core_unit > 1) { ++ switch (core->core_unit) { ++ case 0: ++ mac = sprom->et0mac; ++ break; ++ case 1: ++ mac = sprom->et1mac; ++ break; ++ case 2: ++ mac = sprom->et2mac; ++ break; ++ default: + pr_err("Unsupported core_unit %d\n", core->core_unit); + return -ENOTSUPP; + } +@@ -1600,8 +1609,17 @@ static int bgmac_probe(struct bcma_devic + } + bgmac->cmn = core->bus->drv_gmac_cmn.core; + +- bgmac->phyaddr = core->core_unit ? sprom->et1phyaddr : +- sprom->et0phyaddr; ++ switch (core->core_unit) { ++ case 0: ++ bgmac->phyaddr = sprom->et0phyaddr; ++ break; ++ case 1: ++ bgmac->phyaddr = sprom->et1phyaddr; ++ break; ++ case 2: ++ bgmac->phyaddr = sprom->et2phyaddr; ++ break; ++ } + bgmac->phyaddr &= BGMAC_PHY_MASK; + if (bgmac->phyaddr == BGMAC_PHY_MASK) { + bgmac_err(bgmac, "No PHY found\n"); diff --git a/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch b/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch new file mode 100644 index 0000000000..6015c4aaca --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/710-b53-add-hacky-CPU-port-fixes-for-devices-not-using-p.patch @@ -0,0 +1,35 @@ +From 4abdde3ad6bc0b3b157c4bf6ec0bf139d11d07e8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Wed, 13 May 2015 14:13:28 +0200 +Subject: [PATCH] b53: add hacky CPU port fixes for devices not using port 5 +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/net/phy/b53/b53_common.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/phy/b53/b53_common.c ++++ b/drivers/net/phy/b53/b53_common.c +@@ -25,6 +25,7 @@ + #include <linux/module.h> + #include <linux/switch.h> + #include <linux/platform_data/b53.h> ++#include <linux/of.h> + + #include "b53_regs.h" + #include "b53_priv.h" +@@ -1313,6 +1314,11 @@ static int b53_switch_init(struct b53_de + sw_dev->cpu_port = 5; + } + ++ if (of_machine_is_compatible("asus,rt-ac87u")) ++ sw_dev->cpu_port = 7; ++ else if (of_machine_is_compatible("netgear,r8000")) ++ sw_dev->cpu_port = 8; ++ + /* cpu port is always last */ + sw_dev->ports = sw_dev->cpu_port + 1; + dev->enabled_ports |= BIT(sw_dev->cpu_port); diff --git a/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch b/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch new file mode 100644 index 0000000000..9f2cd396ae --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/800-bcma-use-two-different-initcalls-if-built-in.patch @@ -0,0 +1,65 @@ +From 666bdfc027cde41a171862dc698987a378c8b66a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Mon, 9 Feb 2015 18:00:42 +0100 +Subject: [PATCH RFC] bcma: use two different initcalls if built-in +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is needed as we can't initialize bus during fs_initcall. +Initialization requires SPROM which depends on NVRAM which depends on +mtd. Since mtd, spi, nand, spi-nor use standard module_init, we have to +do the same in bcma. +Without this we'll try to initialize SPROM without having a ready SPROM +proviver registered using bcma_arch_register_fallback_sprom. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- +While this patch seems to work and I can compile bcma as built-in and +module, I'm not too proud of it. I don't really like these #if(n)def +tricks and I'm afraid bcma_modinit may be called even if +bcma_modinit_early failed. + +Do you see any better idea of solving this? +--- + drivers/bcma/main.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -637,13 +637,25 @@ static int bcma_device_uevent(struct dev + core->id.rev, core->id.class); + } + ++/* Bus has to be registered early, before any bcma driver */ ++static int __init bcma_modinit_early(void) ++{ ++ return bus_register(&bcma_bus_type); ++} ++#ifndef MODULE ++fs_initcall(bcma_modinit_early); ++#endif ++ ++/* Initialization has to be done later with SPI/mtd/NAND/SPROM available */ + static int __init bcma_modinit(void) + { + int err; + +- err = bus_register(&bcma_bus_type); ++#ifdef MODULE ++ err = bcma_modinit_early(); + if (err) + return err; ++#endif + + err = bcma_host_soc_register_driver(); + if (err) { +@@ -660,7 +672,7 @@ static int __init bcma_modinit(void) + + return err; + } +-fs_initcall(bcma_modinit); ++module_init(bcma_modinit); + + static void __exit bcma_modexit(void) + { diff --git a/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch b/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch new file mode 100644 index 0000000000..d331ae6573 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/810-USB-bcma-make-helper-creating-platform-dev-more-gene.patch @@ -0,0 +1,73 @@ +From 5b4fed9fc917cc2bfc5297eeab03aeba5d340618 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Tue, 16 Jun 2015 12:33:46 +0200 +Subject: [PATCH] USB: bcma: make helper creating platform dev more generic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Having "bool ohci" argument bounded us to two cases only and didn't +allow re-using this code for XHCI. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/usb/host/bcma-hcd.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -249,7 +249,10 @@ static const struct usb_ehci_pdata ehci_ + static const struct usb_ohci_pdata ohci_pdata = { + }; + +-static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) ++static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, ++ const char *name, u32 addr, ++ const void *data, ++ size_t size) + { + struct platform_device *hci_dev; + struct resource hci_res[2]; +@@ -264,8 +267,7 @@ static struct platform_device *bcma_hcd_ + hci_res[1].start = dev->irq; + hci_res[1].flags = IORESOURCE_IRQ; + +- hci_dev = platform_device_alloc(ohci ? "ohci-platform" : +- "ehci-platform" , 0); ++ hci_dev = platform_device_alloc(name, 0); + if (!hci_dev) + return ERR_PTR(-ENOMEM); + +@@ -276,12 +278,8 @@ static struct platform_device *bcma_hcd_ + ARRAY_SIZE(hci_res)); + if (ret) + goto err_alloc; +- if (ohci) +- ret = platform_device_add_data(hci_dev, &ohci_pdata, +- sizeof(ohci_pdata)); +- else +- ret = platform_device_add_data(hci_dev, &ehci_pdata, +- sizeof(ehci_pdata)); ++ if (data) ++ ret = platform_device_add_data(hci_dev, data, size); + if (ret) + goto err_alloc; + ret = platform_device_add(hci_dev); +@@ -334,11 +332,15 @@ static int bcma_hcd_probe(struct bcma_de + && chipinfo->rev == 0) + ohci_addr = 0x18009000; + +- usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); ++ usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform", ++ ohci_addr, &ohci_pdata, ++ sizeof(ohci_pdata)); + if (IS_ERR(usb_dev->ohci_dev)) + return PTR_ERR(usb_dev->ohci_dev); + +- usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); ++ usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform", ++ dev->addr, &ehci_pdata, ++ sizeof(ehci_pdata)); + if (IS_ERR(usb_dev->ehci_dev)) { + err = PTR_ERR(usb_dev->ehci_dev); + goto err_unregister_ohci_dev; diff --git a/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch b/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch new file mode 100644 index 0000000000..758b0ac1eb --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/811-USB-bcma-use-separated-function-for-USB-2.0-initiali.patch @@ -0,0 +1,102 @@ +From 4aed231f49954114d5ae23e97789e9aa540a0b70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Tue, 16 Jun 2015 12:52:07 +0200 +Subject: [PATCH] USB: bcma: use separated function for USB 2.0 initialization +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This will allow adding USB 3.0 (XHCI) support cleanly. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/usb/host/bcma-hcd.c | 51 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 35 insertions(+), 16 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -34,6 +34,7 @@ MODULE_DESCRIPTION("Common USB driver fo + MODULE_LICENSE("GPL"); + + struct bcma_hcd_device { ++ struct bcma_device *core; + struct platform_device *ehci_dev; + struct platform_device *ohci_dev; + }; +@@ -293,27 +294,16 @@ err_alloc: + return ERR_PTR(ret); + } + +-static int bcma_hcd_probe(struct bcma_device *dev) ++static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev) + { +- int err; ++ struct bcma_device *dev = usb_dev->core; ++ struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo; + u32 ohci_addr; +- struct bcma_hcd_device *usb_dev; +- struct bcma_chipinfo *chipinfo; +- +- chipinfo = &dev->bus->chipinfo; +- +- /* TODO: Probably need checks here; is the core connected? */ ++ int err; + + if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) + return -EOPNOTSUPP; + +- usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), +- GFP_KERNEL); +- if (!usb_dev) +- return -ENOMEM; +- +- bcma_hci_platform_power_gpio(dev, true); +- + switch (dev->id.id) { + case BCMA_CORE_NS_USB20: + bcma_hcd_init_chip_arm(dev); +@@ -346,7 +336,6 @@ static int bcma_hcd_probe(struct bcma_de + goto err_unregister_ohci_dev; + } + +- bcma_set_drvdata(dev, usb_dev); + return 0; + + err_unregister_ohci_dev: +@@ -354,6 +343,36 @@ err_unregister_ohci_dev: + return err; + } + ++static int bcma_hcd_probe(struct bcma_device *dev) ++{ ++ int err; ++ struct bcma_hcd_device *usb_dev; ++ ++ /* TODO: Probably need checks here; is the core connected? */ ++ ++ usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), ++ GFP_KERNEL); ++ if (!usb_dev) ++ return -ENOMEM; ++ usb_dev->core = dev; ++ ++ bcma_hci_platform_power_gpio(dev, true); ++ ++ switch (dev->id.id) { ++ case BCMA_CORE_USB20_HOST: ++ case BCMA_CORE_NS_USB20: ++ err = bcma_hcd_usb20_init(usb_dev); ++ if (err) ++ return err; ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ bcma_set_drvdata(dev, usb_dev); ++ return 0; ++} ++ + static void bcma_hcd_remove(struct bcma_device *dev) + { + struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); diff --git a/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch b/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch new file mode 100644 index 0000000000..3875da4fe4 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/812-USB-bcma-add-USB-3.0-support.patch @@ -0,0 +1,274 @@ +From 12c6932caa6b1fce44d0f0c68ec77d4c00ac0be7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Tue, 16 Jun 2015 17:14:26 +0200 +Subject: [PATCH] USB: bcma: add USB 3.0 support +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/usb/host/bcma-hcd.c | 219 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 219 insertions(+) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -37,6 +37,7 @@ struct bcma_hcd_device { + struct bcma_device *core; + struct platform_device *ehci_dev; + struct platform_device *ohci_dev; ++ struct platform_device *xhci_dev; + }; + + /* Wait for bitmask in a register to get set or cleared. +@@ -343,6 +344,215 @@ err_unregister_ohci_dev: + return err; + } + ++static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask, ++ u32 value, int timeout) ++{ ++ unsigned long deadline = jiffies + timeout; ++ u32 val; ++ ++ do { ++ val = readl(addr); ++ if ((val & mask) == value) ++ return true; ++ cpu_relax(); ++ udelay(10); ++ } while (!time_after_eq(jiffies, deadline)); ++ ++ pr_err("Timeout waiting for register %p\n", addr); ++ ++ return false; ++} ++ ++static void bcma_hcd_usb30_phy_init(struct bcma_hcd_device *bcma_hcd) ++{ ++ struct bcma_device *core = bcma_hcd->core; ++ struct bcma_bus *bus = core->bus; ++ struct bcma_chipinfo *chipinfo = &bus->chipinfo; ++ struct bcma_drv_cc_b *ccb = &bus->drv_cc_b; ++ struct bcma_device *arm_core; ++ void __iomem *dmu = NULL; ++ u32 cru_straps_ctrl; ++ ++ if (chipinfo->id != BCMA_CHIP_ID_BCM4707 && ++ chipinfo->id != BCMA_CHIP_ID_BCM53018) ++ return; ++ ++ arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9); ++ if (!arm_core) ++ return; ++ ++ dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000); ++ if (!dmu) ++ goto out; ++ ++ /* Check strapping of PCIE/USB3 SEL */ ++ cru_straps_ctrl = ioread32(dmu + 0x2a0); ++ if ((cru_straps_ctrl & 0x10) == 0) ++ goto out; ++ ++ /* Perform USB3 system soft reset */ ++ bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); ++ ++ /* Enable MDIO. Setting MDCDIV as 26 */ ++ iowrite32(0x0000009a, ccb->mii + 0x000); ++ udelay(2); ++ ++ switch (chipinfo->id) { ++ case BCMA_CHIP_ID_BCM4707: ++ if (chipinfo->rev == 4) { ++ /* For NS-B0, USB3 PLL Block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8000, ccb->mii + 0x004); ++ ++ /* Clear ana_pllSeqStart */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58061000, ccb->mii + 0x004); ++ ++ /* CMOS Divider ratio to 25 */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582a6400, ccb->mii + 0x004); ++ ++ /* Asserting PLL Reset */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582ec000, ccb->mii + 0x004); ++ ++ /* Deaaserting PLL Reset */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582e8000, ccb->mii + 0x004); ++ ++ /* Deasserting USB3 system reset */ ++ bcma_awrite32(core, BCMA_RESET_CTL, 0); ++ ++ /* Set ana_pllSeqStart */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58069000, ccb->mii + 0x004); ++ ++ /* RXPMD block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8020, ccb->mii + 0x004); ++ ++ /* CDR int loop locking BW to 1 */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58120049, ccb->mii + 0x004); ++ ++ /* CDR int loop acquisition BW to 1 */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580e0049, ccb->mii + 0x004); ++ ++ /* CDR prop loop BW to 1 */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580a005c, ccb->mii + 0x004); ++ ++ /* Waiting MII Mgt interface idle */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ } else { ++ /* PLL30 block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8000, ccb->mii + 0x004); ++ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582a6400, ccb->mii + 0x004); ++ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e80e0, ccb->mii + 0x004); ++ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580a009c, ccb->mii + 0x004); ++ ++ /* Enable SSC */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8040, ccb->mii + 0x004); ++ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580a21d3, ccb->mii + 0x004); ++ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58061003, ccb->mii + 0x004); ++ ++ /* Waiting MII Mgt interface idle */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ ++ /* Deasserting USB3 system reset */ ++ bcma_awrite32(core, BCMA_RESET_CTL, 0); ++ } ++ break; ++ case BCMA_CHIP_ID_BCM53018: ++ /* USB3 PLL Block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8000, ccb->mii + 0x004); ++ ++ /* Assert Ana_Pllseq start */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58061000, ccb->mii + 0x004); ++ ++ /* Assert CML Divider ratio to 26 */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582a6400, ccb->mii + 0x004); ++ ++ /* Asserting PLL Reset */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582ec000, ccb->mii + 0x004); ++ ++ /* Deaaserting PLL Reset */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x582e8000, ccb->mii + 0x004); ++ ++ /* Waiting MII Mgt interface idle */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ ++ /* Deasserting USB3 system reset */ ++ bcma_awrite32(core, BCMA_RESET_CTL, 0); ++ ++ /* PLL frequency monitor enable */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58069000, ccb->mii + 0x004); ++ ++ /* PIPE Block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8060, ccb->mii + 0x004); ++ ++ /* CMPMAX & CMPMINTH setting */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580af30d, ccb->mii + 0x004); ++ ++ /* DEGLITCH MIN & MAX setting */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x580e6302, ccb->mii + 0x004); ++ ++ /* TXPMD block */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x587e8040, ccb->mii + 0x004); ++ ++ /* Enabling SSC */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ iowrite32(0x58061003, ccb->mii + 0x004); ++ ++ /* Waiting MII Mgt interface idle */ ++ bcma_wait_reg(bus, ccb->mii + 0x000, 0x0100, 0x0000, 1000); ++ ++ break; ++ } ++out: ++ if (dmu) ++ iounmap(dmu); ++} ++ ++static int bcma_hcd_usb30_init(struct bcma_hcd_device *bcma_hcd) ++{ ++ struct bcma_device *core = bcma_hcd->core; ++ ++ bcma_core_enable(core, 0); ++ ++ bcma_hcd_usb30_phy_init(bcma_hcd); ++ ++ bcma_hcd->xhci_dev = bcma_hcd_create_pdev(core, "xhci-hcd", core->addr, ++ NULL, 0); ++ if (IS_ERR(bcma_hcd->ohci_dev)) ++ return PTR_ERR(bcma_hcd->ohci_dev); ++ ++ return 0; ++} ++ + static int bcma_hcd_probe(struct bcma_device *dev) + { + int err; +@@ -365,6 +575,11 @@ static int bcma_hcd_probe(struct bcma_de + if (err) + return err; + break; ++ case BCMA_CORE_NS_USB30: ++ err = bcma_hcd_usb30_init(usb_dev); ++ if (err) ++ return err; ++ break; + default: + return -ENODEV; + } +@@ -378,11 +593,14 @@ static void bcma_hcd_remove(struct bcma_ + struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); + struct platform_device *ohci_dev = usb_dev->ohci_dev; + struct platform_device *ehci_dev = usb_dev->ehci_dev; ++ struct platform_device *xhci_dev = usb_dev->xhci_dev; + + if (ohci_dev) + platform_device_unregister(ohci_dev); + if (ehci_dev) + platform_device_unregister(ehci_dev); ++ if (xhci_dev) ++ platform_device_unregister(xhci_dev); + + bcma_core_disable(dev, 0); + } +@@ -419,6 +637,7 @@ static int bcma_hcd_resume(struct bcma_d + static const struct bcma_device_id bcma_hcd_table[] = { + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), + BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS), ++ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB30, BCMA_ANY_REV, BCMA_ANY_CLASS), + {}, + }; + MODULE_DEVICE_TABLE(bcma, bcma_hcd_table); diff --git a/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch b/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch new file mode 100644 index 0000000000..9ba3bdeece --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/813-USB-bcma-fix-setting-VCC-GPIO-value.patch @@ -0,0 +1,45 @@ +From bdc3b01d94b22f8b5f9621a1c37336e78f4f1bce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 21 Jun 2015 12:09:57 +0200 +Subject: [PATCH] USB: bcma: fix setting VCC GPIO value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It wasn't working (on most of devices?) without setting GPIO direction +and wasn't respecting ACTIVE_LOW flag. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/usb/host/bcma-hcd.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/usb/host/bcma-hcd.c ++++ b/drivers/usb/host/bcma-hcd.c +@@ -230,17 +230,22 @@ static void bcma_hcd_init_chip_arm(struc + + static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val) + { ++ enum of_gpio_flags of_flags; + int gpio; + +- gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0); ++ gpio = of_get_named_gpio_flags(dev->dev.of_node, "vcc-gpio", 0, &of_flags); + if (!gpio_is_valid(gpio)) + return; + + if (val) { +- gpio_request(gpio, "bcma-hcd-gpio"); +- gpio_set_value(gpio, 1); ++ unsigned long flags = 0; ++ bool active_low = !!(of_flags & OF_GPIO_ACTIVE_LOW); ++ ++ flags |= active_low ? GPIOF_ACTIVE_LOW : 0; ++ flags |= active_low ? GPIOF_INIT_LOW : GPIOF_INIT_HIGH; ++ gpio_request_one(gpio, flags, "bcma-hcd-gpio"); + } else { +- gpio_set_value(gpio, 0); ++ gpiod_set_value(gpio_to_desc(gpio), 0); + gpio_free(gpio); + } + } diff --git a/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch new file mode 100644 index 0000000000..9a87a75dd4 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/820-xhci-add-Broadcom-specific-fake-doorbell.patch @@ -0,0 +1,94 @@ +From 9cc14ca0aae53c16d10ffea49848ac61a5015562 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 21 Jun 2015 11:10:49 +0200 +Subject: [PATCH] xhci: add Broadcom specific fake doorbell +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This fixes problem with controller seeing devices only in some small +percentage of cold boots. + +Signed-off-by: Rafał Miłecki <zajec5@gmail.com> +--- + drivers/usb/host/xhci.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -121,6 +121,64 @@ int xhci_halt(struct xhci_hcd *xhci) + return ret; + } + ++#ifdef CONFIG_ARCH_BCM_5301X ++int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id) ++{ ++ unsigned int temp1, ret; ++ ++ /* alloc a virt device for slot */ ++ if (!xhci_alloc_virt_device(xhci, slot_id, 0, GFP_NOIO)) { ++ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); ++ return 1; ++ } ++ ++ /* ring fake doorbell for slot_id ep 0 */ ++ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0); ++ mdelay(1); ++ ++ /* read the status register to check if HSE is set or not? */ ++ temp1 = readl(&xhci->op_regs->status); ++ xhci_dbg(xhci, "op reg status = %x\n",temp1); ++ ++ /* clear HSE if set */ ++ if(temp1 & STS_FATAL) { ++ xhci_dbg(xhci, "HSE problem detected\n"); ++ temp1 &= ~(0x1fff); ++ temp1 |= STS_FATAL; ++ xhci_dbg(xhci, "temp1=%x\n",temp1); ++ writel(temp1, &xhci->op_regs->status); ++ mdelay(1); ++ temp1 = readl(&xhci->op_regs->status); ++ xhci_dbg(xhci, "After clear op reg status=%x\n", temp1); ++ } ++ ++ /* Free virt device */ ++ xhci_free_virt_device(xhci, slot_id); ++ ++ /* Run the controller if needed */ ++ temp1 = readl(&xhci->op_regs->command); ++ if (temp1 & CMD_RUN) ++ return 0; ++ temp1 |= (CMD_RUN); ++ ++ writel(temp1, &xhci->op_regs->command); ++ /* ++ * Wait for the HCHalted Status bit to be 0 to indicate the host is running. ++ */ ++ ret = xhci_handshake(xhci, &xhci->op_regs->status, ++ STS_HALT, 0, XHCI_MAX_HALT_USEC); ++ ++ if (ret == -ETIMEDOUT) { ++ xhci_err(xhci, "Host took too long to start, " ++ "waited %u microseconds.\n", ++ XHCI_MAX_HALT_USEC); ++ return 1; ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_ARCH_BCM_5301X */ ++ + /* + * Set the run bit and wait for the host to be running. + */ +@@ -145,6 +203,10 @@ static int xhci_start(struct xhci_hcd *x + xhci_err(xhci, "Host took too long to start, " + "waited %u microseconds.\n", + XHCI_MAX_HALT_USEC); ++#ifdef CONFIG_ARCH_BCM_5301X ++ xhci_fake_doorbell(xhci, 1); ++#endif /* CONFIG_ARCH_BCM_5301X */ ++ + if (!ret) + xhci->xhc_state &= ~XHCI_STATE_HALTED; + return ret; diff --git a/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch b/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch new file mode 100644 index 0000000000..c1dfa92013 --- /dev/null +++ b/target/linux/bcm53xx/patches-4.1/901-mtd-bcm47xxpart-workaround-for-Asus-RT-AC87U-asus-pa.patch @@ -0,0 +1,42 @@ +From 21500872c1dba33848ddcf6bea97d58772675d36 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> +Date: Sun, 17 May 2015 14:00:52 +0200 +Subject: [PATCH] mtd: bcm47xxpart: workaround for Asus RT-AC87U "asus" + partition +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/mtd/bcm47xxpart.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/mtd/bcm47xxpart.c ++++ b/drivers/mtd/bcm47xxpart.c +@@ -14,6 +14,7 @@ + #include <linux/slab.h> + #include <linux/mtd/mtd.h> + #include <linux/mtd/partitions.h> ++#include <linux/of.h> + + #include <uapi/linux/magic.h> + +@@ -135,6 +136,17 @@ static int bcm47xxpart_parse(struct mtd_ + break; + } + ++ /* ++ * Ugly workaround for Asus RT-AC87U and its "asus" partition. ++ * It uses JFFS2 which we don't (want to) detect. We should ++ * probably use DT to define partitions but we need a working ++ * TRX firmware splitter first. ++ */ ++ if (of_machine_is_compatible("asus,rt-ac87u") && offset == 0x7ec0000) { ++ bcm47xxpart_add_part(&parts[curr_part++], "asus", offset, MTD_WRITEABLE); ++ continue; ++ } ++ + /* Read beginning of the block */ + if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, + &bytes_read, (uint8_t *)buf) < 0) { |