bcm53xx: add Cisco Meraki MR32
authorChristian Lamparter <chunkeey@gmail.com>
Sat, 29 Aug 2020 21:48:00 +0000 (23:48 +0200)
committerChristian Lamparter <chunkeey@gmail.com>
Fri, 25 Sep 2020 17:32:34 +0000 (19:32 +0200)
This patch adds support for Cisco Meraki MR32.
The unit was donated by Chris Blake. Thank you!

WARNING:
Only the 1x1:1 abgn Air Marshal WIPS wifi is currently supported by b43:
 b43-phy2: Found PHY: Analog 9, Type 4 (N), Revision 16
 b43-phy2: Found Radio: Manuf 0x17F, ID 0x2057, Revision 9, Version 1
 b43-phy2: Loading firmware version 784.2 (2012-08-15 21:35:19)
 and only as 802.11ABG!

while WIFI1 and WIFI2 (both BCM4352) are not:
 b43-phy0: Broadcom 4352 WLAN found (core revision 42)
 b43-phy0 ERROR: FOUND UNSUPPORTED PHY (Analog 12, Type 11 (AC), Revision 1)

Hardware Highlights:

SoC: Broadcom BCM53016A1 (1 GHz, 2 cores)
RAM: 128 MiB
NAND: 128 MiB Spansion S34ML01G2 (~114 MiB useable)
ETH: 1GBit Ethernet Port - PoE
WIFI1: Broadcom BCM43520 an+ac (2x2:2 - id: 0x4352)
WIFI2: Broadcom BCM43520 bgn (2x2:2 - id: 0x4352)
WIFI3: Broadcom BCM43428 abgn (1x1:1 - id: 43428)

