OpenWrt support for Linksys MX8500

Well, that is how fixed-cells work, its all predetermined, for anything else you need to add a custom NVMEM layout driver

But we can define larger size with header in nvmem-cells:

reg = <0x0 0x6002a>;

and then in aquantia_firmware.c:

  1. check if header exists 13 00 00 00
  2. if exists then use size from header
  3. if not use nvmem-cells size as before

Output from @Ansuel Provision Table Parser script:

python aqr_prov_table_parser.py AQR-G4_v5.6.5-AQR_WNC_SAQA-L2_GT_ID45287_VER24005.cld
Found a new section with priority 1
MMD: 0x1e	Reg: 0xc441	Val: 0x2000	Maks: 0x2000
MMD: 0x7	Reg: 0xc410	Val: 0x210	Maks: 0x73c
MMD: 0x7	Reg: 0xc411	Val: 0x3800	Maks: 0xf800
MMD: 0x7	Reg: 0x10	Val: 0x9000	Maks: 0xb000
MMD: 0x7	Reg: 0xc400	Val: 0x1000	Maks: 0x101f
MMD: 0xa	Reg: 0x4c	Val: 0xfffe	Maks: 0xffff
MMD: 0xa	Reg: 0x0	Val: 0xe	Maks: 0xe
MMD: 0xa	Reg: 0x54	Val: 0x66	Maks: 0xff
MMD: 0xa	Reg: 0x24	Val: 0xf0	Maks: 0xf0
MMD: 0xa	Reg: 0x20	Val: 0x5dc	Maks: 0xffff
MMD: 0xa	Reg: 0x94	Val: 0x302	Maks: 0xffff
MMD: 0x1e	Reg: 0xa152	Val: 0x100	Maks: 0x100
MMD: 0x1e	Reg: 0xc400	Val: 0x0	Maks: 0x8000
MMD: 0x1e	Reg: 0xc470	Val: 0xe04	Maks: 0xe04
MMD: 0x1e	Reg: 0xc43e	Val: 0x0	Maks: 0x1
MMD: 0xa	Reg: 0x23	Val: 0x10	Maks: 0x10
MMD: 0xa	Reg: 0x30	Val: 0x10	Maks: 0x10
MMD: 0xa	Reg: 0x24	Val: 0x1000	Maks: 0x1000
MMD: 0x7	Reg: 0x20	Val: 0x0	Maks: 0x1180
MMD: 0x7	Reg: 0xc400	Val: 0x0	Maks: 0x8000
MMD: 0x7	Reg: 0x10	Val: 0x0	Maks: 0xfe0
MMD: 0x7	Reg: 0x3c	Val: 0x0	Maks: 0xffff
MMD: 0x7	Reg: 0x3e	Val: 0x0	Maks: 0x3
MMD: 0x1	Reg: 0xe400	Val: 0x4	Maks: 0x4
MMD: 0xa	Reg: 0x10	Val: 0x8	Maks: 0x8
MMD: 0xa	Reg: 0x25	Val: 0x7d0	Maks: 0xffff
MMD: 0x1	Reg: 0x93	Val: 0x11	Maks: 0x11
MMD: 0x7	Reg: 0x20	Val: 0x20	Maks: 0x20
MMD: 0x7	Reg: 0x40	Val: 0x8	Maks: 0x8
MMD: 0x7	Reg: 0x20	Val: 0x40	Maks: 0x40
MMD: 0x7	Reg: 0x40	Val: 0x4	Maks: 0x4
MMD: 0x1e	Reg: 0xc475	Val: 0x50	Maks: 0x50
MMD: 0x1e	Reg: 0xc477	Val: 0x1ff	Maks: 0x1ff
MMD: 0xa	Reg: 0x10	Val: 0x0	Maks: 0xf004
MMD: 0xa	Reg: 0x24	Val: 0x0	Maks: 0x4
MMD: 0xa	Reg: 0x62	Val: 0xa00c	Maks: 0xffff
MMD: 0xa	Reg: 0x60	Val: 0x10	Maks: 0x10
MMD: 0xa	Reg: 0x64	Val: 0x3c0f	Maks: 0xff0f
MMD: 0xa	Reg: 0x65	Val: 0x64	Maks: 0x7f
MMD: 0xa	Reg: 0x66	Val: 0xa	Maks: 0x7f
Found a new section with priority 5
MMD: 0xa	Reg: 0x31	Val: 0x6520	Maks: 0xfff8
MMD: 0xa	Reg: 0x2	Val: 0x3	Maks: 0xffff
MMD: 0x7	Reg: 0xe820	Val: 0x0	Maks: 0x4
MMD: 0xa	Reg: 0x31	Val: 0x8180	Maks: 0xfff8
MMD: 0xa	Reg: 0x2	Val: 0x2	Maks: 0xffff
Found a new section with priority 11
MMD: 0x4	Reg: 0xe412	Val: 0x0	Maks: 0xfff
MMD: 0x4	Reg: 0xe413	Val: 0xc5	Maks: 0x1ff
MMD: 0x4	Reg: 0xe411	Val: 0x200	Maks: 0x200
Found a new section with priority 8
MMD: 0x4	Reg: 0xe412	Val: 0x0	Maks: 0xfff
MMD: 0x4	Reg: 0xe413	Val: 0xc5	Maks: 0x1ff
MMD: 0x4	Reg: 0xe411	Val: 0x200	Maks: 0x200
Found a new section with priority 7
MMD: 0x4	Reg: 0xe412	Val: 0x0	Maks: 0xfff
MMD: 0x4	Reg: 0xe413	Val: 0xc5	Maks: 0x1ff
MMD: 0x4	Reg: 0xe411	Val: 0x200	Maks: 0x200
Found a new section with priority 1
MMD: 0xa	Reg: 0x73	Val: 0x6	Maks: 0x307
MMD: 0xa	Reg: 0x72	Val: 0x2626	Maks: 0x3fff
MMD: 0xa	Reg: 0x72	Val: 0x2c00	Maks: 0x3c00
MMD: 0xa	Reg: 0x72	Val: 0x3400	Maks: 0x3c00
MMD: 0xa	Reg: 0x72	Val: 0x3c00	Maks: 0x3c00
Found a new section with priority 2
MMD: 0xa	Reg: 0x0	Val: 0x2	Maks: 0x2
MMD: 0xa	Reg: 0x64	Val: 0x3c00	Maks: 0xff00
Found a new section with priority 3
MMD: 0xa	Reg: 0x0	Val: 0x0	Maks: 0x2
MMD: 0xa	Reg: 0x64	Val: 0x1e00	Maks: 0xff00
Found a new section with priority 23
MMD: 0xa	Reg: 0x1d	Val: 0x24cd	Maks: 0xffff
Found a new section with priority 1
MMD: 0x1e	Reg: 0xc470	Val: 0x0	Maks: 0x1000
MMD: 0x1e	Reg: 0xc430	Val: 0x0	Maks: 0xffff
MMD: 0x1e	Reg: 0xc431	Val: 0x0	Maks: 0xffff
MMD: 0x1e	Reg: 0xc432	Val: 0x0	Maks: 0xffff
MMD: 0x7	Reg: 0x20	Val: 0x0	Maks: 0x1000
MMD: 0x7	Reg: 0x20	Val: 0x0	Maks: 0x100
MMD: 0x7	Reg: 0xc400	Val: 0x0	Maks: 0x800
MMD: 0x7	Reg: 0x20	Val: 0x0	Maks: 0x80
MMD: 0x7	Reg: 0xc400	Val: 0x0	Maks: 0x400
MMD: 0x7	Reg: 0xc400	Val: 0x0	Maks: 0x8000
MMD: 0x1e	Reg: 0xc478	Val: 0x0	Maks: 0x8000
MMD: 0x1e	Reg: 0x6103	Val: 0x101	Maks: 0x101
FOUND BUG IN PROVISION TABLE at pos 270484 for MMD reg 0x1e
MMD: 0x1e	Reg: 0xc08d	Val: 0x20	Maks: 0x20
MMD: 0x1e	Reg: 0xc495	Val: 0x4a	Maks: 0xfe
MMD: 0x1e	Reg: 0xc011	Val: 0x200	Maks: 0x200
MMD: 0x1e	Reg: 0x6103	Val: 0x202	Maks: 0x202
FOUND BUG IN PROVISION TABLE at pos 270512 for MMD reg 0x1e
MMD: 0x1e	Reg: 0xc08d	Val: 0x20	Maks: 0x20
MMD: 0x1e	Reg: 0xc495	Val: 0x4c	Maks: 0xfe
MMD: 0x1e	Reg: 0xc011	Val: 0x200	Maks: 0x200
MMD: 0x1e	Reg: 0x6103	Val: 0x404	Maks: 0x404
FOUND BUG IN PROVISION TABLE at pos 270540 for MMD reg 0x1e
MMD: 0x1	Reg: 0x1f8	Val: 0xc08d	Maks: 0x20
MMD: 0x1	Reg: 0x20	Val: 0xc495	Maks: 0x4e
MMD: 0x1	Reg: 0xfe	Val: 0xc011	Maks: 0x200
MMD: 0x1	Reg: 0x200	Val: 0x6103	Maks: 0x808
MMD: 0x1	Reg: 0x808	Val: 0x808	Maks: 0x1f8
MMD: 0x1	Reg: 0xc08d	Val: 0x20	Maks: 0x20
MMD: 0x1	Reg: 0xc495	Val: 0x50	Maks: 0xfe
MMD: 0x1	Reg: 0xc011	Val: 0x200	Maks: 0x200
MMD: 0x1	Reg: 0x6103	Val: 0x1010	Maks: 0x1010
FOUND BUG IN PROVISION TABLE at pos 270596 for MMD reg 0x1
MMD: 0x4	Reg: 0x1f8	Val: 0xc08d	Maks: 0x20
MMD: 0x4	Reg: 0x20	Val: 0xc495	Maks: 0x52
MMD: 0x4	Reg: 0xfe	Val: 0xc011	Maks: 0x200
MMD: 0x4	Reg: 0x200	Val: 0x6103	Maks: 0x2020
MMD: 0x4	Reg: 0x2020	Val: 0x2020	Maks: 0x1f8
MMD: 0x4	Reg: 0xc08d	Val: 0x20	Maks: 0x20
MMD: 0x4	Reg: 0xc495	Val: 0x54	Maks: 0xfe
MMD: 0x4	Reg: 0xc011	Val: 0x200	Maks: 0x200
MMD: 0x4	Reg: 0x6103	Val: 0x4040	Maks: 0x4040
MMD: 0x4	Reg: 0x4040	Val: 0x1f8	Maks: 0xc08d
MMD: 0x4	Reg: 0x20	Val: 0x20	Maks: 0xc495
MMD: 0x4	Reg: 0x56	Val: 0xfe	Maks: 0xc011
MMD: 0x4	Reg: 0x200	Val: 0x200	Maks: 0x6103
MMD: 0x4	Reg: 0x8080	Val: 0x8080	Maks: 0x8080
MMD: 0x4	Reg: 0x1f8	Val: 0xc08d	Maks: 0x20
MMD: 0x4	Reg: 0x20	Val: 0xc495	Maks: 0x58
MMD: 0x4	Reg: 0xfe	Val: 0xc011	Maks: 0x200
MMD: 0x4	Reg: 0x200	Val: 0x103	Maks: 0xf8
MMD: 0x4	Reg: 0xc885	Val: 0x1	Maks: 0xf
MMD: 0x4	Reg: 0xf8	Val: 0xc441	Maks: 0x0
MMD: 0x4	Reg: 0x10	Val: 0x84	Maks: 0x9
MMD: 0x4	Reg: 0x0	Val: 0xffff	Maks: 0x84
MMD: 0x4	Reg: 0xe400	Val: 0x2	Maks: 0x3
MMD: 0x4	Reg: 0x9c	Val: 0xc400	Maks: 0x800
MMD: 0x4	Reg: 0x800	Val: 0x9c	Maks: 0x20
MMD: 0x4	Reg: 0x100	Val: 0x100	Maks: 0x9c
MMD: 0x4	Reg: 0xc400	Val: 0x400	Maks: 0x400
MMD: 0x4	Reg: 0x9c	Val: 0x20	Maks: 0x80
MMD: 0x4	Reg: 0x80	Val: 0x9c	Maks: 0xc400
MMD: 0x4	Reg: 0x8000	Val: 0x8000	Maks: 0x9c
MMD: 0x4	Reg: 0x10	Val: 0x180	Maks: 0x180
MMD: 0x4	Reg: 0x9c	Val: 0x10	Maks: 0x60
MMD: 0x1e	Reg: 0x310	Val: 0x200	Maks: 0x200
MMD: 0x1e	Reg: 0x31b	Val: 0x200	Maks: 0x200
MMD: 0x1e	Reg: 0x31c	Val: 0x200	Maks: 0x200
Found a new section with priority 25
MMD: 0xa	Reg: 0x2	Val: 0x3	Maks: 0xffff
MMD: 0x1e	Reg: 0xc4a0	Val: 0x0	Maks: 0x1
MMD: 0xa	Reg: 0x2	Val: 0x6	Maks: 0xffff
MMD: 0x7	Reg: 0xc800	Val: 0x4	Maks: 0xe
MMD: 0x3	Reg: 0xe463	Val: 0x0	Maks: 0x2
MMD: 0x3	Reg: 0xc462	Val: 0x0	Maks: 0x2
MMD: 0x3	Reg: 0xe462	Val: 0x600	Maks: 0xf00
MMD: 0x3	Reg: 0xc463	Val: 0x86f0	Maks: 0xfff0
MMD: 0xa	Reg: 0x2	Val: 0x2	Maks: 0xffff
Found a new section with priority 1
MMD: 0x7	Reg: 0xc400	Val: 0x10	Maks: 0x10
MMD: 0x7	Reg: 0xc400	Val: 0x4	Maks: 0xf
MMD: 0x1e	Reg: 0x31f	Val: 0x80	Maks: 0x180
MMD: 0x1e	Reg: 0x31e	Val: 0x80	Maks: 0x180
MMD: 0x1e	Reg: 0x31d	Val: 0x80	Maks: 0x180
MMD: 0x1e	Reg: 0x31c	Val: 0x80	Maks: 0x180
MMD: 0x1e	Reg: 0x31b	Val: 0x80	Maks: 0x180
MMD: 0x1e	Reg: 0x310	Val: 0x80	Maks: 0x180
MMD: 0xa	Reg: 0x8d	Val: 0x1f4	Maks: 0xffff
MMD: 0x1e	Reg: 0x31a	Val: 0x5	Maks: 0xf
MMD: 0x1e	Reg: 0x31f	Val: 0x40	Maks: 0x40
MMD: 0x1e	Reg: 0x31e	Val: 0x40	Maks: 0x40
MMD: 0x1e	Reg: 0x31d	Val: 0x40	Maks: 0x40
MMD: 0x1e	Reg: 0x31c	Val: 0x40	Maks: 0x40
MMD: 0x1e	Reg: 0x31b	Val: 0x40	Maks: 0x40
MMD: 0x4	Reg: 0xe411	Val: 0x800	Maks: 0x800
MMD: 0x4	Reg: 0xe410	Val: 0x2	Maks: 0x2
MMD: 0x4	Reg: 0xc443	Val: 0x800	Maks: 0x800
MMD: 0x4	Reg: 0xc442	Val: 0x2	Maks: 0x2
MMD: 0x1e	Reg: 0xc430	Val: 0x3	Maks: 0x3
MMD: 0x1e	Reg: 0xc430	Val: 0xc	Maks: 0xc
MMD: 0x1e	Reg: 0xc431	Val: 0x20	Maks: 0x20
MMD: 0x1e	Reg: 0xc431	Val: 0x40	Maks: 0x40
MMD: 0x1e	Reg: 0xc431	Val: 0x4000	Maks: 0x4000
MMD: 0x1e	Reg: 0xc431	Val: 0x8000	Maks: 0x8000
MMD: 0xa	Reg: 0x6a	Val: 0x8	Maks: 0x8
MMD: 0xa	Reg: 0x6a	Val: 0x10	Maks: 0x10
MMD: 0x1e	Reg: 0xc08d	Val: 0x20	Maks: 0x20
MMD: 0x1e	Reg: 0xc495	Val: 0x4a	Maks: 0xfe
MMD: 0x1e	Reg: 0xc011	Val: 0x200	Maks: 0x200
MMD: 0x1	Reg: 0xc41c	Val: 0xb0e7	Maks: 0xffff
MMD: 0x1	Reg: 0xc41d	Val: 0xb0e7	Maks: 0xffff
MMD: 0x1	Reg: 0xc41e	Val: 0x5dc5	Maks: 0xffff
MMD: 0x1e	Reg: 0x20	Val: 0x909	Maks: 0xffff
MMD: 0x1e	Reg: 0xc885	Val: 0x50	Maks: 0xf0

