diff --git a/package/boot/uboot-envtools/files/mediatek b/package/boot/uboot-envtools/files/mediatek
index ba6d780c4926..ce28fb31cbca 100644
--- a/package/boot/uboot-envtools/files/mediatek
+++ b/package/boot/uboot-envtools/files/mediatek
@@ -24,6 +24,9 @@ case "$board" in
 	ubootenv_add_uci_config "$envdev" "0x0" "0x80000" "0x80000" "1"
 	ubootenv_add_uci_config "$envdev" "0x80000" "0x80000" "0x80000" "1"
 	;;
+buffalo,wsr-2533dhp2)
+	ubootenv_add_uci_config "/dev/mtd3" "0x0" "0x1000" "0x1000"
+	;;
 esac
 
 config_load ubootenv
diff --git a/package/system/mtd/src/Makefile b/package/system/mtd/src/Makefile
index 6baea52b8f03..e204ecb221d5 100644
--- a/package/system/mtd/src/Makefile
+++ b/package/system/mtd/src/Makefile
@@ -12,6 +12,7 @@ obj.gemini = $(obj.wrgg)
 obj.brcm = trx.o
 obj.bcm47xx = $(obj.brcm)
 obj.bcm53xx = $(obj.brcm) $(obj.seama)
+obj.mediatek = $(obj.brcm)
 obj.bcm63xx = imagetag.o
 obj.bmips = imagetag.o
 obj.ramips = $(obj.seama) $(obj.tpl) $(obj.wrg) linksys_bootcount.o
diff --git a/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts b/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts
new file mode 100644
index 000000000000..198c78476d33
--- /dev/null
+++ b/target/linux/mediatek/dts/mt7622-buffalo-wsr-2533dhp2.dts
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#include "mt7622.dtsi"
+#include "mt6380.dtsi"
+
+/ {
+	model = "Buffalo WSR-2533DHP2";
+	compatible = "buffalo,wsr-2533dhp2", "mediatek,mt7622";
+
+	aliases {
+		serial0 = &uart0;
+		led-boot = &power_green;
+		led-failsafe = &power_amber;
+		led-running = &power_green;
+		led-upgrade = &power_green;
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n8 swiotlb=512";
+	};
+
+	memory {
+		reg = <0 0x40000000 0 0x0F000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		wireless_amber {
+			label = "wsr-2533dhp2:amber:wireless";
+			gpios = <&pio 2 GPIO_ACTIVE_HIGH>;
+		};
+
+		power_amber: power_amber {
+			label = "wsr-2533dhp2:amber:power";
+			gpios = <&pio 3 GPIO_ACTIVE_LOW>;
+		};
+
+		power_green: power_green {
+			label = "wsr-2533dhp2:green:power";
+			gpios = <&pio 4 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+
+		wireless_green {
+			label = "wsr-2533dhp2:green:wireless";
+			gpios = <&pio 15 GPIO_ACTIVE_HIGH>;
+		};
+
+		internet {
+			label = "wsr-2533dhp2:green:internet";
+			gpios = <&pio 19 GPIO_ACTIVE_HIGH>;
+		};
+
+		router {
+			label = "wsr-2533dhp2:green:router";
+			gpios = <&pio 20 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys-polled";
+		poll-interval = <100>;
+
+		reset {
+			label = "reset";
+			gpios = <&pio 0 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+
+		router {
+			label = "router";
+			gpios = <&pio 1 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+			linux,input-type = <EV_SW>;
+		};
+
+		bridge {
+			label = "wb";
+			gpios = <&pio 16 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+			linux,input-type = <EV_SW>;
+		};
+
+		manual {
+			label = "manual";
+			gpios = <&pio 18 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_1>;
+			linux,input-type = <EV_SW>;
+		};
+
+		wps {
+			label = "wps";
+			gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_WPS_BUTTON>;
+		};
+	};
+
+	rtkgsw: rtkgsw@0 {
+		compatible = "mediatek,rtk-gsw";
+		mediatek,ethsys = <&ethsys>;
+		mediatek,mdio = <&mdio>;
+		mediatek,reset-pin = <&pio 54 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&cpu0 {
+	proc-supply = <&mt6380_vcpu_reg>;
+	sram-supply = <&mt6380_vm_reg>;
+};
+
+&cpu1 {
+	proc-supply = <&mt6380_vcpu_reg>;
+	sram-supply = <&mt6380_vm_reg>;
+};
+
+&pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie0_pins>;
+	status = "okay";
+};
+
+&slot0 {
+	status = "okay";
+
+	wifi@0,0 {
+		compatible = "mediatek,mt76";
+		reg = <0x0000 0 0 0 0>;
+		mediatek,mtd-eeprom = <&factory 0x5000>;
+		ieee80211-freq-limit = <5000000 6000000>;
+	};
+};
+
+&pio {
+	eth_pins: eth-pins {
+		mux {
+			function = "eth";
+			groups = "mdc_mdio", "rgmii_via_gmac2";
+		};
+	};
+
+	/* Parallel nand is shared pin with eMMC */
+	parallel_nand_pins: parallel-nand-pins {
+		mux {
+			function = "flash";
+			groups = "par_nand";
+		};
+
+		conf-cmd-dat {
+			pins = "NCEB", "NWEB", "NREB",
+				  "NDL4", "NDL5", "NDL6",
+				  "NDL7", "NRB", "NCLE",
+				  "NALE", "NDL0", "NDL1",
+				  "NDL2", "NDL3";
+			input-enable;
+			drive-strength = <8>;
+			bias-pull-up;
+		};
+	};
+
+	pcie0_pins: pcie0-pins {
+		mux {
+			function = "pcie";
+			groups = "pcie0_pad_perst",
+				 "pcie0_1_waken",
+				 "pcie0_1_clkreq";
+		};
+	};
+
+	pmic_bus_pins: pmic-bus-pins {
+		mux {
+			function = "pmic";
+			groups = "pmic_bus";
+		};
+	};
+
+	pwm7_pins: pwm1-2-pins {
+		mux {
+			function = "pwm";
+			groups = "pwm_ch7_2";
+		};
+	};
+
+	uart0_pins: uart0-pins {
+		mux {
+			function = "uart";
+			groups = "uart0_0_tx_rx" ;
+		};
+	};
+
+	watchdog_pins: watchdog-pins {
+		mux {
+			function = "watchdog";
+			groups = "watchdog";
+		};
+	};
+};
+
+&bch {
+	status = "okay";
+};
+
+&eth {
+	pinctrl-names = "default";
+	pinctrl-0 = <&eth_pins>;
+	status = "okay";
+
+	gmac0: mac@0 {
+		compatible = "mediatek,eth-mac";
+		reg = <0>;
+
+		phy-connection-type = "2500base-x";
+
+		mtd-mac-address = <&factory 0x4>;
+		mtd-mac-address-increment = <(-1)>;
+
+		fixed-link {
+			speed = <2500>;
+			full-duplex;
+			pause;
+		};
+	};
+
+	mdio: mdio-bus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+};
+
+&nandc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&parallel_nand_pins>;
+	status = "okay";
+
+	nand@0 {
+		reg = <0>;
+		nand-ecc-mode = "hw";
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "Preloader";
+				reg = <0x0 0x80000>;
+				read-only;
+			};
+
+			partition@80000 {
+				label = "ATF";
+				reg = <0x80000 0x40000>;
+				read-only;
+			};
+
+			partition@c0000 {
+				label = "Bootloader";
+				reg = <0xc0000 0x80000>;
+				read-only;
+			};
+
+			partition@140000 {
+				label = "Config";
+				reg = <0x140000 0x80000>;
+				read-only;
+			};
+
+			factory: partition@1c0000 {
+				label = "factory";
+				reg = <0x1c0000 0x40000>;
+				read-only;
+			};
+
+			partition@200000 {
+				compatible = "brcm,trx";
+				trx-magic = <0x32504844>;
+				label = "firmware";
+				reg = <0x200000 0x3a00000>;
+			};
+
+			partition@3C00000 {
+				label = "Kernel2";
+				reg = <0x3c00000 0x3a00000>;
+			};
+
+			partition@7600000 {
+				label = "glbcfg";
+				reg = <0x7600000 0x200000>;
+				read-only;
+			};
+
+			partition@7800000 {
+				label = "board_data";
+				reg = <0x7800000 0x200000>;
+				read-only;
+			};
+		};
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm7_pins>;
+	status = "okay";
+};
+
+&pwrap {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pmic_bus_pins>;
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&watchdog {
+	pinctrl-names = "default";
+	pinctrl-0 = <&watchdog_pins>;
+	status = "okay";
+};
+
+&wmac {
+	status = "okay";
+
+	mediatek,mtd-eeprom = <&factory 0x0>;
+};
+
+&rtc {
+	status = "disabled";
+};
diff --git a/target/linux/mediatek/image/mt7622.mk b/target/linux/mediatek/image/mt7622.mk
index 0de1c375b21a..fdc8e496dea5 100644
--- a/target/linux/mediatek/image/mt7622.mk
+++ b/target/linux/mediatek/image/mt7622.mk
@@ -6,6 +6,28 @@ else
   KERNEL_LOADADDR := 0x44000000
 endif
 
+define Image/Prepare
+	# For UBI we want only one extra block
+	rm -f $(KDIR)/ubi_mark
+	echo -ne '\xde\xad\xc0\xde' > $(KDIR)/ubi_mark
+endef
+
+define Build/buffalo-kernel-trx
+	$(eval magic=$(word 1,$(1)))
+	$(eval dummy=$(word 2,$(1)))
+	$(eval kern_size=$(if $(KERNEL_SIZE),$(KERNEL_SIZE),0x400000))
+
+	$(if $(dummy),touch $(dummy))
+	$(STAGING_DIR_HOST)/bin/otrx create $@.new \
+		$(if $(magic),-M $(magic),) \
+		-f $@ \
+		$(if $(dummy),\
+			-a 0x20000 \
+			-b $$(( $(subst k, * 1024,$(kern_size)) )) \
+			-f $(dummy),)
+	mv $@.new $@
+endef
+
 define Build/bl2
 	cat $(STAGING_DIR_IMAGE)/mt7622-$1-bl2.img >> $@
 endef
@@ -34,6 +56,19 @@ define Build/mt7622-gpt
 	rm $@.tmp
 endef
 
+define Build/trx-nand
+	# kernel: always use 4 MiB (-28 B or TRX header) to allow upgrades even
+	#	  if it grows up between releases
+	# root: UBI with one extra block containing UBI mark to trigger erasing
+	#	rest of partition
+	$(STAGING_DIR_HOST)/bin/otrx create $@.new \
+		-M 0x32504844 \
+		-f $(IMAGE_KERNEL) -a 0x20000 -b 0x400000 \
+		-f $@ \
+		-A $(KDIR)/ubi_mark -a 0x20000
+	mv $@.new $@
+endef
+
 define Device/bananapi_bpi-r64
   DEVICE_VENDOR := Bananapi
   DEVICE_MODEL := BPi-R64
@@ -56,6 +91,35 @@ define Device/bananapi_bpi-r64
 endef
 TARGET_DEVICES += bananapi_bpi-r64
 
+define Device/buffalo_wsr-2533dhp2
+  DEVICE_VENDOR := Buffalo
+  DEVICE_MODEL := WSR-2533DHP2
+  DEVICE_DTS := mt7622-buffalo-wsr-2533dhp2
+  DEVICE_DTS_DIR := ../dts
+  IMAGE_SIZE := 59392k
+  KERNEL_SIZE := 4096k
+  BLOCKSIZE := 128k
+  PAGESIZE := 2048
+  SUBPAGESIZE := 512
+  UBINIZE_OPTS := -E 5
+  BUFFALO_TAG_PLATFORM := MTK
+  BUFFALO_TAG_VERSION := 9.99
+  BUFFALO_TAG_MINOR := 9.99
+  IMAGES += factory.bin factory-uboot.bin
+  KERNEL_INITRAMFS := kernel-bin | lzma | \
+	fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd | \
+	buffalo-kernel-trx
+  IMAGE/factory.bin := append-ubi | trx-nand | \
+	buffalo-enc WSR-2533DHP2 $$(BUFFALO_TAG_VERSION) -l | \
+	buffalo-tag-dhp WSR-2533DHP2 JP JP | buffalo-enc-tag -l | buffalo-dhp-image
+  IMAGE/factory-uboot.bin := append-ubi | trx-nand
+  IMAGE/sysupgrade.bin := append-kernel | \
+	buffalo-kernel-trx 0x32504844 $(KDIR)/tmp/$$(DEVICE_NAME).null | \
+	sysupgrade-tar kernel=$$$$@ | append-metadata
+  DEVICE_PACKAGES := kmod-mt7615e kmod-mt7615-firmware swconfig uboot-envtools
+endef
+TARGET_DEVICES += buffalo_wsr-2533dhp2
+
 define Device/elecom_wrc-2533gent
   DEVICE_VENDOR := Elecom
   DEVICE_MODEL := WRC-2533GENT
diff --git a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
index f537ccdb80af..f1daa2fae152 100644
--- a/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
+++ b/target/linux/mediatek/mt7622/base-files/etc/board.d/02_network
@@ -14,6 +14,10 @@ mediatek_setup_interfaces()
 	mediatek,mt7622-rfb1)
 		ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan
 		;;
+	buffalo,wsr-2533dhp2)
+		ucidef_add_switch "switch0" \
+			"0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0"
+		;;
 	ubnt,unifi-6-lr)
 		ucidef_set_interfaces_lan "eth0"
 		;;
diff --git a/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc
new file mode 100644
index 000000000000..81cb6b18b7a8
--- /dev/null
+++ b/target/linux/mediatek/mt7622/base-files/etc/uci-defaults/09_fix_crc
@@ -0,0 +1,10 @@
+. /lib/functions.sh
+
+kernel_size=$(sed -n 's/mtd[0-9]*: \([0-9a-f]*\).*"\(kernel\|linux\)".*/\1/p' /proc/mtd)
+
+case "$(board_name)" in
+buffalo,wsr-2533dhp2)
+	mtd -M 0x44485032 ${kernel_size:+-c 0x$kernel_size} fixtrx firmware && exit 0
+	exit 1
+	;;
+esac
diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/buffalo.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/buffalo.sh
new file mode 100644
index 000000000000..844cc4ed9593
--- /dev/null
+++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/buffalo.sh
@@ -0,0 +1,126 @@
+# ======== dev note ========
+# for following buffalo MT7622 devices:
+#
+# - WSR-2533DHP2 (trx magic: "DHP2")
+# - WSR-2533DHP3 (trx magic: "DHP3")
+# - WSR-3200AX4S (trx magic: "DHP3")
+#
+# sysupgrade-tar image:
+#
+# This is for normal upgrading for OpenWrt.
+# use nand_do_upgrade with CI_KERNPART="firmware"
+#
+# - if the size of new kernel is not equal with the current kernel's
+#   -> block upgrade and print a message about using TRX + UBI
+#      formatted image
+#   (should be flashed the new ubi contains rootfs + rootfs_data
+#   with the offset (=new padded kernel's end) if this case? But
+#   it maybe too hard for writing scripts...)
+#
+# TRX + UBI formatted image:
+#
+# This is for upgrading if the new kernel is larger than the
+# current kernel.
+#
+# ex:
+#   - stock firmware is installed in the flash and booted with
+#     OpenWrt initramfs image
+#   - kernel partition is increased from 4MiB in OpenWrt in the
+#     future
+#
+# packing TRX + UBI formatted image by tar is needed for image validation
+# with the metadata in the future?
+# ====== dev note end ======
+#
+# The mtd partitions "firmware" and "Kernel2" on NAND flash are os-image
+# partitions. These partitions are called as "Image1/Image2" in U-Boot
+# on WSR-2533DHP2, and they are checked conditions when booting.
+# "Image1" is always used for booting.
+#
+# == U-Boot Behaviors ==
+# - "Image1"/"Image2" images are good, images are different or
+#   "Image2" image is broken
+#   -> writes os-image to "Image2" from "Image1"
+#
+# - "Image1" image is broken
+#   -> writes os-image to "Image1" from "Image2"
+#
+# - "Image1"/"Image2" images are broken
+#   -> fall to U-Boot command line
+
+buffalo_check_image() {
+	local board="$1"
+	local boardname="$(echo $board | tr ',' '_')"
+	local magic="$2"
+	local fw_image="$3"
+
+	# return error state if TRX + UBI formatted image specified
+	# to notify about configurations
+	if [ "$magic" = "44485032" -o "$magic" = "44485033" ]; then
+		echo "Your configurations won't be saved if factory-uboot.bin image specified."
+		echo "But if you want to upgrade, please execute sysupgrade with \"-F\" option."
+		return 1
+	fi
+
+	# check if valid tar file specifed
+	if ! tar tf "$fw_image" &>/dev/null; then
+		echo "Specified file is not a tar archive: $fw_image"
+		return 1
+	fi
+
+	local control_len=$( (tar xf $fw_image sysupgrade-$boardname/CONTROL -O | wc -c) 2> /dev/null)
+
+	# check if valid sysupgrade tar archive
+	if [ "$control_len" = "0" ]; then
+		echo "Invalid sysupgrade file: $fw_image"
+		return 1
+	fi
+
+	local kern_part_len=$(grep "\"linux\"" /proc/mtd | sed "s/mtd[0-9]*:[ \t]*\([^ \t]*\).*/\1/")
+	[ -z "$kern_part_len" ] && {
+		echo "Unable to get \"linux\" partition size"
+		return 1
+	}
+	kern_part_len=$((0x$kern_part_len))
+
+	# this also checks if the sysupgrade image is for correct models
+	local kern_bin_len=$( (tar xf $fw_image sysupgrade-${boardname}/kernel -O | wc -c) 2> /dev/null)
+	if [ -z "$kern_bin_len" ]; then
+		echo "Failed to get new kernel size, is valid sysupgrade image specified for the device?"
+		return 1
+	fi
+
+	# kernel binary has a trx header (len: 28 (0x1c))
+	kern_bin_len=$((kern_bin_len - 28))
+
+	if [ "$kern_bin_len" != "$kern_part_len" ]; then
+		echo -n "The length of new kernel is invalid for current "
+		echo "\"linux\" partition, please use factory-uboot.bin image."
+		echo "\"linux\" partition: $kern_part_len, new kernel: $kern_bin_len"
+		return 1
+	fi
+}
+
+# for TRX + UBI formatted image
+buffalo_upgrade_ubinized() {
+	sync
+	echo 3 > /proc/sys/vm/drop_caches
+
+	local mtdnum="$( find_mtd_index "ubi" )"
+	# if no "ubi", don't return error for the purpose of recovery
+	# ex: recovery after accidental erasing "firmware" partition
+	if [ ! "$mtdnum" ]; then
+		echo "cannot find ubi mtd partition \"ubi\", skip detachment"
+	else
+		ubidetach -m "$mtdnum"
+	fi
+
+	# erase all data in "firmware"
+	mtd erase "${PART_NAME}"
+	# write TRX + UBI formatted image to "firmware"
+	get_image "$1" | mtd $MTD_ARGS write - "${PART_NAME:-firmware}"
+	if [ $? -ne 0 ]; then
+		echo "Failed to write the specified image."
+		exit 1
+	fi
+}
diff --git a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh
index 87852881bf4d..97a492c7fb8f 100755
--- a/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh
+++ b/target/linux/mediatek/mt7622/base-files/lib/upgrade/platform.sh
@@ -56,6 +56,18 @@ platform_do_upgrade() {
 		get_image "$1" | dd of=/dev/$fitpart
 		echo $rootdev > /tmp/sysupgrade.rootdev
 		;;
+	buffalo,wsr-2533dhp2)
+		local magic="$(get_magic_long "$1")"
+
+		# use "mtd write" if the magic is "DHP2 (0x44485032)"
+		# or "DHP3 (0x44485033)"
+		if [ "$magic" = "44485032" -o "$magic" = "44485033" ]; then
+			buffalo_upgrade_ubinized "$1"
+		else
+			CI_KERNPART="firmware"
+			nand_do_upgrade "$1"
+		fi
+		;;
 	linksys,e8450-ubi|\
 	mediatek,mt7622,ubi)
 		CI_KERNPART="fit"
@@ -84,6 +96,9 @@ platform_check_image() {
 	[ "$#" -gt 1 ] && return 1
 
 	case "$board" in
+	buffalo,wsr-2533dhp2)
+		buffalo_check_image "$board" "$magic" "$1" || return 1
+		;;
 	*)
 		[ "$magic" != "d00dfeed" ] && {
 			echo "Invalid image type."
diff --git a/target/linux/mediatek/mt7622/config-5.10 b/target/linux/mediatek/mt7622/config-5.10
index 5d80056365df..b899d9dbbb30 100644
--- a/target/linux/mediatek/mt7622/config-5.10
+++ b/target/linux/mediatek/mt7622/config-5.10
@@ -247,6 +247,7 @@ CONFIG_MTD_NAND_MTK_BMT=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MTD_SPI_NAND=y
 CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_PARSER_TRX=y
 CONFIG_MTD_SPLIT_FIRMWARE=y
 CONFIG_MTD_SPLIT_FIT_FW=y
 CONFIG_MTD_UBI=y