BLE: Broadcom BCM20732 (ttyS1)
LEDS:   1 x Programmable RGB Status LED (driven by a PWM)
1 x White LED (GPIO)
1 x Orange LED Fault Indicator (GPIO)
2 x LAN Activity / Speed LEDs (On the RJ45 Port)
BUTTON: one Reset button
MISC:   AT24C64 8KiB EEPROM (i2c - stores Ethernet MAC + Serial#!)
ina219 hardware monitor (i2c)
Kensington Lock

SERIAL:
WARNING: The serial port needs a TTL/RS-232 3V3 level converter!
The Serial setting is 115200-8-N-1. The board has a populated
right angle 1x4 0.1" pinheader.
The pinout is: VCC, RX, TX, GND. (Use a multimeter)

Flashing needs a serial adaptor (due to the lack of a working dropbear on
the original firmware).

This flashing procedure for the MR32 was tested with firmware:
"r23-149867:150252-aacharya".

0. Create a seperate Ethernet LAN which does not have access to the internet.
   Ideally use 192.168.1.2 for your PC. Make sure to reserve 192.168.1.1 it
   will be used later on by the OpenWrt firmware. The original Meraki firmware
   will likely try to setup the network via DHCP Discovery, so make sure your
   PC is running a DHCP-Server (i.e.: dnsmasq)
   '# dnsmasq -i eth# -F 192.168.1.5,192.168.1.50
   Furthermore, the PC needs a supported ssh/http/ftp server in order to
   retrieve the initramfs + dtb file

1. Disassemble the MR32 device by removing all screws (4 screws are located
   under the 4 rubber feets!) and prying open the plastic covers without
   breaking the plastic retention clips. Once inside, remove all the screws
   on the outer metal shielding to get to the PCB. It's not necessary to
   remove the antennas!

2. Connect the serial cable to the serial header.

3. Partially reassemble the outer metal shielding to ensure that the SoC
   has a proper heat sink.

4. Connect the Ethernet patch cable to the device and the power cable.

5. Wait for the device to boot and enter the root shell.
   (rooting is not discussed in detail here please refer to
   Chris Blake - "pwning the meraki mr18" blog post:
   <https://servernetworktech.com/2016/02/pwning-the-meraki-mr18/>
   (The same method works with the MR32's r23-149867:150252-aacharya)

   Wait for the MR32 to enter the "<Meraki>" prompt and enter:
   <Meraki> odm serial_num read
   (Verify that it matches what's on the S/N Sticker on the back!)
   <Meraki> odm serial_num write Q2XX-XXXX-XXXV
   <Meraki> odm serial_num read
   (Verify that the S/N has changed - and the LED start to flash)

   now to flash the firmware:
   <Meraki> odm firmware part.safe "http://192.168.1.2/mr32-initramfs.bin"

Once OpenWrt booted use sysupgrade to permanently install
OpenWrt. To do this: Download the latest sysupgrade.bin file
for the MR32 to the device and use sysupgrade *sysupgrade.bin
to install it.

WARNING: DO NOT DELETE the "storage" ubi volume!

To flash later MR32 Firmwares like r25-201804051805-G885d6d78-dhow-rel
requires in-circut-i2c tools to access the I2C EEPROM AT24C64 next to
the SoC. The idea is pretty much the same as from Step 5 from above:
Change the serial number to Q2XXXXXXXXXV (should be around 0x7c), then
attach a serial cable, ethernet (but make sure the device can't reach
the internet!) hit "s" (the small s!) during boot to enter the root-shell
and add the following commands to the /storage/config there:

serial_allow_odm true
serial_access_enabled true
serial_access_check false
valid_config true

and then hit exit to let it finish booting.

Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
target/linux/bcm53xx/base-files/etc/board.d/02_network
target/linux/bcm53xx/base-files/etc/diag.sh
target/linux/bcm53xx/base-files/lib/preinit/07_set_preinit_iface_bcm53xx [new file with mode: 0644]
target/linux/bcm53xx/base-files/lib/upgrade/platform.sh
target/linux/bcm53xx/image/Makefile
target/linux/bcm53xx/patches-5.4/330-ARM-BCM5301X-Add-DT-for-Meraki-MR32.patch [new file with mode: 0644]
target/linux/bcm53xx/patches-5.4/331-Meraki-MR32-Status-LEDs.patch [new file with mode: 0644]

index 5752b7760d986214e195b4666f098d5e634b6ec3..231566cfa01c9112aef1a5a1c97cbed7795591d8 100755 (executable)
@@ -89,10 +89,15 @@ bcm53xx_setup_macs()
        netgear,r8500)
                # As vendor doesn't use eth0 its MAC may be missing. Use one from eth2.
                et2macaddr="$(nvram get et2macaddr)"
-               [ -n "$et2macaddr" ] && ucidef_set_interface_macaddr "lan" "$et2macaddr"
+               ;;
+       meraki,mr32)
+               # The MAC is stored on an AT24C64 eeprom and not on the nvram
+               et2macaddr=$(get_mac_binary "/sys/bus/i2c/devices/0-0050/eeprom" 0x66)
                ;;
        esac
 
+       [ -n "$et2macaddr" ] && ucidef_set_interface_macaddr "lan" "$et2macaddr"
+
        wan_macaddr="$(nvram get wan_hwaddr)"
        case "$board" in
        asus,rt-ac87u)
index 1a9332327ac30ece061308a44a13873863a6df55..bf5b779aa8a94d64ac622d64dcb8f9a141556675 100644 (file)
@@ -18,6 +18,9 @@ get_status_led() {
                status_led=$(basename $status_led_file)
                return
        fi;
+
+       # And finally, let's also try the device-Tree aliases node
+       status_led="$(get_dt_led status)"
 }
 
 set_state() {
diff --git a/target/linux/bcm53xx/base-files/lib/preinit/07_set_preinit_iface_bcm53xx b/target/linux/bcm53xx/base-files/lib/preinit/07_set_preinit_iface_bcm53xx
new file mode 100644 (file)
index 0000000..9e7c4b8
--- /dev/null
@@ -0,0 +1,14 @@
+set_preinit_iface() {
+       . /lib/functions.sh
+
+       case $(board_name) in
+       meraki,mr32)
+               # switch needs to be out of the vlan mode.
+               swconfig dev switch0 set reset 1
+               swconfig dev switch0 set enable_vlan 0
+               swconfig dev switch0 set apply 1
+               ;;
+       esac
+}
+
+boot_hook_add preinit_main set_preinit_iface
index 40b2ef67be5b9c1f2a0cfbdf1717f0747d148e75..cbb82902752b5adf72e3edf2d5859fedfa6453c5 100644 (file)
@@ -96,7 +96,7 @@ platform_identify() {
        echo "unknown"
 }
 
-platform_check_image() {
+platform_other_check_image() {
        [ "$#" -gt 1 ] && return 1
 
        local file_type=$(platform_identify "$1")
@@ -227,6 +227,25 @@ platform_check_image() {
        return $error
 }
 
+platform_check_image() {
+       case "$(board_name)" in
+       meraki,mr32)
+               # Ideally, REQUIRE_IMAGE_METADATA=1 would suffice
+               # but this would require converting all other
+               # devices too.
+               nand_do_platform_check meraki-mr32 "$1"
+               return $?
+               ;;
+       *)
+               platform_other_check_image "$1"
+               return $?
+               ;;
+       esac
+
+       return 1
+}
+
+
 # $(1): image for upgrade (with possible extra header)
 # $(2): offset of trx in image
 platform_do_upgrade_nand_trx() {
@@ -393,7 +412,7 @@ platform_img_from_seama() {
        echo -n $dir/image-entity.bin
 }
 
-platform_do_upgrade() {
+platform_other_do_upgrade() {
        local file_type=$(platform_identify "$1")
        local trx="$1"
        local cmd=
@@ -424,3 +443,23 @@ platform_do_upgrade() {
 
        default_do_upgrade "$trx" "$cmd"
 }
+
+platform_do_upgrade() {
+       case "$(board_name)" in
+       meraki,mr32)
+               CI_KERNPART="part.safe"
+               nand_do_upgrade "$1"
+               ;;
+       *)
+               platform_other_do_upgrade "$1"
+               ;;
+       esac
+}
+
+platform_nand_pre_upgrade() {
+       case "$(board_name)" in
+       meraki,mr32)
+               CI_KERNPART="part.safe"
+               ;;
+       esac
+}
index 768477160a74dff19c97b6a3a1c6f406b37418c0..9ceb5f6212e6427b21b25591adbb1af33f27ab22 100644 (file)
@@ -320,6 +320,33 @@ define Device/luxul_xwr-3150
 endef
 TARGET_DEVICES += luxul_xwr-3150
 
+define Device/meraki_mr32
+  DEVICE_VENODR := Meraki
+  DEVICE_MODEL := MR32
+  DEVICE_PACKAGES := $(B43) kmod-i2c-bcm-iproc kmod-i2c-gpio kmod-eeprom-at24 \
+       kmod-leds-pwm kmod-hwmon-ina2xx kmod-bluetooth
+  DEVICE_DTS := bcm53016-meraki-mr32
+# Meraki FW r23 tries to resize the part.safe partition before it will
+# flash the image. This is a bit of a problem, since resizing will fail
+# if the partition is smaller than the old one.
+  KERNEL_LOADADDR := 0x00008000
+  KERNEL_INITRAMFS_SUFFIX := .bin
+  KERNEL_INITRAMFS := kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb | \
+       pad-to 10362880
+  KERNEL := kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb
+  IMAGES := sysupgrade.bin
+  IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata
+
+# Currently the only device that uses the new image check
+  SUPPORTED_DEVICES := meraki,mr32
+
+# The loader is specifically looking for fdt@2:
+# [    3.190000] find_itb_subimage: error finding fdt@2: FDT_ERR_NOTFOUND
+# The image won't boot, if it isn't found. :(
+  DEVICE_FDT_NUM := 2
+endef
+TARGET_DEVICES += meraki_mr32
+
 define Device/netgear
   DEVICE_VENDOR := NETGEAR
   IMAGES := chk
diff --git a/target/linux/bcm53xx/patches-5.4/330-ARM-BCM5301X-Add-DT-for-Meraki-MR32.patch b/target/linux/bcm53xx/patches-5.4/330-ARM-BCM5301X-Add-DT-for-Meraki-MR32.patch
new file mode 100644 (file)
index 0000000..29329eb
--- /dev/null
@@ -0,0 +1,261 @@
+From ec88a9c344d9fd8c3b11bff1f99a0b6248ae256d Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Sat, 22 Aug 2020 18:19:23 +0200
+Subject: [PATCH] ARM: BCM5301X: Add DT for Meraki MR32
+
+add support for the Cisco Meraki MR32.
+This is a dual-band enterprise class 802.11ac access point.
+The unit was donated by Chris Blake. Thank you!
+
+SoC:    Broadcom BCM53016A1 (1 GHz, 2 cores)
+RAM:    128 MiB
+NAND:   128 MiB Spansion S34ML01G2 (~114 MiB useable)
+ETH:    1GBit Ethernet Port - PoE
+WIFI1:  Broadcom BCM43520 an+ac (2x2:2 - id: 0x4352)
+WIFI2:  Broadcom BCM43520 bgn (2x2:2 - id: 0x4352)
+WIFI3:  Broadcom BCM43428 abgn (1x1:1 - id: 43428)
+
+BLE:    Broadcom BCM20732 (ttyS1)
+LEDS:   1 x Programmable RGB Status LED (driven by a PWM)
+        1 x White LED (GPIO)
+        1 x Orange LED Fault Indicator (GPIO)
+        2 x LAN Activity / Speed LEDs (On the RJ45 Port)
+BUTTON: one Reset button
+MISC:   AT24C64 8KiB EEPROM (i2c - stores Ethernet MAC)
+        ina219 hardware monitor (i2c)
+        Kensington Lock
+
+SERIAL:
+       WARNING: The serial port needs a TTL/RS-232 3V3 level converter!
+        The Serial setting is 115200-8-N-1. The board has a populated
+        right angle 1x4 0.1" pinheader.
+        The pinout is: VCC, RX, TX, GND.
+
+Odd stuff:
+       - uart0 clock frequency is 62.5 MHz.
+       - The LEDs are labeled as SYS-LED1 through SYS-LED3
+         because of the silkscreen on the PCB.
+       - the original u-boot has been compiled with most functions
+         and commands disabled. The u-boot env isn't setup properly
+         either and as a result, the bcm47xxpart probing is not
+         working. Hence, the nand partitions are specified through a
+         "fixed-partition" binding.
+       - The "WICED SMART(TM)" Bluetooth LE 4.0 BCM20732 chip is
+         connected to uart2 of the SoC. The BCM20732 does not
+         provide a HCI. So the linux' bluetooth stack is useless.
+         The mock-up node with the compatible binding and
+         enable-gpios property is provided solely as documentation.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+
+--- a/arch/arm/boot/dts/Makefile
++++ b/arch/arm/boot/dts/Makefile
+@@ -119,6 +119,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
+       bcm47094-luxul-xwr-3150-v1.dtb \
+       bcm47094-netgear-r8500.dtb \
+       bcm47094-phicomm-k3.dtb \
++      bcm53016-meraki-mr32.dtb \
+       bcm94708.dtb \
+       bcm94709.dtb \
+       bcm953012er.dtb \
+--- /dev/null
++++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
+@@ -0,0 +1,197 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++/*
++ * Broadcom BCM470X / BCM5301X ARM platform code.
++ * DTS for Meraki MR32 / Codename: Espresso
++ *
++ * Copyright (C) 2018-2020 Christian Lamparter <chunkeey@gmail.com>
++ */
++
++/dts-v1/;
++
++#include "bcm4708.dtsi"
++#include "bcm5301x-nand-cs0-bch8.dtsi"
++#include <dt-bindings/leds/common.h>
++
++/ {
++      compatible = "meraki,mr32", "brcm,brcm53016", "brcm,bcm4708";
++      model = "Meraki MR32";
++
++      chosen {
++              bootargs = " console=ttyS0,115200n8 earlycon";
++      };
++
++      memory {
++              reg = <0x00000000 0x08000000>;
++              device_type = "memory";
++      };
++
++      aliases {
++              serial1 = &uart2;
++      };
++
++      leds {
++              compatible = "gpio-leds";
++
++              sysled3 {
++                      function = LED_FUNCTION_FAULT;
++                      color = <LED_COLOR_ID_AMBER>;
++                      gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
++                      panic-indicator;
++              };
++              sysled2 {
++                      function = LED_FUNCTION_INDICATOR;
++                      color = <LED_COLOR_ID_WHITE>;
++                      gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>;
++              };
++      };
++
++      keys {
++              compatible = "gpio-keys";
++              #address-cells = <1>;
++              #size-cells = <0>;
++
++              restart {
++                      label = "Reset";
++                      linux,code = <KEY_RESTART>;
++                      gpios = <&chipcommon 21 GPIO_ACTIVE_LOW>;
++              };
++      };
++
++      pwm-leds {
++              compatible = "pwm-leds";
++
++              red {
++                      /* SYS-LED 1 - Tricolor */
++                      function = LED_FUNCTION_INDICATOR;
++                      color = <LED_COLOR_ID_RED>;
++                      pwms = <&pwm 0 50000 0>;
++                      max-brightness = <255>;
++              };
++
++              green {
++                      /* SYS-LED 1 - Tricolor */
++                      function = LED_FUNCTION_POWER;
++                      color = <LED_COLOR_ID_GREEN>;
++                      pwms = <&pwm 1 50000 0>;
++                      max-brightness = <255>;
++              };
++
++              blue {
++                      /* SYS-LED 1 - Tricolor */
++                      function = LED_FUNCTION_INDICATOR;
++                      color = <LED_COLOR_ID_BLUE>;
++                      pwms = <&pwm 2 50000 0>;
++                      max-brightness = <255>;
++              };
++      };
++
++      i2c {
++              /*
++               * The platform provided I2C does not budge.
++               * This is a replacement until I can figure
++               * out what are the missing bits...
++               */
++
++              compatible = "i2c-gpio";
++              sda-gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
++              scl-gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
++              i2c-gpio,delay-us = <10>; /* close to 100 kHz */
++              #address-cells = <1>;
++              #size-cells = <0>;
++
++              current_sense: ina219@45 {
++                      compatible = "ti,ina219";
++                      reg = <0x45>;
++                      shunt-resistor = <60000>; /* = 60 mOhms */
++              };
++
++              eeprom: eeprom@50 {
++                      compatible = "atmel,24c64";
++                      reg = <0x50>;
++                      pagesize = <32>;
++                      read-only;
++              };
++      };
++};
++
++&uart0 {
++      clock-frequency = <62500000>;
++      /delete-property/ clocks;
++};
++
++&uart1 {
++      status = "disabled";
++};
++
++&uart2 {
++      status = "okay";
++      /*
++       * bluetooth-le {
++       *      compatible = "brcm,bcm20732";
++       *      enable-gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>;
++       *};
++       */
++};
++
++&gmac1 {
++      status = "disabled";
++};
++&gmac2 {
++      status = "disabled";
++};
++&gmac3 {
++      status = "disabled";
++};
++
++&pwm {
++      status = "okay";
++      pinctrl-names = "default";
++      pinctrl-0 = <&pinmux_pwm>;
++};
++
++&nandcs {
++      nand-ecc-algo = "hw";
++
++      partitions {
++              /*
++               * The partition autodetection does not work for this device.
++               * It will only detect the "nvram" partition with an incorrect size.
++               *      [    1.721667] 1 bcm47xxpart partitions found on MTD device brcmnand.0
++               *      [    1.727962] Creating 1 MTD partitions on "brcmnand.0":
++               *      [    1.733117] 0x000000400000-0x000008000000 : "nvram"
++               */
++
++              compatible = "fixed-partitions";
++              #address-cells = <0x1>;
++              #size-cells = <0x1>;
++
++              partition0@0 {
++                      label = "u-boot";
++                      reg = <0x0 0x100000>;
++                      read-only;
++              };
++
++              partition1@100000 {
++                      label = "bootkernel1";
++                      reg = <0x100000 0x300000>;
++                      read-only;
++              };
++
++              partition2@400000 {
++                      label = "nvram";
++                      reg = <0x400000 0x100000>;
++                      read-only;
++              };
++
++              partition3@500000 {
++                      label = "bootkernel2";
++                      reg = <0x500000 0x300000>;
++                      read-only;
++              };
++
++              partition4@800000 {
++                      label = "ubi";
++                      reg = <0x800000 0x7780000>;
++              };
++      };
++};
diff --git a/target/linux/bcm53xx/patches-5.4/331-Meraki-MR32-Status-LEDs.patch b/target/linux/bcm53xx/patches-5.4/331-Meraki-MR32-Status-LEDs.patch
new file mode 100644 (file)
index 0000000..fb78ee9
--- /dev/null
@@ -0,0 +1,28 @@
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 7 Jun 2018 19:29:12 +0200
+Subject: bcm53xx: add LED status label alias for Meraki MR32
+
+add an led-status alias label. This is used by OpenWrt's LED
+DTS lookup function to identifiy the indicator LED
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+
+--- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
++++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
+@@ -27,6 +27,7 @@
+       aliases {
+               serial1 = &uart2;
++              led-status = &led_status;
+       };
+       leds {
+@@ -68,7 +69,7 @@
+                       max-brightness = <255>;
+               };
+-              green {
++              led_status: green {
+                       /* SYS-LED 1 - Tricolor */
+                       function = LED_FUNCTION_POWER;
+                       color = <LED_COLOR_ID_GREEN>;