No we cant, as buffer passed by NVMEM cell is supposed to be the same thing as when you are loading a binary from rootfs.
This additional post processing is not universal and not upstreamable.

If you want to do any kind of processing it needs to happen in a separate NVMEM layout driver or like, but its probably not worth it at all since I am yet to see a vendor ship updated FW

So should we use the size of the latest firmware in dts and add instructions on how to update the firmware, or leave the size of the old firmware that is installed by default?

I would go for latest FW and instructions on it

I created a simple script that adds an MBN header to the firmware file that can be run on the router.
Do you think this script can be included for devices with AQR PHY?

#!/bin/sh

data_2bin_str_be() {
        local data=$1
        local len=${#1}
        local bin_str_data

        for i in $(seq $((len - 2)) -2 0); do
                bin_str_data="${bin_str_data}\x${data:i:2}"
        done

        echo -n $bin_str_data
}

mbn_header() {
        local img_type=0x13
        local version=0x3
        local base=0x44000000
        local size=$(wc -c < "$1")
        local base_size=$((base + size))
        local header="$img_type $version 0x0 $base $size $size $base_size 0x0 $base_size 0x0"
        local header_data

        for segment in $header; do
                header_data="${header_data}$(data_2bin_str_be `printf '%08x' $segment`)"
        done

        echo -ne $header_data
}

if ! [[ "$1" && "$2" ]]; then
        echo "Usage: aqr_fw_mbn.sh AQR-G4_v5.6.5-AQR_WNC_SAQA-L2_GT_ID45287_VER24005.cld aqr_fw.mbn"
        exit
elif [ ! -f "$1" ]; then
        echo "Firmware file not found!"
        exit 1
elif [ -f "$2" ]; then
        echo "Output file already exist!"
        exit 1
fi

mbn_header "$1" | dd conv=notrunc bs=2 of="$2"
dd conv=notrunc bs=2 if="$1" >> "$2"

Personally I dont see how it makes anything easier when you can just add the MBN header before copying the binary to the router

I'm wondering how to easily distribute the script.

What could be the reason for the lack of communication on the serial port from Bluetooth?
Should all GPIOs have identical state and configuration on OEM and OpenWrt?

Simply link to it in the device Wiki along with instructions.

What IC is used for BT?

There is no Wiki yet.

BT chip is NXP K32W041. There is no any special initialization in the OEM firmware:

# Program BT Mac address
BT_MAC_ADDR=`syscfg get bt_mac_addr`
echo "[utopia][init] Bluetooth Mac Address: $BT_MAC_ADDR" >> /dev/console
BT_MAC_ADDR=`echo "$BT_MAC_ADDR" | tr -d ':'`
#Only need program FW and MAC to flash once, temporary for HW2 board
#if [ -z "`syscfg get ProgramBTFW`" ]; then                                          
#   /bin/K32WScript_ProgramFirmware /etc/hci_black_box_bm_dec7.bin  2>&1 > /dev/null
#   sleep 1
#   /bin/K32WScript_ProgramMAC $BT_MAC_ADDR 2>&1 > /dev/null
#   sleep 0.5
#   syscfg set ProgramBTFW 1
#fi
gpio 21 0; gpio 21 1
sleep 1
hciattach -s 115200 /dev/ttyMSM1 any 115200
sleep 0.5
hciconfig hci0 up
wait_hci0_program_bt_fw
wait_hci0_program_bt_fw()
{
   local NUM=0
   local need_program=0
   local STATUS=`hciconfig -a | grep "UP" | awk '{print $2}'`
   while [ "${STATUS}" != "RUNNING" ] && [ $NUM -le 5 ]; do
        NUM=$(($NUM + 1))
        sleep 0.5 
        STATUS=`hciconfig -a | grep "UP" |awk '{print $2}'`
   done
   if [ "${STATUS}" == "RUNNING" ]; then
	echo "===>success hci0 up,num:$NUM"
   	let BT_CURR_VERSION=`hciconfig -a | grep LMP | awk '{ print $6}'`
	echo "===> BT FW current version $BT_CURR_VERSION"
   	let BT_BASE_VERSION=0x1503
	if [ $BT_CURR_VERSION -lt $BT_BASE_VERSION ]; then
	     echo "===>Need program BT FW due to cur_version is lower!"
	     need_program=1
   	fi
   else
	  echo "===>failed hci up!"
	  need_program=1
   fi

  if [ "1" == "$need_program" ]; then
     echo "===>Need upgrade BT FW, programming BT FW now......"
     killall hciattach
     /bin/K32WScript_ProgramFirmware /etc/hci_latest.bin  2>&1 > /dev/null
     sleep 1
     /bin/K32WScript_ProgramMAC $BT_MAC_ADDR 2>&1 > /dev/null
     sleep 0.5
     gpio 21 0; gpio 21 1
     #hciattach -s 115200 /dev/ttyMSM1 any 115200
  else
     echo "===>Need NOT program BT FW!!"
     #hciconfig hci0 down
     killall hciattach
     gpio 21 0; gpio 21 1
     # hciattach -s 115200 /dev/ttyMSM1 any 115200
  fi

}

BT works. hsuart is used for BT.
I don't know what the additional serial port is used for in OEM firmware:

lrwxrwxrwx    1 root     root             0 Dec 31  1969 ttyMSM0 -> ../../devices/platform/soc/78b3000.serial/tty/ttyMSM0
lrwxrwxrwx    1 root     root             0 Dec 31  1969 ttyMSM1 -> ../../devices/platform/soc/78b1000.serial/tty/ttyMSM1
lrwxrwxrwx    1 root     root             0 Dec 31  1969 ttyMSM2 -> ../../devices/platform/soc/78b4000.serial/tty/ttyMSM2
root@OpenWrt:/# hciconfig -a
hci0:	Type: Primary  Bus: UART
	BD Address: *:*:*:*:*:*  ACL MTU: 251:2  SCO MTU: 0:0
	UP RUNNING 
	RX bytes:520 acl:0 sco:0 events:40 errors:0
	TX bytes:226 acl:0 sco:0 commands:40 errors:0
	Features: 0x00 0x00 0x00 0x00 0x60 0x00 0x00 0x00
	Packet type: DM1 DH1 HV1 
	Link policy: 
	Link mode: PERIPHERAL ACCEPT 
	Name: 'Linksys'
	Class: 0x000000
	Service Classes: Unspecified
	Device Class: Miscellaneous, 
	HCI Version: 5.0 (0x9)  Revision: 0x415
	LMP Version: 5.0 (0x9)  Subversion: 0x1503
	Manufacturer: NXP Semiconductors (formerly Philips Semiconductors) (37)

It could just be a leftover from whatever reference board they used, nice to see one that is compatible with bluez and doesn't use some custom FW for BT

There is a chance that it can be used as Thread Border Router. But first firmware need to be prepared and updated: https://github.com/openthread/ot-nxp/blob/main/src/k32w0/k32w061/README.md

1 Like

@robimarko Is there anything that can be done to fix this issue in kernel 6.6 for now?

Which issue?

[ 14.024498] ssdk_phy_driver_init[372]:INFO:dev_id = 0, phy_adress = 8, phy_id = 0x0 phytype doesn't match

Well, one option would be to load the SSDK and NSS-DP later, cause currently they are loaded relatively early, but on the other hand firmware loading takes quite a while anyway.

So, some kind of defferal would need to be implemented in SSDK and good luck untangling that mess

But the problem occurs even when the firmware is loaded from u-boot.

Nothing changed after setting loading order:

90-qca-ssdk
95-qca-nss-dp

This should fix it, please give it a go: