From c70545f397187b36c1220ae16b4db19f39857c93 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:01:09 +0800 Subject: [PATCH 01/35] ramips: copy patches and kernel config to 5.4 Copy patches and kernel config to 5.4 for ramips Signed-off-by: DENG Qingfang --- target/linux/ramips/mt7621/config-5.4 | 315 ++ ...IPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch | 45 + ...ci-rt2880-set-pci-controller-of_node.patch | 32 + ...reservation-in-bootmem_init-for-cert.patch | 45 + ...4-MIPS-ralink-add-MT7621-pcie-driver.patch | 861 ++++ ...e-to-enable-disable-the-cevt-r4k-irq.patch | 82 + ...IPS-ralink-add-cpu-frequency-scaling.patch | 200 + ...-the-commandline-from-the-devicetree.patch | 21 + .../0009-PCI-MIPS-enable-PCIe-on-MT7688.patch | 28 + ...013-owrt-hack-fix-mt7688-cache-issue.patch | 28 + ...-select-illegal-access-driver-by-def.patch | 25 + .../0024-GPIO-add-named-gpio-exports.patch | 165 + ...25-pinctrl-ralink-add-pinctrl-driver.patch | 524 ++ ...DT-Add-documentation-for-gpio-ralink.patch | 59 + ...alink-add-gpio-driver-for-ralink-SoC.patch | 430 ++ ...IO-ralink-add-mt7621-gpio-controller.patch | 405 ++ ...support-for-GPIO-as-interrupt-contro.patch | 44 + ...0031-uvc-add-iPassion-iP2970-support.patch | 246 + .../0032-USB-dwc2-add-device_reset.patch | 29 + .../0034-NET-multi-phy-support.patch | 59 + ...mtd-cfi-cmdset-0002-force-word-write.patch | 70 + ...d-Remove-unused-chip-write_page-hook.patch | 67 + .../0039-mtd-add-mt7621-nand-support.patch | 4437 +++++++++++++++++ .../ramips/patches-5.4/0040-nand-hack.patch | 32 + ...-DT-Add-documentation-for-spi-rt2880.patch | 44 + ...SPI-ralink-add-Ralink-SoC-spi-driver.patch | 574 +++ .../0043-spi-add-mt7621-support.patch | 487 ++ ...0044-i2c-MIPS-adds-ralink-I2C-driver.patch | 507 ++ .../0045-i2c-add-mt7621-driver.patch | 473 ++ ...IPS-ralink-add-sdhci-for-mt7620a-SoC.patch | 43 + ...047-DMA-ralink-add-rt2880-dma-engine.patch | 1757 +++++++ .../0048-asoc-add-mt7620-support.patch | 1046 ++++ ...erial-add-ugly-custom-baud-rate-hack.patch | 22 + .../0052-pwm-add-mediatek-support.patch | 217 + ...d-spi-nor-add-w25q256-3b-mode-switch.patch | 214 + ...spi-nor-w25q256-respect-default-mode.patch | 73 + .../0069-awake-rt305x-dwc2-controller.patch | 15 + .../patches-5.4/0070-weak_reordering.patch | 10 + .../ramips/patches-5.4/0098-disable_cm.patch | 19 + .../ramips/patches-5.4/0099-pci-mt7620.patch | 10 + .../patches-5.4/0200-linkit_bootstrap.patch | 97 + .../100-mt7621-core-detect-hack.patch | 61 + .../ramips/patches-5.4/101-mt7621-timer.patch | 87 + .../102-mt7621-fix-cpu-clk-add-clkdev.patch | 224 + .../105-mt7621-memory-detect.patch | 125 + .../patches-5.4/110-mt7621-perfctr-fix.patch | 15 + ...0-mt7620-export-chip-version-and-pkg.patch | 19 + .../302-spi-nor-add-gd25q512.patch | 14 + ...or-enable-4B-opcodes-for-mx25l25635f.patch | 72 + .../patches-5.4/999-fix-pci-init-mt7620.patch | 21 + 50 files changed, 14495 insertions(+) create mode 100644 target/linux/ramips/mt7621/config-5.4 create mode 100644 target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch create mode 100644 target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch create mode 100644 target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch create mode 100644 target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch create mode 100644 target/linux/ramips/patches-5.4/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch create mode 100644 target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch create mode 100644 target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch create mode 100644 target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch create mode 100644 target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch create mode 100644 target/linux/ramips/patches-5.4/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch create mode 100644 target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch create mode 100644 target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch create mode 100644 target/linux/ramips/patches-5.4/0026-DT-Add-documentation-for-gpio-ralink.patch create mode 100644 target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch create mode 100644 target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch create mode 100644 target/linux/ramips/patches-5.4/0029-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch create mode 100644 target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch create mode 100644 target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch create mode 100644 target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch create mode 100644 target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch create mode 100644 target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch create mode 100644 target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch create mode 100644 target/linux/ramips/patches-5.4/0040-nand-hack.patch create mode 100644 target/linux/ramips/patches-5.4/0041-DT-Add-documentation-for-spi-rt2880.patch create mode 100644 target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch create mode 100644 target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch create mode 100644 target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch create mode 100644 target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch create mode 100644 target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch create mode 100644 target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch create mode 100644 target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch create mode 100644 target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch create mode 100644 target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch create mode 100644 target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch create mode 100644 target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch create mode 100644 target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch create mode 100644 target/linux/ramips/patches-5.4/0070-weak_reordering.patch create mode 100644 target/linux/ramips/patches-5.4/0098-disable_cm.patch create mode 100644 target/linux/ramips/patches-5.4/0099-pci-mt7620.patch create mode 100644 target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch create mode 100644 target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch create mode 100644 target/linux/ramips/patches-5.4/101-mt7621-timer.patch create mode 100644 target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch create mode 100644 target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch create mode 100644 target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch create mode 100644 target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch create mode 100644 target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch create mode 100644 target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch create mode 100644 target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch diff --git a/target/linux/ramips/mt7621/config-5.4 b/target/linux/ramips/mt7621/config-5.4 new file mode 100644 index 0000000000..4112cad780 --- /dev/null +++ b/target/linux/ramips/mt7621/config-5.4 @@ -0,0 +1,315 @@ +CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set +# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set +# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOARD_SCACHE=y +CONFIG_BOUNCE=y +CONFIG_CEVT_R4K=y +# CONFIG_CEVT_SYSTICK_QUIRK is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKSRC_MIPS_GIC=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_BOSTON is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MIPSR2_IRQ_EI=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRC16=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_NULL2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_FIXED_PHY=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_IPI=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_MT7621=y +# CONFIG_GPIO_RALINK is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_WATCHDOG=y +# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set +# CONFIG_GRO_CELLS is not set +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +# CONFIG_HAVE_ARCH_BITREVERSE is not set +CONFIG_HAVE_ARCH_COMPILER_H=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CBPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_COPY_THREAD_TLS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HIGHMEM=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_MT7621=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CBPF_JIT=y +CONFIG_MIPS_CLOCK_VSYSCALL=y +CONFIG_MIPS_CM=y +# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set +# CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +CONFIG_MIPS_CPC=y +CONFIG_MIPS_CPS=y +# CONFIG_MIPS_CPS_NS16550 is not set +CONFIG_MIPS_CPU_SCACHE=y +# CONFIG_MIPS_ELF_APPENDED_DTB is not set +CONFIG_MIPS_GIC=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MIPS_MT=y +CONFIG_MIPS_MT_FPAFF=y +CONFIG_MIPS_MT_SMP=y +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +# CONFIG_MIPS_VPE_LOADER is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MT7621_WDT=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_MINOR_FW=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_SPLIT_TPLINK_FW=y +CONFIG_MTD_SPLIT_TRX_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_MTD_UBI_FASTMAP is not set +# CONFIG_MTD_UBI_GLUEBI is not set +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTK_MTD_NAND=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_MEDIATEK_GSW_MT7621=y +CONFIG_NET_MEDIATEK_MDIO=y +CONFIG_NET_MEDIATEK_MDIO_MT7620=y +CONFIG_NET_MEDIATEK_MT7621=y +CONFIG_NET_MEDIATEK_OFFLOAD=y +CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_VENDOR_MEDIATEK=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_NR_CPUS=4 +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PADATA=y +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +# CONFIG_PHY_RALINK_USB is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_SUPPLY=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RALINK=y +# CONFIG_RALINK_WDT is not set +CONFIG_RATIONAL=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_BQ32K=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +# CONFIG_SCHED_INFO is not set +CONFIG_SCHED_SMT=y +# CONFIG_SCSI_DMA is not set +# CONFIG_SERIAL_8250_FSL is not set +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SMP=y +CONFIG_SMP_UP=y +# CONFIG_SOC_MT7620 is not set +CONFIG_SOC_MT7621=y +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MT7621=y +# CONFIG_SPI_RT2880 is not set +CONFIG_SRCU=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWPHY=y +CONFIG_SYNC_R4K=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_MIPS_CPS=y +CONFIG_SYS_SUPPORTS_MULTITHREADING=y +CONFIG_SYS_SUPPORTS_SCHED_SMT=y +CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WEAK_ORDERING=y +CONFIG_WEAK_REORDERING_BEYOND_LLSC=y +CONFIG_XPS=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y diff --git a/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch b/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch new file mode 100644 index 0000000000..4f803dfd0d --- /dev/null +++ b/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch @@ -0,0 +1,45 @@ +From 35d017947401d9f449a7e55e52506744e0c62577 Mon Sep 17 00:00:00 2001 +From: Mathias Kresin +Date: Wed, 22 Aug 2018 22:38:06 +0200 +Subject: [PATCH] MIPS: ralink: Add rt3352 SPI_CS1 pinmux + +The rt3352 has a pin that can be used as second spi chip select, +watchdog reset or GPIO. The pinmux setup was missing the definition of +said pin. + +The pin is configured via the same bit on rt5350, so reuse the existing +macro. + +Signed-off-by: Mathias Kresin +Signed-off-by: Paul Burton +Patchwork: https://patchwork.linux-mips.org/patch/20301/ +Cc: John Crispin +Cc: Ralf Baechle +Cc: James Hogan +Cc: linux-mips@linux-mips.org +Cc: linux-kernel@vger.kernel.org +--- + arch/mips/ralink/rt305x.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -49,6 +49,10 @@ static struct rt2880_pmx_func rgmii_func + static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; + static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; + static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; ++static struct rt2880_pmx_func rt3352_cs1_func[] = { ++ FUNC("spi_cs1", 0, 45, 1), ++ FUNC("wdg_cs1", 1, 45, 1), ++}; + + static struct rt2880_pmx_group rt3050_pinmux_data[] = { + GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), +@@ -75,6 +79,7 @@ static struct rt2880_pmx_group rt3352_pi + GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA), + GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA), + GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED), ++ GRP("spi_cs1", rt3352_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1), + { 0 } + }; + diff --git a/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch b/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch new file mode 100644 index 0000000000..7ac092cfb0 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch @@ -0,0 +1,32 @@ +From 0eb1cfffd5433d8dce3e4163a5cd9accc6000856 Mon Sep 17 00:00:00 2001 +From: Tobias Wolf +Date: Wed, 5 Sep 2018 08:51:26 +0200 +Subject: [PATCH] MIPS: pci-rt2880: set pci controller of_node + +Set the PCI controller of_node such that PCI devices can be +instantiated via device tree. + +Signed-off-by: Tobias Wolf +Signed-off-by: Mathias Kresin +Acked-by: John Crispin +Signed-off-by: Paul Burton +Patchwork: https://patchwork.linux-mips.org/patch/20423/ +Cc: Ralf Baechle +Cc: James Hogan +Cc: linux-mips@linux-mips.org +Cc: linux-kernel@vger.kernel.org +--- + arch/mips/pci/pci-rt2880.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/pci/pci-rt2880.c ++++ b/arch/mips/pci/pci-rt2880.c +@@ -246,6 +246,8 @@ static int rt288x_pci_probe(struct platf + rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); + (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); + ++ rt2880_pci_controller.of_node = pdev->dev.of_node; ++ + register_pci_controller(&rt2880_pci_controller); + return 0; + } diff --git a/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch b/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch new file mode 100644 index 0000000000..77f2622b9d --- /dev/null +++ b/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch @@ -0,0 +1,45 @@ +From: Tobias Wolf +Subject: [v2] MIPS: Fix memory reservation in bootmem_init for certain non-usermem setups + +Commit 67a3ba25aa95 ("MIPS: Fix incorrect mem=X@Y handling") introduced a new +issue for rt288x where "PHYS_OFFSET" is 0x0 but the calculated "ramstart" is +not. As the prerequisite of custom memory map has been removed, this results +in the full memory range of 0x0 - 0x8000000 to be marked as reserved for this +platform. + +v2: Correctly compare that usermem is not null. + +This patch adds the originally intended prerequisite again. + +Signed-off-by: Tobias Wolf +--- + +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -369,6 +369,8 @@ static unsigned long __init bootmap_byte + return ALIGN(bytes, sizeof(long)); + } + ++static int usermem __initdata; ++ + static void __init bootmem_init(void) + { + unsigned long reserved_end; +@@ -442,7 +444,7 @@ static void __init bootmem_init(void) + /* + * Reserve any memory between the start of RAM and PHYS_OFFSET + */ +- if (ramstart > PHYS_OFFSET) ++ if (usermem && ramstart > PHYS_OFFSET) + add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET, + BOOT_MEM_RESERVED); + +@@ -652,8 +654,6 @@ static void __init bootmem_init(void) + * initialization hook for anything else was introduced. + */ + +-static int usermem __initdata; +- + static int __init early_parse_mem(char *p) + { + phys_addr_t start, size; diff --git a/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch b/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch new file mode 100644 index 0000000000..b6f1ce93f4 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch @@ -0,0 +1,861 @@ +From fec11d4e8dc5cc79bcd7c8fd55038ac21ac39965 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 16 Mar 2014 05:22:39 +0000 +Subject: [PATCH 04/53] MIPS: ralink: add MT7621 pcie driver + +Signed-off-by: John Crispin +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-mt7621.c | 813 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 814 insertions(+) + create mode 100644 arch/mips/pci/pci-mt7621.c + +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -47,6 +47,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o ++obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o + obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o +--- /dev/null ++++ b/arch/mips/pci/pci-mt7621.c +@@ -0,0 +1,836 @@ ++/************************************************************************** ++ * ++ * BRIEF MODULE DESCRIPTION ++ * PCI init for Ralink RT2880 solution ++ * ++ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ ************************************************************************** ++ * May 2007 Bruce Chang ++ * Initial Release ++ * ++ * May 2009 Bruce Chang ++ * support RT2880/RT3883 PCIe ++ * ++ * May 2011 Bruce Chang ++ * support RT6855/MT7620 PCIe ++ * ++ ************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++extern void pcie_phy_init(void); ++extern void chk_phy_pll(void); ++ ++/* ++ * These functions and structures provide the BIOS scan and mapping of the PCI ++ * devices. ++ */ ++ ++#define CONFIG_PCIE_PORT0 ++#define CONFIG_PCIE_PORT1 ++#define CONFIG_PCIE_PORT2 ++#define RALINK_PCIE0_CLK_EN (1<<24) ++#define RALINK_PCIE1_CLK_EN (1<<25) ++#define RALINK_PCIE2_CLK_EN (1<<26) ++ ++#define RALINK_PCI_CONFIG_ADDR 0x20 ++#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24 ++#define RALINK_INT_PCIE0 pcie_irq[0] ++#define RALINK_INT_PCIE1 pcie_irq[1] ++#define RALINK_INT_PCIE2 pcie_irq[2] ++#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028) ++#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C) ++#define RALINK_PCIE0_RST (1<<24) ++#define RALINK_PCIE1_RST (1<<25) ++#define RALINK_PCIE2_RST (1<<26) ++#define RALINK_SYSCTL_BASE 0xBE000000 ++ ++#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000) ++#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C) ++#define RALINK_PCI_BASE 0xBE140000 ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RT6855_PCIE0_OFFSET 0x2000 ++#define RT6855_PCIE1_OFFSET 0x3000 ++#define RT6855_PCIE2_OFFSET 0x4000 ++ ++#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010) ++#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018) ++#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030) ++#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034) ++#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038) ++#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050) ++#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060) ++#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064) ++ ++#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010) ++#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018) ++#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030) ++#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034) ++#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038) ++#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050) ++#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060) ++#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064) ++ ++#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010) ++#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018) ++#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030) ++#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034) ++#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038) ++#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050) ++#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060) ++#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064) ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000) ++ ++ ++#define MV_WRITE(ofs, data) \ ++ *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data) ++#define MV_READ(ofs, data) \ ++ *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++#define MV_READ_DATA(ofs) \ ++ le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_16(ofs, data) \ ++ *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data) ++#define MV_READ_16(ofs, data) \ ++ *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_8(ofs, data) \ ++ *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data ++#define MV_READ_8(ofs, data) \ ++ *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) ++ ++ ++ ++#define RALINK_PCI_MM_MAP_BASE 0x60000000 ++#define RALINK_PCI_IO_MAP_BASE 0x1e160000 ++ ++#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000 ++#define GPIO_PERST ++#define ASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL |= val; \ ++ else \ ++ RALINK_RSTCTRL &= ~val; \ ++ } while(0) ++#define DEASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL &= ~val; \ ++ else \ ++ RALINK_RSTCTRL |= val; \ ++ } while(0) ++#define RALINK_SYSCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14) ++#define RALINK_CLKCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30) ++#define RALINK_RSTCTRL *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34) ++#define RALINK_GPIOMODE *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60) ++#define RALINK_PCIE_CLK_GEN *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c) ++#define RALINK_PCIE_CLK_GEN1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80) ++#define PPLL_CFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c) ++#define PPLL_DRV *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0) ++//RALINK_SYSCFG1 bit ++#define RALINK_PCI_HOST_MODE_EN (1<<7) ++#define RALINK_PCIE_RC_MODE_EN (1<<8) ++//RALINK_RSTCTRL bit ++#define RALINK_PCIE_RST (1<<23) ++#define RALINK_PCI_RST (1<<24) ++//RALINK_CLKCFG1 bit ++#define RALINK_PCI_CLK_EN (1<<19) ++#define RALINK_PCIE_CLK_EN (1<<21) ++//RALINK_GPIOMODE bit ++#define PCI_SLOTx2 (1<<11) ++#define PCI_SLOTx1 (2<<11) ++//MTK PCIE PLL bit ++#define PDRV_SW_SET (1<<31) ++#define LC_CKDRVPD_ (1<<19) ++ ++#define MEMORY_BASE 0x0 ++static int pcie_link_status = 0; ++ ++#define PCI_ACCESS_READ_1 0 ++#define PCI_ACCESS_READ_2 1 ++#define PCI_ACCESS_READ_4 2 ++#define PCI_ACCESS_WRITE_1 3 ++#define PCI_ACCESS_WRITE_2 4 ++#define PCI_ACCESS_WRITE_4 5 ++ ++static int pcie_irq[3]; ++ ++static int config_access(unsigned char access_type, struct pci_bus *bus, ++ unsigned int devfn, unsigned int where, u32 * data) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ uint32_t address_reg, data_reg; ++ unsigned int address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ ++ address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ MV_WRITE(address_reg, address); ++ ++ switch(access_type) { ++ case PCI_ACCESS_WRITE_1: ++ MV_WRITE_8(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_2: ++ MV_WRITE_16(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_4: ++ MV_WRITE(data_reg, *data); ++ break; ++ case PCI_ACCESS_READ_1: ++ MV_READ_8( data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_2: ++ MV_READ_16(data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_4: ++ MV_READ(data_reg, data); ++ break; ++ default: ++ printk("no specify access type\n"); ++ break; ++ } ++ return 0; ++} ++ ++static int ++read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) ++{ ++ return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) ++{ ++ return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) ++{ ++ return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static int ++pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) ++{ ++ switch (size) { ++ case 1: ++ return read_config_byte(bus, devfn, where, (u8 *) val); ++ case 2: ++ return read_config_word(bus, devfn, where, (u16 *) val); ++ default: ++ return read_config_dword(bus, devfn, where, val); ++ } ++} ++ ++static int ++pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) ++{ ++ switch (size) { ++ case 1: ++ return write_config_byte(bus, devfn, where, (u8) val); ++ case 2: ++ return write_config_word(bus, devfn, where, (u16) val); ++ default: ++ return write_config_dword(bus, devfn, where, val); ++ } ++} ++ ++struct pci_ops mt7621_pci_ops= { ++ .read = pci_config_read, ++ .write = pci_config_write, ++}; ++ ++static struct resource mt7621_res_pci_mem1 = { ++ .name = "PCI MEM1", ++ .start = RALINK_PCI_MM_MAP_BASE, ++ .end = (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), ++ .flags = IORESOURCE_MEM, ++}; ++static struct resource mt7621_res_pci_io1 = { ++ .name = "PCI I/O1", ++ .start = RALINK_PCI_IO_MAP_BASE, ++ .end = (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller mt7621_controller = { ++ .pci_ops = &mt7621_pci_ops, ++ .mem_resource = &mt7621_res_pci_mem1, ++ .io_resource = &mt7621_res_pci_io1, ++ .mem_offset = 0x00000000UL, ++ .io_offset = 0x00000000UL, ++ .io_map_base = 0xa0000000, ++}; ++ ++static void ++read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_READ(data_reg, val); ++ return; ++} ++ ++static void ++write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_WRITE(data_reg, val); ++ return; ++} ++ ++ ++int ++pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ u32 val; ++ int irq = 0; ++ ++ if ((dev->bus->number == 0) && (slot == 0)) { ++ write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 0 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x1)) { ++ write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 1 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x2)) { ++ write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 2 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if ((dev->bus->number == 1) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 2: ++ case 6: ++ irq = RALINK_INT_PCIE1; ++ break; ++ case 4: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE0; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x1)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x0)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x1)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x2)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else { ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ return 0; ++ } ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); ++ return irq; ++} ++ ++void ++set_pcie_phy(u32 *addr, int start_b, int bits, int val) ++{ ++// printk("0x%p:", addr); ++// printk(" %x", *addr); ++ *(unsigned int *)(addr) &= ~(((1< %x\n", *addr); ++} ++ ++void ++bypass_pipe_rst(void) ++{ ++#if defined (CONFIG_PCIE_PORT0) ++ /* PCIe Port 0 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ /* PCIe Port 1 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* PCIe Port 2 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++} ++ ++void ++set_phy_for_ssc(void) ++{ ++ unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)); ++ ++ reg = (reg >> 6) & 0x7; ++#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1) ++ /* Set PCIe Port0 & Port1 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ printk("***** Xtal 40MHz *****\n"); ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { ++ printk("***** Xtal 25MHz *****\n"); ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } else { ++ printk("***** Xtal 20MHz *****\n"); ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* Set PCIe Port2 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { // 25MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++#endif ++} ++ ++void setup_cm_memory_region(struct resource *mem_resource) ++{ ++ resource_size_t mask; ++ if (mips_cps_numiocu(0)) { ++ /* FIXME: hardware doesn't accept mask values with 1s after ++ 0s (e.g. 0xffef), so it would be great to warn if that's ++ about to happen */ ++ mask = ~(mem_resource->end - mem_resource->start); ++ ++ write_gcr_reg1_base(mem_resource->start); ++ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); ++ printk("PCI coherence region base: 0x%08lx, mask/settings: 0x%08lx\n", ++ read_gcr_reg1_base(), ++ read_gcr_reg1_mask()); ++ } ++} ++ ++static int mt7621_pci_probe(struct platform_device *pdev) ++{ ++ unsigned long val = 0; ++ int i; ++ ++ for (i = 0; i < 3; i++) ++ pcie_irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i); ++ ++ iomem_resource.start = 0; ++ iomem_resource.end= ~0; ++ ioport_resource.start= 0; ++ ioport_resource.end = ~0; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST); ++ printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3); ++ *(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3; ++ mdelay(100); ++ *(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3) ++ mdelay(100); ++ *(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7); // clear DATA ++ ++ mdelay(100); ++#else ++ *(unsigned int *)(0xbe000060) &= ~0x00000c00; ++#endif ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ DEASSERT_SYSRST_PCIE(val); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++ if ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2 ++ bypass_pipe_rst(); ++ set_phy_for_ssc(); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++#if defined (CONFIG_PCIE_PORT0) ++ read_config(0, 0, 0, 0x70c, &val); ++ printk("Port 0 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ read_config(0, 1, 0, 0x70c, &val); ++ printk("Port 1 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ read_config(0, 2, 0, 0x70c, &val); ++ printk("Port 2 N_FTS = %x\n", (unsigned int)val); ++#endif ++ ++ RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST); ++ RALINK_SYSCFG1 &= ~(0x30); ++ RALINK_SYSCFG1 |= (2<<4); ++ RALINK_PCIE_CLK_GEN &= 0x7fffffff; ++ RALINK_PCIE_CLK_GEN1 &= 0x80ffffff; ++ RALINK_PCIE_CLK_GEN1 |= 0xa << 24; ++ RALINK_PCIE_CLK_GEN |= 0x80000000; ++ mdelay(50); ++ RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST); ++ ++ ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // set DATA ++ mdelay(100); ++#else ++ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST ++#endif ++ mdelay(500); ++ ++ ++ mdelay(500); ++#if defined (CONFIG_PCIE_PORT0) ++ if(( RALINK_PCI0_STATUS & 0x1) == 0) ++ { ++ printk("PCIE0 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN); ++ pcie_link_status &= ~(1<<0); ++ } else { ++ pcie_link_status |= 1<<0; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ if(( RALINK_PCI1_STATUS & 0x1) == 0) ++ { ++ printk("PCIE1 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN); ++ pcie_link_status &= ~(1<<1); ++ } else { ++ pcie_link_status |= 1<<1; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ if (( RALINK_PCI2_STATUS & 0x1) == 0) { ++ printk("PCIE2 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN); ++ pcie_link_status &= ~(1<<2); ++ } else { ++ pcie_link_status |= 1<<2; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt ++ } ++#endif ++ if (pcie_link_status == 0) ++ return 0; ++ ++/* ++pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num ++3'b000 x x x ++3'b001 x x 0 ++3'b010 x 0 x ++3'b011 x 1 0 ++3'b100 0 x x ++3'b101 1 x 0 ++3'b110 1 0 x ++3'b111 2 1 0 ++*/ ++ switch(pcie_link_status) { ++ case 2: ++ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ break; ++ case 4: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 24; //port2 ++ break; ++ case 5: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ case 6: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ } ++ printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR); ++ //printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL); ++ ++/* ++ ioport_resource.start = mt7621_res_pci_io1.start; ++ ioport_resource.end = mt7621_res_pci_io1.end; ++*/ ++ ++ RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE; ++ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ //PCIe0 ++ if((pcie_link_status & 0x1) != 0) { ++ RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI0_CLASS = 0x06040001; ++ printk("PCIE0 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ //PCIe1 ++ if ((pcie_link_status & 0x2) != 0) { ++ RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI1_CLASS = 0x06040001; ++ printk("PCIE1 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ //PCIe2 ++ if ((pcie_link_status & 0x4) != 0) { ++ RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI2_CLASS = 0x06040001; ++ printk("PCIE2 enabled\n"); ++ } ++#endif ++ ++ ++ switch(pcie_link_status) { ++ case 7: ++ read_config(0, 2, 0, 0x4, &val); ++ write_config(0, 2, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 2, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 2, 0, 0x70c, val); ++ case 3: ++ case 5: ++ case 6: ++ read_config(0, 1, 0, 0x4, &val); ++ write_config(0, 1, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 1, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 1, 0, 0x70c, val); ++ default: ++ read_config(0, 0, 0, 0x4, &val); ++ write_config(0, 0, 0, 0x4, val|0x4); //bus master enable ++ // write_config(0, 0, 0, 0x4, val|0x7); //bus master enable ++ read_config(0, 0, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 0, 0, 0x70c, val); ++ } ++ ++ pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node); ++ setup_cm_memory_region(mt7621_controller.mem_resource); ++ register_pci_controller(&mt7621_controller); ++ return 0; ++ ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_pci_ids[] = { ++ { .compatible = "mediatek,mt7621-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_pci_ids); ++ ++static struct platform_driver mt7621_pci_driver = { ++ .probe = mt7621_pci_probe, ++ .driver = { ++ .name = "mt7621-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mt7621_pci_ids), ++ }, ++}; ++ ++static int __init mt7621_pci_init(void) ++{ ++ return platform_driver_register(&mt7621_pci_driver); ++} ++ ++arch_initcall(mt7621_pci_init); diff --git a/target/linux/ramips/patches-5.4/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-5.4/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch new file mode 100644 index 0000000000..773c74f4e9 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0005-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -0,0 +1,82 @@ +From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 14 Jul 2013 23:08:11 +0200 +Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k + irq + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Kconfig | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -1,12 +1,17 @@ + # SPDX-License-Identifier: GPL-2.0 + if RALINK + ++config CEVT_SYSTICK_QUIRK ++ bool ++ default n ++ + config CLKEVT_RT3352 + bool + depends on SOC_RT305X || SOC_MT7620 + default y + select TIMER_OF + select CLKSRC_MMIO ++ select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC + bool +--- a/arch/mips/kernel/cevt-r4k.c ++++ b/arch/mips/kernel/cevt-r4k.c +@@ -15,6 +15,26 @@ + #include + #include + ++static int mips_state_oneshot(struct clock_event_device *evt) ++{ ++ if (!cp0_timer_irq_installed) { ++ cp0_timer_irq_installed = 1; ++ setup_irq(evt->irq, &c0_compare_irqaction); ++ } ++ ++ return 0; ++} ++ ++static int mips_state_shutdown(struct clock_event_device *evt) ++{ ++ if (cp0_timer_irq_installed) { ++ cp0_timer_irq_installed = 0; ++ remove_irq(evt->irq, &c0_compare_irqaction); ++ } ++ ++ return 0; ++} ++ + static int mips_next_event(unsigned long delta, + struct clock_event_device *evt) + { +@@ -281,17 +301,21 @@ int r4k_clockevent_init(void) + cd->rating = 300; + cd->irq = irq; + cd->cpumask = cpumask_of(cpu); ++ cd->set_state_shutdown = mips_state_shutdown; ++ cd->set_state_oneshot = mips_state_oneshot; + cd->set_next_event = mips_next_event; + cd->event_handler = mips_event_handler; + + clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); + ++#ifndef CONFIG_CEVT_SYSTICK_QUIRK + if (cp0_timer_irq_installed) + return 0; + + cp0_timer_irq_installed = 1; + + setup_irq(irq, &c0_compare_irqaction); ++#endif + + return 0; + } diff --git a/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch b/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch new file mode 100644 index 0000000000..90215fbf86 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch @@ -0,0 +1,200 @@ +From bd30f19a006fb52bac80c6463c49dd2f4159f4ac Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 28 Jul 2013 16:26:41 +0200 +Subject: [PATCH 06/53] MIPS: ralink: add cpu frequency scaling + +This feature will break udelay() and cause the delay loop to have longer delays +when the frequency is scaled causing a performance hit. + +Signed-off-by: John Crispin +--- + arch/mips/ralink/cevt-rt3352.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/arch/mips/ralink/cevt-rt3352.c ++++ b/arch/mips/ralink/cevt-rt3352.c +@@ -29,6 +29,10 @@ + /* enable the counter */ + #define CFG_CNT_EN 0x1 + ++/* mt7620 frequency scaling defines */ ++#define CLK_LUT_CFG 0x40 ++#define SLEEP_EN BIT(31) ++ + struct systick_device { + void __iomem *membase; + struct clock_event_device dev; +@@ -36,21 +40,53 @@ struct systick_device { + int freq_scale; + }; + ++static void (*systick_freq_scaling)(struct systick_device *sdev, int status); ++ + static int systick_set_oneshot(struct clock_event_device *evt); + static int systick_shutdown(struct clock_event_device *evt); + ++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) ++{ ++ if (sdev->freq_scale == status) ++ return; ++ ++ sdev->freq_scale = status; ++ ++ pr_info("%s: %s autosleep mode\n", sdev->dev.name, ++ (status) ? ("enable") : ("disable")); ++ if (status) ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); ++ else ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); ++} ++ ++static inline unsigned int read_count(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COUNT); ++} ++ ++static inline unsigned int read_compare(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COMPARE); ++} ++ ++static inline void write_compare(struct systick_device *sdev, unsigned int val) ++{ ++ iowrite32(val, sdev->membase + SYSTICK_COMPARE); ++} ++ + static int systick_next_event(unsigned long delta, + struct clock_event_device *evt) + { + struct systick_device *sdev; +- u32 count; ++ int res; + + sdev = container_of(evt, struct systick_device, dev); +- count = ioread32(sdev->membase + SYSTICK_COUNT); +- count = (count + delta) % SYSTICK_FREQ; +- iowrite32(count, sdev->membase + SYSTICK_COMPARE); ++ delta += read_count(sdev); ++ write_compare(sdev, delta); ++ res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0; + +- return 0; ++ return res; + } + + static void systick_event_handler(struct clock_event_device *dev) +@@ -60,20 +96,25 @@ static void systick_event_handler(struct + + static irqreturn_t systick_interrupt(int irq, void *dev_id) + { +- struct clock_event_device *dev = (struct clock_event_device *) dev_id; ++ int ret = 0; ++ struct clock_event_device *cdev; ++ struct systick_device *sdev; + +- dev->event_handler(dev); ++ if (read_c0_cause() & STATUSF_IP7) { ++ cdev = (struct clock_event_device *) dev_id; ++ sdev = container_of(cdev, struct systick_device, dev); ++ ++ /* Clear Count/Compare Interrupt */ ++ write_compare(sdev, read_compare(sdev)); ++ cdev->event_handler(cdev); ++ ret = 1; ++ } + +- return IRQ_HANDLED; ++ return IRQ_RETVAL(ret); + } + + static struct systick_device systick = { + .dev = { +- /* +- * cevt-r4k uses 300, make sure systick +- * gets used if available +- */ +- .rating = 310, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = systick_next_event, + .set_state_shutdown = systick_shutdown, +@@ -95,9 +136,15 @@ static int systick_shutdown(struct clock + sdev = container_of(evt, struct systick_device, dev); + + if (sdev->irq_requested) +- free_irq(systick.dev.irq, &systick_irqaction); ++ remove_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 0; +- iowrite32(0, systick.membase + SYSTICK_CONFIG); ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 0); ++ ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 1); + + return 0; + } +@@ -117,34 +164,48 @@ static int systick_set_oneshot(struct cl + return 0; + } + ++static const struct of_device_id systick_match[] = { ++ { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling}, ++ {}, ++}; ++ + static int __init ralink_systick_init(struct device_node *np) + { ++ const struct of_device_id *match; ++ int rating = 200; + int ret; + + systick.membase = of_iomap(np, 0); + if (!systick.membase) + return -ENXIO; + +- systick_irqaction.name = np->name; +- systick.dev.name = np->name; +- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); +- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); +- systick.dev.max_delta_ticks = 0x7fff; +- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); +- systick.dev.min_delta_ticks = 0x3; ++ match = of_match_node(systick_match, np); ++ if (match) { ++ systick_freq_scaling = match->data; ++ /* ++ * cevt-r4k uses 300, make sure systick ++ * gets used if available ++ */ ++ rating = 310; ++ } ++ ++ /* enable counter than register clock source */ ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, ++ SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up); ++ ++ /* register clock event */ + systick.dev.irq = irq_of_parse_and_map(np, 0); + if (!systick.dev.irq) { + pr_err("%s: request_irq failed", np->name); + return -EINVAL; + } + +- ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, +- SYSTICK_FREQ, 301, 16, +- clocksource_mmio_readl_up); +- if (ret) +- return ret; +- +- clockevents_register_device(&systick.dev); ++ systick_irqaction.name = np->name; ++ systick.dev.name = np->name; ++ systick.dev.rating = rating; ++ systick.dev.cpumask = cpumask_of(0); ++ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); + + pr_info("%s: running - mult: %d, shift: %d\n", + np->name, systick.dev.mult, systick.dev.shift); diff --git a/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch b/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch new file mode 100644 index 0000000000..c05ee8018d --- /dev/null +++ b/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch @@ -0,0 +1,21 @@ +From 67b7bff0fd364c194e653f69baa623ba2141bd4c Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 4 Aug 2014 18:46:02 +0200 +Subject: [PATCH 07/53] MIPS: ralink: copy the commandline from the devicetree + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -82,6 +82,8 @@ void __init plat_mem_setup(void) + + __dt_setup_arch(dtb); + ++ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); ++ + of_scan_flat_dt(early_init_dt_find_memory, NULL); + if (memory_dtb) + of_scan_flat_dt(early_init_dt_scan_memory, NULL); diff --git a/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch b/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch new file mode 100644 index 0000000000..6ca15fe32e --- /dev/null +++ b/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch @@ -0,0 +1,28 @@ +From 7768798964eb0e4f95eaecffb93b5d0ca28a38af Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 3 Jun 2017 20:00:03 +0200 +Subject: [PATCH] MIPS: pci-mt7620: enabled PCIe on MT7688 +To: linux-mips@linux-mips.org, + John Crispin +Cc: Wei Yongjun , + Ralf Baechle , + linux-mediatek@lists.infradead.org + +Use PCIe support for MT7628AN also on MT7688. +Tested on WRTNODE2R. + +Signed-off-by: Daniel Golle +--- + arch/mips/pci/pci-mt7620.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -316,6 +316,7 @@ static int mt7620_pci_probe(struct platf + break; + + case MT762X_SOC_MT7628AN: ++ case MT762X_SOC_MT7688: + if (mt7628_pci_hw_init(pdev)) + return -1; + break; diff --git a/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch b/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch new file mode 100644 index 0000000000..442f3180a3 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch @@ -0,0 +1,28 @@ +From 5ede027f6c4a57ed25da872420508b7f1168b36b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:15:32 +0100 +Subject: [PATCH 13/53] owrt: hack: fix mt7688 cache issue + +Signed-off-by: John Crispin +--- + arch/mips/kernel/setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -910,7 +910,6 @@ static void __init arch_mem_init(char ** + crashk_res.end - crashk_res.start + 1, + BOOTMEM_DEFAULT); + #endif +- device_tree_init(); + sparse_init(); + plat_swiotlb_setup(); + +@@ -1026,6 +1025,7 @@ void __init setup_arch(char **cmdline_p) + + cpu_cache_init(); + paging_init(); ++ device_tree_init(); + } + + unsigned long kernelsp[NR_CPUS]; diff --git a/target/linux/ramips/patches-5.4/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch b/target/linux/ramips/patches-5.4/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch new file mode 100644 index 0000000000..1dc54ccf23 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0015-arch-mips-do-not-select-illegal-access-driver-by-def.patch @@ -0,0 +1,25 @@ +From 9e6ce539092a1dd605a20bf73c655a9de58d8641 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:18:05 +0100 +Subject: [PATCH 15/53] arch: mips: do not select illegal access driver by + default + +Signed-off-by: John Crispin +--- + arch/mips/ralink/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -14,9 +14,9 @@ config CLKEVT_RT3352 + select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC +- bool ++ bool "illegal access irq" + depends on SOC_RT305X +- default y ++ default n + + config IRQ_INTC + bool diff --git a/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch b/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch new file mode 100644 index 0000000000..61ed9ea784 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,165 @@ +From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 24/53] GPIO: add named gpio exports + +Signed-off-by: John Crispin +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib-sysfs.c | 10 +++++- + include/asm-generic/gpio.h | 6 ++++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 91 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -23,6 +23,8 @@ + #include + #include + #include ++#include ++#include + + #include "gpiolib.h" + +@@ -513,3 +515,68 @@ void of_gpiochip_remove(struct gpio_chip + gpiochip_remove_pin_ranges(chip); + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ if (!gpio_is_valid(gpio)) ++ return gpio; ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++ .probe = of_gpio_export_probe, ++}; ++ ++module_platform_driver(gpio_export_driver); +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -553,7 +553,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + struct gpio_device *gdev; +@@ -615,6 +615,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (chip->names && chip->names[offset]) + ioname = chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, &gdev->dev, + MKDEV(0, 0), data, gpio_groups, +@@ -636,6 +638,12 @@ err_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *desc) +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -127,6 +127,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -451,6 +451,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_ + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -458,6 +459,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { diff --git a/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch b/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch new file mode 100644 index 0000000000..a374e01b59 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch @@ -0,0 +1,524 @@ +From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:34:05 +0100 +Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 2 + + drivers/pinctrl/Kconfig | 5 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-rt2880.c | 474 ++++++++++++++++++++++++++++++++++++++ + 4 files changed, 482 insertions(+) + create mode 100644 drivers/pinctrl/pinctrl-rt2880.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -629,6 +629,8 @@ config RALINK + select CLKDEV_LOOKUP + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_RT2880 + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -143,6 +143,11 @@ config PINCTRL_LPC18XX + help + Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU). + ++config PINCTRL_RT2880 ++ bool ++ depends on RALINK ++ select PINMUX ++ + config PINCTRL_FALCON + bool + depends on SOC_FALCON +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl- + obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o + obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o + obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_SIRF) += sirf/ +--- /dev/null ++++ b/drivers/pinctrl/pinctrl-rt2880.c +@@ -0,0 +1,472 @@ ++/* ++ * linux/drivers/pinctrl/pinctrl-rt2880.c ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "core.h" ++ ++#define SYSC_REG_GPIO_MODE 0x60 ++#define SYSC_REG_GPIO_MODE2 0x64 ++ ++struct rt2880_priv { ++ struct device *dev; ++ ++ struct pinctrl_pin_desc *pads; ++ struct pinctrl_desc *desc; ++ ++ struct rt2880_pmx_func **func; ++ int func_count; ++ ++ struct rt2880_pmx_group *groups; ++ const char **group_names; ++ int group_count; ++ ++ uint8_t *gpio; ++ int max_pins; ++}; ++ ++static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->group_count; ++} ++ ++static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return NULL; ++ ++ return p->group_names[group]; ++} ++ ++static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, ++ unsigned group, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return -EINVAL; ++ ++ *pins = p->groups[group].func[0].pins; ++ *num_pins = p->groups[group].func[0].pin_count; ++ ++ return 0; ++} ++ ++static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, ++ struct pinctrl_map *map, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || ++ map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) ++ kfree(map[i].data.configs.configs); ++ kfree(map); ++} ++ ++static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ seq_printf(s, "ralink pio"); ++} ++ ++static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np, ++ struct pinctrl_map **map) ++{ ++ const char *function; ++ int func = of_property_read_string(np, "ralink,function", &function); ++ int grps = of_property_count_strings(np, "ralink,group"); ++ int i; ++ ++ if (func || !grps) ++ return; ++ ++ for (i = 0; i < grps; i++) { ++ const char *group; ++ ++ of_property_read_string_index(np, "ralink,group", i, &group); ++ ++ (*map)->type = PIN_MAP_TYPE_MUX_GROUP; ++ (*map)->name = function; ++ (*map)->data.mux.group = group; ++ (*map)->data.mux.function = function; ++ (*map)++; ++ } ++} ++ ++static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np_config, ++ struct pinctrl_map **map, ++ unsigned *num_maps) ++{ ++ int max_maps = 0; ++ struct pinctrl_map *tmp; ++ struct device_node *np; ++ ++ for_each_child_of_node(np_config, np) { ++ int ret = of_property_count_strings(np, "ralink,group"); ++ ++ if (ret >= 0) ++ max_maps += ret; ++ } ++ ++ if (!max_maps) ++ return -EINVAL; ++ ++ *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); ++ if (!*map) ++ return -ENOMEM; ++ ++ tmp = *map; ++ ++ for_each_child_of_node(np_config, np) ++ rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); ++ *num_maps = max_maps; ++ ++ return 0; ++} ++ ++static const struct pinctrl_ops rt2880_pctrl_ops = { ++ .get_groups_count = rt2880_get_group_count, ++ .get_group_name = rt2880_get_group_name, ++ .get_group_pins = rt2880_get_group_pins, ++ .pin_dbg_show = rt2880_pinctrl_pin_dbg_show, ++ .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, ++ .dt_free_map = rt2880_pinctrl_dt_free_map, ++}; ++ ++static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func_count; ++} ++ ++static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, ++ unsigned func) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func[func]->name; ++} ++ ++static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (p->func[func]->group_count == 1) ++ *groups = &p->group_names[p->func[func]->groups[0]]; ++ else ++ *groups = p->group_names; ++ ++ *num_groups = p->func[func]->group_count; ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ u32 mode = 0; ++ u32 reg = SYSC_REG_GPIO_MODE; ++ int i; ++ int shift; ++ ++ /* dont allow double use */ ++ if (p->groups[group].enabled) { ++ dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); ++ return -EBUSY; ++ } ++ ++ p->groups[group].enabled = 1; ++ p->func[func]->enabled = 1; ++ ++ shift = p->groups[group].shift; ++ if (shift >= 32) { ++ shift -= 32; ++ reg = SYSC_REG_GPIO_MODE2; ++ } ++ mode = rt_sysc_r32(reg); ++ mode &= ~(p->groups[group].mask << shift); ++ ++ /* mark the pins as gpio */ ++ for (i = 0; i < p->groups[group].func[0].pin_count; i++) ++ p->gpio[p->groups[group].func[0].pins[i]] = 1; ++ ++ /* function 0 is gpio and needs special handling */ ++ if (func == 0) { ++ mode |= p->groups[group].gpio << shift; ++ } else { ++ for (i = 0; i < p->func[func]->pin_count; i++) ++ p->gpio[p->func[func]->pins[i]] = 0; ++ mode |= p->func[func]->value << shift; ++ } ++ rt_sysc_w32(mode, reg); ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, ++ struct pinctrl_gpio_range *range, ++ unsigned pin) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (!p->gpio[pin]) { ++ dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct pinmux_ops rt2880_pmx_group_ops = { ++ .get_functions_count = rt2880_pmx_func_count, ++ .get_function_name = rt2880_pmx_func_name, ++ .get_function_groups = rt2880_pmx_group_get_groups, ++ .set_mux = rt2880_pmx_group_enable, ++ .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, ++}; ++ ++static struct pinctrl_desc rt2880_pctrl_desc = { ++ .owner = THIS_MODULE, ++ .name = "rt2880-pinmux", ++ .pctlops = &rt2880_pctrl_ops, ++ .pmxops = &rt2880_pmx_group_ops, ++}; ++ ++static struct rt2880_pmx_func gpio_func = { ++ .name = "gpio", ++}; ++ ++static int rt2880_pinmux_index(struct rt2880_priv *p) ++{ ++ struct rt2880_pmx_func **f; ++ struct rt2880_pmx_group *mux = p->groups; ++ int i, j, c = 0; ++ ++ /* count the mux functions */ ++ while (mux->name) { ++ p->group_count++; ++ mux++; ++ } ++ ++ /* allocate the group names array needed by the gpio function */ ++ p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); ++ if (!p->group_names) ++ return -1; ++ ++ for (i = 0; i < p->group_count; i++) { ++ p->group_names[i] = p->groups[i].name; ++ p->func_count += p->groups[i].func_count; ++ } ++ ++ /* we have a dummy function[0] for gpio */ ++ p->func_count++; ++ ++ /* allocate our function and group mapping index buffers */ ++ f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); ++ gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); ++ if (!f || !gpio_func.groups) ++ return -1; ++ ++ /* add a backpointer to the function so it knows its group */ ++ gpio_func.group_count = p->group_count; ++ for (i = 0; i < gpio_func.group_count; i++) ++ gpio_func.groups[i] = i; ++ ++ f[c] = &gpio_func; ++ c++; ++ ++ /* add remaining functions */ ++ for (i = 0; i < p->group_count; i++) { ++ for (j = 0; j < p->groups[i].func_count; j++) { ++ f[c] = &p->groups[i].func[j]; ++ f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); ++ f[c]->groups[0] = i; ++ f[c]->group_count = 1; ++ c++; ++ } ++ } ++ return 0; ++} ++ ++static int rt2880_pinmux_pins(struct rt2880_priv *p) ++{ ++ int i, j; ++ ++ /* loop over the functions and initialize the pins array. also work out the highest pin used */ ++ for (i = 0; i < p->func_count; i++) { ++ int pin; ++ ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->func[i]->pins[j] = p->func[i]->pin_first + j; ++ ++ pin = p->func[i]->pin_first + p->func[i]->pin_count; ++ if (pin > p->max_pins) ++ p->max_pins = pin; ++ } ++ ++ /* the buffer that tells us which pins are gpio */ ++ p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, ++ GFP_KERNEL); ++ /* the pads needed to tell pinctrl about our pins */ ++ p->pads = devm_kzalloc(p->dev, ++ sizeof(struct pinctrl_pin_desc) * p->max_pins, ++ GFP_KERNEL); ++ if (!p->pads || !p->gpio ) { ++ dev_err(p->dev, "Failed to allocate gpio data\n"); ++ return -ENOMEM; ++ } ++ ++ memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); ++ for (i = 0; i < p->func_count; i++) { ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->gpio[p->func[i]->pins[j]] = 0; ++ } ++ ++ /* pin 0 is always a gpio */ ++ p->gpio[0] = 1; ++ ++ /* set the pads */ ++ for (i = 0; i < p->max_pins; i++) { ++ /* strlen("ioXY") + 1 = 5 */ ++ char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); ++ ++ if (!name) { ++ dev_err(p->dev, "Failed to allocate pad name\n"); ++ return -ENOMEM; ++ } ++ snprintf(name, 5, "io%d", i); ++ p->pads[i].number = i; ++ p->pads[i].name = name; ++ } ++ p->desc->pins = p->pads; ++ p->desc->npins = p->max_pins; ++ ++ return 0; ++} ++ ++static int rt2880_pinmux_probe(struct platform_device *pdev) ++{ ++ struct rt2880_priv *p; ++ struct pinctrl_dev *dev; ++ struct device_node *np; ++ ++ if (!rt2880_pinmux_data) ++ return -ENOSYS; ++ ++ /* setup the private data */ ++ p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ p->dev = &pdev->dev; ++ p->desc = &rt2880_pctrl_desc; ++ p->groups = rt2880_pinmux_data; ++ platform_set_drvdata(pdev, p); ++ ++ /* init the device */ ++ if (rt2880_pinmux_index(p)) { ++ dev_err(&pdev->dev, "failed to load index\n"); ++ return -EINVAL; ++ } ++ if (rt2880_pinmux_pins(p)) { ++ dev_err(&pdev->dev, "failed to load pins\n"); ++ return -EINVAL; ++ } ++ dev = pinctrl_register(p->desc, &pdev->dev, p); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ /* finalize by adding gpio ranges for enables gpio controllers */ ++ for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { ++ const __be32 *ngpio, *gpiobase; ++ struct pinctrl_gpio_range *range; ++ char *name; ++ ++ if (!of_device_is_available(np)) ++ continue; ++ ++ ngpio = of_get_property(np, "ralink,nr-gpio", NULL); ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (!ngpio || !gpiobase) { ++ dev_err(&pdev->dev, "failed to load chip info\n"); ++ return -EINVAL; ++ } ++ ++ range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); ++ range->name = name = (char *) &range[1]; ++ sprintf(name, "pio"); ++ range->npins = __be32_to_cpu(*ngpio); ++ range->base = __be32_to_cpu(*gpiobase); ++ range->pin_base = range->base; ++ pinctrl_add_gpio_range(dev, range); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id rt2880_pinmux_match[] = { ++ { .compatible = "ralink,rt2880-pinmux" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); ++ ++static struct platform_driver rt2880_pinmux_driver = { ++ .probe = rt2880_pinmux_probe, ++ .driver = { ++ .name = "rt2880-pinmux", ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_pinmux_match, ++ }, ++}; ++ ++int __init rt2880_pinmux_init(void) ++{ ++ return platform_driver_register(&rt2880_pinmux_driver); ++} ++ ++core_initcall_sync(rt2880_pinmux_init); diff --git a/target/linux/ramips/patches-5.4/0026-DT-Add-documentation-for-gpio-ralink.patch b/target/linux/ramips/patches-5.4/0026-DT-Add-documentation-for-gpio-ralink.patch new file mode 100644 index 0000000000..0bce0b433a --- /dev/null +++ b/target/linux/ramips/patches-5.4/0026-DT-Add-documentation-for-gpio-ralink.patch @@ -0,0 +1,59 @@ +From d410e5478c622c01fcf31427533df5f433df9146 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 28 Jul 2013 19:45:30 +0200 +Subject: [PATCH 26/53] DT: Add documentation for gpio-ralink + +Describe gpio-ralink binding. + +Signed-off-by: John Crispin +Cc: linux-mips@linux-mips.org +Cc: devicetree@vger.kernel.org +Cc: linux-gpio@vger.kernel.org +--- + .../devicetree/bindings/gpio/gpio-ralink.txt | 40 ++++++++++++++++++++ + 1 file changed, 40 insertions(+) + create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt +@@ -0,0 +1,40 @@ ++Ralink SoC GPIO controller bindings ++ ++Required properties: ++- compatible: ++ - "ralink,rt2880-gpio" for Ralink controllers ++- #gpio-cells : Should be two. ++ - first cell is the pin number ++ - second cell is used to specify optional parameters (unused) ++- gpio-controller : Marks the device node as a GPIO controller ++- reg : Physical base address and length of the controller's registers ++- interrupt-parent: phandle to the INTC device node ++- interrupts : Specify the INTC interrupt number ++- ralink,nr-gpio : Specify the number of GPIOs ++- ralink,register-map : The register layout depends on the GPIO bank and actual ++ SoC type. Register offsets need to be in this order. ++ [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ] ++ ++Optional properties: ++- ralink,gpio-base : Specify the GPIO chips base number ++ ++Example: ++ ++ gpio0: gpio@600 { ++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; ++ ++ #gpio-cells = <2>; ++ gpio-controller; ++ ++ reg = <0x600 0x34>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ ralink,gpio-base = <0>; ++ ralink,nr-gpio = <24>; ++ ralink,register-map = [ 00 04 08 0c ++ 20 24 28 2c ++ 30 34 ]; ++ ++ }; diff --git a/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch new file mode 100644 index 0000000000..eaae0d3d02 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch @@ -0,0 +1,430 @@ +From 69fdd2c4f937796b934e89c33acde9d082e27bfd Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 4 Aug 2014 20:36:29 +0200 +Subject: [PATCH 27/53] GPIO: MIPS: ralink: add gpio driver for ralink SoC + +Add gpio driver for Ralink SoC. This driver makes the gpio core on +RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. + +Signed-off-by: John Crispin +Cc: linux-mips@linux-mips.org +Cc: linux-gpio@vger.kernel.org +--- + arch/mips/include/asm/mach-ralink/gpio.h | 24 ++ + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-ralink.c | 355 ++++++++++++++++++++++++++++++ + 4 files changed, 386 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h + create mode 100644 drivers/gpio/gpio-ralink.c + +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/gpio.h +@@ -0,0 +1,24 @@ ++/* ++ * Ralink SoC GPIO API support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos ++ * Copyright (C) 2008 Imre Kaloz ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __ASM_MACH_RALINK_GPIO_H ++#define __ASM_MACH_RALINK_GPIO_H ++ ++#define ARCH_NR_GPIOS 128 ++#include ++ ++#define gpio_get_value __gpio_get_value ++#define gpio_set_value __gpio_set_value ++#define gpio_cansleep __gpio_cansleep ++#define gpio_to_irq __gpio_to_irq ++ ++#endif /* __ASM_MACH_RALINK_GPIO_H */ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -398,6 +398,12 @@ config GPIO_REG + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + ++config GPIO_RALINK ++ bool "Ralink GPIO Support" ++ depends on RALINK ++ help ++ Say yes here to support the Ralink SoC GPIO device ++ + config GPIO_SPEAR_SPICS + bool "ST SPEAr13xx SPI Chip Select as GPIO support" + depends on PLAT_SPEAR +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-p + obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o + obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o ++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +--- /dev/null ++++ b/drivers/gpio/gpio-ralink.c +@@ -0,0 +1,355 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum ralink_gpio_reg { ++ GPIO_REG_INT = 0, ++ GPIO_REG_EDGE, ++ GPIO_REG_RENA, ++ GPIO_REG_FENA, ++ GPIO_REG_DATA, ++ GPIO_REG_DIR, ++ GPIO_REG_POL, ++ GPIO_REG_SET, ++ GPIO_REG_RESET, ++ GPIO_REG_TOGGLE, ++ GPIO_REG_MAX ++}; ++ ++struct ralink_gpio_chip { ++ struct gpio_chip chip; ++ u8 regs[GPIO_REG_MAX]; ++ ++ spinlock_t lock; ++ void __iomem *membase; ++ struct irq_domain *domain; ++ int irq; ++ ++ u32 rising; ++ u32 falling; ++}; ++ ++#define MAP_MAX 4 ++static struct irq_domain *irq_map[MAP_MAX]; ++static int irq_map_count; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) ++{ ++ struct ralink_gpio_chip *rg; ++ ++ rg = container_of(chip, struct ralink_gpio_chip, chip); ++ ++ return rg; ++} ++ ++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, rg->membase + rg->regs[reg]); ++} ++ ++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) ++{ ++ return ioread32(rg->membase + rg->regs[reg]); ++} ++ ++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); ++} ++ ++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t &= ~BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ ralink_gpio_set(chip, offset, value); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t |= BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ if (rg->irq < 1) ++ return -1; ++ ++ return irq_create_mapping(rg->domain, pin); ++} ++ ++static void ralink_gpio_irq_handler(struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < irq_map_count; i++) { ++ struct irq_domain *domain = irq_map[i]; ++ struct ralink_gpio_chip *rg; ++ unsigned long pending; ++ int bit; ++ ++ rg = (struct ralink_gpio_chip *) domain->host_data; ++ pending = rt_gpio_r32(rg, GPIO_REG_INT); ++ ++ for_each_set_bit(bit, &pending, rg->chip.ngpio) { ++ u32 map = irq_find_mapping(domain, bit); ++ generic_handle_irq(map); ++ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); ++ } ++ } ++} ++ ++static void ralink_gpio_irq_unmask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ralink_gpio_irq_mask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ struct ralink_gpio_chip *rg; ++ u32 mask = BIT(d->hwirq); ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip ralink_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = ralink_gpio_irq_unmask, ++ .irq_mask = ralink_gpio_irq_mask, ++ .irq_mask_ack = ralink_gpio_irq_mask, ++ .irq_set_type = ralink_gpio_irq_type, ++}; ++ ++static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = gpio_map, ++}; ++ ++static void ralink_gpio_irq_init(struct device_node *np, ++ struct ralink_gpio_chip *rg) ++{ ++ if (irq_map_count >= MAP_MAX) ++ return; ++ ++ rg->irq = irq_of_parse_and_map(np, 0); ++ if (!rg->irq) ++ return; ++ ++ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, ++ &irq_domain_ops, rg); ++ if (!rg->domain) { ++ dev_err(rg->chip.parent, "irq_domain_add_linear failed\n"); ++ return; ++ } ++ ++ irq_map[irq_map_count++] = rg->domain; ++ ++ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); ++ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); ++ ++ if (!atomic_read(&irq_refcount)) ++ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); ++ atomic_inc(&irq_refcount); ++ ++ dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio); ++} ++ ++static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ return pinctrl_request_gpio(gpio); ++} ++ ++static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ pinctrl_free_gpio(gpio); ++} ++ ++static int ralink_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct ralink_gpio_chip *rg; ++ const __be32 *ngpio, *gpiobase; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "failed to find resource\n"); ++ return -ENOMEM; ++ } ++ ++ rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct ralink_gpio_chip), GFP_KERNEL); ++ if (!rg) ++ return -ENOMEM; ++ ++ rg->membase = devm_ioremap_resource(&pdev->dev, res); ++ if (!rg->membase) { ++ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); ++ return -ENOMEM; ++ } ++ ++ if (of_property_read_u8_array(np, "ralink,register-map", ++ rg->regs, GPIO_REG_MAX)) { ++ dev_err(&pdev->dev, "failed to read register definition\n"); ++ return -EINVAL; ++ } ++ ++ ngpio = of_get_property(np, "ralink,nr-gpio", NULL); ++ if (!ngpio) { ++ dev_err(&pdev->dev, "failed to read number of pins\n"); ++ return -EINVAL; ++ } ++ ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (gpiobase) ++ rg->chip.base = be32_to_cpu(*gpiobase); ++ else ++ rg->chip.base = -1; ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.parent = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = np; ++ rg->chip.ngpio = be32_to_cpu(*ngpio); ++ rg->chip.direction_input = ralink_gpio_direction_input; ++ rg->chip.direction_output = ralink_gpio_direction_output; ++ rg->chip.get = ralink_gpio_get; ++ rg->chip.set = ralink_gpio_set; ++ rg->chip.request = ralink_gpio_request; ++ rg->chip.to_irq = ralink_gpio_to_irq; ++ rg->chip.free = ralink_gpio_free; ++ ++ /* set polarity to low for all lines */ ++ rt_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ ralink_gpio_irq_init(np, rg); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static const struct of_device_id ralink_gpio_match[] = { ++ { .compatible = "ralink,rt2880-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_gpio_match); ++ ++static struct platform_driver ralink_gpio_driver = { ++ .probe = ralink_gpio_probe, ++ .driver = { ++ .name = "rt2880_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_gpio_match, ++ }, ++}; ++ ++static int __init ralink_gpio_init(void) ++{ ++ return platform_driver_register(&ralink_gpio_driver); ++} ++ ++subsys_initcall(ralink_gpio_init); diff --git a/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch b/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch new file mode 100644 index 0000000000..debeae2806 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch @@ -0,0 +1,405 @@ +From 61ac7d9b4228de8c332900902c2b93189b042eab Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:00:32 +0100 +Subject: [PATCH 28/53] GPIO: ralink: add mt7621 gpio controller + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 3 + + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-mt7621.c | 354 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 364 insertions(+) + create mode 100644 drivers/gpio/gpio-mt7621.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -631,6 +631,9 @@ config RALINK + select RESET_CONTROLLER + select PINCTRL + select PINCTRL_RT2880 ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select ARCH_REQUIRE_GPIOLIB + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -298,6 +298,12 @@ config GPIO_MENZ127 + help + Say yes here to support the MEN 16Z127 GPIO Controller + ++config GPIO_MT7621 ++ bool "Mediatek GPIO Support" ++ depends on SOC_MT7620 || SOC_MT7621 ++ help ++ Say yes here to support the Mediatek SoC GPIO device ++ + config GPIO_MM_LANTIQ + bool "Lantiq Memory mapped GPIOs" + depends on LANTIQ && SOC_XWAY +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -152,3 +152,4 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o + obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o + obj-$(CONFIG_GPIO_ZX) += gpio-zx.o + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o ++obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o +--- /dev/null ++++ b/drivers/gpio/gpio-mt7621.c +@@ -0,0 +1,354 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos ++ * Copyright (C) 2013 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_MAX_BANK 3 ++#define MTK_BANK_WIDTH 32 ++ ++enum mediatek_gpio_reg { ++ GPIO_REG_CTRL = 0, ++ GPIO_REG_POL, ++ GPIO_REG_DATA, ++ GPIO_REG_DSET, ++ GPIO_REG_DCLR, ++ GPIO_REG_REDGE, ++ GPIO_REG_FEDGE, ++ GPIO_REG_HLVL, ++ GPIO_REG_LLVL, ++ GPIO_REG_STAT, ++ GPIO_REG_EDGE, ++}; ++ ++static void __iomem *mediatek_gpio_membase; ++static int mediatek_gpio_irq; ++static struct irq_domain *mediatek_gpio_irq_domain; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++struct mtk_gc { ++ struct gpio_chip chip; ++ spinlock_t lock; ++ int bank; ++ u32 rising; ++ u32 falling; ++} *gc_map[MTK_MAX_BANK]; ++ ++static inline struct mtk_gc ++*to_mediatek_gpio(struct gpio_chip *chip) ++{ ++ struct mtk_gc *mgc; ++ ++ mgc = container_of(chip, struct mtk_gc, chip); ++ ++ return mgc; ++} ++ ++static inline void ++mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static inline u32 ++mtk_gpio_r32(struct mtk_gc *rg, u8 reg) ++{ ++ return ioread32(mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static void ++mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset)); ++} ++ ++static int ++mediatek_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ++mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t &= ~BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t |= BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ mediatek_gpio_set(chip, offset, value); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_get_direction(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ if (t & BIT(offset)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH)); ++} ++ ++static int ++mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank) ++{ ++ const __be32 *id = of_get_property(bank, "reg", NULL); ++ struct mtk_gc *rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct mtk_gc), GFP_KERNEL); ++ ++ if (!rg || !id || be32_to_cpu(*id) > MTK_MAX_BANK) ++ return -ENOMEM; ++ ++ gc_map[be32_to_cpu(*id)] = rg; ++ ++ memset(rg, 0, sizeof(struct mtk_gc)); ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.parent = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = bank; ++ rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id); ++ rg->chip.ngpio = MTK_BANK_WIDTH; ++ rg->chip.direction_input = mediatek_gpio_direction_input; ++ rg->chip.direction_output = mediatek_gpio_direction_output; ++ rg->chip.get_direction = mediatek_gpio_get_direction; ++ rg->chip.get = mediatek_gpio_get; ++ rg->chip.set = mediatek_gpio_set; ++ if (mediatek_gpio_irq_domain) ++ rg->chip.to_irq = mediatek_gpio_to_irq; ++ rg->bank = be32_to_cpu(*id); ++ ++ /* set polarity to low for all gpios */ ++ mtk_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static void ++mediatek_gpio_irq_handler(struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < MTK_MAX_BANK; i++) { ++ struct mtk_gc *rg = gc_map[i]; ++ unsigned long pending; ++ int bit; ++ ++ if (!rg) ++ continue; ++ ++ pending = mtk_gpio_r32(rg, GPIO_REG_STAT); ++ ++ for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { ++ u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit); ++ ++ generic_handle_irq(map); ++ mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); ++ } ++ } ++} ++ ++static void ++mediatek_gpio_irq_unmask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising)); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ++mediatek_gpio_irq_mask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq)); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ++mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ u32 mask = BIT(d->hwirq); ++ ++ if (!rg) ++ return -1; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip mediatek_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = mediatek_gpio_irq_unmask, ++ .irq_mask = mediatek_gpio_irq_mask, ++ .irq_mask_ack = mediatek_gpio_irq_mask, ++ .irq_set_type = mediatek_gpio_irq_type, ++}; ++ ++static int ++mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = mediatek_gpio_gpio_map, ++}; ++ ++static int ++mediatek_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *bank, *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(mediatek_gpio_membase)) ++ return PTR_ERR(mediatek_gpio_membase); ++ ++ mediatek_gpio_irq = irq_of_parse_and_map(np, 0); ++ if (mediatek_gpio_irq) { ++ mediatek_gpio_irq_domain = irq_domain_add_linear(np, ++ MTK_MAX_BANK * MTK_BANK_WIDTH, ++ &irq_domain_ops, NULL); ++ if (!mediatek_gpio_irq_domain) ++ dev_err(&pdev->dev, "irq_domain_add_linear failed\n"); ++ } ++ ++ for_each_child_of_node(np, bank) ++ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank")) ++ mediatek_gpio_bank_probe(pdev, bank); ++ ++ if (mediatek_gpio_irq_domain) ++ irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler); ++ ++ return 0; ++} ++ ++static const struct of_device_id mediatek_gpio_match[] = { ++ { .compatible = "mtk,mt7621-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mediatek_gpio_match); ++ ++static struct platform_driver mediatek_gpio_driver = { ++ .probe = mediatek_gpio_probe, ++ .driver = { ++ .name = "mt7621_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = mediatek_gpio_match, ++ }, ++}; ++ ++static int __init ++mediatek_gpio_init(void) ++{ ++ return platform_driver_register(&mediatek_gpio_driver); ++} ++ ++subsys_initcall(mediatek_gpio_init); diff --git a/target/linux/ramips/patches-5.4/0029-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch b/target/linux/ramips/patches-5.4/0029-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch new file mode 100644 index 0000000000..8520ce32ff --- /dev/null +++ b/target/linux/ramips/patches-5.4/0029-gpio-ralink-Add-support-for-GPIO-as-interrupt-contro.patch @@ -0,0 +1,44 @@ +From 57fa7f2f4ef6f78ce1d30509c0d111aa3791b524 Mon Sep 17 00:00:00 2001 +From: Daniel Santos +Date: Sun, 4 Nov 2018 20:24:32 -0600 +Subject: gpio-ralink: Add support for GPIO as interrupt-controller + +Signed-off-by: Daniel Santos +--- + Documentation/devicetree/bindings/gpio/gpio-ralink.txt | 6 ++++++ + drivers/gpio/gpio-ralink.c | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/Documentation/devicetree/bindings/gpio/gpio-ralink.txt ++++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt +@@ -17,6 +17,9 @@ Required properties: + + Optional properties: + - ralink,gpio-base : Specify the GPIO chips base number ++- interrupt-controller : marks this as an interrupt controller ++- #interrupt-cells : a standard two-cell interrupt flag, see ++ interrupt-controller/interrupts.txt + + Example: + +@@ -28,6 +31,9 @@ Example: + + reg = <0x600 0x34>; + ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ + interrupt-parent = <&intc>; + interrupts = <6>; + +--- a/drivers/gpio/gpio-ralink.c ++++ b/drivers/gpio/gpio-ralink.c +@@ -220,7 +220,7 @@ static int gpio_map(struct irq_domain *d + } + + static const struct irq_domain_ops irq_domain_ops = { +- .xlate = irq_domain_xlate_onecell, ++ .xlate = irq_domain_xlate_twocell, + .map = gpio_map, + }; + diff --git a/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch new file mode 100644 index 0000000000..7ed1a616f6 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch @@ -0,0 +1,246 @@ +From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 19 Sep 2013 01:50:59 +0200 +Subject: [PATCH 31/53] uvc: add iPassion iP2970 support + +Signed-off-by: John Crispin +--- + drivers/media/usb/uvc/uvc_driver.c | 12 +++ + drivers/media/usb/uvc/uvc_status.c | 2 + + drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++ + drivers/media/usb/uvc/uvcvideo.h | 5 +- + 4 files changed, 165 insertions(+), 1 deletion(-) + +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2749,6 +2749,18 @@ static const struct usb_device_id uvc_id + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_FORCE_Y8 }, ++ /* iPassion iP2970 */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x1B3B, ++ .idProduct = 0x2970, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_MINMAX ++ | UVC_QUIRK_STREAM_NO_FID ++ | UVC_QUIRK_MOTION ++ | UVC_QUIRK_SINGLE_ISO }, + /* Generic USB Video Class */ + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, +--- a/drivers/media/usb/uvc/uvc_status.c ++++ b/drivers/media/usb/uvc/uvc_status.c +@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u + switch (dev->status[0] & 0x0f) { + case UVC_STATUS_TYPE_CONTROL: + uvc_event_control(dev, dev->status, len); ++ dev->motion = 1; + break; + + case UVC_STATUS_TYPE_STREAMING: +@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d + } + + pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); ++ dev->motion = 0; + + /* For high-speed interrupt endpoints, the bInterval value is used as + * an exponent of two. Some developers forgot about it. +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -21,6 +21,11 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + + #include + +@@ -1101,9 +1106,149 @@ static void uvc_video_decode_data(struct + } + } + ++struct bh_priv { ++ unsigned long seen; ++}; ++ ++struct bh_event { ++ const char *name; ++ struct sk_buff *skb; ++ struct work_struct work; ++}; ++ ++#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args ) ++#define BH_DBG(fmt, args...) do {} while (0) ++#define BH_SKB_SIZE 2048 ++ ++extern u64 uevent_next_seqnum(void); ++static int seen = 0; ++ ++static int bh_event_add_var(struct bh_event *event, int argv, ++ const char *format, ...) ++{ ++ static char buf[128]; ++ char *s; ++ va_list args; ++ int len; ++ ++ if (argv) ++ return 0; ++ ++ va_start(args, format); ++ len = vsnprintf(buf, sizeof(buf), format, args); ++ va_end(args); ++ ++ if (len >= sizeof(buf)) { ++ BH_ERR("buffer size too small\n"); ++ WARN_ON(1); ++ return -ENOMEM; ++ } ++ ++ s = skb_put(event->skb, len + 1); ++ strcpy(s, buf); ++ ++ BH_DBG("added variable '%s'\n", s); ++ ++ return 0; ++} ++ ++static int motion_hotplug_fill_event(struct bh_event *event) ++{ ++ int s = jiffies; ++ int ret; ++ ++ if (!seen) ++ seen = jiffies; ++ ++ ret = bh_event_add_var(event, 0, "HOME=%s", "/"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "PATH=%s", ++ "/sbin:/bin:/usr/sbin:/usr/bin"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "ACTION=motion"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen); ++ if (ret) ++ return ret; ++ seen = s; ++ ++ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); ++ ++ return ret; ++} ++ ++static void motion_hotplug_work(struct work_struct *work) ++{ ++ struct bh_event *event = container_of(work, struct bh_event, work); ++ int ret = 0; ++ ++ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); ++ if (!event->skb) ++ goto out_free_event; ++ ++ ret = bh_event_add_var(event, 0, "%s@", "add"); ++ if (ret) ++ goto out_free_skb; ++ ++ ret = motion_hotplug_fill_event(event); ++ if (ret) ++ goto out_free_skb; ++ ++ NETLINK_CB(event->skb).dst_group = 1; ++ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); ++ ++out_free_skb: ++ if (ret) { ++ BH_ERR("work error %d\n", ret); ++ kfree_skb(event->skb); ++ } ++out_free_event: ++ kfree(event); ++} ++ ++static int motion_hotplug_create_event(void) ++{ ++ struct bh_event *event; ++ ++ event = kzalloc(sizeof(*event), GFP_KERNEL); ++ if (!event) ++ return -ENOMEM; ++ ++ event->name = "motion"; ++ ++ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work); ++ schedule_work(&event->work); ++ ++ return 0; ++} ++ ++#define MOTION_FLAG_OFFSET 4 + static void uvc_video_decode_end(struct uvc_streaming *stream, + struct uvc_buffer *buf, const __u8 *data, int len) + { ++ if ((stream->dev->quirks & UVC_QUIRK_MOTION) && ++ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { ++ u8 *mem; ++ buf->state = UVC_BUF_STATE_READY; ++ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET); ++ if ( stream->dev->motion ) { ++ stream->dev->motion = 0; ++ motion_hotplug_create_event(); ++ } else { ++ *mem &= 0x7f; ++ } ++ } ++ + /* Mark the buffer as done if the EOF marker is set. */ + if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { + uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); +@@ -1518,6 +1663,8 @@ static int uvc_init_video_isoc(struct uv + if (npackets == 0) + return -ENOMEM; + ++ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO) ++ npackets = 1; + size = npackets * psize; + + for (i = 0; i < UVC_URBS; ++i) { +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -186,7 +186,9 @@ + #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 + #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400 + #define UVC_QUIRK_FORCE_Y8 0x00000800 +- ++#define UVC_QUIRK_MOTION 0x00001000 ++#define UVC_QUIRK_SINGLE_ISO 0x00002000 ++ + /* Format flags */ + #define UVC_FMT_FLAG_COMPRESSED 0x00000001 + #define UVC_FMT_FLAG_STREAM 0x00000002 +@@ -584,6 +586,7 @@ struct uvc_device { + __u8 *status; + struct input_dev *input; + char input_phys[64]; ++ int motion; + }; + + enum uvc_handle_state { diff --git a/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch b/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch new file mode 100644 index 0000000000..c04e2db661 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch @@ -0,0 +1,29 @@ +From a758e0870c6d1e4b0272f6e7f9efa9face5534bb Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:49:07 +0100 +Subject: [PATCH 32/53] USB: dwc2: add device_reset() + +Signed-off-by: John Crispin +--- + drivers/usb/dwc2/hcd.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -5215,6 +5216,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso + + retval = -ENOMEM; + ++ device_reset(hsotg->dev); ++ + hcfg = dwc2_readl(hsotg->regs + HCFG); + dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); + diff --git a/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch b/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch new file mode 100644 index 0000000000..5536e3f61c --- /dev/null +++ b/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch @@ -0,0 +1,59 @@ +From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:38:50 +0100 +Subject: [PATCH 34/53] NET: multi phy support + +Signed-off-by: John Crispin +--- + drivers/net/phy/phy.c | 9 ++++++--- + include/linux/phy.h | 1 + + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -913,7 +913,10 @@ void phy_state_machine(struct work_struc + /* If the link is down, give up on negotiation for now */ + if (!phydev->link) { + phydev->state = PHY_NOLINK; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + break; + } + +@@ -1000,7 +1003,10 @@ void phy_state_machine(struct work_struc + phy_link_up(phydev); + } else { + phydev->state = PHY_NOLINK; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + } + + if (phy_interrupt_is_valid(phydev)) +@@ -1010,7 +1016,10 @@ void phy_state_machine(struct work_struc + case PHY_HALTED: + if (phydev->link) { + phydev->link = 0; +- phy_link_down(phydev, true); ++ if (!phydev->no_auto_carrier_off) ++ phy_link_down(phydev, true); ++ else ++ phy_link_down(phydev, false); + do_suspend = true; + } + break; +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -412,6 +412,7 @@ struct phy_device { + bool suspended; + bool sysfs_links; + bool loopback_enabled; ++ bool no_auto_carrier_off; + + enum phy_state state; + diff --git a/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch b/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch new file mode 100644 index 0000000000..478af4cbc9 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch @@ -0,0 +1,70 @@ +From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 15 Jul 2013 00:39:21 +0200 +Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write + +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -40,7 +40,7 @@ + #include + + #define AMD_BOOTLOC_BUG +-#define FORCE_WORD_WRITE 0 ++#define FORCE_WORD_WRITE 1 + + #define MAX_RETRIES 3 + +@@ -51,7 +51,9 @@ + + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#if !FORCE_WORD_WRITE + static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#endif + static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); + static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); + static void cfi_amdstd_sync (struct mtd_info *); +@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m + } + #endif + ++#if !FORCE_WORD_WRITE + static void fixup_use_write_buffers(struct mtd_info *mtd) + { + struct map_info *map = mtd->priv; +@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru + mtd->_write = cfi_amdstd_write_buffers; + } + } ++#endif /* !FORCE_WORD_WRITE */ + + /* Atmel chips don't use the same PRI format as AMD chips */ + static void fixup_convert_atmel_pri(struct mtd_info *mtd) +@@ -1798,6 +1802,7 @@ static int cfi_amdstd_write_words(struct + /* + * FIXME: interleaved mode not tested, and probably not supported! + */ ++#if !FORCE_WORD_WRITE + static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, + int len) +@@ -1926,7 +1931,6 @@ static int __xipram do_write_buffer(stru + return ret; + } + +- + static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) + { +@@ -2001,6 +2005,7 @@ static int cfi_amdstd_write_buffers(stru + + return 0; + } ++#endif /* !FORCE_WORD_WRITE */ + + /* + * Wait for the flash chip to become ready to write data diff --git a/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch b/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch new file mode 100644 index 0000000000..4758f18558 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch @@ -0,0 +1,67 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] Revert "mtd: nand: Remove unused chip->write_page() hook" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reverts commit f107d7a43923a83d837b3ea3c7b7de58cd014bbd. + +OpenWrt's downstream driver mtk_nand2 still uses that callback. + +Signed-off-by: Rafał Miłecki +--- + +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -2577,7 +2577,7 @@ static int nand_write_page_syndrome(stru + } + + /** +- * nand_write_page - write one page ++ * nand_write_page - [REPLACEABLE] write one page + * @mtd: MTD device structure + * @chip: NAND chip descriptor + * @offset: address offset within the page +@@ -2761,9 +2761,9 @@ static int nand_do_write_ops(struct mtd_ + memset(chip->oob_poi, 0xff, mtd->oobsize); + } + +- ret = nand_write_page(mtd, chip, column, bytes, wbuf, +- oob_required, page, +- (ops->mode == MTD_OPS_RAW)); ++ ret = chip->write_page(mtd, chip, column, bytes, wbuf, ++ oob_required, page, ++ (ops->mode == MTD_OPS_RAW)); + if (ret) + break; + +@@ -4719,6 +4719,9 @@ int nand_scan_tail(struct mtd_info *mtd) + } + } + ++ if (!chip->write_page) ++ chip->write_page = nand_write_page; ++ + /* + * Check ECC mode, default to software if 3byte/512byte hardware ECC is + * selected and we have 256 byte pagesize fallback to software ECC +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -862,6 +862,7 @@ struct nand_manufacturer_ops { + * structure which is shared among multiple independent + * devices. + * @priv: [OPTIONAL] pointer to private chip data ++ * @write_page: [REPLACEABLE] High-level page write function + * @manufacturer: [INTERN] Contains manufacturer information + */ + +@@ -885,6 +886,9 @@ struct nand_chip { + int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); + int (*erase)(struct mtd_info *mtd, int page); + int (*scan_bbt)(struct mtd_info *mtd); ++ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, ++ uint32_t offset, int data_len, const uint8_t *buf, ++ int oob_required, int page, int raw); + int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip, + int feature_addr, uint8_t *subfeature_para); + int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip, diff --git a/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch b/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch new file mode 100644 index 0000000000..3c6a59b863 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch @@ -0,0 +1,4437 @@ +From 0e1c4e3c97b83b4e7da65b1c56f0a7d40736ac53 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:05:17 +0100 +Subject: [PATCH 39/53] mtd: add mt7621 nand support + +Signed-off-by: John Crispin +--- + drivers/mtd/nand/Kconfig | 6 + + drivers/mtd/nand/Makefile | 1 + + drivers/mtd/nand/bmt.c | 750 ++++++++++++ + drivers/mtd/nand/bmt.h | 80 ++ + drivers/mtd/nand/dev-nand.c | 63 + + drivers/mtd/nand/mt6575_typedefs.h | 340 ++++++ + drivers/mtd/nand/mtk_nand2.c | 2304 +++++++++++++++++++++++++++++++++++ + drivers/mtd/nand/mtk_nand2.h | 452 +++++++ + drivers/mtd/nand/nand_base.c | 6 +- + drivers/mtd/nand/nand_def.h | 123 ++ + drivers/mtd/nand/nand_device_list.h | 55 + + drivers/mtd/nand/partition.h | 115 ++ + 13 files changed, 4311 insertions(+), 3 deletions(-) + create mode 100644 drivers/mtd/nand/bmt.c + create mode 100644 drivers/mtd/nand/bmt.h + create mode 100644 drivers/mtd/nand/dev-nand.c + create mode 100644 drivers/mtd/nand/mt6575_typedefs.h + create mode 100644 drivers/mtd/nand/mtk_nand2.c + create mode 100644 drivers/mtd/nand/mtk_nand2.h + create mode 100644 drivers/mtd/nand/nand_def.h + create mode 100644 drivers/mtd/nand/nand_device_list.h + create mode 100644 drivers/mtd/nand/partition.h + +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -563,4 +563,10 @@ config MTD_NAND_MTK + Enables support for NAND controller on MTK SoCs. + This controller is found on mt27xx, mt81xx, mt65xx SoCs. + ++config MTK_MTD_NAND ++ tristate "Support for MTK SoC NAND controller" ++ depends on SOC_MT7621 ++ select MTD_NAND_IDS ++ select MTD_NAND_ECC ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_HISI504) + + obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ + obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o + obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o ++obj-$(CONFIG_MTK_MTD_NAND) += mtk_nand2.o bmt.o + + nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_amd.o +--- /dev/null ++++ b/drivers/mtd/nand/bmt.c +@@ -0,0 +1,750 @@ ++#include "bmt.h" ++ ++typedef struct ++{ ++ char signature[3]; ++ u8 version; ++ u8 bad_count; // bad block count in pool ++ u8 mapped_count; // mapped block count in pool ++ u8 checksum; ++ u8 reseverd[13]; ++} phys_bmt_header; ++ ++typedef struct ++{ ++ phys_bmt_header header; ++ bmt_entry table[MAX_BMT_SIZE]; ++} phys_bmt_struct; ++ ++typedef struct ++{ ++ char signature[3]; ++} bmt_oob_data; ++ ++static char MAIN_SIGNATURE[] = "BMT"; ++static char OOB_SIGNATURE[] = "bmt"; ++#define SIGNATURE_SIZE (3) ++ ++#define MAX_DAT_SIZE 0x1000 ++#define MAX_OOB_SIZE 0x80 ++ ++static struct mtd_info *mtd_bmt; ++static struct nand_chip *nand_chip_bmt; ++#define BLOCK_SIZE_BMT (1 << nand_chip_bmt->phys_erase_shift) ++#define PAGE_SIZE_BMT (1 << nand_chip_bmt->page_shift) ++ ++#define OFFSET(block) ((block) * BLOCK_SIZE_BMT) ++#define PAGE_ADDR(block) ((block) * BLOCK_SIZE_BMT / PAGE_SIZE_BMT) ++ ++/********************************************************************* ++* Flash is splited into 2 parts, system part is for normal system * ++* system usage, size is system_block_count, another is replace pool * ++* +-------------------------------------------------+ * ++* | system_block_count | bmt_block_count | * ++* +-------------------------------------------------+ * ++*********************************************************************/ ++static u32 total_block_count; // block number in flash ++static u32 system_block_count; ++static int bmt_block_count; // bmt table size ++// static int bmt_count; // block used in bmt ++static int page_per_block; // page per count ++ ++static u32 bmt_block_index; // bmt block index ++static bmt_struct bmt; // dynamic created global bmt table ++ ++static u8 dat_buf[MAX_DAT_SIZE]; ++static u8 oob_buf[MAX_OOB_SIZE]; ++static bool pool_erased; ++ ++/*************************************************************** ++* ++* Interface adaptor for preloader/uboot/kernel ++* These interfaces operate on physical address, read/write ++* physical data. ++* ++***************************************************************/ ++int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ return mtk_nand_exec_read_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob); ++} ++ ++bool nand_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_bad_hw(mtd_bmt, offset); ++} ++ ++bool nand_erase_bmt(u32 offset) ++{ ++ int status; ++ if (offset < 0x20000) ++ { ++ MSG(INIT, "erase offset: 0x%x\n", offset); ++ } ++ ++ status = mtk_nand_erase_hw(mtd_bmt, offset / PAGE_SIZE_BMT); // as nand_chip structure doesn't have a erase function defined ++ if (status & NAND_STATUS_FAIL) ++ return false; ++ else ++ return true; ++} ++ ++int mark_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_markbad_hw(mtd_bmt, offset); //mark_block_bad_hw(offset); ++} ++ ++bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ if (mtk_nand_exec_write_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob)) ++ return false; ++ else ++ return true; ++} ++ ++/*************************************************************** ++* * ++* static internal function * ++* * ++***************************************************************/ ++static void dump_bmt_info(bmt_struct * bmt) ++{ ++ int i; ++ ++ MSG(INIT, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count); ++ for (i = 0; i < bmt->mapped_count; i++) ++ { ++ MSG(INIT, "\t0x%x -> 0x%x\n", bmt->table[i].bad_index, bmt->table[i].mapped_index); ++ } ++} ++ ++static bool match_bmt_signature(u8 * dat, u8 * oob) ++{ ++ ++ if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ return false; ++ } ++ ++ if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ MSG(INIT, "main signature match, oob signature doesn't match, but ignore\n"); ++ } ++ return true; ++} ++ ++static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size) ++{ ++ int i; ++ u8 checksum = 0; ++ u8 *dat = (u8 *) phys_table; ++ ++ checksum += phys_table->header.version; ++ checksum += phys_table->header.mapped_count; ++ ++ dat += sizeof(phys_bmt_header); ++ for (i = 0; i < bmt_size * sizeof(bmt_entry); i++) ++ { ++ checksum += dat[i]; ++ } ++ ++ return checksum; ++} ++ ++ ++static int is_block_mapped(int index) ++{ ++ int i; ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (index == bmt.table[i].mapped_index) ++ return i; ++ } ++ return -1; ++} ++ ++static bool is_page_used(u8 * dat, u8 * oob) ++{ ++ return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF)); ++} ++ ++static bool valid_bmt_data(phys_bmt_struct * phys_table) ++{ ++ int i; ++ u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count); ++ ++ // checksum correct? ++ if (phys_table->header.checksum != checksum) ++ { ++ MSG(INIT, "BMT Data checksum error: %x %x\n", phys_table->header.checksum, checksum); ++ return false; ++ } ++ ++ MSG(INIT, "BMT Checksum is: 0x%x\n", phys_table->header.checksum); ++ ++ // block index correct? ++ for (i = 0; i < phys_table->header.mapped_count; i++) ++ { ++ if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count) ++ { ++ MSG(INIT, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index); ++ return false; ++ } ++ } ++ ++ // pass check, valid bmt. ++ MSG(INIT, "Valid BMT, version v%d\n", phys_table->header.version); ++ return true; ++} ++ ++static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob) ++{ ++ phys_bmt_struct phys_bmt; ++ ++ dump_bmt_info(bmt); ++ ++ // fill phys_bmt_struct structure with bmt_struct ++ memset(&phys_bmt, 0xFF, sizeof(phys_bmt)); ++ ++ memcpy(phys_bmt.header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE); ++ phys_bmt.header.version = BMT_VERSION; ++ // phys_bmt.header.bad_count = bmt->bad_count; ++ phys_bmt.header.mapped_count = bmt->mapped_count; ++ memcpy(phys_bmt.table, bmt->table, sizeof(bmt_entry) * bmt_block_count); ++ ++ phys_bmt.header.checksum = cal_bmt_checksum(&phys_bmt, bmt_block_count); ++ ++ memcpy(dat + MAIN_SIGNATURE_OFFSET, &phys_bmt, sizeof(phys_bmt)); ++ memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE); ++} ++ ++// return valid index if found BMT, else return 0 ++static int load_bmt_data(int start, int pool_size) ++{ ++ int bmt_index = start + pool_size - 1; // find from the end ++ phys_bmt_struct phys_table; ++ int i; ++ ++ MSG(INIT, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index); ++ ++ for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--) ++ { ++ if (nand_block_bad_bmt(OFFSET(bmt_index))) ++ { ++ MSG(INIT, "Skip bad block: %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Error found when read block %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!match_bmt_signature(dat_buf, oob_buf)) ++ { ++ continue; ++ } ++ ++ MSG(INIT, "Match bmt signature @ block: 0x%x\n", bmt_index); ++ ++ memcpy(&phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_table)); ++ ++ if (!valid_bmt_data(&phys_table)) ++ { ++ MSG(INIT, "BMT data is not correct %d\n", bmt_index); ++ continue; ++ } else ++ { ++ bmt.mapped_count = phys_table.header.mapped_count; ++ bmt.version = phys_table.header.version; ++ // bmt.bad_count = phys_table.header.bad_count; ++ memcpy(bmt.table, phys_table.table, bmt.mapped_count * sizeof(bmt_entry)); ++ ++ MSG(INIT, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count); ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index))) ++ { ++ MSG(INIT, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index); ++ mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index)); ++ } ++ } ++ ++ return bmt_index; ++ } ++ } ++ ++ MSG(INIT, "bmt block not found!\n"); ++ return 0; ++} ++ ++/************************************************************************* ++* Find an available block and erase. * ++* start_from_end: if true, find available block from end of flash. * ++* else, find from the beginning of the pool * ++* need_erase: if true, all unmapped blocks in the pool will be erased * ++*************************************************************************/ ++static int find_available_block(bool start_from_end) ++{ ++ int i; // , j; ++ int block = system_block_count; ++ int direction; ++ // int avail_index = 0; ++ MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased); ++ ++ // erase all un-mapped blocks in pool when finding avaliable block ++ if (!pool_erased) ++ { ++ MSG(INIT, "Erase all un-mapped blocks in pool\n"); ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block + i); ++ continue; ++ } ++//if(block==4095) ++//{ ++// continue; ++//} ++ ++ if (is_block_mapped(block + i) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block + i); ++ continue; ++ } ++ ++ if (!nand_erase_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Erase block 0x%x failed\n", block + i); ++ mark_block_bad_bmt(OFFSET(block + i)); ++ } ++ } ++ ++ pool_erased = 1; ++ } ++ ++ if (start_from_end) ++ { ++ block = total_block_count - 1; ++ direction = -1; ++ } else ++ { ++ block = system_block_count; ++ direction = 1; ++ } ++ ++ for (i = 0; i < bmt_block_count; i++, block += direction) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block); ++ continue; ++ } ++ ++ if (is_block_mapped(block) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block); ++ continue; ++ } ++ ++ MSG(INIT, "Find block 0x%x available\n", block); ++ return block; ++ } ++ ++ return 0; ++} ++ ++static unsigned short get_bad_index_from_oob(u8 * oob_buf) ++{ ++ unsigned short index; ++ memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE); ++ ++ return index; ++} ++ ++void set_bad_index_to_oob(u8 * oob, u16 index) ++{ ++ memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index)); ++} ++ ++static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob) ++{ ++ int page; ++ int error_block = offset / BLOCK_SIZE_BMT; ++ int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; ++ int to_index; ++ ++ memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ to_index = find_available_block(false); ++ ++ if (!to_index) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return 0; ++ } ++ ++ { // migrate error page first ++ MSG(INIT, "Write error page: 0x%x\n", error_page); ++ if (!write_dat) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL); ++ write_dat = dat_buf; ++ } ++ // memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ if (error_block < system_block_count) ++ set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ ++ for (page = 0; page < page_per_block; page++) ++ { ++ if (page != error_page) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); ++ if (is_page_used(dat_buf, oob_buf)) ++ { ++ if (error_block < system_block_count) ++ { ++ set_bad_index_to_oob(oob_buf, error_block); ++ } ++ MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page); ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ } ++ } ++ ++ MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index); ++ ++ return to_index; ++} ++ ++static bool write_bmt_to_flash(u8 * dat, u8 * oob) ++{ ++ bool need_erase = true; ++ MSG(INIT, "Try to write BMT\n"); ++ ++ if (bmt_block_index == 0) ++ { ++ // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() ++ need_erase = false; ++ if (!(bmt_block_index = find_available_block(true))) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return false; ++ } ++ } ++ ++ MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index); ++ ++ // write bmt to flash ++ if (need_erase) ++ { ++ if (!nand_erase_bmt(OFFSET(bmt_block_index))) ++ { ++ MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ } ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob)) ++ { ++ MSG(INIT, "Write BMT data fail, need to write again\n"); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ ++ MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index); ++ return true; ++} ++ ++/******************************************************************* ++* Reconstruct bmt, called when found bmt info doesn't match bad ++* block info in flash. ++* ++* Return NULL for failure ++*******************************************************************/ ++bmt_struct *reconstruct_bmt(bmt_struct * bmt) ++{ ++ int i; ++ int index = system_block_count; ++ unsigned short bad_index; ++ int mapped; ++ ++ // init everything in BMT struct ++ bmt->version = BMT_VERSION; ++ bmt->bad_count = 0; ++ bmt->mapped_count = 0; ++ ++ memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry)); ++ ++ for (i = 0; i < bmt_block_count; i++, index++) ++ { ++ if (nand_block_bad_bmt(OFFSET(index))) ++ { ++ MSG(INIT, "Skip bad block: 0x%x\n", index); ++ // bmt->bad_count++; ++ continue; ++ } ++ ++ MSG(INIT, "read page: 0x%x\n", PAGE_ADDR(index)); ++ nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf); ++ /* if (mtk_nand_read_page_hw(PAGE_ADDR(index), dat_buf)) ++ { ++ MSG(INIT, "Error when read block %d\n", bmt_block_index); ++ continue; ++ } */ ++ ++ if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count) ++ { ++ MSG(INIT, "get bad index: 0x%x\n", bad_index); ++ if (bad_index != 0xFFFF) ++ MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index); ++ continue; ++ } ++ ++ MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index); ++ ++ if (!nand_block_bad_bmt(OFFSET(bad_index))) ++ { ++ MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index); ++ continue; // no need to erase here, it will be erased later when trying to write BMT ++ } ++ ++ if ((mapped = is_block_mapped(bad_index)) >= 0) ++ { ++ MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index); ++ bmt->table[mapped].mapped_index = index; // use new one instead. ++ } else ++ { ++ // add mapping to BMT ++ bmt->table[bmt->mapped_count].bad_index = bad_index; ++ bmt->table[bmt->mapped_count].mapped_index = index; ++ bmt->mapped_count++; ++ } ++ ++ MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index); ++ ++ } ++ ++ MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count); ++ // dump_bmt_info(bmt); ++ ++ // fill NAND BMT buffer ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(bmt, dat_buf, oob_buf); ++ ++ // write BMT back ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ { ++ MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n"); ++ } ++ ++ return bmt; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Init bmt from nand. Reconstruct if not found or data error ++* ++* Parameter: ++* size: size of bmt and replace pool ++* ++* Return: ++* NULL for failure, and a bmt struct for success ++*******************************************************************/ ++bmt_struct *init_bmt(struct nand_chip * chip, int size) ++{ ++ struct mtk_nand_host *host; ++ ++ if (size > 0 && size < MAX_BMT_SIZE) ++ { ++ MSG(INIT, "Init bmt table, size: %d\n", size); ++ bmt_block_count = size; ++ } else ++ { ++ MSG(INIT, "Invalid bmt table size: %d\n", size); ++ return NULL; ++ } ++ nand_chip_bmt = chip; ++ system_block_count = chip->chipsize >> chip->phys_erase_shift; ++ total_block_count = bmt_block_count + system_block_count; ++ page_per_block = BLOCK_SIZE_BMT / PAGE_SIZE_BMT; ++ host = (struct mtk_nand_host *)chip->priv; ++ mtd_bmt = host->mtd; ++ ++ MSG(INIT, "mtd_bmt: %p, nand_chip_bmt: %p\n", mtd_bmt, nand_chip_bmt); ++ MSG(INIT, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count); ++ ++ // set this flag, and unmapped block in pool will be erased. ++ pool_erased = 0; ++ memset(bmt.table, 0, size * sizeof(bmt_entry)); ++ if ((bmt_block_index = load_bmt_data(system_block_count, size))) ++ { ++ MSG(INIT, "Load bmt data success @ block 0x%x\n", bmt_block_index); ++ dump_bmt_info(&bmt); ++ return &bmt; ++ } else ++ { ++ MSG(INIT, "Load bmt data fail, need re-construct!\n"); ++#ifndef __UBOOT_NAND__ // BMT is not re-constructed in UBOOT. ++ if (reconstruct_bmt(&bmt)) ++ return &bmt; ++ else ++#endif ++ return NULL; ++ } ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Update BMT. ++* ++* Parameter: ++* offset: update block/page offset. ++* reason: update reason, see update_reason_t for reason. ++* dat/oob: data and oob buffer for write fail. ++* ++* Return: ++* Return true for success, and false for failure. ++*******************************************************************/ ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob) ++{ ++ int map_index; ++ int orig_bad_block = -1; ++ // int bmt_update_index; ++ int i; ++ int bad_index = offset / BLOCK_SIZE_BMT; ++ ++#ifndef MTK_NAND_BMT ++ return false; ++#endif ++ if (reason == UPDATE_WRITE_FAIL) ++ { ++ MSG(INIT, "Write fail, need to migrate\n"); ++ if (!(map_index = migrate_from_bad(offset, dat, oob))) ++ { ++ MSG(INIT, "migrate fail\n"); ++ return false; ++ } ++ } else ++ { ++ if (!(map_index = find_available_block(false))) ++ { ++ MSG(INIT, "Cannot find block in pool\n"); ++ return false; ++ } ++ } ++ ++ // now let's update BMT ++ if (bad_index >= system_block_count) // mapped block become bad, find original bad block ++ { ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (bmt.table[i].mapped_index == bad_index) ++ { ++ orig_bad_block = bmt.table[i].bad_index; ++ break; ++ } ++ } ++ // bmt.bad_count++; ++ MSG(INIT, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block); ++ ++ bmt.table[i].mapped_index = map_index; ++ } else ++ { ++ bmt.table[bmt.mapped_count].mapped_index = map_index; ++ bmt.table[bmt.mapped_count].bad_index = bad_index; ++ bmt.mapped_count++; ++ } ++ ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf); ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ return false; ++ ++ mark_block_bad_bmt(offset); ++ ++ return true; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Given an block index, return mapped index if it's mapped, else ++* return given index. ++* ++* Parameter: ++* index: given an block index. This value cannot exceed ++* system_block_count. ++* ++* Return NULL for failure ++*******************************************************************/ ++u16 get_mapping_block_index(int index) ++{ ++ int i; ++#ifndef MTK_NAND_BMT ++ return index; ++#endif ++ if (index > system_block_count) ++ { ++ return index; ++ } ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (bmt.table[i].bad_index == index) ++ { ++ return bmt.table[i].mapped_index; ++ } ++ } ++ ++ return index; ++} ++#ifdef __KERNEL_NAND__ ++EXPORT_SYMBOL_GPL(init_bmt); ++EXPORT_SYMBOL_GPL(update_bmt); ++EXPORT_SYMBOL_GPL(get_mapping_block_index); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("MediaTek"); ++MODULE_DESCRIPTION("Bad Block mapping management for MediaTek NAND Flash Driver"); ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/bmt.h +@@ -0,0 +1,80 @@ ++#ifndef __BMT_H__ ++#define __BMT_H__ ++ ++#include "nand_def.h" ++ ++#if defined(__PRELOADER_NAND__) ++ ++#include "nand.h" ++ ++#elif defined(__UBOOT_NAND__) ++ ++#include ++#include "mtk_nand2.h" ++ ++#elif defined(__KERNEL_NAND__) ++ ++#include ++#include ++#include ++#include "mtk_nand2.h" ++ ++#endif ++ ++ ++#define MAX_BMT_SIZE (0x80) ++#define BMT_VERSION (1) // initial version ++ ++#define MAIN_SIGNATURE_OFFSET (0) ++#define OOB_SIGNATURE_OFFSET (1) ++#define OOB_INDEX_OFFSET (29) ++#define OOB_INDEX_SIZE (2) ++#define FAKE_INDEX (0xAAAA) ++ ++typedef struct _bmt_entry_ ++{ ++ u16 bad_index; // bad block index ++ u16 mapped_index; // mapping block index in the replace pool ++} bmt_entry; ++ ++typedef enum ++{ ++ UPDATE_ERASE_FAIL, ++ UPDATE_WRITE_FAIL, ++ UPDATE_UNMAPPED_BLOCK, ++ UPDATE_REASON_COUNT, ++} update_reason_t; ++ ++typedef struct ++{ ++ bmt_entry table[MAX_BMT_SIZE]; ++ u8 version; ++ u8 mapped_count; // mapped block count in pool ++ u8 bad_count; // bad block count in pool. Not used in V1 ++} bmt_struct; ++ ++/*************************************************************** ++* * ++* Interface BMT need to use * ++* * ++***************************************************************/ ++extern bool mtk_nand_exec_read_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++extern int mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_erase_hw(struct mtd_info *mtd, int page); ++extern int mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_exec_write_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++ ++ ++/*************************************************************** ++* * ++* Different function interface for preloader/uboot/kernel * ++* * ++***************************************************************/ ++void set_bad_index_to_oob(u8 * oob, u16 index); ++ ++ ++bmt_struct *init_bmt(struct nand_chip *nand, int size); ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob); ++unsigned short get_mapping_block_index(int index); ++ ++#endif // #ifndef __BMT_H__ +--- /dev/null ++++ b/drivers/mtd/nand/dev-nand.c +@@ -0,0 +1,63 @@ ++#include ++#include ++#include ++ ++#include "mt6575_typedefs.h" ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define NFI_base RALINK_NAND_CTRL_BASE ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++#define NFIECC_base RALINK_NANDECC_CTRL_BASE ++#define MT7621_NFI_IRQ_ID SURFBOARDINT_NAND ++#define MT7621_NFIECC_IRQ_ID SURFBOARDINT_NAND_ECC ++ ++#define SURFBOARDINT_NAND 22 ++#define SURFBOARDINT_NAND_ECC 23 ++ ++static struct resource MT7621_resource_nand[] = { ++ { ++ .start = NFI_base, ++ .end = NFI_base + 0x1A0, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = NFIECC_base, ++ .end = NFIECC_base + 0x150, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = MT7621_NFI_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ .start = MT7621_NFIECC_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device MT7621_nand_dev = { ++ .name = "MT7621-NAND", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(MT7621_resource_nand), ++ .resource = MT7621_resource_nand, ++ .dev = { ++ .platform_data = &mt7621_nand_hw, ++ }, ++}; ++ ++ ++int __init mtk_nand_register(void) ++{ ++ ++ int retval = 0; ++ ++ retval = platform_device_register(&MT7621_nand_dev); ++ if (retval != 0) { ++ printk(KERN_ERR "register nand device fail\n"); ++ return retval; ++ } ++ ++ ++ return retval; ++} ++arch_initcall(mtk_nand_register); +--- /dev/null ++++ b/drivers/mtd/nand/mt6575_typedefs.h +@@ -0,0 +1,340 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++/***************************************************************************** ++* Copyright Statement: ++* -------------------- ++* This software is protected by Copyright and the information contained ++* herein is confidential. The software may not be copied and the information ++* contained herein may not be used or disclosed except with the written ++* permission of MediaTek Inc. (C) 2008 ++* ++* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON ++* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH ++* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO ++* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S ++* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. ++* ++* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE ++* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO ++* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++* ++* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE ++* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF ++* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND ++* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER ++* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). ++* ++*****************************************************************************/ ++ ++#ifndef _MT6575_TYPEDEFS_H ++#define _MT6575_TYPEDEFS_H ++ ++#if defined (__KERNEL_NAND__) ++#include ++#else ++#define true 1 ++#define false 0 ++#define bool u8 ++#endif ++ ++// --------------------------------------------------------------------------- ++// Basic Type Definitions ++// --------------------------------------------------------------------------- ++ ++typedef volatile unsigned char *P_kal_uint8; ++typedef volatile unsigned short *P_kal_uint16; ++typedef volatile unsigned int *P_kal_uint32; ++ ++typedef long LONG; ++typedef unsigned char UBYTE; ++typedef short SHORT; ++ ++typedef signed char kal_int8; ++typedef signed short kal_int16; ++typedef signed int kal_int32; ++typedef long long kal_int64; ++typedef unsigned char kal_uint8; ++typedef unsigned short kal_uint16; ++typedef unsigned int kal_uint32; ++typedef unsigned long long kal_uint64; ++typedef char kal_char; ++ ++typedef unsigned int *UINT32P; ++typedef volatile unsigned short *UINT16P; ++typedef volatile unsigned char *UINT8P; ++typedef unsigned char *U8P; ++ ++typedef volatile unsigned char *P_U8; ++typedef volatile signed char *P_S8; ++typedef volatile unsigned short *P_U16; ++typedef volatile signed short *P_S16; ++typedef volatile unsigned int *P_U32; ++typedef volatile signed int *P_S32; ++typedef unsigned long long *P_U64; ++typedef signed long long *P_S64; ++ ++typedef unsigned char U8; ++typedef signed char S8; ++typedef unsigned short U16; ++typedef signed short S16; ++typedef unsigned int U32; ++typedef signed int S32; ++typedef unsigned long long U64; ++typedef signed long long S64; ++//typedef unsigned char bool; ++ ++typedef unsigned char UINT8; ++typedef unsigned short UINT16; ++typedef unsigned int UINT32; ++typedef unsigned short USHORT; ++typedef signed char INT8; ++typedef signed short INT16; ++typedef signed int INT32; ++typedef unsigned int DWORD; ++typedef void VOID; ++typedef unsigned char BYTE; ++typedef float FLOAT; ++ ++typedef char *LPCSTR; ++typedef short *LPWSTR; ++ ++ ++// --------------------------------------------------------------------------- ++// Constants ++// --------------------------------------------------------------------------- ++ ++#define IMPORT EXTERN ++#ifndef __cplusplus ++ #define EXTERN extern ++#else ++ #define EXTERN extern "C" ++#endif ++#define LOCAL static ++#define GLOBAL ++#define EXPORT GLOBAL ++ ++#define EQ == ++#define NEQ != ++#define AND && ++#define OR || ++#define XOR(A,B) ((!(A) AND (B)) OR ((A) AND !(B))) ++ ++#ifndef FALSE ++ #define FALSE (0) ++#endif ++ ++#ifndef TRUE ++ #define TRUE (1) ++#endif ++ ++#ifndef NULL ++ #define NULL (0) ++#endif ++ ++//enum boolean {false, true}; ++enum {RX, TX, NONE}; ++ ++#ifndef BOOL ++typedef unsigned char BOOL; ++#endif ++ ++typedef enum { ++ KAL_FALSE = 0, ++ KAL_TRUE = 1, ++} kal_bool; ++ ++ ++// --------------------------------------------------------------------------- ++// Type Casting ++// --------------------------------------------------------------------------- ++ ++#define AS_INT32(x) (*(INT32 *)((void*)x)) ++#define AS_INT16(x) (*(INT16 *)((void*)x)) ++#define AS_INT8(x) (*(INT8 *)((void*)x)) ++ ++#define AS_UINT32(x) (*(UINT32 *)((void*)x)) ++#define AS_UINT16(x) (*(UINT16 *)((void*)x)) ++#define AS_UINT8(x) (*(UINT8 *)((void*)x)) ++ ++ ++// --------------------------------------------------------------------------- ++// Register Manipulations ++// --------------------------------------------------------------------------- ++ ++#define READ_REGISTER_UINT32(reg) \ ++ (*(volatile UINT32 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT32(reg, val) \ ++ (*(volatile UINT32 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT16(reg) \ ++ (*(volatile UINT16 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT16(reg, val) \ ++ (*(volatile UINT16 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT8(reg) \ ++ (*(volatile UINT8 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT8(reg, val) \ ++ (*(volatile UINT8 * const)(reg)) = (val) ++ ++#define INREG8(x) READ_REGISTER_UINT8((UINT8*)((void*)(x))) ++#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8*)((void*)(x)), (UINT8)(y)) ++#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) ++#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) ++#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) ++ ++#define INREG16(x) READ_REGISTER_UINT16((UINT16*)((void*)(x))) ++#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16*)((void*)(x)),(UINT16)(y)) ++#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) ++#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) ++#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) ++ ++#define INREG32(x) READ_REGISTER_UINT32((UINT32*)((void*)(x))) ++#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32*)((void*)(x)), (UINT32)(y)) ++#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) ++#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) ++#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) ++ ++ ++#define DRV_Reg8(addr) INREG8(addr) ++#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) ++#define DRV_SetReg8(addr, data) SETREG8(addr, data) ++#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) ++ ++#define DRV_Reg16(addr) INREG16(addr) ++#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) ++#define DRV_SetReg16(addr, data) SETREG16(addr, data) ++#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) ++ ++#define DRV_Reg32(addr) INREG32(addr) ++#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) ++#define DRV_SetReg32(addr, data) SETREG32(addr, data) ++#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) ++ ++// !!! DEPRECATED, WILL BE REMOVED LATER !!! ++#define DRV_Reg(addr) DRV_Reg16(addr) ++#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) ++#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) ++#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) ++ ++ ++// --------------------------------------------------------------------------- ++// Compiler Time Deduction Macros ++// --------------------------------------------------------------------------- ++ ++#define _MASK_OFFSET_1(x, n) ((x) & 0x1) ? (n) : ++#define _MASK_OFFSET_2(x, n) _MASK_OFFSET_1((x), (n)) _MASK_OFFSET_1((x) >> 1, (n) + 1) ++#define _MASK_OFFSET_4(x, n) _MASK_OFFSET_2((x), (n)) _MASK_OFFSET_2((x) >> 2, (n) + 2) ++#define _MASK_OFFSET_8(x, n) _MASK_OFFSET_4((x), (n)) _MASK_OFFSET_4((x) >> 4, (n) + 4) ++#define _MASK_OFFSET_16(x, n) _MASK_OFFSET_8((x), (n)) _MASK_OFFSET_8((x) >> 8, (n) + 8) ++#define _MASK_OFFSET_32(x, n) _MASK_OFFSET_16((x), (n)) _MASK_OFFSET_16((x) >> 16, (n) + 16) ++ ++#define MASK_OFFSET_ERROR (0xFFFFFFFF) ++ ++#define MASK_OFFSET(x) (_MASK_OFFSET_32(x, 0) MASK_OFFSET_ERROR) ++ ++ ++// --------------------------------------------------------------------------- ++// Assertions ++// --------------------------------------------------------------------------- ++ ++#ifndef ASSERT ++ #define ASSERT(expr) BUG_ON(!(expr)) ++#endif ++ ++#ifndef NOT_IMPLEMENTED ++ #define NOT_IMPLEMENTED() BUG_ON(1) ++#endif ++ ++#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) ++#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) ++#define STATIC_ASSERT_XX(pred, line) \ ++ extern char assertion_failed_at_##line[(pred) ? 1 : -1] ++ ++// --------------------------------------------------------------------------- ++// Resolve Compiler Warnings ++// --------------------------------------------------------------------------- ++ ++#define NOT_REFERENCED(x) { (x) = (x); } ++ ++ ++// --------------------------------------------------------------------------- ++// Utilities ++// --------------------------------------------------------------------------- ++ ++#define MAXIMUM(A,B) (((A)>(B))?(A):(B)) ++#define MINIMUM(A,B) (((A)<(B))?(A):(B)) ++ ++#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) ++#define DVT_DELAYMACRO(u4Num) \ ++{ \ ++ UINT32 u4Count = 0 ; \ ++ for (u4Count = 0; u4Count < u4Num; u4Count++ ); \ ++} \ ++ ++#define A68351B 0 ++#define B68351B 1 ++#define B68351D 2 ++#define B68351E 3 ++#define UNKNOWN_IC_VERSION 0xFF ++ ++/* NAND driver */ ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern unsigned int CFG_BLOCKSIZE; ++ ++#endif // _MT6575_TYPEDEFS_H ++ +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand2.c +@@ -0,0 +1,2345 @@ ++/****************************************************************************** ++* mtk_nand2.c - MTK NAND Flash Device Driver ++ * ++* Copyright 2009-2012 MediaTek Co.,Ltd. ++ * ++* DESCRIPTION: ++* This file provid the other drivers nand relative functions ++ * ++* modification history ++* ---------------------------------------- ++* v3.0, 11 Feb 2010, mtk ++* ---------------------------------------- ++******************************************************************************/ ++#include "nand_def.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "mtk_nand2.h" ++#include "nand_device_list.h" ++ ++#include "bmt.h" ++#include "partition.h" ++ ++unsigned int CFG_BLOCKSIZE; ++ ++static int shift_on_bbt = 0; ++int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page); ++ ++static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL }; ++ ++#define NAND_CMD_STATUS_MULTI 0x71 ++ ++void show_stack(struct task_struct *tsk, unsigned long *sp); ++extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); ++extern void mt_irq_set_polarity(unsigned int irq,unsigned int polarity); ++ ++struct mtk_nand_host mtk_nand_host; /* include mtd_info and nand_chip structs */ ++struct mtk_nand_host_hw mt7621_nand_hw = { ++ .nfi_bus_width = 8, ++ .nfi_access_timing = NFI_DEFAULT_ACCESS_TIMING, ++ .nfi_cs_num = NFI_CS_NUM, ++ .nand_sec_size = 512, ++ .nand_sec_shift = 9, ++ .nand_ecc_size = 2048, ++ .nand_ecc_bytes = 32, ++ .nand_ecc_mode = NAND_ECC_HW, ++}; ++ ++ ++/******************************************************************************* ++ * Gloable Varible Definition ++ *******************************************************************************/ ++ ++#define NFI_ISSUE_COMMAND(cmd, col_addr, row_addr, col_num, row_num) \ ++ do { \ ++ DRV_WriteReg(NFI_CMD_REG16,cmd);\ ++ while (DRV_Reg32(NFI_STA_REG32) & STA_CMD_STATE);\ ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);\ ++ DRV_WriteReg32(NFI_ROWADDR_REG32, row_addr);\ ++ DRV_WriteReg(NFI_ADDRNOB_REG16, col_num | (row_num<priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6)); ++ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6); ++} ++ ++static int nand_bbt_get(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *this = mtd->priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; ++} ++ ++void nand_enable_clock(void) ++{ ++ //enable_clock(MT65XX_PDN_PERI_NFI, "NAND"); ++} ++ ++void nand_disable_clock(void) ++{ ++ //disable_clock(MT65XX_PDN_PERI_NFI, "NAND"); ++} ++ ++struct nand_ecclayout { ++ __u32 eccbytes; ++ __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; ++ __u32 oobavail; ++ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; ++}; ++ ++static struct nand_ecclayout *layout; ++ ++static struct nand_ecclayout nand_oob_16 = { ++ .eccbytes = 8, ++ .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, ++ .oobfree = {{1, 6}, {0, 0}} ++}; ++ ++struct nand_ecclayout nand_oob_64 = { ++ .eccbytes = 32, ++ .eccpos = {32, 33, 34, 35, 36, 37, 38, 39, ++ 40, 41, 42, 43, 44, 45, 46, 47, ++ 48, 49, 50, 51, 52, 53, 54, 55, ++ 56, 57, 58, 59, 60, 61, 62, 63}, ++ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 6}, {0, 0}} ++}; ++ ++struct nand_ecclayout nand_oob_128 = { ++ .eccbytes = 64, ++ .eccpos = { ++ 64, 65, 66, 67, 68, 69, 70, 71, ++ 72, 73, 74, 75, 76, 77, 78, 79, ++ 80, 81, 82, 83, 84, 85, 86, 86, ++ 88, 89, 90, 91, 92, 93, 94, 95, ++ 96, 97, 98, 99, 100, 101, 102, 103, ++ 104, 105, 106, 107, 108, 109, 110, 111, ++ 112, 113, 114, 115, 116, 117, 118, 119, ++ 120, 121, 122, 123, 124, 125, 126, 127}, ++ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 7}, {33, 7}, {41, 7}, {49, 7}, {57, 6}} ++}; ++ ++flashdev_info devinfo; ++ ++void dump_nfi(void) ++{ ++} ++ ++void dump_ecc(void) ++{ ++} ++ ++u32 ++nand_virt_to_phys_add(u32 va) ++{ ++ u32 pageOffset = (va & (PAGE_SIZE - 1)); ++ pgd_t *pgd; ++ pmd_t *pmd; ++ pte_t *pte; ++ u32 pa; ++ ++ if (virt_addr_valid(va)) ++ return __virt_to_phys(va); ++ ++ if (NULL == current) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR ,current is NULL! \n"); ++ return 0; ++ } ++ ++ if (NULL == current->mm) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR current->mm is NULL! tgid=0x%x, name=%s \n", current->tgid, current->comm); ++ return 0; ++ } ++ ++ pgd = pgd_offset(current->mm, va); /* what is tsk->mm */ ++ if (pgd_none(*pgd) || pgd_bad(*pgd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pgd invalid! \n", va); ++ return 0; ++ } ++ ++ pmd = pmd_offset((pud_t *)pgd, va); ++ if (pmd_none(*pmd) || pmd_bad(*pmd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pmd invalid! \n", va); ++ return 0; ++ } ++ ++ pte = pte_offset_map(pmd, va); ++ if (pte_present(*pte)) { ++ pa = (pte_val(*pte) & (PAGE_MASK)) | pageOffset; ++ return pa; ++ } ++ ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR va=0x%x, pte invalid! \n", va); ++ return 0; ++} ++EXPORT_SYMBOL(nand_virt_to_phys_add); ++ ++bool ++get_device_info(u16 id, u32 ext_id, flashdev_info * pdevinfo) ++{ ++ u32 index; ++ for (index = 0; gen_FlashTable[index].id != 0; index++) { ++ if (id == gen_FlashTable[index].id && ext_id == gen_FlashTable[index].ext_id) { ++ pdevinfo->id = gen_FlashTable[index].id; ++ pdevinfo->ext_id = gen_FlashTable[index].ext_id; ++ pdevinfo->blocksize = gen_FlashTable[index].blocksize; ++ pdevinfo->addr_cycle = gen_FlashTable[index].addr_cycle; ++ pdevinfo->iowidth = gen_FlashTable[index].iowidth; ++ pdevinfo->timmingsetting = gen_FlashTable[index].timmingsetting; ++ pdevinfo->advancedmode = gen_FlashTable[index].advancedmode; ++ pdevinfo->pagesize = gen_FlashTable[index].pagesize; ++ pdevinfo->sparesize = gen_FlashTable[index].sparesize; ++ pdevinfo->totalsize = gen_FlashTable[index].totalsize; ++ memcpy(pdevinfo->devciename, gen_FlashTable[index].devciename, sizeof(pdevinfo->devciename)); ++ printk(KERN_INFO "Device found in MTK table, ID: %x, EXT_ID: %x\n", id, ext_id); ++ ++ goto find; ++ } ++ } ++ ++find: ++ if (0 == pdevinfo->id) { ++ printk(KERN_INFO "Device not found, ID: %x\n", id); ++ return false; ++ } else { ++ return true; ++ } ++} ++ ++static void ++ECC_Config(struct mtk_nand_host_hw *hw,u32 ecc_bit) ++{ ++ u32 u4ENCODESize; ++ u32 u4DECODESize; ++ u32 ecc_bit_cfg = ECC_CNFG_ECC4; ++ ++ switch(ecc_bit){ ++ case 4: ++ ecc_bit_cfg = ECC_CNFG_ECC4; ++ break; ++ case 8: ++ ecc_bit_cfg = ECC_CNFG_ECC8; ++ break; ++ case 10: ++ ecc_bit_cfg = ECC_CNFG_ECC10; ++ break; ++ case 12: ++ ecc_bit_cfg = ECC_CNFG_ECC12; ++ break; ++ default: ++ break; ++ } ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++ do { ++ } while (!DRV_Reg16(ECC_DECIDLE_REG16)); ++ ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++ do { ++ } while (!DRV_Reg32(ECC_ENCIDLE_REG32)); ++ ++ /* setup FDM register base */ ++ DRV_WriteReg32(ECC_FDMADDR_REG32, NFI_FDM0L_REG32); ++ ++ /* Sector + FDM */ ++ u4ENCODESize = (hw->nand_sec_size + 8) << 3; ++ /* Sector + FDM + YAFFS2 meta data bits */ ++ u4DECODESize = ((hw->nand_sec_size + 8) << 3) + ecc_bit * 13; ++ ++ /* configure ECC decoder && encoder */ ++ DRV_WriteReg32(ECC_DECCNFG_REG32, ecc_bit_cfg | DEC_CNFG_NFI | DEC_CNFG_EMPTY_EN | (u4DECODESize << DEC_CNFG_CODE_SHIFT)); ++ ++ DRV_WriteReg32(ECC_ENCCNFG_REG32, ecc_bit_cfg | ENC_CNFG_NFI | (u4ENCODESize << ENC_CNFG_MSG_SHIFT)); ++ NFI_SET_REG32(ECC_DECCNFG_REG32, DEC_CNFG_EL); ++} ++ ++static void ++ECC_Decode_Start(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_EN); ++} ++ ++static void ++ECC_Decode_End(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++} ++ ++static void ++ECC_Encode_Start(void) ++{ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ++ ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_EN); ++} ++ ++static void ++ECC_Encode_End(void) ++{ ++ /* wait for device returning idle */ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++} ++ ++static bool ++mtk_nand_check_bch_error(struct mtd_info *mtd, u8 * pDataBuf, u32 u4SecIndex, u32 u4PageAddr) ++{ ++ bool bRet = true; ++ u16 u2SectorDoneMask = 1 << u4SecIndex; ++ u32 u4ErrorNumDebug, i, u4ErrNum; ++ u32 timeout = 0xFFFF; ++ // int el; ++ u32 au4ErrBitLoc[6]; ++ u32 u4ErrByteLoc, u4BitOffset; ++ u32 u4ErrBitLoc1th, u4ErrBitLoc2nd; ++ ++ //4 // Wait for Decode Done ++ while (0 == (u2SectorDoneMask & DRV_Reg16(ECC_DECDONE_REG16))) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ /* We will manually correct the error bits in the last sector, not all the sectors of the page! */ ++ memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc)); ++ u4ErrorNumDebug = DRV_Reg32(ECC_DECENUM_REG32); ++ u4ErrNum = DRV_Reg32(ECC_DECENUM_REG32) >> (u4SecIndex << 2); ++ u4ErrNum &= 0xF; ++ ++ if (u4ErrNum) { ++ if (0xF == u4ErrNum) { ++ mtd->ecc_stats.failed++; ++ bRet = false; ++ printk(KERN_ERR"mtk_nand: UnCorrectable at PageAddr=%d\n", u4PageAddr); ++ } else { ++ for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) { ++ au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i); ++ u4ErrBitLoc1th = au4ErrBitLoc[i] & 0x1FFF; ++ if (u4ErrBitLoc1th < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc1th / 8; ++ u4BitOffset = u4ErrBitLoc1th % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ } ++ u4ErrBitLoc2nd = (au4ErrBitLoc[i] >> 16) & 0x1FFF; ++ if (0 != u4ErrBitLoc2nd) { ++ if (u4ErrBitLoc2nd < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc2nd / 8; ++ u4BitOffset = u4ErrBitLoc2nd % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ //printk(KERN_ERR"UnCorrectable High ErrLoc=%d\n", au4ErrBitLoc[i]); ++ } ++ } ++ } ++ } ++ if (0 == (DRV_Reg16(ECC_DECFER_REG16) & (1 << u4SecIndex))) ++ bRet = false; ++ } ++ return bRet; ++} ++ ++static bool ++mtk_nand_RFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ while (FIFO_RD_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) < u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_WFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while (FIFO_WR_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) > u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_status_ready(u32 u4Status) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while ((DRV_Reg32(NFI_STA_REG32) & u4Status) != 0) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_reset(void) ++{ ++ int timeout = 0xFFFF; ++ if (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ while (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ timeout--; ++ if (!timeout) ++ MSG(INIT, "Wait for NFI_MASTERSTA timeout\n"); ++ } ++ } ++ /* issue reset operation */ ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ ++ return mtk_nand_status_ready(STA_NFI_FSM_MASK | STA_NAND_BUSY) && mtk_nand_RFIFOValidSize(0) && mtk_nand_WFIFOValidSize(0); ++} ++ ++static void ++mtk_nand_set_mode(u16 u2OpMode) ++{ ++ u16 u2Mode = DRV_Reg16(NFI_CNFG_REG16); ++ u2Mode &= ~CNFG_OP_MODE_MASK; ++ u2Mode |= u2OpMode; ++ DRV_WriteReg16(NFI_CNFG_REG16, u2Mode); ++} ++ ++static void ++mtk_nand_set_autoformat(bool bEnable) ++{ ++ if (bEnable) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++} ++ ++static void ++mtk_nand_configure_fdm(u16 u2FDMSize) ++{ ++ NFI_CLN_REG16(NFI_PAGEFMT_REG16, PAGEFMT_FDM_MASK | PAGEFMT_FDM_ECC_MASK); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_SHIFT); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_ECC_SHIFT); ++} ++ ++static void ++mtk_nand_configure_lock(void) ++{ ++ u32 u4WriteColNOB = 2; ++ u32 u4WriteRowNOB = 3; ++ u32 u4EraseColNOB = 0; ++ u32 u4EraseRowNOB = 3; ++ DRV_WriteReg16(NFI_LOCKANOB_REG16, ++ (u4WriteColNOB << PROG_CADD_NOB_SHIFT) | (u4WriteRowNOB << PROG_RADD_NOB_SHIFT) | (u4EraseColNOB << ERASE_CADD_NOB_SHIFT) | (u4EraseRowNOB << ERASE_RADD_NOB_SHIFT)); ++ ++ if (CHIPVER_ECO_1 == g_u4ChipVer) { ++ int i; ++ for (i = 0; i < 16; ++i) { ++ DRV_WriteReg32(NFI_LOCK00ADD_REG32 + (i << 1), 0xFFFFFFFF); ++ DRV_WriteReg32(NFI_LOCK00FMT_REG32 + (i << 1), 0xFFFFFFFF); ++ } ++ //DRV_WriteReg16(NFI_LOCKANOB_REG16, 0x0); ++ DRV_WriteReg32(NFI_LOCKCON_REG32, 0xFFFFFFFF); ++ DRV_WriteReg16(NFI_LOCK_REG16, NFI_LOCK_ON); ++ } ++} ++ ++static bool ++mtk_nand_pio_ready(void) ++{ ++ int count = 0; ++ while (!(DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)) { ++ count++; ++ if (count > 0xffff) { ++ printk("PIO_DIRDY timeout\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_set_command(u16 command) ++{ ++ mb(); ++ DRV_WriteReg16(NFI_CMD_REG16, command); ++ return mtk_nand_status_ready(STA_CMD_STATE); ++} ++ ++static bool ++mtk_nand_set_address(u32 u4ColAddr, u32 u4RowAddr, u16 u2ColNOB, u16 u2RowNOB) ++{ ++ mb(); ++ DRV_WriteReg32(NFI_COLADDR_REG32, u4ColAddr); ++ DRV_WriteReg32(NFI_ROWADDR_REG32, u4RowAddr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, u2ColNOB | (u2RowNOB << ADDR_ROW_NOB_SHIFT)); ++ return mtk_nand_status_ready(STA_ADDR_STATE); ++} ++ ++static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) ++{ ++ if (ctrl & NAND_ALE) { ++ mtk_nand_set_address(dat, 0, 1, 0); ++ } else if (ctrl & NAND_CLE) { ++ mtk_nand_reset(); ++ mtk_nand_set_mode(0x6000); ++ mtk_nand_set_command(dat); ++ } ++} ++ ++static bool ++mtk_nand_check_RW_count(u16 u2WriteSize) ++{ ++ u32 timeout = 0xFFFF; ++ u16 u2SecNum = u2WriteSize >> 9; ++ ++ while (ADDRCNTR_CNTR(DRV_Reg16(NFI_ADDRCNTR_REG16)) < u2SecNum) { ++ timeout--; ++ if (0 == timeout) { ++ printk(KERN_INFO "[%s] timeout\n", __FUNCTION__); ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_ready_for_read(struct nand_chip *nand, u32 u4RowAddr, u32 u4ColAddr, bool full, u8 * buf) ++{ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ bool bRet = false; ++ u16 sec_num = 1 << (nand->page_shift - 9); ++ u32 col_addr = u4ColAddr; ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ if (!mtk_nand_reset()) ++ goto cleanup; ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ ++ mtk_nand_set_mode(CNFG_OP_READ); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ if (full) ++ if (g_bHwEcc) ++ ECC_Decode_Start(); ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto cleanup; ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto cleanup; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_ready_for_write(struct nand_chip *nand, u32 u4RowAddr, u32 col_addr, bool full, u8 * buf) ++{ ++ bool bRet = false; ++ u32 sec_num = 1 << (nand->page_shift - 9); ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ if (!mtk_nand_reset()) ++ return false; ++ ++ mtk_nand_set_mode(CNFG_OP_PRGM); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ ++ if (full) ++ if (g_bHwEcc) ++ ECC_Encode_Start(); ++ ++ if (!mtk_nand_set_command(NAND_CMD_SEQIN)) ++ goto cleanup; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_check_dececc_done(u32 u4SecNum) ++{ ++ u32 timeout, dec_mask; ++ ++ timeout = 0xffff; ++ dec_mask = (1 << u4SecNum) - 1; ++ while ((dec_mask != DRV_Reg(ECC_DECDONE_REG16)) && timeout > 0) ++ timeout--; ++ if (timeout == 0) { ++ MSG(VERIFY, "ECC_DECDONE: timeout\n"); ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_mcu_read_data(u8 * buf, u32 length) ++{ ++ int timeout = 0xffff; ++ u32 i; ++ u32 *buf32 = (u32 *) buf; ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ //DRV_WriteReg32(NFI_STRADDR_REG32, 0); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf++ = (u8) DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf32++ = DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_read_page_data(struct mtd_info *mtd, u8 * pDataBuf, u32 u4Size) ++{ ++ return mtk_nand_mcu_read_data(pDataBuf, u4Size); ++} ++ ++static bool ++mtk_nand_mcu_write_data(struct mtd_info *mtd, const u8 * buf, u32 length) ++{ ++ u32 timeout = 0xFFFF; ++ u32 i; ++ u32 *pBuf32; ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ pBuf32 = (u32 *) buf; ++ ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *buf++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *pBuf32++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_write_page_data(struct mtd_info *mtd, u8 * buf, u32 size) ++{ ++ return mtk_nand_mcu_write_data(mtd, buf, size); ++} ++ ++static void ++mtk_nand_read_fdm_data(u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i; ++ u32 *pBuf32 = (u32 *) pDataBuf; ++ ++ if (pBuf32) { ++ for (i = 0; i < u4SecNum; ++i) { ++ *pBuf32++ = DRV_Reg32(NFI_FDM0L_REG32 + (i << 1)); ++ *pBuf32++ = DRV_Reg32(NFI_FDM0M_REG32 + (i << 1)); ++ } ++ } ++} ++ ++static u8 fdm_buf[64]; ++static void ++mtk_nand_write_fdm_data(struct nand_chip *chip, u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i, j; ++ u8 checksum = 0; ++ bool empty = true; ++ struct nand_oobfree *free_entry; ++ u32 *pBuf32; ++ ++ memcpy(fdm_buf, pDataBuf, u4SecNum * 8); ++ ++ free_entry = layout->oobfree; ++ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free_entry[i].length; i++) { ++ for (j = 0; j < free_entry[i].length; j++) { ++ if (pDataBuf[free_entry[i].offset + j] != 0xFF) ++ empty = false; ++ checksum ^= pDataBuf[free_entry[i].offset + j]; ++ } ++ } ++ ++ if (!empty) { ++ fdm_buf[free_entry[i - 1].offset + free_entry[i - 1].length] = checksum; ++ } ++ ++ pBuf32 = (u32 *) fdm_buf; ++ for (i = 0; i < u4SecNum; ++i) { ++ DRV_WriteReg32(NFI_FDM0L_REG32 + (i << 1), *pBuf32++); ++ DRV_WriteReg32(NFI_FDM0M_REG32 + (i << 1), *pBuf32++); ++ } ++} ++ ++static void ++mtk_nand_stop_read(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ mtk_nand_reset(); ++ if (g_bHwEcc) ++ ECC_Decode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++static void ++mtk_nand_stop_write(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ if (g_bHwEcc) ++ ECC_Encode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++bool ++mtk_nand_exec_read_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ u8 *buf; ++ bool bRet = true; ++ struct nand_chip *nand = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ ++ buf = pPageBuf; ++ if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) { ++ int j; ++ for (j = 0 ; j < u4SecNum; j++) { ++ if (!mtk_nand_read_page_data(mtd, buf+j*512, 512)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_dececc_done(j+1)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_bch_error(mtd, buf+j*512, j, u4RowAddr)) ++ bRet = false; ++ } ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ bRet = false; ++ ++ mtk_nand_read_fdm_data(pFDMBuf, u4SecNum); ++ mtk_nand_stop_read(); ++ } ++ ++ return bRet; ++} ++ ++int ++mtk_nand_exec_write_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ u8 *buf; ++ u8 status; ++ ++ MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr); ++ ++ buf = pPageBuf; ++ ++ if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) { ++ mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum); ++ (void)mtk_nand_write_page_data(mtd, buf, u4PageSize); ++ (void)mtk_nand_check_RW_count(u4PageSize); ++ mtk_nand_stop_write(); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ; ++ } ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ return 0; ++} ++ ++static int ++get_start_end_block(struct mtd_info *mtd, int block, int *start_blk, int *end_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ ++ *start_blk = 0; ++ for (i = 0; i <= part_num; i++) ++ { ++ if (i == part_num) ++ { ++ // try the last reset partition ++ *end_blk = (chip->chipsize >> chip->phys_erase_shift) - 1; ++ if (*start_blk <= *end_blk) ++ { ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ } ++ } ++ // skip All partition entry ++ else if (g_pasStatic_Partition[i].size == MTDPART_SIZ_FULL) ++ { ++ continue; ++ } ++ *end_blk = *start_blk + (g_pasStatic_Partition[i].size >> chip->phys_erase_shift) - 1; ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ *start_blk = *end_blk + 1; ++ } ++ if (*start_blk > *end_blk) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++block_remap(struct mtd_info *mtd, int block) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int start_blk, end_blk; ++ int j, block_offset; ++ int bad_block = 0; ++ ++ if (chip->bbt == NULL) { ++ printk("ERROR!! no bbt table for block_remap\n"); ++ return -1; ++ } ++ ++ if (get_start_end_block(mtd, block, &start_blk, &end_blk) < 0) { ++ printk("ERROR!! can not find start_blk and end_blk\n"); ++ return -1; ++ } ++ ++ block_offset = block - start_blk; ++ for (j = start_blk; j <= end_blk;j++) { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) == 0x0) { ++ if (!block_offset) ++ break; ++ block_offset--; ++ } else { ++ bad_block++; ++ } ++ } ++ if (j <= end_blk) { ++ return j; ++ } else { ++ // remap to the bad block ++ for (j = end_blk; bad_block > 0; j--) ++ { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) != 0x0) ++ { ++ bad_block--; ++ if (bad_block <= block_offset) ++ return j; ++ } ++ } ++ } ++ ++ printk("Error!! block_remap error\n"); ++ return -1; ++} ++ ++int ++check_block_remap(struct mtd_info *mtd, int block) ++{ ++ if (shift_on_bbt) ++ return block_remap(mtd, block); ++ else ++ return block; ++} ++EXPORT_SYMBOL(check_block_remap); ++ ++ ++static int ++write_next_on_fail(struct mtd_info *mtd, char *write_buf, int page, int * to_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i, j, to_page = 0, first_page; ++ char *buf, *oob; ++ int start_blk = 0, end_blk; ++ int mapped_block; ++ int page_per_block_bit = chip->phys_erase_shift - chip->page_shift; ++ int block = page >> page_per_block_bit; ++ ++ // find next available block in the same MTD partition ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ ++ get_start_end_block(mtd, block, &start_blk, &end_blk); ++ ++ buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL | GFP_DMA); ++ if (buf == NULL) ++ return -1; ++ ++ oob = buf + mtd->writesize; ++ for ((*to_blk) = block + 1; (*to_blk) <= end_blk ; (*to_blk)++) { ++ if (nand_bbt_get(mtd, (*to_blk) << page_per_block_bit) == 0) { ++ int status; ++ status = mtk_nand_erase_hw(mtd, (*to_blk) << page_per_block_bit); ++ if (status & NAND_STATUS_FAIL) { ++ mtk_nand_block_markbad_hw(mtd, (*to_blk) << chip->phys_erase_shift); ++ nand_bbt_set(mtd, (*to_blk) << page_per_block_bit, 0x3); ++ } else { ++ /* good block */ ++ to_page = (*to_blk) << page_per_block_bit; ++ break; ++ } ++ } ++ } ++ ++ if (!to_page) { ++ kfree(buf); ++ return -1; ++ } ++ ++ first_page = (page >> page_per_block_bit) << page_per_block_bit; ++ for (i = 0; i < (1 << page_per_block_bit); i++) { ++ if ((first_page + i) != page) { ++ mtk_nand_read_oob_hw(mtd, chip, (first_page+i)); ++ for (j = 0; j < mtd->oobsize; j++) ++ if (chip->oob_poi[j] != (unsigned char)0xff) ++ break; ++ if (j < mtd->oobsize) { ++ mtk_nand_exec_read_page(mtd, (first_page+i), mtd->writesize, buf, oob); ++ memset(oob, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)buf, oob) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } else { ++ memset(chip->oob_poi, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)write_buf, chip->oob_poi) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, write_buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } ++ ++ kfree(buf); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset, ++ int data_len, const u8 * buf, int oob_required, int page, int raw) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_exec_write_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, (u8 *)buf, chip->oob_poi)) { ++ MSG(INIT, "write fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, UPDATE_WRITE_FAIL, (u8 *) buf, chip->oob_poi)) { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ { ++ int new_blk; ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (write_next_on_fail(mtd, (char *)buf, page_in_block + mapped_block * page_per_block, &new_blk) != 0) ++ { ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ return NAND_STATUS_FAIL; ++ } ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ break; ++ } ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static void ++mtk_nand_command_bp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) ++{ ++ struct nand_chip *nand = mtd->priv; ++ ++ switch (command) { ++ case NAND_CMD_SEQIN: ++ memset(g_kCMD.au1OOB, 0xFF, sizeof(g_kCMD.au1OOB)); ++ g_kCMD.pDataBuf = NULL; ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (g_kCMD.pDataBuf || (0xFF != g_kCMD.au1OOB[nand_badblock_offset])) { ++ u8 *pDataBuf = g_kCMD.pDataBuf ? g_kCMD.pDataBuf : nand->buffers->databuf; ++ mtk_nand_exec_write_page(mtd, g_kCMD.u4RowAddr, mtd->writesize, pDataBuf, g_kCMD.au1OOB); ++ g_kCMD.u4RowAddr = (u32) - 1; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ } ++ break; ++ ++ case NAND_CMD_READOOB: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column + mtd->writesize; ++ break; ++ ++ case NAND_CMD_READ0: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_ERASE1: ++ nand->state=FL_ERASING; ++ (void)mtk_nand_reset(); ++ mtk_nand_set_mode(CNFG_OP_ERASE); ++ (void)mtk_nand_set_command(NAND_CMD_ERASE1); ++ (void)mtk_nand_set_address(0, page_addr, 0, devinfo.addr_cycle - 2); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ (void)mtk_nand_set_command(NAND_CMD_ERASE2); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ break; ++ ++ case NAND_CMD_STATUS: ++ (void)mtk_nand_reset(); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ mtk_nand_set_mode(CNFG_READ_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ (void)mtk_nand_set_command(NAND_CMD_STATUS); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD | (1 << CON_NFI_NOB_SHIFT)); ++ g_bcmdstatus = true; ++ break; ++ ++ case NAND_CMD_RESET: ++ (void)mtk_nand_reset(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, INTR_RST_DONE_EN); ++ (void)mtk_nand_set_command(NAND_CMD_RESET); ++ DRV_WriteReg16(NFI_BASE+0x44, 0xF1); ++ while(!(DRV_Reg16(NFI_INTR_REG16)&INTR_RST_DONE_EN)) ++ ; ++ break; ++ ++ case NAND_CMD_READID: ++ mtk_nand_reset(); ++ /* Disable HW ECC */ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN | CNFG_BYTE_RW); ++ (void)mtk_nand_reset(); ++ mb(); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ (void)mtk_nand_set_command(NAND_CMD_READID); ++ (void)mtk_nand_set_address(0, 0, 1, 0); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_DATAR_STATE) ++ ; ++ break; ++ ++ default: ++ BUG(); ++ break; ++ } ++} ++ ++static void ++mtk_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ if ((chip == -1) && (false == g_bInitDone)) { ++ struct nand_chip *nand = mtd->priv; ++ struct mtk_nand_host *host = nand->priv; ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 spare_per_sector = mtd->oobsize / (mtd->writesize / 512); ++ u32 ecc_bit = 4; ++ u32 spare_bit = PAGEFMT_SPARE_16; ++ ++ if (spare_per_sector >= 28) { ++ spare_bit = PAGEFMT_SPARE_28; ++ ecc_bit = 12; ++ spare_per_sector = 28; ++ } else if (spare_per_sector >= 27) { ++ spare_bit = PAGEFMT_SPARE_27; ++ ecc_bit = 8; ++ spare_per_sector = 27; ++ } else if (spare_per_sector >= 26) { ++ spare_bit = PAGEFMT_SPARE_26; ++ ecc_bit = 8; ++ spare_per_sector = 26; ++ } else if (spare_per_sector >= 16) { ++ spare_bit = PAGEFMT_SPARE_16; ++ ecc_bit = 4; ++ spare_per_sector = 16; ++ } else { ++ MSG(INIT, "[NAND]: NFI not support oobsize: %x\n", spare_per_sector); ++ ASSERT(0); ++ } ++ mtd->oobsize = spare_per_sector*(mtd->writesize/512); ++ MSG(INIT, "[NAND]select ecc bit:%d, sparesize :%d spare_per_sector=%d\n",ecc_bit,mtd->oobsize,spare_per_sector); ++ /* Setup PageFormat */ ++ if (4096 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_4K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } else if (2048 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } ++ ECC_Config(hw,ecc_bit); ++ g_bInitDone = true; ++ } ++ switch (chip) { ++ case -1: ++ break; ++ case 0: ++ case 1: ++ /* Jun Shen, 2011.04.13 */ ++ /* Note: MT6577 EVB NAND is mounted on CS0, but FPGA is CS1 */ ++ DRV_WriteReg16(NFI_CSEL_REG16, chip); ++ /* Jun Shen, 2011.04.13 */ ++ break; ++ } ++} ++ ++static uint8_t ++mtk_nand_read_byte(struct mtd_info *mtd) ++{ ++ uint8_t retval = 0; ++ ++ if (!mtk_nand_pio_ready()) { ++ printk("pio ready timeout\n"); ++ retval = false; ++ } ++ ++ if (g_bcmdstatus) { ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mtk_nand_reset(); ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ g_bcmdstatus = false; ++ } else ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ ++ return retval; ++} ++ ++static void ++mtk_nand_read_buf(struct mtd_info *mtd, uint8_t * buf, int len) ++{ ++ struct nand_chip *nand = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr < u4PageSize) { ++ if ((u4ColAddr == 0) && (len >= u4PageSize)) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, pkCMD->au1OOB); ++ if (len > u4PageSize) { ++ u32 u4Size = min(len - u4PageSize, sizeof(pkCMD->au1OOB)); ++ memcpy(buf + u4PageSize, pkCMD->au1OOB, u4Size); ++ } ++ } else { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ memcpy(buf, nand->buffers->databuf + u4ColAddr, len); ++ } ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } else { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u32 u4Size = min(len - u4Offset, sizeof(pkCMD->au1OOB)); ++ if (pkCMD->u4OOBRowAddr != pkCMD->u4RowAddr) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } ++ memcpy(buf, pkCMD->au1OOB + u4Offset, u4Size); ++ } ++ pkCMD->u4ColAddr += len; ++} ++ ++static void ++mtk_nand_write_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ int i4Size, i; ++ ++ if (u4ColAddr >= u4PageSize) { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u8 *pOOB = pkCMD->au1OOB + u4Offset; ++ i4Size = min(len, (int)(sizeof(pkCMD->au1OOB) - u4Offset)); ++ for (i = 0; i < i4Size; i++) { ++ pOOB[i] &= buf[i]; ++ } ++ } else { ++ pkCMD->pDataBuf = (u8 *) buf; ++ } ++ ++ pkCMD->u4ColAddr += len; ++} ++ ++static int ++mtk_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, int oob_required, int page) ++{ ++ mtk_nand_write_buf(mtd, buf, mtd->writesize); ++ mtk_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ return 0; ++} ++ ++static int ++mtk_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, int oob_required, int page) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr == 0) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, chip->oob_poi); ++ pkCMD->u4ColAddr += u4PageSize + mtd->oobsize; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, u8 * buf, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, ++ mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++ ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++ else ++ return -EIO; ++#endif ++} ++ ++int ++mtk_nand_erase_hw(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ ++ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); ++ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); ++ ++ return chip->waitfunc(mtd, chip); ++} ++ ++static int ++mtk_nand_erase(struct mtd_info *mtd, int page) ++{ ++ // get mapping ++ struct nand_chip *chip = mtd->priv; ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int page_in_block = page % page_per_block; ++ int block = page / page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ ++ do { ++ int status = mtk_nand_erase_hw(mtd, page_in_block + page_per_block * mapped_block); ++ ++ if (status & NAND_STATUS_FAIL) { ++#if defined (MTK_NAND_BMT) ++ if (update_bmt( (page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_ERASE_FAIL, NULL, NULL)) ++ { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT success\n", mapped_block); ++ return 0; ++ } else { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT fail\n", mapped_block); ++ return NAND_STATUS_FAIL; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else ++ return NAND_STATUS_FAIL; ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob_raw(struct mtd_info *mtd, uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int res = 0; ++ u32 colnob = 2, rawnob = devinfo.addr_cycle - 2; ++ int randomread = 0; ++ int read_len = 0; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ if (len > spare_per_sector) ++ randomread = 1; ++ if (!randomread || !(devinfo.advancedmode & RAMDOM_READ)) { ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); // TODO: Fix this hard-code 16 ++ if (!mtk_nand_ready_for_read(chip, page_addr, col_addr, false, NULL)) { ++ printk(KERN_WARNING "mtk_nand_ready_for_read return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_check_RW_count(read_len); ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } else { ++ col_addr = NAND_SECTOR_SIZE; ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ if (!mtk_nand_reset()) ++ goto error; ++ mtk_nand_set_mode(0x6000); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ++ mtk_nand_set_autoformat(false); ++ ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto error; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, page_addr, colnob, rawnob)) ++ goto error; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ sector++; ++ len -= read_len; ++ mtk_nand_stop_read(); ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_set_command(0x05)) ++ goto error; ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, 2); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ if (!mtk_nand_status_ready(STA_ADDR_STATE)) ++ goto error; ++ if (!mtk_nand_set_command(0xE0)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } ++error: ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ return res; ++} ++ ++static int ++mtk_nand_write_oob_raw(struct mtd_info *mtd, const uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int write_len = 0; ++ int status; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ ++ while (len > 0) { ++ write_len = min(len, spare_per_sector); ++ col_addr = sector * (NAND_SECTOR_SIZE + spare_per_sector) + NAND_SECTOR_SIZE; ++ if (!mtk_nand_ready_for_write(chip, page_addr, col_addr, false, NULL)) ++ return -EIO; ++ if (!mtk_nand_mcu_write_data(mtd, buf + sector * spare_per_sector, write_len)) ++ return -EIO; ++ (void)mtk_nand_check_RW_count(write_len); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) { ++ printk(KERN_INFO "status: %d\n", status); ++ return -EIO; ++ } ++ len -= write_len; ++ sector++; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i, iter; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ ++ // copy ecc data ++ for (i = 0; i < layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ local_oob_buf[iter] = chip->oob_poi[layout->eccpos[i]]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) ++ memcpy(&local_oob_buf[i * spare_per_sector], &chip->oob_poi[i * OOB_AVAI_PER_SECTOR], OOB_AVAI_PER_SECTOR); ++ ++ return mtk_nand_write_oob_raw(mtd, local_oob_buf, page, mtd->oobsize); ++} ++ ++static int mtk_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) ++ { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_write_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block /* page */)) { ++ MSG(INIT, "write oob fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_WRITE_FAIL, NULL, chip->oob_poi)) ++ { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, mapped_block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else { ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ } else ++ break; ++ } while (1); ++ ++ return 0; ++} ++ ++int ++mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int page = block * (1 << (chip->phys_erase_shift - chip->page_shift)); ++ u8 buf[8]; ++ ++ memset(buf, 0xFF, 8); ++ buf[0] = 0; ++ return mtk_nand_write_oob_raw(mtd, buf, page, 8); ++} ++ ++static int ++mtk_nand_block_markbad(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int ret; ++ int mapped_block = block; ++ ++ nand_get_device(chip, mtd, FL_WRITING); ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) { ++ printk("NAND mark bad failed\n"); ++ nand_release_device(mtd); ++ return NAND_STATUS_FAIL; ++ } ++ } ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#endif ++ nand_release_device(mtd); ++ ++ return ret; ++} ++ ++int ++mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i; ++ u8 iter = 0; ++ ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (mtk_nand_read_oob_raw(mtd, chip->oob_poi, page, mtd->oobsize)) { ++ printk(KERN_ERR "[%s]mtk_nand_read_oob_raw return failed\n", __FUNCTION__); ++ return -EIO; ++ } ++ ++ // adjust to ecc physical layout to memory layout ++ /*********************************************************/ ++ /* FDM0 | ECC0 | FDM1 | ECC1 | FDM2 | ECC2 | FDM3 | ECC3 */ ++ /* 8B | 8B | 8B | 8B | 8B | 8B | 8B | 8B */ ++ /*********************************************************/ ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ // copy ecc data ++ for (i = 0; i < layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ chip->oob_poi[layout->eccpos[i]] = local_oob_buf[iter]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) { ++ memcpy(&chip->oob_poi[i * OOB_AVAI_PER_SECTOR], &local_oob_buf[i * spare_per_sector], OOB_AVAI_PER_SECTOR); ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ // allow to read oob even if the block is bad ++ } ++ if (mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block)!=0) ++ return -1; ++#endif ++ return 0; ++} ++ ++int ++mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int page_addr = (int)(ofs >> chip->page_shift); ++ unsigned int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ unsigned char oob_buf[8]; ++ ++ page_addr &= ~(page_per_block - 1); ++ if (mtk_nand_read_oob_raw(mtd, oob_buf, page_addr, sizeof(oob_buf))) { ++ printk(KERN_WARNING "mtk_nand_read_oob_raw return error\n"); ++ return 1; ++ } ++ ++ if (oob_buf[0] != 0xff) { ++ printk(KERN_WARNING "Bad block detected at 0x%x, oob_buf[0] is 0x%x\n", page_addr, oob_buf[0]); ++ // dump_nfi(); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_block_bad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int block = (int)ofs >> chip->phys_erase_shift; ++ int mapped_block = block; ++ int ret; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ } ++#endif ++ ++ ret = mtk_nand_block_bad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#if defined (MTK_NAND_BMT) ++ if (ret) { ++ MSG(INIT, "Unmapped bad block: 0x%x\n", mapped_block); ++ if (update_bmt(mapped_block << chip->phys_erase_shift, UPDATE_UNMAPPED_BLOCK, NULL, NULL)) { ++ MSG(INIT, "Update BMT success\n"); ++ ret = 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ ret = 1; ++ } ++ } ++#endif ++ ++ return ret; ++} ++ ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++char gacBuf[4096 + 288]; ++ ++static int ++mtk_nand_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4PageSize = mtd->writesize; ++ u32 *pSrc, *pDst; ++ int i; ++ ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, gacBuf, gacBuf + u4PageSize); ++ ++ pSrc = (u32 *) buf; ++ pDst = (u32 *) gacBuf; ++ len = len / sizeof(u32); ++ for (i = 0; i < len; ++i) { ++ if (*pSrc != *pDst) { ++ MSG(VERIFY, "mtk_nand_verify_buf page fail at page %d\n", pkCMD->u4RowAddr); ++ return -1; ++ } ++ pSrc++; ++ pDst++; ++ } ++ ++ pSrc = (u32 *) chip->oob_poi; ++ pDst = (u32 *) (gacBuf + u4PageSize); ++ ++ if ((pSrc[0] != pDst[0]) || (pSrc[1] != pDst[1]) || (pSrc[2] != pDst[2]) || (pSrc[3] != pDst[3]) || (pSrc[4] != pDst[4]) || (pSrc[5] != pDst[5])) { ++ // TODO: Ask Designer Why? ++ //(pSrc[6] != pDst[6]) || (pSrc[7] != pDst[7])) ++ MSG(VERIFY, "mtk_nand_verify_buf oob fail at page %d\n", pkCMD->u4RowAddr); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5], pSrc[6], pSrc[7]); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pDst[0], pDst[1], pDst[2], pDst[3], pDst[4], pDst[5], pDst[6], pDst[7]); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++static void ++mtk_nand_init_hw(struct mtk_nand_host *host) { ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ MSG(INIT, "Enable NFI Clock\n"); ++ nand_enable_clock(); ++ ++ g_bInitDone = false; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ ++ /* Set default NFI access timing control */ ++ DRV_WriteReg32(NFI_ACCCON_REG32, hw->nfi_access_timing); ++ DRV_WriteReg16(NFI_CNFG_REG16, 0); ++ DRV_WriteReg16(NFI_PAGEFMT_REG16, 0); ++ ++ /* Reset the state machine and data FIFO, because flushing FIFO */ ++ (void)mtk_nand_reset(); ++ ++ /* Set the ECC engine */ ++ if (hw->nand_ecc_mode == NAND_ECC_HW) { ++ MSG(INIT, "%s : Use HW ECC\n", MODULE_NAME); ++ if (g_bHwEcc) ++ NFI_SET_REG32(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ECC_Config(host->hw,4); ++ mtk_nand_configure_fdm(8); ++ mtk_nand_configure_lock(); ++ } ++ ++ NFI_SET_REG16(NFI_IOCON_REG16, 0x47); ++} ++ ++static int mtk_nand_dev_ready(struct mtd_info *mtd) ++{ ++ return !(DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY); ++} ++ ++#define FACT_BBT_BLOCK_NUM 32 // use the latest 32 BLOCK for factory bbt table ++#define FACT_BBT_OOB_SIGNATURE 1 ++#define FACT_BBT_SIGNATURE_LEN 7 ++const u8 oob_signature[] = "mtknand"; ++static u8 *fact_bbt = 0; ++static u32 bbt_size = 0; ++ ++static int ++read_fact_bbt(struct mtd_info *mtd, unsigned int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ ++ // read oob ++ if (mtk_nand_read_oob_hw(mtd, chip, page)==0) ++ { ++ if (chip->oob_poi[nand_badblock_offset] != 0xFF) ++ { ++ printk("Bad Block on Page %x\n", page); ++ return -1; ++ } ++ if (memcmp(&chip->oob_poi[FACT_BBT_OOB_SIGNATURE], oob_signature, FACT_BBT_SIGNATURE_LEN) != 0) ++ { ++ printk("compare signature failed %x\n", page); ++ return -1; ++ } ++ if (mtk_nand_exec_read_page(mtd, page, mtd->writesize, chip->buffers->databuf, chip->oob_poi)) ++ { ++ printk("Signature matched and data read!\n"); ++ memcpy(fact_bbt, chip->buffers->databuf, (bbt_size <= mtd->writesize)? bbt_size:mtd->writesize); ++ return 0; ++ } ++ ++ } ++ printk("failed at page %x\n", page); ++ return -1; ++} ++ ++static int ++load_fact_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ u32 total_block; ++ ++ total_block = 1 << (chip->chip_shift - chip->phys_erase_shift); ++ bbt_size = total_block >> 2; ++ ++ if ((!fact_bbt) && (bbt_size)) ++ fact_bbt = (u8 *)kmalloc(bbt_size, GFP_KERNEL); ++ if (!fact_bbt) ++ return -1; ++ ++ for (i = total_block - 1; i >= (total_block - FACT_BBT_BLOCK_NUM); i--) ++ { ++ if (read_fact_bbt(mtd, i << (chip->phys_erase_shift - chip->page_shift)) == 0) ++ { ++ printk("load_fact_bbt success %d\n", i); ++ return 0; ++ } ++ ++ } ++ printk("load_fact_bbt failed\n"); ++ return -1; ++} ++ ++static int oob_mtk_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ oobregion->length = 8; ++ oobregion->offset = layout->eccpos[section * 8]; ++ ++ return 0; ++} ++ ++static int oob_mtk_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oobregion) ++{ ++ if (section >= (layout->eccbytes / 8)) { ++ return -ERANGE; ++ } ++ oobregion->offset = layout->oobfree[section].offset; ++ oobregion->length = layout->oobfree[section].length; ++ ++ return 0; ++} ++ ++ ++static const struct mtd_ooblayout_ops oob_mtk_ops = { ++ .ecc = oob_mtk_ooblayout_ecc, ++ .free = oob_mtk_ooblayout_free, ++}; ++ ++static int ++mtk_nand_probe(struct platform_device *pdev) ++{ ++ struct mtd_part_parser_data ppdata; ++ struct mtk_nand_host_hw *hw; ++ struct nand_chip *nand_chip; ++ struct mtd_info *mtd; ++ u8 ext_id1, ext_id2, ext_id3; ++ int err = 0; ++ int id; ++ u32 ext_id; ++ int i; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ hw = &mt7621_nand_hw; ++ BUG_ON(!hw); ++ /* Allocate memory for the device structure (and zero it) */ ++ host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL); ++ if (!host) { ++ MSG(INIT, "mtk_nand: failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ ++ host->hw = hw; ++ ++ /* init mtd data structure */ ++ nand_chip = &host->nand_chip; ++ nand_chip->priv = host; /* link the private data structures */ ++ ++ mtd = host->mtd = &nand_chip->mtd; ++ mtd->priv = nand_chip; ++ mtd->owner = THIS_MODULE; ++ mtd->name = "MT7621-NAND"; ++ ++ hw->nand_ecc_mode = NAND_ECC_HW; ++ ++ /* Set address of NAND IO lines */ ++ nand_chip->IO_ADDR_R = (void __iomem *)NFI_DATAR_REG32; ++ nand_chip->IO_ADDR_W = (void __iomem *)NFI_DATAW_REG32; ++ nand_chip->chip_delay = 20; /* 20us command delay time */ ++ nand_chip->ecc.mode = hw->nand_ecc_mode; /* enable ECC */ ++ nand_chip->ecc.strength = 1; ++ nand_chip->read_byte = mtk_nand_read_byte; ++ nand_chip->read_buf = mtk_nand_read_buf; ++ nand_chip->write_buf = mtk_nand_write_buf; ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++ nand_chip->verify_buf = mtk_nand_verify_buf; ++#endif ++ nand_chip->select_chip = mtk_nand_select_chip; ++ nand_chip->dev_ready = mtk_nand_dev_ready; ++ nand_chip->cmdfunc = mtk_nand_command_bp; ++ nand_chip->ecc.read_page = mtk_nand_read_page_hwecc; ++ nand_chip->ecc.write_page = mtk_nand_write_page_hwecc; ++ ++ mtd_set_ooblayout(mtd, &oob_mtk_ops); ++ nand_chip->ecc.size = hw->nand_ecc_size; //2048 ++ nand_chip->ecc.bytes = hw->nand_ecc_bytes; //32 ++ ++ // For BMT, we need to revise driver architecture ++ nand_chip->write_page = mtk_nand_write_page; ++ nand_chip->ecc.write_oob = mtk_nand_write_oob; ++ nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device(). ++ nand_chip->read_page = mtk_nand_read_page; ++ nand_chip->ecc.read_oob = mtk_nand_read_oob; ++ nand_chip->block_bad = mtk_nand_block_bad; ++ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; ++ ++ //Qwert:Add for Uboot ++ mtk_nand_init_hw(host); ++ /* Select the device */ ++ nand_chip->select_chip(mtd, NFI_DEFAULT_CS); ++ ++ /* ++ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) ++ * after power-up ++ */ ++ nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ++ ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ ++ /* Send the command for reading device ID */ ++ ++ nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ /* Read manufacturer and device IDs */ ++ manu_id = nand_chip->read_byte(mtd); ++ dev_id = nand_chip->read_byte(mtd); ++ id = dev_id | (manu_id << 8); ++ ext_id1 = nand_chip->read_byte(mtd); ++ ext_id2 = nand_chip->read_byte(mtd); ++ ext_id3 = nand_chip->read_byte(mtd); ++ ext_id = ext_id1 << 16 | ext_id2 << 8 | ext_id3; ++ if (!get_device_info(id, ext_id, &devinfo)) { ++ u32 chip_mode = RALINK_REG(RALINK_SYSCTL_BASE+0x010)&0x0F; ++ MSG(INIT, "Not Support this Device! \r\n"); ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ MSG(INIT, "chip_mode=%08X\n",chip_mode); ++ ++ /* apply bootstrap first */ ++ devinfo.addr_cycle = 5; ++ devinfo.iowidth = 8; ++ ++ switch (chip_mode) { ++ case 10: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ case 11: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 1024; ++ devinfo.blocksize = 256; ++ break; ++ case 12: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 224; ++ devinfo.totalsize = 2048; ++ devinfo.blocksize = 512; ++ break; ++ default: ++ case 1: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 64; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ } ++ ++ devinfo.timmingsetting = NFI_DEFAULT_ACCESS_TIMING; ++ devinfo.devciename[0] = 'U'; ++ devinfo.advancedmode = 0; ++ } ++ mtd->writesize = devinfo.pagesize; ++ mtd->erasesize = (devinfo.blocksize<<10); ++ mtd->oobsize = devinfo.sparesize; ++ ++ nand_chip->chipsize = (devinfo.totalsize<<20); ++ nand_chip->page_shift = ffs(mtd->writesize) - 1; ++ nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1; ++ nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1; ++ nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1; ++ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; ++ ++ if (devinfo.pagesize == 4096) ++ layout = &nand_oob_128; ++ else if (devinfo.pagesize == 2048) ++ layout = &nand_oob_64; ++ else if (devinfo.pagesize == 512) ++ layout = &nand_oob_16; ++ ++ layout->eccbytes = devinfo.sparesize-OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE); ++ for (i = 0; i < layout->eccbytes; i++) ++ layout->eccpos[i]=OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE)+i; ++ ++ MSG(INIT, "Support this Device in MTK table! %x \r\n", id); ++ hw->nfi_bus_width = devinfo.iowidth; ++ DRV_WriteReg32(NFI_ACCCON_REG32, devinfo.timmingsetting); ++ ++ /* 16-bit bus width */ ++ if (hw->nfi_bus_width == 16) { ++ MSG(INIT, "%s : Set the 16-bit I/O settings!\n", MODULE_NAME); ++ nand_chip->options |= NAND_BUSWIDTH_16; ++ } ++ mtd->oobsize = devinfo.sparesize; ++ hw->nfi_cs_num = 1; ++ ++ nand_chip->options |= NAND_USE_BOUNCE_BUFFER; ++ nand_chip->buf_align = 16; ++ ++ /* Scan to find existance of the device */ ++ if (nand_scan(mtd, hw->nfi_cs_num)) { ++ MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME); ++ err = -ENXIO; ++ goto out; ++ } ++ ++ nand_chip->erase = mtk_nand_erase; ++ ++ g_page_size = mtd->writesize; ++ platform_set_drvdata(pdev, host); ++ if (hw->nfi_bus_width == 16) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, PAGEFMT_DBYTE_EN); ++ } ++ ++ nand_chip->select_chip(mtd, 0); ++#if defined(MTK_NAND_BMT) ++ nand_chip->chipsize -= (BMT_POOL_SIZE) << nand_chip->phys_erase_shift; ++#endif ++ mtd->size = nand_chip->chipsize; ++ ++ CFG_BLOCKSIZE = mtd->erasesize; ++ ++#if defined(MTK_NAND_BMT) ++ if (!g_bmt) { ++ if (!(g_bmt = init_bmt(nand_chip, BMT_POOL_SIZE))) { ++ MSG(INIT, "Error: init bmt failed\n"); ++ return 0; ++ } ++ } ++#endif ++ ++ nand_set_flash_node(nand_chip, pdev->dev.of_node); ++ err = mtd_device_parse_register(mtd, probe_types, &ppdata, ++ NULL, 0); ++ if (!err) { ++ MSG(INIT, "[mtk_nand] probe successfully!\n"); ++ nand_disable_clock(); ++ shift_on_bbt = 0; ++ if (load_fact_bbt(mtd) == 0) { ++ int i; ++ for (i = 0; i < 0x100; i++) ++ nand_chip->bbt[i] |= fact_bbt[i]; ++ } ++ ++ return err; ++ } ++ ++out: ++ MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err); ++ nand_release(mtd); ++ platform_set_drvdata(pdev, NULL); ++ kfree(host); ++ nand_disable_clock(); ++ return err; ++} ++ ++static int ++mtk_nand_remove(struct platform_device *pdev) ++{ ++ struct mtk_nand_host *host = platform_get_drvdata(pdev); ++ struct mtd_info *mtd = host->mtd; ++ struct nand_chip *nand_chip = &host->nand_chip; ++ ++ nand_release(mtd); ++ kfree(host); ++ nand_disable_clock(); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_nand_match[] = { ++ { .compatible = "mtk,mt7621-nand" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_nand_match); ++ ++static struct platform_driver mtk_nand_driver = { ++ .probe = mtk_nand_probe, ++ .remove = mtk_nand_remove, ++ .driver = { ++ .name = "MT7621-NAND", ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_nand_match, ++ }, ++}; ++ ++static int __init ++mtk_nand_init(void) ++{ ++ printk("MediaTek Nand driver init, version %s\n", VERSION); ++ ++ return platform_driver_register(&mtk_nand_driver); ++} ++ ++static void __exit ++mtk_nand_exit(void) ++{ ++ platform_driver_unregister(&mtk_nand_driver); ++} ++ ++module_init(mtk_nand_init); ++module_exit(mtk_nand_exit); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand2.h +@@ -0,0 +1,452 @@ ++#ifndef __MTK_NAND_H ++#define __MTK_NAND_H ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define RALINK_SYSCTL_BASE 0xBE000000 ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++/******************************************************************************* ++ * NFI Register Definition ++ *******************************************************************************/ ++ ++#define NFI_CNFG_REG16 ((volatile P_U16)(NFI_BASE+0x0000)) ++#define NFI_PAGEFMT_REG16 ((volatile P_U16)(NFI_BASE+0x0004)) ++#define NFI_CON_REG16 ((volatile P_U16)(NFI_BASE+0x0008)) ++#define NFI_ACCCON_REG32 ((volatile P_U32)(NFI_BASE+0x000C)) ++#define NFI_INTR_EN_REG16 ((volatile P_U16)(NFI_BASE+0x0010)) ++#define NFI_INTR_REG16 ((volatile P_U16)(NFI_BASE+0x0014)) ++ ++#define NFI_CMD_REG16 ((volatile P_U16)(NFI_BASE+0x0020)) ++ ++#define NFI_ADDRNOB_REG16 ((volatile P_U16)(NFI_BASE+0x0030)) ++#define NFI_COLADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0034)) ++#define NFI_ROWADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0038)) ++ ++#define NFI_STRDATA_REG16 ((volatile P_U16)(NFI_BASE+0x0040)) ++ ++#define NFI_DATAW_REG32 ((volatile P_U32)(NFI_BASE+0x0050)) ++#define NFI_DATAR_REG32 ((volatile P_U32)(NFI_BASE+0x0054)) ++#define NFI_PIO_DIRDY_REG16 ((volatile P_U16)(NFI_BASE+0x0058)) ++ ++#define NFI_STA_REG32 ((volatile P_U32)(NFI_BASE+0x0060)) ++#define NFI_FIFOSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0064)) ++#define NFI_LOCKSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0068)) ++ ++#define NFI_ADDRCNTR_REG16 ((volatile P_U16)(NFI_BASE+0x0070)) ++ ++#define NFI_STRADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0080)) ++#define NFI_BYTELEN_REG16 ((volatile P_U16)(NFI_BASE+0x0084)) ++ ++#define NFI_CSEL_REG16 ((volatile P_U16)(NFI_BASE+0x0090)) ++#define NFI_IOCON_REG16 ((volatile P_U16)(NFI_BASE+0x0094)) ++ ++#define NFI_FDM0L_REG32 ((volatile P_U32)(NFI_BASE+0x00A0)) ++#define NFI_FDM0M_REG32 ((volatile P_U32)(NFI_BASE+0x00A4)) ++ ++#define NFI_LOCK_REG16 ((volatile P_U16)(NFI_BASE+0x0100)) ++#define NFI_LOCKCON_REG32 ((volatile P_U32)(NFI_BASE+0x0104)) ++#define NFI_LOCKANOB_REG16 ((volatile P_U16)(NFI_BASE+0x0108)) ++#define NFI_LOCK00ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0110)) ++#define NFI_LOCK00FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0114)) ++#define NFI_LOCK01ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0118)) ++#define NFI_LOCK01FMT_REG32 ((volatile P_U32)(NFI_BASE+0x011C)) ++#define NFI_LOCK02ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0120)) ++#define NFI_LOCK02FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0124)) ++#define NFI_LOCK03ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0128)) ++#define NFI_LOCK03FMT_REG32 ((volatile P_U32)(NFI_BASE+0x012C)) ++#define NFI_LOCK04ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0130)) ++#define NFI_LOCK04FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0134)) ++#define NFI_LOCK05ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0138)) ++#define NFI_LOCK05FMT_REG32 ((volatile P_U32)(NFI_BASE+0x013C)) ++#define NFI_LOCK06ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0140)) ++#define NFI_LOCK06FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0144)) ++#define NFI_LOCK07ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0148)) ++#define NFI_LOCK07FMT_REG32 ((volatile P_U32)(NFI_BASE+0x014C)) ++#define NFI_LOCK08ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0150)) ++#define NFI_LOCK08FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0154)) ++#define NFI_LOCK09ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0158)) ++#define NFI_LOCK09FMT_REG32 ((volatile P_U32)(NFI_BASE+0x015C)) ++#define NFI_LOCK10ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0160)) ++#define NFI_LOCK10FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0164)) ++#define NFI_LOCK11ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0168)) ++#define NFI_LOCK11FMT_REG32 ((volatile P_U32)(NFI_BASE+0x016C)) ++#define NFI_LOCK12ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0170)) ++#define NFI_LOCK12FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0174)) ++#define NFI_LOCK13ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0178)) ++#define NFI_LOCK13FMT_REG32 ((volatile P_U32)(NFI_BASE+0x017C)) ++#define NFI_LOCK14ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0180)) ++#define NFI_LOCK14FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0184)) ++#define NFI_LOCK15ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0188)) ++#define NFI_LOCK15FMT_REG32 ((volatile P_U32)(NFI_BASE+0x018C)) ++ ++#define NFI_FIFODATA0_REG32 ((volatile P_U32)(NFI_BASE+0x0190)) ++#define NFI_FIFODATA1_REG32 ((volatile P_U32)(NFI_BASE+0x0194)) ++#define NFI_FIFODATA2_REG32 ((volatile P_U32)(NFI_BASE+0x0198)) ++#define NFI_FIFODATA3_REG32 ((volatile P_U32)(NFI_BASE+0x019C)) ++#define NFI_MASTERSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0210)) ++ ++ ++/******************************************************************************* ++ * NFI Register Field Definition ++ *******************************************************************************/ ++ ++/* NFI_CNFG */ ++#define CNFG_AHB (0x0001) ++#define CNFG_READ_EN (0x0002) ++#define CNFG_DMA_BURST_EN (0x0004) ++#define CNFG_BYTE_RW (0x0040) ++#define CNFG_HW_ECC_EN (0x0100) ++#define CNFG_AUTO_FMT_EN (0x0200) ++#define CNFG_OP_IDLE (0x0000) ++#define CNFG_OP_READ (0x1000) ++#define CNFG_OP_SRD (0x2000) ++#define CNFG_OP_PRGM (0x3000) ++#define CNFG_OP_ERASE (0x4000) ++#define CNFG_OP_RESET (0x5000) ++#define CNFG_OP_CUST (0x6000) ++#define CNFG_OP_MODE_MASK (0x7000) ++#define CNFG_OP_MODE_SHIFT (12) ++ ++/* NFI_PAGEFMT */ ++#define PAGEFMT_512 (0x0000) ++#define PAGEFMT_2K (0x0001) ++#define PAGEFMT_4K (0x0002) ++ ++#define PAGEFMT_PAGE_MASK (0x0003) ++ ++#define PAGEFMT_DBYTE_EN (0x0008) ++ ++#define PAGEFMT_SPARE_16 (0x0000) ++#define PAGEFMT_SPARE_26 (0x0001) ++#define PAGEFMT_SPARE_27 (0x0002) ++#define PAGEFMT_SPARE_28 (0x0003) ++#define PAGEFMT_SPARE_MASK (0x0030) ++#define PAGEFMT_SPARE_SHIFT (4) ++ ++#define PAGEFMT_FDM_MASK (0x0F00) ++#define PAGEFMT_FDM_SHIFT (8) ++ ++#define PAGEFMT_FDM_ECC_MASK (0xF000) ++#define PAGEFMT_FDM_ECC_SHIFT (12) ++ ++/* NFI_CON */ ++#define CON_FIFO_FLUSH (0x0001) ++#define CON_NFI_RST (0x0002) ++#define CON_NFI_SRD (0x0010) ++ ++#define CON_NFI_NOB_MASK (0x0060) ++#define CON_NFI_NOB_SHIFT (5) ++ ++#define CON_NFI_BRD (0x0100) ++#define CON_NFI_BWR (0x0200) ++ ++#define CON_NFI_SEC_MASK (0xF000) ++#define CON_NFI_SEC_SHIFT (12) ++ ++/* NFI_ACCCON */ ++#define ACCCON_SETTING () ++ ++/* NFI_INTR_EN */ ++#define INTR_RD_DONE_EN (0x0001) ++#define INTR_WR_DONE_EN (0x0002) ++#define INTR_RST_DONE_EN (0x0004) ++#define INTR_ERASE_DONE_EN (0x0008) ++#define INTR_BSY_RTN_EN (0x0010) ++#define INTR_ACC_LOCK_EN (0x0020) ++#define INTR_AHB_DONE_EN (0x0040) ++#define INTR_ALL_INTR_DE (0x0000) ++#define INTR_ALL_INTR_EN (0x007F) ++ ++/* NFI_INTR */ ++#define INTR_RD_DONE (0x0001) ++#define INTR_WR_DONE (0x0002) ++#define INTR_RST_DONE (0x0004) ++#define INTR_ERASE_DONE (0x0008) ++#define INTR_BSY_RTN (0x0010) ++#define INTR_ACC_LOCK (0x0020) ++#define INTR_AHB_DONE (0x0040) ++ ++/* NFI_ADDRNOB */ ++#define ADDR_COL_NOB_MASK (0x0003) ++#define ADDR_COL_NOB_SHIFT (0) ++#define ADDR_ROW_NOB_MASK (0x0030) ++#define ADDR_ROW_NOB_SHIFT (4) ++ ++/* NFI_STA */ ++#define STA_READ_EMPTY (0x00001000) ++#define STA_ACC_LOCK (0x00000010) ++#define STA_CMD_STATE (0x00000001) ++#define STA_ADDR_STATE (0x00000002) ++#define STA_DATAR_STATE (0x00000004) ++#define STA_DATAW_STATE (0x00000008) ++ ++#define STA_NAND_FSM_MASK (0x1F000000) ++#define STA_NAND_BUSY (0x00000100) ++#define STA_NAND_BUSY_RETURN (0x00000200) ++#define STA_NFI_FSM_MASK (0x000F0000) ++#define STA_NFI_OP_MASK (0x0000000F) ++ ++/* NFI_FIFOSTA */ ++#define FIFO_RD_EMPTY (0x0040) ++#define FIFO_RD_FULL (0x0080) ++#define FIFO_WR_FULL (0x8000) ++#define FIFO_WR_EMPTY (0x4000) ++#define FIFO_RD_REMAIN(x) (0x1F&(x)) ++#define FIFO_WR_REMAIN(x) ((0x1F00&(x))>>8) ++ ++/* NFI_ADDRCNTR */ ++#define ADDRCNTR_CNTR(x) ((0xF000&(x))>>12) ++#define ADDRCNTR_OFFSET(x) (0x03FF&(x)) ++ ++/* NFI_LOCK */ ++#define NFI_LOCK_ON (0x0001) ++ ++/* NFI_LOCKANOB */ ++#define PROG_RADD_NOB_MASK (0x7000) ++#define PROG_RADD_NOB_SHIFT (12) ++#define PROG_CADD_NOB_MASK (0x0300) ++#define PROG_CADD_NOB_SHIFT (8) ++#define ERASE_RADD_NOB_MASK (0x0070) ++#define ERASE_RADD_NOB_SHIFT (4) ++#define ERASE_CADD_NOB_MASK (0x0007) ++#define ERASE_CADD_NOB_SHIFT (0) ++ ++/******************************************************************************* ++ * ECC Register Definition ++ *******************************************************************************/ ++ ++#define ECC_ENCCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0000)) ++#define ECC_ENCCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0004)) ++#define ECC_ENCDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0008)) ++#define ECC_ENCIDLE_REG32 ((volatile P_U32)(NFIECC_BASE+0x000C)) ++#define ECC_ENCPAR0_REG32 ((volatile P_U32)(NFIECC_BASE+0x0010)) ++#define ECC_ENCPAR1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0014)) ++#define ECC_ENCPAR2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0018)) ++#define ECC_ENCPAR3_REG32 ((volatile P_U32)(NFIECC_BASE+0x001C)) ++#define ECC_ENCPAR4_REG32 ((volatile P_U32)(NFIECC_BASE+0x0020)) ++#define ECC_ENCSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0024)) ++#define ECC_ENCIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0028)) ++#define ECC_ENCIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x002C)) ++ ++#define ECC_DECCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0100)) ++#define ECC_DECCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0104)) ++#define ECC_DECDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0108)) ++#define ECC_DECIDLE_REG16 ((volatile P_U16)(NFIECC_BASE+0x010C)) ++#define ECC_DECFER_REG16 ((volatile P_U16)(NFIECC_BASE+0x0110)) ++#define ECC_DECENUM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0114)) ++#define ECC_DECDONE_REG16 ((volatile P_U16)(NFIECC_BASE+0x0118)) ++#define ECC_DECEL0_REG32 ((volatile P_U32)(NFIECC_BASE+0x011C)) ++#define ECC_DECEL1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0120)) ++#define ECC_DECEL2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0124)) ++#define ECC_DECEL3_REG32 ((volatile P_U32)(NFIECC_BASE+0x0128)) ++#define ECC_DECEL4_REG32 ((volatile P_U32)(NFIECC_BASE+0x012C)) ++#define ECC_DECEL5_REG32 ((volatile P_U32)(NFIECC_BASE+0x0130)) ++#define ECC_DECIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0134)) ++#define ECC_DECIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x0138)) ++#define ECC_FDMADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x013C)) ++#define ECC_DECFSM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0140)) ++#define ECC_SYNSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0144)) ++#define ECC_DECNFIDI_REG32 ((volatile P_U32)(NFIECC_BASE+0x0148)) ++#define ECC_SYN0_REG32 ((volatile P_U32)(NFIECC_BASE+0x014C)) ++ ++/******************************************************************************* ++ * ECC register definition ++ *******************************************************************************/ ++/* ECC_ENCON */ ++#define ENC_EN (0x0001) ++#define ENC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define ECC_CNFG_ECC4 (0x0000) ++#define ECC_CNFG_ECC6 (0x0001) ++#define ECC_CNFG_ECC8 (0x0002) ++#define ECC_CNFG_ECC10 (0x0003) ++#define ECC_CNFG_ECC12 (0x0004) ++#define ECC_CNFG_ECC_MASK (0x00000007) ++ ++#define ENC_CNFG_NFI (0x0010) ++#define ENC_CNFG_MODE_MASK (0x0010) ++ ++#define ENC_CNFG_META6 (0x10300000) ++#define ENC_CNFG_META8 (0x10400000) ++ ++#define ENC_CNFG_MSG_MASK (0x1FFF0000) ++#define ENC_CNFG_MSG_SHIFT (0x10) ++ ++/* ECC_ENCIDLE */ ++#define ENC_IDLE (0x0001) ++ ++/* ECC_ENCSTA */ ++#define STA_FSM (0x001F) ++#define STA_COUNT_PS (0xFF10) ++#define STA_COUNT_MS (0x3FFF0000) ++ ++/* ECC_ENCIRQEN */ ++#define ENC_IRQEN (0x0001) ++ ++/* ECC_ENCIRQSTA */ ++#define ENC_IRQSTA (0x0001) ++ ++/* ECC_DECCON */ ++#define DEC_EN (0x0001) ++#define DEC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define DEC_CNFG_ECC4 (0x0000) ++//#define DEC_CNFG_ECC6 (0x0001) ++//#define DEC_CNFG_ECC12 (0x0002) ++#define DEC_CNFG_NFI (0x0010) ++//#define DEC_CNFG_META6 (0x10300000) ++//#define DEC_CNFG_META8 (0x10400000) ++ ++#define DEC_CNFG_FER (0x01000) ++#define DEC_CNFG_EL (0x02000) ++#define DEC_CNFG_CORRECT (0x03000) ++#define DEC_CNFG_TYPE_MASK (0x03000) ++ ++#define DEC_CNFG_EMPTY_EN (0x80000000) ++ ++#define DEC_CNFG_CODE_MASK (0x1FFF0000) ++#define DEC_CNFG_CODE_SHIFT (0x10) ++ ++/* ECC_DECIDLE */ ++#define DEC_IDLE (0x0001) ++ ++/* ECC_DECFER */ ++#define DEC_FER0 (0x0001) ++#define DEC_FER1 (0x0002) ++#define DEC_FER2 (0x0004) ++#define DEC_FER3 (0x0008) ++#define DEC_FER4 (0x0010) ++#define DEC_FER5 (0x0020) ++#define DEC_FER6 (0x0040) ++#define DEC_FER7 (0x0080) ++ ++/* ECC_DECENUM */ ++#define ERR_NUM0 (0x0000000F) ++#define ERR_NUM1 (0x000000F0) ++#define ERR_NUM2 (0x00000F00) ++#define ERR_NUM3 (0x0000F000) ++#define ERR_NUM4 (0x000F0000) ++#define ERR_NUM5 (0x00F00000) ++#define ERR_NUM6 (0x0F000000) ++#define ERR_NUM7 (0xF0000000) ++ ++/* ECC_DECDONE */ ++#define DEC_DONE0 (0x0001) ++#define DEC_DONE1 (0x0002) ++#define DEC_DONE2 (0x0004) ++#define DEC_DONE3 (0x0008) ++#define DEC_DONE4 (0x0010) ++#define DEC_DONE5 (0x0020) ++#define DEC_DONE6 (0x0040) ++#define DEC_DONE7 (0x0080) ++ ++/* ECC_DECIRQEN */ ++#define DEC_IRQEN (0x0001) ++ ++/* ECC_DECIRQSTA */ ++#define DEC_IRQSTA (0x0001) ++ ++#define CHIPVER_ECO_1 (0x8a00) ++#define CHIPVER_ECO_2 (0x8a01) ++ ++//#define NAND_PFM ++ ++/******************************************************************************* ++ * Data Structure Definition ++ *******************************************************************************/ ++struct mtk_nand_host ++{ ++ struct nand_chip nand_chip; ++ struct mtd_info *mtd; ++ struct mtk_nand_host_hw *hw; ++}; ++ ++struct NAND_CMD ++{ ++ u32 u4ColAddr; ++ u32 u4RowAddr; ++ u32 u4OOBRowAddr; ++ u8 au1OOB[288]; ++ u8* pDataBuf; ++#ifdef NAND_PFM ++ u32 pureReadOOB; ++ u32 pureReadOOBNum; ++#endif ++}; ++ ++/* ++ * ECC layout control structure. Exported to userspace for ++ * diagnosis and to allow creation of raw images ++struct nand_ecclayout { ++ uint32_t eccbytes; ++ uint32_t eccpos[64]; ++ uint32_t oobavail; ++ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; ++}; ++*/ ++#define __DEBUG_NAND 1 /* Debug information on/off */ ++ ++/* Debug message event */ ++#define DBG_EVT_NONE 0x00000000 /* No event */ ++#define DBG_EVT_INIT 0x00000001 /* Initial related event */ ++#define DBG_EVT_VERIFY 0x00000002 /* Verify buffer related event */ ++#define DBG_EVT_PERFORMANCE 0x00000004 /* Performance related event */ ++#define DBG_EVT_READ 0x00000008 /* Read related event */ ++#define DBG_EVT_WRITE 0x00000010 /* Write related event */ ++#define DBG_EVT_ERASE 0x00000020 /* Erase related event */ ++#define DBG_EVT_BADBLOCK 0x00000040 /* Badblock related event */ ++#define DBG_EVT_POWERCTL 0x00000080 /* Suspend/Resume related event */ ++ ++#define DBG_EVT_ALL 0xffffffff ++ ++#define DBG_EVT_MASK (DBG_EVT_INIT) ++ ++#if __DEBUG_NAND ++#define MSG(evt, fmt, args...) \ ++do { \ ++ if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \ ++ printk(fmt, ##args); \ ++ } \ ++} while(0) ++ ++#define MSG_FUNC_ENTRY(f) MSG(FUC, ": %s\n", __FUNCTION__) ++#else ++#define MSG(evt, fmt, args...) do{}while(0) ++#define MSG_FUNC_ENTRY(f) do{}while(0) ++#endif ++ ++#define RAMDOM_READ 1<<0 ++#define CACHE_READ 1<<1 ++ ++typedef struct ++{ ++ u16 id; //deviceid+menuid ++ u32 ext_id; ++ u8 addr_cycle; ++ u8 iowidth; ++ u16 totalsize; ++ u16 blocksize; ++ u16 pagesize; ++ u16 sparesize; ++ u32 timmingsetting; ++ char devciename[14]; ++ u32 advancedmode; // ++}flashdev_info,*pflashdev_info; ++ ++/* NAND driver */ ++#if 0 ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern u32 CFG_BLOCKSIZE; ++#endif ++#endif +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -48,7 +48,7 @@ + #include + #include + +-static int nand_get_device(struct mtd_info *mtd, int new_state); ++int nand_get_device(struct mtd_info *mtd, int new_state); + + static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); +@@ -240,7 +240,7 @@ static int check_offs_len(struct mtd_inf + * + * Release chip lock and wake up anyone waiting on the device. + */ +-static void nand_release_device(struct mtd_info *mtd) ++void nand_release_device(struct mtd_info *mtd) + { + struct nand_chip *chip = mtd_to_nand(mtd); + +@@ -968,7 +968,7 @@ static void panic_nand_get_device(struct + * + * Get the device and lock it for exclusive access + */ +-static int ++int + nand_get_device(struct mtd_info *mtd, int new_state) + { + struct nand_chip *chip = mtd_to_nand(mtd); +--- /dev/null ++++ b/drivers/mtd/nand/nand_def.h +@@ -0,0 +1,123 @@ ++#ifndef __NAND_DEF_H__ ++#define __NAND_DEF_H__ ++ ++#define VERSION "v2.1 Fix AHB virt2phys error" ++#define MODULE_NAME "# MTK NAND #" ++#define PROCNAME "driver/nand" ++ ++#undef TESTTIME ++//#define __UBOOT_NAND__ 1 ++#define __KERNEL_NAND__ 1 ++//#define __PRELOADER_NAND__ 1 ++//#define PMT 1 ++//#define _MTK_NAND_DUMMY_DRIVER ++//#define CONFIG_BADBLOCK_CHECK 1 ++//#ifdef CONFIG_BADBLOCK_CHECK ++//#define MTK_NAND_BMT 1 ++//#endif ++#define ECC_ENABLE 1 ++#define MANUAL_CORRECT 1 ++//#define __INTERNAL_USE_AHB_MODE__ (0) ++#define SKIP_BAD_BLOCK ++#define FACT_BBT ++ ++#ifndef NAND_OTP_SUPPORT ++#define NAND_OTP_SUPPORT 0 ++#endif ++ ++/******************************************************************************* ++ * Macro definition ++ *******************************************************************************/ ++//#define NFI_SET_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) | (value))) ++//#define NFI_SET_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) | (value))) ++//#define NFI_CLN_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) & (~(value)))) ++//#define NFI_CLN_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) & (~(value)))) ++ ++#if defined (__KERNEL_NAND__) ++#define NFI_SET_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) | (value));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_SET_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) | (value));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) & (~(value)));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) & (~(value)));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++#endif ++ ++#define NFI_WAIT_STATE_DONE(state) do{;}while (__raw_readl(NFI_STA_REG32) & state) ++#define NFI_WAIT_TO_READY() do{;}while (!(__raw_readl(NFI_STA_REG32) & STA_BUSY2READY)) ++ ++ ++#define NAND_SECTOR_SIZE (512) ++#define OOB_PER_SECTOR (16) ++#define OOB_AVAI_PER_SECTOR (8) ++ ++#ifndef PART_SIZE_BMTPOOL ++#define BMT_POOL_SIZE (80) ++#else ++#define BMT_POOL_SIZE (PART_SIZE_BMTPOOL) ++#endif ++ ++#define PMT_POOL_SIZE (2) ++ ++#define TIMEOUT_1 0x1fff ++#define TIMEOUT_2 0x8ff ++#define TIMEOUT_3 0xffff ++#define TIMEOUT_4 0xffff//5000 //PIO ++ ++ ++/* temporarity definiation */ ++#if !defined (__KERNEL_NAND__) ++#define KERN_INFO ++#define KERN_WARNING ++#define KERN_ERR ++#define PAGE_SIZE (4096) ++#endif ++#define AddStorageTrace //AddStorageTrace ++#define STORAGE_LOGGER_MSG_NAND 0 ++#define NFI_BASE RALINK_NAND_CTRL_BASE ++#define NFIECC_BASE RALINK_NANDECC_CTRL_BASE ++ ++#ifdef __INTERNAL_USE_AHB_MODE__ ++#define MT65xx_POLARITY_LOW 0 ++#define MT65XX_PDN_PERI_NFI 0 ++#define MT65xx_EDGE_SENSITIVE 0 ++#define MT6575_NFI_IRQ_ID (58) ++#endif ++ ++#if defined (__KERNEL_NAND__) ++#define RALINK_REG(x) (*((volatile u32 *)(x))) ++#define __virt_to_phys(x) virt_to_phys((volatile void*)x) ++#else ++#define CONFIG_MTD_NAND_VERIFY_WRITE (1) ++#define printk printf ++#define ra_dbg printf ++#define BUG() //BUG() ++#define BUG_ON(x) //BUG_ON() ++#define NUM_PARTITIONS 1 ++#endif ++ ++#define NFI_DEFAULT_ACCESS_TIMING (0x30C77fff) //(0x44333) ++ ++//uboot only support 1 cs ++#define NFI_CS_NUM (1) ++#define NFI_DEFAULT_CS (0) ++ ++#include "mt6575_typedefs.h" ++ ++#endif /* __NAND_DEF_H__ */ +--- /dev/null ++++ b/drivers/mtd/nand/nand_device_list.h +@@ -0,0 +1,60 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef __NAND_DEVICE_LIST_H__ ++#define __NAND_DEVICE_LIST_H__ ++ ++static const flashdev_info gen_FlashTable[]={ ++ {0x20BC, 0x105554, 5, 16, 512, 128, 2048, 64, 0x1123, "EHD013151MA_5", 0}, ++ {0xECBC, 0x005554, 5, 16, 512, 128, 2048, 64, 0x1123, "K524G2GACB_A0", 0}, ++ {0x2CBC, 0x905556, 5, 16, 512, 128, 2048, 64, 0x21044333, "MT29C4G96MAZA", 0}, ++ {0x2CDA, 0x909506, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "MT29F2G08ABAE", 0}, ++ {0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0}, ++ {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0}, ++ {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0}, ++ {0xC8D1, 0x809540, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81MA", 0}, ++ {0xC8DA, 0x909544, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "F59L2G81A", 0}, ++ {0xC8DC, 0x909554, 5, 8, 512, 128, 2048, 64, 0x30C77fff, "F59L4G81A", 0}, ++ {0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0}, ++ {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0}, ++ {0xC2F1, 0x809502, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G18AC", 0}, ++ {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0}, ++ {0x01DA, 0x909546, 5, 8, 256, 128, 2048, 128, 0x30C77fff, "S34ML02G200TF", 0}, ++ {0x01DC, 0x909556, 5, 8, 512, 128, 2048, 128, 0x30C77fff, "S34ML04G200TF", 0}, ++ {0x0000, 0x000000, 0, 0, 0, 0, 0, 0, 0, "xxxxxxxxxx", 0}, ++}; ++ ++ ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/partition.h +@@ -0,0 +1,115 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include ++#include ++#include ++ ++#define RECONFIG_PARTITION_SIZE 1 ++ ++#define MTD_BOOT_PART_SIZE 0x80000 ++#define MTD_CONFIG_PART_SIZE 0x20000 ++#define MTD_FACTORY_PART_SIZE 0x20000 ++ ++extern unsigned int CFG_BLOCKSIZE; ++#define LARGE_MTD_BOOT_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_CONFIG_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_FACTORY_PART_SIZE (CFG_BLOCKSIZE<<1) ++ ++/*=======================================================================*/ ++/* NAND PARTITION Mapping */ ++/*=======================================================================*/ ++//#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition g_pasStatic_Partition[] = { ++ { ++ name: "ALL", ++ size: MTDPART_SIZ_FULL, ++ offset: 0, ++ }, ++ /* Put your own partition definitions here */ ++ { ++ name: "Bootloader", ++ size: MTD_BOOT_PART_SIZE, ++ offset: 0, ++ }, { ++ name: "Config", ++ size: MTD_CONFIG_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "Factory", ++ size: MTD_FACTORY_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "Kernel", ++ size: MTD_KERN_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "RootFS", ++ size: MTD_ROOTFS_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++#ifdef CONFIG_ROOTFS_IN_FLASH_NO_PADDING ++ }, { ++ name: "Kernel_RootFS", ++ size: MTD_KERN_PART_SIZE + MTD_ROOTFS_PART_SIZE, ++ offset: MTD_BOOT_PART_SIZE + MTD_CONFIG_PART_SIZE + MTD_FACTORY_PART_SIZE, ++#endif ++#else //CONFIG_RT2880_ROOTFS_IN_RAM ++ }, { ++ name: "Kernel", ++ size: 0x10000, ++ offset: MTDPART_OFS_APPEND, ++#endif ++#ifdef CONFIG_DUAL_IMAGE ++ }, { ++ name: "Kernel2", ++ size: MTD_KERN2_PART_SIZE, ++ offset: MTD_KERN2_PART_OFFSET, ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "RootFS2", ++ size: MTD_ROOTFS2_PART_SIZE, ++ offset: MTD_ROOTFS2_PART_OFFSET, ++#endif ++#endif ++ } ++ ++}; ++ ++#define NUM_PARTITIONS ARRAY_SIZE(g_pasStatic_Partition) ++extern int part_num; // = NUM_PARTITIONS; ++//#endif ++#undef RECONFIG_PARTITION_SIZE ++ diff --git a/target/linux/ramips/patches-5.4/0040-nand-hack.patch b/target/linux/ramips/patches-5.4/0040-nand-hack.patch new file mode 100644 index 0000000000..58cdf1bce7 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0040-nand-hack.patch @@ -0,0 +1,32 @@ +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -1908,6 +1908,9 @@ static int nand_do_read_ops(struct mtd_i + __func__, buf); + + read_retry: ++#ifdef CONFIG_MTK_MTD_NAND ++ ret = chip->read_page(mtd, chip, bufpoi, page); ++#else + if (nand_standard_page_accessors(&chip->ecc)) + chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); + +@@ -1927,6 +1930,7 @@ read_retry: + else + ret = chip->ecc.read_page(mtd, chip, bufpoi, + oob_required, page); ++#endif + if (ret < 0) { + if (use_bufpoi) + /* Invalidate page cache */ +--- a/include/linux/mtd/rawnand.h ++++ b/include/linux/mtd/rawnand.h +@@ -897,6 +897,9 @@ struct nand_chip { + int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, + const struct nand_data_interface *conf); + ++#ifdef CONFIG_MTK_MTD_NAND ++ int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int page); ++#endif /* CONFIG_MTK_MTD_NAND */ + + int chip_delay; + unsigned int options; diff --git a/target/linux/ramips/patches-5.4/0041-DT-Add-documentation-for-spi-rt2880.patch b/target/linux/ramips/patches-5.4/0041-DT-Add-documentation-for-spi-rt2880.patch new file mode 100644 index 0000000000..e2643e3f25 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0041-DT-Add-documentation-for-spi-rt2880.patch @@ -0,0 +1,44 @@ +From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Fri, 9 Aug 2013 20:12:59 +0200 +Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880 + +Describe the SPI master found on the MIPS based Ralink RT2880 SoC. + +Signed-off-by: John Crispin +--- + .../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++ + 1 file changed, 28 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt +@@ -0,0 +1,28 @@ ++Ralink SoC RT2880 SPI master controller. ++ ++This SPI controller is found on most wireless SoCs made by ralink. ++ ++Required properties: ++- compatible : "ralink,rt2880-spi" ++- reg : The register base for the controller. ++- #address-cells : <1>, as required by generic SPI binding. ++- #size-cells : <0>, also as required by generic SPI binding. ++ ++Child nodes as per the generic SPI binding. ++ ++Example: ++ ++ spi@b00 { ++ compatible = "ralink,rt2880-spi"; ++ reg = <0xb00 0x100>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ m25p80@0 { ++ compatible = "m25p80"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++ diff --git a/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch new file mode 100644 index 0000000000..1dd9f40c39 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch @@ -0,0 +1,574 @@ +From 683af4ebb91a1600df1946ac4769d916b8a1be65 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 11:15:12 +0100 +Subject: [PATCH 42/53] SPI: ralink: add Ralink SoC spi driver + +Add the driver needed to make SPI work on Ralink SoC. + +Signed-off-by: Gabor Juhos +Acked-by: John Crispin +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-rt2880.c | 530 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 537 insertions(+) + create mode 100644 drivers/spi/spi-rt2880.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -563,6 +563,12 @@ config SPI_QUP + This driver can also be built as a module. If so, the module + will be called spi_qup. + ++config SPI_RT2880 ++ tristate "Ralink RT288x SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the Ralink RT288x/RT305x SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o + obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o + obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o ++obj-$(CONFIG_SPI_RT2880) += spi-rt2880.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o + spi-s3c24xx-hw-y := spi-s3c24xx.o + spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o +--- /dev/null ++++ b/drivers/spi/spi-rt2880.c +@@ -0,0 +1,530 @@ ++/* ++ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy ++ * Copyright (C) 2011-2013 Gabor Juhos ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "spi-rt2880" ++ ++#define RAMIPS_SPI_STAT 0x00 ++#define RAMIPS_SPI_CFG 0x10 ++#define RAMIPS_SPI_CTL 0x14 ++#define RAMIPS_SPI_DATA 0x20 ++#define RAMIPS_SPI_ADDR 0x24 ++#define RAMIPS_SPI_BS 0x28 ++#define RAMIPS_SPI_USER 0x2C ++#define RAMIPS_SPI_TXFIFO 0x30 ++#define RAMIPS_SPI_RXFIFO 0x34 ++#define RAMIPS_SPI_FIFO_STAT 0x38 ++#define RAMIPS_SPI_MODE 0x3C ++#define RAMIPS_SPI_DEV_OFFSET 0x40 ++#define RAMIPS_SPI_DMA 0x80 ++#define RAMIPS_SPI_DMASTAT 0x84 ++#define RAMIPS_SPI_ARBITER 0xF0 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++/* SPICFG register bit field */ ++#define SPICFG_ADDRMODE BIT(12) ++#define SPICFG_RXENVDIS BIT(11) ++#define SPICFG_RXCAP BIT(10) ++#define SPICFG_SPIENMODE BIT(9) ++#define SPICFG_MSBFIRST BIT(8) ++#define SPICFG_SPICLKPOL BIT(6) ++#define SPICFG_RXCLKEDGE_FALLING BIT(5) ++#define SPICFG_TXCLKEDGE_FALLING BIT(4) ++#define SPICFG_HIZSPI BIT(3) ++#define SPICFG_SPICLK_PRESCALE_MASK 0x7 ++#define SPICFG_SPICLK_DIV2 0 ++#define SPICFG_SPICLK_DIV4 1 ++#define SPICFG_SPICLK_DIV8 2 ++#define SPICFG_SPICLK_DIV16 3 ++#define SPICFG_SPICLK_DIV32 4 ++#define SPICFG_SPICLK_DIV64 5 ++#define SPICFG_SPICLK_DIV128 6 ++#define SPICFG_SPICLK_DISABLE 7 ++ ++/* SPICTL register bit field */ ++#define SPICTL_START BIT(4) ++#define SPICTL_HIZSDO BIT(3) ++#define SPICTL_STARTWR BIT(2) ++#define SPICTL_STARTRD BIT(1) ++#define SPICTL_SPIENA BIT(0) ++ ++/* SPIUSER register bit field */ ++#define SPIUSER_USERMODE BIT(21) ++#define SPIUSER_INSTR_PHASE BIT(20) ++#define SPIUSER_ADDR_PHASE_MASK 0x7 ++#define SPIUSER_ADDR_PHASE_OFFSET 17 ++#define SPIUSER_MODE_PHASE BIT(16) ++#define SPIUSER_DUMMY_PHASE_MASK 0x3 ++#define SPIUSER_DUMMY_PHASE_OFFSET 14 ++#define SPIUSER_DATA_PHASE_MASK 0x3 ++#define SPIUSER_DATA_PHASE_OFFSET 12 ++#define SPIUSER_DATA_READ (BIT(0) << SPIUSER_DATA_PHASE_OFFSET) ++#define SPIUSER_DATA_WRITE (BIT(1) << SPIUSER_DATA_PHASE_OFFSET) ++#define SPIUSER_ADDR_TYPE_OFFSET 9 ++#define SPIUSER_MODE_TYPE_OFFSET 6 ++#define SPIUSER_DUMMY_TYPE_OFFSET 3 ++#define SPIUSER_DATA_TYPE_OFFSET 0 ++#define SPIUSER_TRANSFER_MASK 0x7 ++#define SPIUSER_TRANSFER_SINGLE BIT(0) ++#define SPIUSER_TRANSFER_DUAL BIT(1) ++#define SPIUSER_TRANSFER_QUAD BIT(2) ++ ++#define SPIUSER_TRANSFER_TYPE(type) ( \ ++ (type << SPIUSER_ADDR_TYPE_OFFSET) | \ ++ (type << SPIUSER_MODE_TYPE_OFFSET) | \ ++ (type << SPIUSER_DUMMY_TYPE_OFFSET) | \ ++ (type << SPIUSER_DATA_TYPE_OFFSET) \ ++) ++ ++/* SPIFIFOSTAT register bit field */ ++#define SPIFIFOSTAT_TXEMPTY BIT(19) ++#define SPIFIFOSTAT_RXEMPTY BIT(18) ++#define SPIFIFOSTAT_TXFULL BIT(17) ++#define SPIFIFOSTAT_RXFULL BIT(16) ++#define SPIFIFOSTAT_FIFO_MASK 0xff ++#define SPIFIFOSTAT_TX_OFFSET 8 ++#define SPIFIFOSTAT_RX_OFFSET 0 ++ ++#define SPI_FIFO_DEPTH 16 ++ ++/* SPIMODE register bit field */ ++#define SPIMODE_MODE_OFFSET 24 ++#define SPIMODE_DUMMY_OFFSET 0 ++ ++/* SPIARB register bit field */ ++#define SPICTL_ARB_EN BIT(31) ++#define SPICTL_CSCTL1 BIT(16) ++#define SPI1_POR BIT(1) ++#define SPI0_POR BIT(0) ++ ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \ ++ SPI_CS_HIGH) ++ ++static atomic_t hw_reset_count = ATOMIC_INIT(0); ++ ++struct rt2880_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ u32 speed; ++ u16 wait_loops; ++ u16 mode; ++ struct clk *clk; ++}; ++ ++static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, ++ const u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ ++ iowrite32((ioread32(addr) | mask), addr); ++} ++ ++static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ ++ iowrite32((ioread32(addr) & ~mask), addr); ++} ++ ++static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ u32 rate; ++ u32 prescale; ++ ++ /* ++ * the supported rates are: 2, 4, 8, ... 128 ++ * round up as we look for equal or less speed ++ */ ++ rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed); ++ rate = roundup_pow_of_two(rate); ++ ++ /* Convert the rate to SPI clock divisor value. */ ++ prescale = ilog2(rate / 2); ++ ++ /* some tolerance. double and add 100 */ ++ rs->wait_loops = (8 * HZ * loops_per_jiffy) / ++ (clk_get_rate(rs->clk) / rate); ++ rs->wait_loops = (rs->wait_loops << 1) + 100; ++ rs->speed = speed; ++ ++ dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n", ++ clk_get_rate(rs->clk) / rate, speed, rate, prescale, ++ rs->wait_loops); ++ ++ return prescale; ++} ++ ++static u32 get_arbiter_offset(struct spi_master *master) ++{ ++ u32 offset; ++ ++ offset = RAMIPS_SPI_ARBITER; ++ if (master->bus_num == 1) ++ offset -= RAMIPS_SPI_DEV_OFFSET; ++ ++ return offset; ++} ++ ++static void rt2880_spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ ++ if (enable) ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ else ++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++} ++ ++static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len) ++{ ++ int loop = rs->wait_loops * len; ++ ++ while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop) ++ cpu_relax(); ++ ++ if (loop) ++ return 0; ++ ++ return -ETIMEDOUT; ++} ++ ++static void rt2880_dump_reg(struct spi_master *master) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ ++ dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \ ++ "data: %08x, arb: %08x\n", ++ rt2880_spi_read(rs, RAMIPS_SPI_STAT), ++ rt2880_spi_read(rs, RAMIPS_SPI_CFG), ++ rt2880_spi_read(rs, RAMIPS_SPI_CTL), ++ rt2880_spi_read(rs, RAMIPS_SPI_DATA), ++ rt2880_spi_read(rs, get_arbiter_offset(master))); ++} ++ ++static int rt2880_spi_transfer_one(struct spi_master *master, ++ struct spi_device *spi, struct spi_transfer *xfer) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ unsigned len; ++ const u8 *tx = xfer->tx_buf; ++ u8 *rx = xfer->rx_buf; ++ int err = 0; ++ ++ /* change clock speed */ ++ if (unlikely(rs->speed != xfer->speed_hz)) { ++ u32 reg; ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ reg &= ~SPICFG_SPICLK_PRESCALE_MASK; ++ reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz); ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ } ++ ++ if (tx) { ++ len = xfer->len; ++ while (len-- > 0) { ++ rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); ++ err = rt2880_spi_wait_ready(rs, 1); ++ if (err) { ++ dev_err(&spi->dev, "TX failed, err=%d\n", err); ++ goto out; ++ } ++ } ++ } ++ ++ if (rx) { ++ len = xfer->len; ++ while (len-- > 0) { ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); ++ err = rt2880_spi_wait_ready(rs, 1); ++ if (err) { ++ dev_err(&spi->dev, "RX failed, err=%d\n", err); ++ goto out; ++ } ++ *rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); ++ } ++ } ++ ++out: ++ return err; ++} ++ ++/* copy from spi.c */ ++static void spi_set_cs(struct spi_device *spi, bool enable) ++{ ++ if (spi->mode & SPI_CS_HIGH) ++ enable = !enable; ++ ++ if (spi->cs_gpio >= 0) ++ gpio_set_value(spi->cs_gpio, !enable); ++ else if (spi->master->set_cs) ++ spi->master->set_cs(spi, !enable); ++} ++ ++static int rt2880_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ u32 reg, old_reg, arbit_off; ++ ++ if ((spi->max_speed_hz > master->max_speed_hz) || ++ (spi->max_speed_hz < master->min_speed_hz)) { ++ dev_err(&spi->dev, "invalide requested speed %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ if (!(master->bits_per_word_mask & ++ BIT(spi->bits_per_word - 1))) { ++ dev_err(&spi->dev, "invalide bits_per_word %d\n", ++ spi->bits_per_word); ++ return -EINVAL; ++ } ++ ++ /* the hardware seems can't work on mode0 force it to mode3 */ ++ if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) { ++ dev_warn(&spi->dev, "force spi mode3\n"); ++ spi->mode |= SPI_MODE_3; ++ } ++ ++ /* chip polarity */ ++ arbit_off = get_arbiter_offset(master); ++ reg = old_reg = rt2880_spi_read(rs, arbit_off); ++ if (spi->mode & SPI_CS_HIGH) { ++ switch (master->bus_num) { ++ case 1: ++ reg |= SPI1_POR; ++ break; ++ default: ++ reg |= SPI0_POR; ++ break; ++ } ++ } else { ++ switch (master->bus_num) { ++ case 1: ++ reg &= ~SPI1_POR; ++ break; ++ default: ++ reg &= ~SPI0_POR; ++ break; ++ } ++ } ++ ++ /* enable spi1 */ ++ if (master->bus_num == 1) ++ reg |= SPICTL_ARB_EN; ++ ++ if (reg != old_reg) ++ rt2880_spi_write(rs, arbit_off, reg); ++ ++ /* deselected the spi device */ ++ spi_set_cs(spi, false); ++ ++ rt2880_dump_reg(master); ++ ++ return 0; ++} ++ ++static int rt2880_spi_prepare_message(struct spi_master *master, ++ struct spi_message *msg) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = msg->spi; ++ u32 reg; ++ ++ if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz)) ++ return 0; ++ ++#if 0 ++ /* set spido to tri-state */ ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO); ++#endif ++ ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ ++ reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL | ++ SPICFG_RXCLKEDGE_FALLING | ++ SPICFG_TXCLKEDGE_FALLING | ++ SPICFG_SPICLK_PRESCALE_MASK); ++ ++ /* MSB */ ++ if (!(spi->mode & SPI_LSB_FIRST)) ++ reg |= SPICFG_MSBFIRST; ++ ++ /* spi mode */ ++ switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ reg |= SPICFG_TXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_1: ++ reg |= SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_2: ++ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_3: ++ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING; ++ break; ++ } ++ rs->mode = spi->mode; ++ ++#if 0 ++ /* set spiclk and spiena to tri-state */ ++ reg |= SPICFG_HIZSPI; ++#endif ++ ++ /* clock divide */ ++ reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz); ++ ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ ++ return 0; ++} ++ ++static int rt2880_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ void __iomem *base; ++ struct resource *r; ++ struct clk *clk; ++ int ret; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock\n"); ++ return PTR_ERR(clk); ++ } ++ ++ ret = clk_prepare_enable(clk); ++ if (ret) ++ goto err_clk; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_dbg(&pdev->dev, "master allocation failed\n"); ++ ret = -ENOMEM; ++ goto err_clk; ++ } ++ ++ master->dev.of_node = pdev->dev.of_node; ++ master->mode_bits = RT2880_SPI_MODE_BITS; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->min_speed_hz = clk_get_rate(clk) / 128; ++ master->max_speed_hz = clk_get_rate(clk) / 2; ++ master->flags = SPI_MASTER_HALF_DUPLEX; ++ master->setup = rt2880_spi_setup; ++ master->prepare_message = rt2880_spi_prepare_message; ++ master->set_cs = rt2880_spi_set_cs; ++ master->transfer_one = rt2880_spi_transfer_one, ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->master = master; ++ rs->base = base; ++ rs->clk = clk; ++ ++ if (atomic_inc_return(&hw_reset_count) == 1) ++ device_reset(&pdev->dev); ++ ++ ret = devm_spi_register_master(&pdev->dev, master); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "devm_spi_register_master error.\n"); ++ goto err_master; ++ } ++ ++ return ret; ++ ++err_master: ++ spi_master_put(master); ++ kfree(master); ++err_clk: ++ clk_disable_unprepare(clk); ++ ++ return ret; ++} ++ ++static int rt2880_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable_unprepare(rs->clk); ++ atomic_dec(&hw_reset_count); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static const struct of_device_id rt2880_spi_match[] = { ++ { .compatible = "ralink,rt2880-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_spi_match); ++ ++static struct platform_driver rt2880_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_spi_match, ++ }, ++ .probe = rt2880_spi_probe, ++ .remove = rt2880_spi_remove, ++}; ++ ++module_platform_driver(rt2880_spi_driver); ++ ++MODULE_DESCRIPTION("Ralink SPI driver"); ++MODULE_AUTHOR("Sergiy "); ++MODULE_AUTHOR("Gabor Juhos "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch b/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch new file mode 100644 index 0000000000..b607f2bdf4 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch @@ -0,0 +1,487 @@ +From cbd66c626e16743b05af807ad48012c0a097b9fb Mon Sep 17 00:00:00 2001 +From: Stefan Roese +Date: Mon, 25 Mar 2019 09:29:25 +0100 +Subject: [PATCH] spi: mt7621: Move SPI driver out of staging + +This patch moves the MT7621 SPI driver, which is used on some Ralink / +MediaTek MT76xx MIPS SoC's, out of the staging directory. No changes to +the source code are done in this patch. + +This driver version was tested successfully on an MT7688 based platform +with an SPI NOR on CS0 and an SPI NAND on CS1 without any issues (so +far). + +This patch also documents the devicetree bindings for the MT7621 SPI +device driver. + +Signed-off-by: Stefan Roese +Cc: Rob Herring +Cc: Mark Brown +Cc: Greg Kroah-Hartman +Cc: NeilBrown +Cc: Sankalp Negi +Cc: Chuanhong Guo +Cc: John Crispin +Cc: Armando Miraglia +Signed-off-by: Mark Brown +--- + .../devicetree/bindings/spi/spi-mt7621.txt | 26 ++++++ + drivers/spi/Kconfig | 6 ++ + drivers/spi/Makefile | 1 + + .../{staging/mt7621-spi => spi}/spi-mt7621.c | 83 +++++++++---------- + drivers/staging/Kconfig | 2 - + drivers/staging/Makefile | 1 - + drivers/staging/mt7621-spi/Kconfig | 6 -- + drivers/staging/mt7621-spi/Makefile | 1 - + drivers/staging/mt7621-spi/TODO | 5 -- + 9 files changed, 74 insertions(+), 57 deletions(-) + create mode 100644 Documentation/devicetree/bindings/spi/spi-mt7621.txt + rename drivers/{staging/mt7621-spi => spi}/spi-mt7621.c (88%) + delete mode 100644 drivers/staging/mt7621-spi/Kconfig + delete mode 100644 drivers/staging/mt7621-spi/Makefile + delete mode 100644 drivers/staging/mt7621-spi/TODO + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -569,6 +569,12 @@ config SPI_RT2880 + help + This selects a driver for the Ralink RT288x/RT305x SPI Controller. + ++config SPI_MT7621 ++ tristate "MediaTek MT7621 SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the MediaTek MT7621 SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp + obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o + obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o + obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o ++obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o + obj-$(CONFIG_SPI_MXS) += spi-mxs.o + obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o + obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o +--- /dev/null ++++ b/drivers/spi/spi-mt7621.c +@@ -0,0 +1,416 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// ++// spi-mt7621.c -- MediaTek MT7621 SPI controller driver ++// ++// Copyright (C) 2011 Sergiy ++// Copyright (C) 2011-2013 Gabor Juhos ++// Copyright (C) 2014-2015 Felix Fietkau ++// ++// Some parts are based on spi-orion.c: ++// Author: Shadi Ammouri ++// Copyright (C) 2007-2008 Marvell Ltd. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRIVER_NAME "spi-mt7621" ++ ++/* in usec */ ++#define RALINK_SPI_WAIT_MAX_LOOP 2000 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++#define MT7621_SPI_TRANS 0x00 ++#define SPITRANS_BUSY BIT(16) ++ ++#define MT7621_SPI_OPCODE 0x04 ++#define MT7621_SPI_DATA0 0x08 ++#define MT7621_SPI_DATA4 0x18 ++#define SPI_CTL_TX_RX_CNT_MASK 0xff ++#define SPI_CTL_START BIT(8) ++ ++#define MT7621_SPI_MASTER 0x28 ++#define MASTER_MORE_BUFMODE BIT(2) ++#define MASTER_FULL_DUPLEX BIT(10) ++#define MASTER_RS_CLK_SEL GENMASK(27, 16) ++#define MASTER_RS_CLK_SEL_SHIFT 16 ++#define MASTER_RS_SLAVE_SEL GENMASK(31, 29) ++ ++#define MT7621_SPI_MOREBUF 0x2c ++#define MT7621_SPI_POLAR 0x38 ++#define MT7621_SPI_SPACE 0x3c ++ ++#define MT7621_CPHA BIT(5) ++#define MT7621_CPOL BIT(4) ++#define MT7621_LSB_FIRST BIT(3) ++ ++struct mt7621_spi { ++ struct spi_controller *master; ++ void __iomem *base; ++ unsigned int sys_freq; ++ unsigned int speed; ++ struct clk *clk; ++ int pending_write; ++}; ++ ++static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) ++{ ++ return spi_controller_get_devdata(spi->master); ++} ++ ++static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static void mt7621_spi_set_cs(struct spi_device *spi, int enable) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ int cs = spi->chip_select; ++ u32 polar = 0; ++ u32 master; ++ ++ /* ++ * Select SPI device 7, enable "more buffer mode" and disable ++ * full-duplex (only half-duplex really works on this chip ++ * reliably) ++ */ ++ master = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE; ++ master &= ~MASTER_FULL_DUPLEX; ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, master); ++ ++ rs->pending_write = 0; ++ ++ if (enable) ++ polar = BIT(cs); ++ mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); ++} ++ ++static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ u32 rate; ++ u32 reg; ++ ++ dev_dbg(&spi->dev, "speed:%u\n", speed); ++ ++ rate = DIV_ROUND_UP(rs->sys_freq, speed); ++ dev_dbg(&spi->dev, "rate-1:%u\n", rate); ++ ++ if (rate > 4097) ++ return -EINVAL; ++ ++ if (rate < 2) ++ rate = 2; ++ ++ reg = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ reg &= ~MASTER_RS_CLK_SEL; ++ reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT; ++ rs->speed = speed; ++ ++ reg &= ~MT7621_LSB_FIRST; ++ if (spi->mode & SPI_LSB_FIRST) ++ reg |= MT7621_LSB_FIRST; ++ ++ /* ++ * This SPI controller seems to be tested on SPI flash only and some ++ * bits are swizzled under other SPI modes probably due to incorrect ++ * wiring inside the silicon. Only mode 0 works correctly. ++ */ ++ reg &= ~(MT7621_CPHA | MT7621_CPOL); ++ ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); ++ ++ return 0; ++} ++ ++static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs) ++{ ++ int i; ++ ++ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { ++ u32 status; ++ ++ status = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ if ((status & SPITRANS_BUSY) == 0) ++ return 0; ++ cpu_relax(); ++ udelay(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs, ++ int rx_len, u8 *buf) ++{ ++ int tx_len; ++ ++ /* ++ * Combine with any pending write, and perform one or more half-duplex ++ * transactions reading 'len' bytes. Data to be written is already in ++ * MT7621_SPI_DATA. ++ */ ++ tx_len = rs->pending_write; ++ rs->pending_write = 0; ++ ++ while (rx_len || tx_len) { ++ int i; ++ u32 val = (min(tx_len, 4) * 8) << 24; ++ int rx = min(rx_len, 32); ++ ++ if (tx_len > 4) ++ val |= (tx_len - 4) * 8; ++ val |= (rx * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); ++ ++ tx_len = 0; ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(rs); ++ ++ for (i = 0; i < rx; i++) { ++ if ((i % 4) == 0) ++ val = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); ++ *buf++ = val & 0xff; ++ val >>= 8; ++ } ++ ++ rx_len -= i; ++ } ++} ++ ++static inline void mt7621_spi_flush(struct mt7621_spi *rs) ++{ ++ mt7621_spi_read_half_duplex(rs, 0, NULL); ++} ++ ++static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs, ++ int tx_len, const u8 *buf) ++{ ++ int len = rs->pending_write; ++ int val = 0; ++ ++ if (len & 3) { ++ val = mt7621_spi_read(rs, MT7621_SPI_OPCODE + (len & ~3)); ++ if (len < 4) { ++ val <<= (4 - len) * 8; ++ val = swab32(val); ++ } ++ } ++ ++ while (tx_len > 0) { ++ if (len >= 36) { ++ rs->pending_write = len; ++ mt7621_spi_flush(rs); ++ len = 0; ++ } ++ ++ val |= *buf++ << (8 * (len & 3)); ++ len++; ++ if ((len & 3) == 0) { ++ if (len == 4) ++ /* The byte-order of the opcode is weird! */ ++ val = swab32(val); ++ mt7621_spi_write(rs, MT7621_SPI_OPCODE + len - 4, val); ++ val = 0; ++ } ++ tx_len -= 1; ++ } ++ ++ if (len & 3) { ++ if (len < 4) { ++ val = swab32(val); ++ val >>= (4 - len) * 8; ++ } ++ mt7621_spi_write(rs, MT7621_SPI_OPCODE + (len & ~3), val); ++ } ++ ++ rs->pending_write = len; ++} ++ ++static int mt7621_spi_transfer_one_message(struct spi_controller *master, ++ struct spi_message *m) ++{ ++ struct mt7621_spi *rs = spi_controller_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ unsigned int speed = spi->max_speed_hz; ++ struct spi_transfer *t = NULL; ++ int status = 0; ++ ++ mt7621_spi_wait_till_ready(rs); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) ++ if (t->speed_hz < speed) ++ speed = t->speed_hz; ++ ++ if (mt7621_spi_prepare(spi, speed)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ /* Assert CS */ ++ mt7621_spi_set_cs(spi, 1); ++ ++ m->actual_length = 0; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ if ((t->rx_buf) && (t->tx_buf)) { ++ /* ++ * This controller will shift some extra data out ++ * of spi_opcode if (mosi_bit_cnt > 0) && ++ * (cmd_bit_cnt == 0). So the claimed full-duplex ++ * support is broken since we have no way to read ++ * the MISO value during that bit. ++ */ ++ status = -EIO; ++ goto msg_done; ++ } else if (t->rx_buf) { ++ mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf); ++ } else if (t->tx_buf) { ++ mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf); ++ } ++ m->actual_length += t->len; ++ } ++ ++ /* Flush data and deassert CS */ ++ mt7621_spi_flush(rs); ++ mt7621_spi_set_cs(spi, 0); ++ ++msg_done: ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int mt7621_spi_setup(struct spi_device *spi) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ ++ if ((spi->max_speed_hz == 0) || ++ (spi->max_speed_hz > (rs->sys_freq / 2))) ++ spi->max_speed_hz = (rs->sys_freq / 2); ++ ++ if (spi->max_speed_hz < (rs->sys_freq / 4097)) { ++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_spi_match[] = { ++ { .compatible = "ralink,mt7621-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_spi_match); ++ ++static int mt7621_spi_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct spi_controller *master; ++ struct mt7621_spi *rs; ++ void __iomem *base; ++ struct resource *r; ++ int status = 0; ++ struct clk *clk; ++ int ret; ++ ++ match = of_match_device(mt7621_spi_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", ++ status); ++ return PTR_ERR(clk); ++ } ++ ++ status = clk_prepare_enable(clk); ++ if (status) ++ return status; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (!master) { ++ dev_info(&pdev->dev, "master allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ master->mode_bits = SPI_LSB_FIRST; ++ master->flags = SPI_CONTROLLER_HALF_DUPLEX; ++ master->setup = mt7621_spi_setup; ++ master->transfer_one_message = mt7621_spi_transfer_one_message; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->dev.of_node = pdev->dev.of_node; ++ master->num_chipselect = 2; ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_controller_get_devdata(master); ++ rs->base = base; ++ rs->clk = clk; ++ rs->master = master; ++ rs->sys_freq = clk_get_rate(rs->clk); ++ rs->pending_write = 0; ++ dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); ++ ++ ret = device_reset(&pdev->dev); ++ if (ret) { ++ dev_err(&pdev->dev, "SPI reset failed!\n"); ++ return ret; ++ } ++ ++ return devm_spi_register_controller(&pdev->dev, master); ++} ++ ++static int mt7621_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_controller *master; ++ struct mt7621_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_controller_get_devdata(master); ++ ++ clk_disable_unprepare(rs->clk); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static struct platform_driver mt7621_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .of_match_table = mt7621_spi_match, ++ }, ++ .probe = mt7621_spi_probe, ++ .remove = mt7621_spi_remove, ++}; ++ ++module_platform_driver(mt7621_spi_driver); ++ ++MODULE_DESCRIPTION("MT7621 SPI driver"); ++MODULE_AUTHOR("Felix Fietkau "); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch new file mode 100644 index 0000000000..4905aba046 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch @@ -0,0 +1,507 @@ +From 723b8beaabf3c3c4b1ce69480141f1e926f3f3b2 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:52:56 +0100 +Subject: [PATCH 44/53] i2c: MIPS: adds ralink I2C driver + +Signed-off-by: John Crispin +--- + .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++ + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-ralink.c | 327 ++++++++++++++++++++ + 4 files changed, 359 insertions(+) + create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt + create mode 100644 drivers/i2c/busses/i2c-ralink.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt +@@ -0,0 +1,27 @@ ++I2C for Ralink platforms ++ ++Required properties : ++- compatible : Must be "link,rt3052-i2c" ++- reg: physical base address of the controller and length of memory mapped ++ region. ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Optional properties: ++- Child nodes conforming to i2c bus binding ++ ++Example : ++ ++palmbus@10000000 { ++ i2c@900 { ++ compatible = "link,rt3052-i2c"; ++ reg = <0x900 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hwmon@4b { ++ compatible = "national,lm92"; ++ reg = <0x4b>; ++ }; ++ }; ++}; +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -864,6 +864,11 @@ config I2C_RK3X + This driver can also be built as a module. If so, the module will + be called i2c-rk3x. + ++config I2C_RALINK ++ tristate "Ralink I2C Controller" ++ depends on RALINK && !SOC_MT7621 ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o + obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o ++obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ralink.c +@@ -0,0 +1,435 @@ ++/* ++ * drivers/i2c/busses/i2c-ralink.c ++ * ++ * Copyright (C) 2013 Steven Liu ++ * Copyright (C) 2016 Michael Lee ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_CONFIG_REG 0x00 ++#define REG_CLKDIV_REG 0x04 ++#define REG_DEVADDR_REG 0x08 ++#define REG_ADDR_REG 0x0C ++#define REG_DATAOUT_REG 0x10 ++#define REG_DATAIN_REG 0x14 ++#define REG_STATUS_REG 0x18 ++#define REG_STARTXFR_REG 0x1C ++#define REG_BYTECNT_REG 0x20 ++ ++/* REG_CONFIG_REG */ ++#define I2C_ADDRLEN_OFFSET 5 ++#define I2C_DEVADLEN_OFFSET 2 ++#define I2C_ADDRLEN_MASK 0x3 ++#define I2C_ADDR_DIS BIT(1) ++#define I2C_DEVADDR_DIS BIT(0) ++#define I2C_ADDRLEN_8 (7 << I2C_ADDRLEN_OFFSET) ++#define I2C_DEVADLEN_7 (6 << I2C_DEVADLEN_OFFSET) ++#define I2C_CONF_DEFAULT (I2C_ADDRLEN_8 | I2C_DEVADLEN_7) ++ ++/* REG_CLKDIV_REG */ ++#define I2C_CLKDIV_MASK 0xffff ++ ++/* REG_DEVADDR_REG */ ++#define I2C_DEVADDR_MASK 0x7f ++ ++/* REG_ADDR_REG */ ++#define I2C_ADDR_MASK 0xff ++ ++/* REG_STATUS_REG */ ++#define I2C_STARTERR BIT(4) ++#define I2C_ACKERR BIT(3) ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++/* REG_STARTXFR_REG */ ++#define NOSTOP_CMD BIT(2) ++#define NODATA_CMD BIT(1) ++#define READ_CMD BIT(0) ++ ++/* REG_BYTECNT_REG */ ++#define BYTECNT_MAX 64 ++#define SET_BYTECNT(x) (x - 1) ++ ++/* timeout waiting for I2C devices to respond (clock streching) */ ++#define TIMEOUT_MS 1000 ++#define DELAY_INTERVAL_US 100 ++ ++struct rt_i2c { ++ void __iomem *base; ++ struct clk *clk; ++ struct device *dev; ++ struct i2c_adapter adap; ++ u32 cur_clk; ++ u32 clk_div; ++ u32 flags; ++}; ++ ++static void rt_i2c_w32(struct rt_i2c *i2c, u32 val, unsigned reg) ++{ ++ iowrite32(val, i2c->base + reg); ++} ++ ++static u32 rt_i2c_r32(struct rt_i2c *i2c, unsigned reg) ++{ ++ return ioread32(i2c->base + reg); ++} ++ ++static int poll_down_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ ++ do { ++ if (!(readl_relaxed(addr) & mask)) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; ++} ++ ++static int rt_i2c_wait_idle(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_down_timeout(i2c->base + REG_STATUS_REG, I2C_BUSY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "idle err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int poll_up_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ u32 status; ++ ++ do { ++ status = readl_relaxed(addr); ++ ++ /* check error status */ ++ if (status & I2C_STARTERR) ++ return -EAGAIN; ++ else if (status & I2C_ACKERR) ++ return -ENXIO; ++ else if (status & mask) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int rt_i2c_wait_rx_done(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_DATARDY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "rx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int rt_i2c_wait_tx_done(struct rt_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_SDOEMPTY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "tx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static void rt_i2c_reset(struct rt_i2c *i2c) ++{ ++ device_reset(i2c->adap.dev.parent); ++ barrier(); ++ rt_i2c_w32(i2c, i2c->clk_div, REG_CLKDIV_REG); ++} ++ ++static void rt_i2c_dump_reg(struct rt_i2c *i2c) ++{ ++ dev_dbg(i2c->dev, "conf %08x, clkdiv %08x, devaddr %08x, " \ ++ "addr %08x, dataout %08x, datain %08x, " \ ++ "status %08x, startxfr %08x, bytecnt %08x\n", ++ rt_i2c_r32(i2c, REG_CONFIG_REG), ++ rt_i2c_r32(i2c, REG_CLKDIV_REG), ++ rt_i2c_r32(i2c, REG_DEVADDR_REG), ++ rt_i2c_r32(i2c, REG_ADDR_REG), ++ rt_i2c_r32(i2c, REG_DATAOUT_REG), ++ rt_i2c_r32(i2c, REG_DATAIN_REG), ++ rt_i2c_r32(i2c, REG_STATUS_REG), ++ rt_i2c_r32(i2c, REG_STARTXFR_REG), ++ rt_i2c_r32(i2c, REG_BYTECNT_REG)); ++} ++ ++static int rt_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct rt_i2c *i2c; ++ struct i2c_msg *pmsg; ++ unsigned char addr; ++ int i, j, ret; ++ u32 cmd; ++ ++ i2c = i2c_get_adapdata(adap); ++ ++ for (i = 0; i < num; i++) { ++ pmsg = &msgs[i]; ++ if (i == (num - 1)) ++ cmd = 0; ++ else ++ cmd = NOSTOP_CMD; ++ ++ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x, stop: %d\n", ++ pmsg->addr, pmsg->len, pmsg->flags, ++ (cmd == 0)? 1 : 0); ++ ++ /* wait hardware idle */ ++ if ((ret = rt_i2c_wait_idle(i2c))) ++ goto err_timeout; ++ ++ if (pmsg->flags & I2C_M_TEN) { ++ rt_i2c_w32(i2c, I2C_CONF_DEFAULT, REG_CONFIG_REG); ++ /* 10 bits address */ ++ addr = 0x78 | ((pmsg->addr >> 8) & 0x03); ++ rt_i2c_w32(i2c, addr & I2C_DEVADDR_MASK, ++ REG_DEVADDR_REG); ++ rt_i2c_w32(i2c, pmsg->addr & I2C_ADDR_MASK, ++ REG_ADDR_REG); ++ } else { ++ rt_i2c_w32(i2c, I2C_CONF_DEFAULT | I2C_ADDR_DIS, ++ REG_CONFIG_REG); ++ /* 7 bits address */ ++ rt_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, ++ REG_DEVADDR_REG); ++ } ++ ++ /* buffer length */ ++ if (pmsg->len == 0) ++ cmd |= NODATA_CMD; ++ else ++ rt_i2c_w32(i2c, SET_BYTECNT(pmsg->len), ++ REG_BYTECNT_REG); ++ ++ j = 0; ++ if (pmsg->flags & I2C_M_RD) { ++ cmd |= READ_CMD; ++ /* start transfer */ ++ barrier(); ++ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); ++ do { ++ /* wait */ ++ if ((ret = rt_i2c_wait_rx_done(i2c))) ++ goto err_timeout; ++ /* read data */ ++ if (pmsg->len) ++ pmsg->buf[j] = rt_i2c_r32(i2c, ++ REG_DATAIN_REG); ++ j++; ++ } while (j < pmsg->len); ++ } else { ++ do { ++ /* write data */ ++ if (pmsg->len) ++ rt_i2c_w32(i2c, pmsg->buf[j], ++ REG_DATAOUT_REG); ++ /* start transfer */ ++ if (j == 0) { ++ barrier(); ++ rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); ++ } ++ /* wait */ ++ if ((ret = rt_i2c_wait_tx_done(i2c))) ++ goto err_timeout; ++ j++; ++ } while (j < pmsg->len); ++ } ++ } ++ /* the return value is number of executed messages */ ++ ret = i; ++ ++ return ret; ++ ++err_timeout: ++ rt_i2c_dump_reg(i2c); ++ rt_i2c_reset(i2c); ++ return ret; ++} ++ ++static u32 rt_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm rt_i2c_algo = { ++ .master_xfer = rt_i2c_master_xfer, ++ .functionality = rt_i2c_func, ++}; ++ ++static const struct of_device_id i2c_rt_dt_ids[] = { ++ { .compatible = "ralink,rt2880-i2c" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); ++ ++static struct i2c_adapter_quirks rt_i2c_quirks = { ++ .max_write_len = BYTECNT_MAX, ++ .max_read_len = BYTECNT_MAX, ++}; ++ ++static int rt_i2c_init(struct rt_i2c *i2c) ++{ ++ u32 reg; ++ ++ /* i2c_sclk = periph_clk / ((2 * clk_div) + 5) */ ++ i2c->clk_div = (clk_get_rate(i2c->clk) - (5 * i2c->cur_clk)) / ++ (2 * i2c->cur_clk); ++ if (i2c->clk_div < 8) ++ i2c->clk_div = 8; ++ if (i2c->clk_div > I2C_CLKDIV_MASK) ++ i2c->clk_div = I2C_CLKDIV_MASK; ++ ++ /* check support combinde/repeated start message */ ++ rt_i2c_w32(i2c, NOSTOP_CMD, REG_STARTXFR_REG); ++ reg = rt_i2c_r32(i2c, REG_STARTXFR_REG) & NOSTOP_CMD; ++ ++ rt_i2c_reset(i2c); ++ ++ return reg; ++} ++ ++static int rt_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct rt_i2c *i2c; ++ struct i2c_adapter *adap; ++ const struct of_device_id *match; ++ int ret, restart; ++ ++ match = of_match_device(i2c_rt_dt_ids, &pdev->dev); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(struct rt_i2c), GFP_KERNEL); ++ if (!i2c) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) ++ return PTR_ERR(i2c->base); ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return -ENODEV; ++ } ++ clk_prepare_enable(i2c->clk); ++ i2c->dev = &pdev->dev; ++ ++ if (of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &i2c->cur_clk)) ++ i2c->cur_clk = 100000; ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adap->algo = &rt_i2c_algo; ++ adap->retries = 3; ++ adap->dev.parent = &pdev->dev; ++ i2c_set_adapdata(adap, i2c); ++ adap->dev.of_node = pdev->dev.of_node; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->quirks = &rt_i2c_quirks; ++ ++ platform_set_drvdata(pdev, i2c); ++ ++ restart = rt_i2c_init(i2c); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to add adapter\n"); ++ clk_disable_unprepare(i2c->clk); ++ return ret; ++ } ++ ++ dev_info(&pdev->dev, "clock %uKHz, re-start %ssupport\n", ++ i2c->cur_clk/1000, restart ? "" : "not "); ++ ++ return ret; ++} ++ ++static int rt_i2c_remove(struct platform_device *pdev) ++{ ++ struct rt_i2c *i2c = platform_get_drvdata(pdev); ++ ++ i2c_del_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver rt_i2c_driver = { ++ .probe = rt_i2c_probe, ++ .remove = rt_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-ralink", ++ .of_match_table = i2c_rt_dt_ids, ++ }, ++}; ++ ++static int __init i2c_rt_init (void) ++{ ++ return platform_driver_register(&rt_i2c_driver); ++} ++subsys_initcall(i2c_rt_init); ++ ++static void __exit i2c_rt_exit (void) ++{ ++ platform_driver_unregister(&rt_i2c_driver); ++} ++module_exit(i2c_rt_exit); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_DESCRIPTION("Ralink I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:Ralink-I2C"); diff --git a/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch b/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch new file mode 100644 index 0000000000..a848085520 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch @@ -0,0 +1,473 @@ +From d5c54ff3d1db0a4348fa04d8e78f3bf6063e3afc Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:21:27 +0100 +Subject: [PATCH 45/53] i2c: add mt7621 driver + +Signed-off-by: John Crispin +--- + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-mt7621.c | 303 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 308 insertions(+) + create mode 100644 drivers/i2c/busses/i2c-mt7621.c + +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -869,6 +869,11 @@ config I2C_RALINK + depends on RALINK && !SOC_MT7621 + select OF_I2C + ++config I2C_MT7621 ++ tristate "MT7621/MT7628 I2C Controller" ++ depends on RALINK && (SOC_MT7620 || SOC_MT7621) ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o + obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o ++obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-mt7621.c +@@ -0,0 +1,433 @@ ++/* ++ * drivers/i2c/busses/i2c-mt7621.c ++ * ++ * Copyright (C) 2013 Steven Liu ++ * Copyright (C) 2016 Michael Lee ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak ++ * ++ * This software is licensed under the terms of the GNU General Public ++ * License version 2, as published by the Free Software Foundation, and ++ * may be copied, distributed, and modified under those terms. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define REG_SM0CFG0 0x08 ++#define REG_SM0DOUT 0x10 ++#define REG_SM0DIN 0x14 ++#define REG_SM0ST 0x18 ++#define REG_SM0AUTO 0x1C ++#define REG_SM0CFG1 0x20 ++#define REG_SM0CFG2 0x28 ++#define REG_SM0CTL0 0x40 ++#define REG_SM0CTL1 0x44 ++#define REG_SM0D0 0x50 ++#define REG_SM0D1 0x54 ++#define REG_PINTEN 0x5C ++#define REG_PINTST 0x60 ++#define REG_PINTCL 0x64 ++ ++/* REG_SM0CFG0 */ ++#define I2C_DEVADDR_MASK 0x7f ++ ++/* REG_SM0ST */ ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++/* REG_SM0AUTO */ ++#define READ_CMD BIT(0) ++ ++/* REG_SM0CFG1 */ ++#define BYTECNT_MAX 64 ++#define SET_BYTECNT(x) (x - 1) ++ ++/* REG_SM0CFG2 */ ++#define AUTOMODE_EN BIT(0) ++ ++/* REG_SM0CTL0 */ ++#define ODRAIN_HIGH_SM0 BIT(31) ++#define VSYNC_SHIFT 28 ++#define VSYNC_MASK 0x3 ++#define VSYNC_PULSE (0x1 << VSYNC_SHIFT) ++#define VSYNC_RISING (0x2 << VSYNC_SHIFT) ++#define CLK_DIV_SHIFT 16 ++#define CLK_DIV_MASK 0xfff ++#define DEG_CNT_SHIFT 8 ++#define DEG_CNT_MASK 0xff ++#define WAIT_HIGH BIT(6) ++#define DEG_EN BIT(5) ++#define CS_STATUA BIT(4) ++#define SCL_STATUS BIT(3) ++#define SDA_STATUS BIT(2) ++#define SM0_EN BIT(1) ++#define SCL_STRECH BIT(0) ++ ++/* REG_SM0CTL1 */ ++#define ACK_SHIFT 16 ++#define ACK_MASK 0xff ++#define PGLEN_SHIFT 8 ++#define PGLEN_MASK 0x7 ++#define SM0_MODE_SHIFT 4 ++#define SM0_MODE_MASK 0x7 ++#define SM0_MODE_START 0x1 ++#define SM0_MODE_WRITE 0x2 ++#define SM0_MODE_STOP 0x3 ++#define SM0_MODE_READ_NACK 0x4 ++#define SM0_MODE_READ_ACK 0x5 ++#define SM0_TRI_BUSY BIT(0) ++ ++/* timeout waiting for I2C devices to respond (clock streching) */ ++#define TIMEOUT_MS 1000 ++#define DELAY_INTERVAL_US 100 ++ ++struct mtk_i2c { ++ void __iomem *base; ++ struct clk *clk; ++ struct device *dev; ++ struct i2c_adapter adap; ++ u32 cur_clk; ++ u32 clk_div; ++ u32 flags; ++}; ++ ++static void mtk_i2c_w32(struct mtk_i2c *i2c, u32 val, unsigned reg) ++{ ++ iowrite32(val, i2c->base + reg); ++} ++ ++static u32 mtk_i2c_r32(struct mtk_i2c *i2c, unsigned reg) ++{ ++ return ioread32(i2c->base + reg); ++} ++ ++static int poll_down_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ ++ do { ++ if (!(readl_relaxed(addr) & mask)) ++ return 0; ++ ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; ++} ++ ++static int mtk_i2c_wait_idle(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_down_timeout(i2c->base + REG_SM0ST, I2C_BUSY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "idle err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int poll_up_timeout(void __iomem *addr, u32 mask) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); ++ u32 status; ++ ++ do { ++ status = readl_relaxed(addr); ++ if (status & mask) ++ return 0; ++ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); ++ } while (time_before(jiffies, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static int mtk_i2c_wait_rx_done(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_DATARDY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "rx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static int mtk_i2c_wait_tx_done(struct mtk_i2c *i2c) ++{ ++ int ret; ++ ++ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_SDOEMPTY); ++ if (ret < 0) ++ dev_dbg(i2c->dev, "tx err(%d)\n", ret); ++ ++ return ret; ++} ++ ++static void mtk_i2c_reset(struct mtk_i2c *i2c) ++{ ++ u32 reg; ++ device_reset(i2c->adap.dev.parent); ++ barrier(); ++ ++ /* ctrl0 */ ++ reg = ODRAIN_HIGH_SM0 | VSYNC_PULSE | (i2c->clk_div << CLK_DIV_SHIFT) | ++ WAIT_HIGH | SM0_EN; ++ mtk_i2c_w32(i2c, reg, REG_SM0CTL0); ++ ++ /* auto mode */ ++ mtk_i2c_w32(i2c, AUTOMODE_EN, REG_SM0CFG2); ++} ++ ++static void mtk_i2c_dump_reg(struct mtk_i2c *i2c) ++{ ++ dev_dbg(i2c->dev, "cfg0 %08x, dout %08x, din %08x, " \ ++ "status %08x, auto %08x, cfg1 %08x, " \ ++ "cfg2 %08x, ctl0 %08x, ctl1 %08x\n", ++ mtk_i2c_r32(i2c, REG_SM0CFG0), ++ mtk_i2c_r32(i2c, REG_SM0DOUT), ++ mtk_i2c_r32(i2c, REG_SM0DIN), ++ mtk_i2c_r32(i2c, REG_SM0ST), ++ mtk_i2c_r32(i2c, REG_SM0AUTO), ++ mtk_i2c_r32(i2c, REG_SM0CFG1), ++ mtk_i2c_r32(i2c, REG_SM0CFG2), ++ mtk_i2c_r32(i2c, REG_SM0CTL0), ++ mtk_i2c_r32(i2c, REG_SM0CTL1)); ++} ++ ++static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num) ++{ ++ struct mtk_i2c *i2c; ++ struct i2c_msg *pmsg; ++ int i, j, ret; ++ u32 cmd; ++ ++ i2c = i2c_get_adapdata(adap); ++ ++ for (i = 0; i < num; i++) { ++ pmsg = &msgs[i]; ++ cmd = 0; ++ ++ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x\n", ++ pmsg->addr, pmsg->len, pmsg->flags); ++ ++ /* wait hardware idle */ ++ if ((ret = mtk_i2c_wait_idle(i2c))) ++ goto err_timeout; ++ ++ if (pmsg->flags & I2C_M_TEN) { ++ dev_dbg(i2c->dev, "10 bits addr not supported\n"); ++ return -EINVAL; ++ } else { ++ /* 7 bits address */ ++ mtk_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, ++ REG_SM0CFG0); ++ } ++ ++ /* buffer length */ ++ if (pmsg->len == 0) { ++ dev_dbg(i2c->dev, "length is 0\n"); ++ return -EINVAL; ++ } else ++ mtk_i2c_w32(i2c, SET_BYTECNT(pmsg->len), ++ REG_SM0CFG1); ++ ++ j = 0; ++ if (pmsg->flags & I2C_M_RD) { ++ cmd |= READ_CMD; ++ /* start transfer */ ++ barrier(); ++ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); ++ do { ++ /* wait */ ++ if ((ret = mtk_i2c_wait_rx_done(i2c))) ++ goto err_timeout; ++ /* read data */ ++ if (pmsg->len) ++ pmsg->buf[j] = mtk_i2c_r32(i2c, ++ REG_SM0DIN); ++ j++; ++ } while (j < pmsg->len); ++ } else { ++ do { ++ /* write data */ ++ if (pmsg->len) ++ mtk_i2c_w32(i2c, pmsg->buf[j], ++ REG_SM0DOUT); ++ /* start transfer */ ++ if (j == 0) { ++ barrier(); ++ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); ++ } ++ /* wait */ ++ if ((ret = mtk_i2c_wait_tx_done(i2c))) ++ goto err_timeout; ++ j++; ++ } while (j < pmsg->len); ++ } ++ } ++ /* the return value is number of executed messages */ ++ ret = i; ++ ++ return ret; ++ ++err_timeout: ++ mtk_i2c_dump_reg(i2c); ++ mtk_i2c_reset(i2c); ++ return ret; ++} ++ ++static u32 mtk_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm mtk_i2c_algo = { ++ .master_xfer = mtk_i2c_master_xfer, ++ .functionality = mtk_i2c_func, ++}; ++ ++static const struct of_device_id i2c_mtk_dt_ids[] = { ++ { .compatible = "mediatek,mt7621-i2c" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids); ++ ++static struct i2c_adapter_quirks mtk_i2c_quirks = { ++ .max_write_len = BYTECNT_MAX, ++ .max_read_len = BYTECNT_MAX, ++}; ++ ++static void mtk_i2c_init(struct mtk_i2c *i2c) ++{ ++ i2c->clk_div = clk_get_rate(i2c->clk) / i2c->cur_clk; ++ if (i2c->clk_div > CLK_DIV_MASK) ++ i2c->clk_div = CLK_DIV_MASK; ++ ++ mtk_i2c_reset(i2c); ++} ++ ++static int mtk_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct mtk_i2c *i2c; ++ struct i2c_adapter *adap; ++ const struct of_device_id *match; ++ int ret; ++ ++ match = of_match_device(i2c_mtk_dt_ids, &pdev->dev); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); ++ if (!i2c) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ i2c->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2c->base)) ++ return PTR_ERR(i2c->base); ++ ++ i2c->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2c->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return -ENODEV; ++ } ++ clk_prepare_enable(i2c->clk); ++ i2c->dev = &pdev->dev; ++ ++ if (of_property_read_u32(pdev->dev.of_node, ++ "clock-frequency", &i2c->cur_clk)) ++ i2c->cur_clk = 100000; ++ ++ adap = &i2c->adap; ++ adap->owner = THIS_MODULE; ++ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adap->algo = &mtk_i2c_algo; ++ adap->retries = 3; ++ adap->dev.parent = &pdev->dev; ++ i2c_set_adapdata(adap, i2c); ++ adap->dev.of_node = pdev->dev.of_node; ++ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); ++ adap->quirks = &mtk_i2c_quirks; ++ ++ platform_set_drvdata(pdev, i2c); ++ ++ mtk_i2c_init(i2c); ++ ++ ret = i2c_add_adapter(adap); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to add adapter\n"); ++ clk_disable_unprepare(i2c->clk); ++ return ret; ++ } ++ ++ dev_info(&pdev->dev, "clock %uKHz, re-start not support\n", ++ i2c->cur_clk/1000); ++ ++ return ret; ++} ++ ++static int mtk_i2c_remove(struct platform_device *pdev) ++{ ++ struct mtk_i2c *i2c = platform_get_drvdata(pdev); ++ ++ i2c_del_adapter(&i2c->adap); ++ clk_disable_unprepare(i2c->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_i2c_driver = { ++ .probe = mtk_i2c_probe, ++ .remove = mtk_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-mt7621", ++ .of_match_table = i2c_mtk_dt_ids, ++ }, ++}; ++ ++static int __init i2c_mtk_init (void) ++{ ++ return platform_driver_register(&mtk_i2c_driver); ++} ++subsys_initcall(i2c_mtk_init); ++ ++static void __exit i2c_mtk_exit (void) ++{ ++ platform_driver_unregister(&mtk_i2c_driver); ++} ++module_exit(i2c_mtk_exit); ++ ++MODULE_AUTHOR("Steven Liu "); ++MODULE_DESCRIPTION("MT7621 I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:MT7621-I2C"); diff --git a/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch new file mode 100644 index 0000000000..0535811ea3 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch @@ -0,0 +1,43 @@ +From 23147af14531cbdada194b94120ef8774f46292d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Thu, 13 Nov 2014 19:08:40 +0100 +Subject: [PATCH 46/53] mmc: MIPS: ralink: add sdhci for mt7620a SoC + +Signed-off-by: John Crispin +--- + drivers/mmc/host/Kconfig | 2 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/mtk-mmc/Kconfig | 16 + + drivers/mmc/host/mtk-mmc/Makefile | 42 + + drivers/mmc/host/mtk-mmc/board.h | 137 ++ + drivers/mmc/host/mtk-mmc/dbg.c | 347 ++++ + drivers/mmc/host/mtk-mmc/dbg.h | 156 ++ + drivers/mmc/host/mtk-mmc/mt6575_sd.h | 1001 +++++++++++ + drivers/mmc/host/mtk-mmc/sd.c | 3060 ++++++++++++++++++++++++++++++++++ + 9 files changed, 4762 insertions(+) + create mode 100644 drivers/mmc/host/mtk-mmc/Kconfig + create mode 100644 drivers/mmc/host/mtk-mmc/Makefile + create mode 100644 drivers/mmc/host/mtk-mmc/board.h + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.c + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.h + create mode 100644 drivers/mmc/host/mtk-mmc/mt6575_sd.h + create mode 100644 drivers/mmc/host/mtk-mmc/sd.c + +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -901,3 +901,5 @@ config MMC_SDHCI_XENON + This selects Marvell Xenon eMMC/SD/SDIO SDHCI. + If you have a controller with this interface, say Y or M here. + If unsure, say N. ++ ++source "drivers/mmc/host/mtk-mmc/Kconfig" +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -3,6 +3,7 @@ + # Makefile for MMC/SD host controller drivers + # + ++obj-$(CONFIG_MTK_MMC) += mtk-mmc/ + obj-$(CONFIG_MMC_ARMMMCI) += armmmci.o + armmmci-y := mmci.o + armmmci-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o diff --git a/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch b/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch new file mode 100644 index 0000000000..b74a48a220 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch @@ -0,0 +1,1757 @@ +From f1c4d9e622c800e1f38b3818f933ec7597d1ccfb Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:29:51 +0100 +Subject: [PATCH 47/53] DMA: ralink: add rt2880 dma engine + +Signed-off-by: John Crispin +--- + drivers/dma/Kconfig | 6 + + drivers/dma/Makefile | 1 + + drivers/dma/ralink-gdma.c | 577 +++++++++++++++++++++++++++++++++++++++++++++ + include/linux/dmaengine.h | 1 + + 4 files changed, 585 insertions(+) + create mode 100644 drivers/dma/ralink-gdma.c + +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -40,6 +40,18 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH + config ARCH_HAS_ASYNC_TX_FIND_CHANNEL + bool + ++config DMA_RALINK ++ tristate "RALINK DMA support" ++ depends on RALINK && !SOC_RT288X ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ ++config MTK_HSDMA ++ tristate "MTK HSDMA support" ++ depends on RALINK && SOC_MT7621 ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ + config DMA_ENGINE + bool + +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -71,6 +71,8 @@ obj-$(CONFIG_TI_EDMA) += edma.o + obj-$(CONFIG_XGENE_DMA) += xgene-dma.o + obj-$(CONFIG_ZX_DMA) += zx_dma.o + obj-$(CONFIG_ST_FDMA) += st_fdma.o ++obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o ++obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o + + obj-y += qcom/ + obj-y += xilinx/ +--- /dev/null ++++ b/drivers/dma/ralink-gdma.c +@@ -0,0 +1,928 @@ ++/* ++ * Copyright (C) 2013, Lars-Peter Clausen ++ * GDMA4740 DMAC support ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "virt-dma.h" ++ ++#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) ++#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) ++ ++#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) ++#define GDMA_REG_CTRL0_TX_MASK 0xffff ++#define GDMA_REG_CTRL0_TX_SHIFT 16 ++#define GDMA_REG_CTRL0_CURR_MASK 0xff ++#define GDMA_REG_CTRL0_CURR_SHIFT 8 ++#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) ++#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) ++#define GDMA_REG_CTRL0_BURST_MASK 0x7 ++#define GDMA_REG_CTRL0_BURST_SHIFT 3 ++#define GDMA_REG_CTRL0_DONE_INT BIT(2) ++#define GDMA_REG_CTRL0_ENABLE BIT(1) ++#define GDMA_REG_CTRL0_SW_MODE BIT(0) ++ ++#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) ++#define GDMA_REG_CTRL1_SEG_MASK 0xf ++#define GDMA_REG_CTRL1_SEG_SHIFT 22 ++#define GDMA_REG_CTRL1_REQ_MASK 0x3f ++#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 ++#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 ++#define GDMA_REG_CTRL1_CONTINOUS BIT(14) ++#define GDMA_REG_CTRL1_NEXT_MASK 0x1f ++#define GDMA_REG_CTRL1_NEXT_SHIFT 3 ++#define GDMA_REG_CTRL1_COHERENT BIT(2) ++#define GDMA_REG_CTRL1_FAIL BIT(1) ++#define GDMA_REG_CTRL1_MASK BIT(0) ++ ++#define GDMA_REG_UNMASK_INT 0x200 ++#define GDMA_REG_DONE_INT 0x204 ++ ++#define GDMA_REG_GCT 0x220 ++#define GDMA_REG_GCT_CHAN_MASK 0x3 ++#define GDMA_REG_GCT_CHAN_SHIFT 3 ++#define GDMA_REG_GCT_VER_MASK 0x3 ++#define GDMA_REG_GCT_VER_SHIFT 1 ++#define GDMA_REG_GCT_ARBIT_RR BIT(0) ++ ++#define GDMA_REG_REQSTS 0x2a0 ++#define GDMA_REG_ACKSTS 0x2a4 ++#define GDMA_REG_FINSTS 0x2a8 ++ ++/* for RT305X gdma registers */ ++#define GDMA_RT305X_CTRL0_REQ_MASK 0xf ++#define GDMA_RT305X_CTRL0_SRC_REQ_SHIFT 12 ++#define GDMA_RT305X_CTRL0_DST_REQ_SHIFT 8 ++ ++#define GDMA_RT305X_CTRL1_FAIL BIT(4) ++#define GDMA_RT305X_CTRL1_NEXT_MASK 0x7 ++#define GDMA_RT305X_CTRL1_NEXT_SHIFT 1 ++ ++#define GDMA_RT305X_STATUS_INT 0x80 ++#define GDMA_RT305X_STATUS_SIGNAL 0x84 ++#define GDMA_RT305X_GCT 0x88 ++ ++/* for MT7621 gdma registers */ ++#define GDMA_REG_PERF_START(x) (0x230 + (x) * 0x8) ++#define GDMA_REG_PERF_END(x) (0x234 + (x) * 0x8) ++ ++enum gdma_dma_transfer_size { ++ GDMA_TRANSFER_SIZE_4BYTE = 0, ++ GDMA_TRANSFER_SIZE_8BYTE = 1, ++ GDMA_TRANSFER_SIZE_16BYTE = 2, ++ GDMA_TRANSFER_SIZE_32BYTE = 3, ++ GDMA_TRANSFER_SIZE_64BYTE = 4, ++}; ++ ++struct gdma_dma_sg { ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ u32 len; ++}; ++ ++struct gdma_dma_desc { ++ struct virt_dma_desc vdesc; ++ ++ enum dma_transfer_direction direction; ++ bool cyclic; ++ ++ u32 residue; ++ unsigned int num_sgs; ++ struct gdma_dma_sg sg[]; ++}; ++ ++struct gdma_dmaengine_chan { ++ struct virt_dma_chan vchan; ++ unsigned int id; ++ unsigned int slave_id; ++ ++ dma_addr_t fifo_addr; ++ enum gdma_dma_transfer_size burst_size; ++ ++ struct gdma_dma_desc *desc; ++ unsigned int next_sg; ++}; ++ ++struct gdma_dma_dev { ++ struct dma_device ddev; ++ struct device_dma_parameters dma_parms; ++ struct gdma_data *data; ++ void __iomem *base; ++ struct tasklet_struct task; ++ volatile unsigned long chan_issued; ++ atomic_t cnt; ++ ++ struct gdma_dmaengine_chan chan[]; ++}; ++ ++struct gdma_data ++{ ++ int chancnt; ++ u32 done_int_reg; ++ void (*init)(struct gdma_dma_dev *dma_dev); ++ int (*start_transfer)(struct gdma_dmaengine_chan *chan); ++}; ++ ++static struct gdma_dma_dev *gdma_dma_chan_get_dev( ++ struct gdma_dmaengine_chan *chan) ++{ ++ return container_of(chan->vchan.chan.device, struct gdma_dma_dev, ++ ddev); ++} ++ ++static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) ++{ ++ return container_of(c, struct gdma_dmaengine_chan, vchan.chan); ++} ++ ++static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) ++{ ++ return container_of(vdesc, struct gdma_dma_desc, vdesc); ++} ++ ++static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, ++ unsigned int reg) ++{ ++ return readl(dma_dev->base + reg); ++} ++ ++static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, ++ unsigned reg, uint32_t val) ++{ ++ writel(val, dma_dev->base + reg); ++} ++ ++static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) ++{ ++ return kzalloc(sizeof(struct gdma_dma_desc) + ++ sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); ++} ++ ++static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) ++{ ++ if (maxburst < 2) ++ return GDMA_TRANSFER_SIZE_4BYTE; ++ else if (maxburst < 4) ++ return GDMA_TRANSFER_SIZE_8BYTE; ++ else if (maxburst < 8) ++ return GDMA_TRANSFER_SIZE_16BYTE; ++ else if (maxburst < 16) ++ return GDMA_TRANSFER_SIZE_32BYTE; ++ else ++ return GDMA_TRANSFER_SIZE_64BYTE; ++} ++ ++static int gdma_dma_config(struct dma_chan *c, ++ struct dma_slave_config *config) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ ++ if (config->device_fc) { ++ dev_err(dma_dev->ddev.dev, "not support flow controller\n"); ++ return -EINVAL; ++ } ++ ++ switch (config->direction) { ++ case DMA_MEM_TO_DEV: ++ if (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { ++ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); ++ return -EINVAL; ++ } ++ chan->slave_id = config->slave_id; ++ chan->fifo_addr = config->dst_addr; ++ chan->burst_size = gdma_dma_maxburst(config->dst_maxburst); ++ break; ++ case DMA_DEV_TO_MEM: ++ if (config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { ++ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); ++ return -EINVAL; ++ } ++ chan->slave_id = config->slave_id; ++ chan->fifo_addr = config->src_addr; ++ chan->burst_size = gdma_dma_maxburst(config->src_maxburst); ++ break; ++ default: ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ config->direction); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int gdma_dma_terminate_all(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned long flags, timeout; ++ LIST_HEAD(head); ++ int i = 0; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ chan->desc = NULL; ++ clear_bit(chan->id, &dma_dev->chan_issued); ++ vchan_get_all_descriptors(&chan->vchan, &head); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ vchan_dma_desc_free_list(&chan->vchan, &head); ++ ++ /* wait dma transfer complete */ ++ timeout = jiffies + msecs_to_jiffies(5000); ++ while (gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)) & ++ GDMA_REG_CTRL0_ENABLE) { ++ if (time_after_eq(jiffies, timeout)) { ++ dev_err(dma_dev->ddev.dev, "chan %d wait timeout\n", ++ chan->id); ++ /* restore to init value */ ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), 0); ++ break; ++ } ++ cpu_relax(); ++ i++; ++ } ++ ++ if (i) ++ dev_dbg(dma_dev->ddev.dev, "terminate chan %d loops %d\n", ++ chan->id, i); ++ ++ return 0; ++} ++ ++static void rt305x_dump_reg(struct gdma_dma_dev *dma_dev, int id) ++{ ++ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ ++ "ctr1 %08x, intr %08x, signal %08x\n", id, ++ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), ++ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_INT), ++ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_SIGNAL)); ++} ++ ++static int rt305x_gdma_start_transfer(struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ dma_addr_t src_addr, dst_addr; ++ struct gdma_dma_sg *sg; ++ uint32_t ctrl0, ctrl1; ++ ++ /* verify chan is already stopped */ ++ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); ++ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { ++ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", ++ chan->id, ctrl0); ++ rt305x_dump_reg(dma_dev, chan->id); ++ return -EINVAL; ++ } ++ ++ sg = &chan->desc->sg[chan->next_sg]; ++ if (chan->desc->direction == DMA_MEM_TO_DEV) { ++ src_addr = sg->src_addr; ++ dst_addr = chan->fifo_addr; ++ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED | \ ++ (8 << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ ++ (chan->slave_id << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { ++ src_addr = chan->fifo_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED | \ ++ (chan->slave_id << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ ++ (8 << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { ++ /* ++ * TODO: memcpy function have bugs. sometime it will copy ++ * more 8 bytes data when using dmatest verify. ++ */ ++ src_addr = sg->src_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SW_MODE | \ ++ (8 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (8 << GDMA_REG_CTRL1_DST_REQ_SHIFT); ++ } else { ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ chan->desc->direction); ++ return -EINVAL; ++ } ++ ++ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ ++ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ ++ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; ++ ctrl1 = chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; ++ ++ chan->next_sg++; ++ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); ++ ++ /* make sure next_sg is update */ ++ wmb(); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); ++ ++ return 0; ++} ++ ++static void rt3883_dump_reg(struct gdma_dma_dev *dma_dev, int id) ++{ ++ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ ++ "ctr1 %08x, unmask %08x, done %08x, " \ ++ "req %08x, ack %08x, fin %08x\n", id, ++ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), ++ gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT), ++ gdma_dma_read(dma_dev, GDMA_REG_DONE_INT), ++ gdma_dma_read(dma_dev, GDMA_REG_REQSTS), ++ gdma_dma_read(dma_dev, GDMA_REG_ACKSTS), ++ gdma_dma_read(dma_dev, GDMA_REG_FINSTS)); ++} ++ ++static int rt3883_gdma_start_transfer(struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ dma_addr_t src_addr, dst_addr; ++ struct gdma_dma_sg *sg; ++ uint32_t ctrl0, ctrl1; ++ ++ /* verify chan is already stopped */ ++ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); ++ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { ++ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", ++ chan->id, ctrl0); ++ rt3883_dump_reg(dma_dev, chan->id); ++ return -EINVAL; ++ } ++ ++ sg = &chan->desc->sg[chan->next_sg]; ++ if (chan->desc->direction == DMA_MEM_TO_DEV) { ++ src_addr = sg->src_addr; ++ dst_addr = chan->fifo_addr; ++ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED; ++ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (chan->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT); ++ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { ++ src_addr = chan->fifo_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED; ++ ctrl1 = (chan->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ ++ GDMA_REG_CTRL1_COHERENT; ++ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { ++ src_addr = sg->src_addr; ++ dst_addr = sg->dst_addr; ++ ctrl0 = GDMA_REG_CTRL0_SW_MODE; ++ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ ++ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ ++ GDMA_REG_CTRL1_COHERENT; ++ } else { ++ dev_err(dma_dev->ddev.dev, "direction type %d error\n", ++ chan->desc->direction); ++ return -EINVAL; ++ } ++ ++ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ ++ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ ++ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; ++ ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; ++ ++ chan->next_sg++; ++ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); ++ ++ /* make sure next_sg is update */ ++ wmb(); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); ++ ++ return 0; ++} ++ ++static inline int gdma_start_transfer(struct gdma_dma_dev *dma_dev, ++ struct gdma_dmaengine_chan *chan) ++{ ++ return dma_dev->data->start_transfer(chan); ++} ++ ++static int gdma_next_desc(struct gdma_dmaengine_chan *chan) ++{ ++ struct virt_dma_desc *vdesc; ++ ++ vdesc = vchan_next_desc(&chan->vchan); ++ if (!vdesc) { ++ chan->desc = NULL; ++ return 0; ++ } ++ chan->desc = to_gdma_dma_desc(vdesc); ++ chan->next_sg = 0; ++ ++ return 1; ++} ++ ++static void gdma_dma_chan_irq(struct gdma_dma_dev *dma_dev, ++ struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_desc *desc; ++ unsigned long flags; ++ int chan_issued; ++ ++ chan_issued = 0; ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ desc = chan->desc; ++ if (desc) { ++ if (desc->cyclic) { ++ vchan_cyclic_callback(&desc->vdesc); ++ if (chan->next_sg == desc->num_sgs) ++ chan->next_sg = 0; ++ chan_issued = 1; ++ } else { ++ desc->residue -= desc->sg[chan->next_sg - 1].len; ++ if (chan->next_sg == desc->num_sgs) { ++ list_del(&desc->vdesc.node); ++ vchan_cookie_complete(&desc->vdesc); ++ chan_issued = gdma_next_desc(chan); ++ } else ++ chan_issued = 1; ++ } ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to complete\n", ++ chan->id); ++ if (chan_issued) ++ set_bit(chan->id, &dma_dev->chan_issued); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++} ++ ++static irqreturn_t gdma_dma_irq(int irq, void *devid) ++{ ++ struct gdma_dma_dev *dma_dev = devid; ++ u32 done, done_reg; ++ unsigned int i; ++ ++ done_reg = dma_dev->data->done_int_reg; ++ done = gdma_dma_read(dma_dev, done_reg); ++ if (unlikely(!done)) ++ return IRQ_NONE; ++ ++ /* clean done bits */ ++ gdma_dma_write(dma_dev, done_reg, done); ++ ++ i = 0; ++ while (done) { ++ if (done & 0x1) { ++ gdma_dma_chan_irq(dma_dev, &dma_dev->chan[i]); ++ atomic_dec(&dma_dev->cnt); ++ } ++ done >>= 1; ++ i++; ++ } ++ ++ /* start only have work to do */ ++ if (dma_dev->chan_issued) ++ tasklet_schedule(&dma_dev->task); ++ ++ return IRQ_HANDLED; ++} ++ ++static void gdma_dma_issue_pending(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { ++ if (gdma_next_desc(chan)) { ++ set_bit(chan->id, &dma_dev->chan_issued); ++ tasklet_schedule(&dma_dev->task); ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", ++ chan->id); ++ } ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( ++ struct dma_chan *c, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ struct scatterlist *sg; ++ unsigned int i; ++ ++ desc = gdma_dma_alloc_desc(sg_len); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc sg decs error\n"); ++ return NULL; ++ } ++ desc->residue = 0; ++ ++ for_each_sg(sgl, sg, sg_len, i) { ++ if (direction == DMA_MEM_TO_DEV) ++ desc->sg[i].src_addr = sg_dma_address(sg); ++ else if (direction == DMA_DEV_TO_MEM) ++ desc->sg[i].dst_addr = sg_dma_address(sg); ++ else { ++ dev_err(c->device->dev, "direction type %d error\n", ++ direction); ++ goto free_desc; ++ } ++ ++ if (unlikely(sg_dma_len(sg) > GDMA_REG_CTRL0_TX_MASK)) { ++ dev_err(c->device->dev, "sg len too large %d\n", ++ sg_dma_len(sg)); ++ goto free_desc; ++ } ++ desc->sg[i].len = sg_dma_len(sg); ++ desc->residue += sg_dma_len(sg); ++ } ++ ++ desc->num_sgs = sg_len; ++ desc->direction = direction; ++ desc->cyclic = false; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++ ++free_desc: ++ kfree(desc); ++ return NULL; ++} ++ ++static struct dma_async_tx_descriptor * gdma_dma_prep_dma_memcpy( ++ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ unsigned int num_periods, i; ++ size_t xfer_count; ++ ++ if (len <= 0) ++ return NULL; ++ ++ chan->burst_size = gdma_dma_maxburst(len >> 2); ++ ++ xfer_count = GDMA_REG_CTRL0_TX_MASK; ++ num_periods = DIV_ROUND_UP(len, xfer_count); ++ ++ desc = gdma_dma_alloc_desc(num_periods); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc memcpy decs error\n"); ++ return NULL; ++ } ++ desc->residue = len; ++ ++ for (i = 0; i < num_periods; i++) { ++ desc->sg[i].src_addr = src; ++ desc->sg[i].dst_addr = dest; ++ if (len > xfer_count) { ++ desc->sg[i].len = xfer_count; ++ } else { ++ desc->sg[i].len = len; ++ } ++ src += desc->sg[i].len; ++ dest += desc->sg[i].len; ++ len -= desc->sg[i].len; ++ } ++ ++ desc->num_sgs = num_periods; ++ desc->direction = DMA_MEM_TO_MEM; ++ desc->cyclic = false; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( ++ struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, ++ unsigned long flags) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ unsigned int num_periods, i; ++ ++ if (buf_len % period_len) ++ return NULL; ++ ++ if (period_len > GDMA_REG_CTRL0_TX_MASK) { ++ dev_err(c->device->dev, "cyclic len too large %d\n", ++ period_len); ++ return NULL; ++ } ++ ++ num_periods = buf_len / period_len; ++ desc = gdma_dma_alloc_desc(num_periods); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc cyclic decs error\n"); ++ return NULL; ++ } ++ desc->residue = buf_len; ++ ++ for (i = 0; i < num_periods; i++) { ++ if (direction == DMA_MEM_TO_DEV) ++ desc->sg[i].src_addr = buf_addr; ++ else if (direction == DMA_DEV_TO_MEM) ++ desc->sg[i].dst_addr = buf_addr; ++ else { ++ dev_err(c->device->dev, "direction type %d error\n", ++ direction); ++ goto free_desc; ++ } ++ desc->sg[i].len = period_len; ++ buf_addr += period_len; ++ } ++ ++ desc->num_sgs = num_periods; ++ desc->direction = direction; ++ desc->cyclic = true; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++ ++free_desc: ++ kfree(desc); ++ return NULL; ++} ++ ++static enum dma_status gdma_dma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct virt_dma_desc *vdesc; ++ enum dma_status status; ++ unsigned long flags; ++ struct gdma_dma_desc *desc; ++ ++ status = dma_cookie_status(c, cookie, state); ++ if (status == DMA_COMPLETE || !state) ++ return status; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ desc = chan->desc; ++ if (desc && (cookie == desc->vdesc.tx.cookie)) { ++ /* ++ * We never update edesc->residue in the cyclic case, so we ++ * can tell the remaining room to the end of the circular ++ * buffer. ++ */ ++ if (desc->cyclic) ++ state->residue = desc->residue - ++ ((chan->next_sg - 1) * desc->sg[0].len); ++ else ++ state->residue = desc->residue; ++ } else if ((vdesc = vchan_find_desc(&chan->vchan, cookie))) ++ state->residue = to_gdma_dma_desc(vdesc)->residue; ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ dev_dbg(c->device->dev, "tx residue %d bytes\n", state->residue); ++ ++ return status; ++} ++ ++static void gdma_dma_free_chan_resources(struct dma_chan *c) ++{ ++ vchan_free_chan_resources(to_virt_chan(c)); ++} ++ ++static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) ++{ ++ kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); ++} ++ ++static void gdma_dma_tasklet(unsigned long arg) ++{ ++ struct gdma_dma_dev *dma_dev = (struct gdma_dma_dev *)arg; ++ struct gdma_dmaengine_chan *chan; ++ static unsigned int last_chan; ++ unsigned int i, chan_mask; ++ ++ /* record last chan to round robin all chans */ ++ i = last_chan; ++ chan_mask = dma_dev->data->chancnt - 1; ++ do { ++ /* ++ * on mt7621. when verify with dmatest with all ++ * channel is enable. we need to limit only two ++ * channel is working at the same time. otherwise the ++ * data will have problem. ++ */ ++ if (atomic_read(&dma_dev->cnt) >= 2) { ++ last_chan = i; ++ break; ++ } ++ ++ if (test_and_clear_bit(i, &dma_dev->chan_issued)) { ++ chan = &dma_dev->chan[i]; ++ if (chan->desc) { ++ atomic_inc(&dma_dev->cnt); ++ gdma_start_transfer(dma_dev, chan); ++ } else ++ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", chan->id); ++ ++ if (!dma_dev->chan_issued) ++ break; ++ } ++ ++ i = (i + 1) & chan_mask; ++ } while (i != last_chan); ++} ++ ++static void rt305x_gdma_init(struct gdma_dma_dev *dma_dev) ++{ ++ uint32_t gct; ++ ++ /* all chans round robin */ ++ gdma_dma_write(dma_dev, GDMA_RT305X_GCT, GDMA_REG_GCT_ARBIT_RR); ++ ++ gct = gdma_dma_read(dma_dev, GDMA_RT305X_GCT); ++ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", ++ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, ++ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & ++ GDMA_REG_GCT_CHAN_MASK)); ++} ++ ++static void rt3883_gdma_init(struct gdma_dma_dev *dma_dev) ++{ ++ uint32_t gct; ++ ++ /* all chans round robin */ ++ gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); ++ ++ gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); ++ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", ++ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, ++ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & ++ GDMA_REG_GCT_CHAN_MASK)); ++} ++ ++static struct gdma_data rt305x_gdma_data = { ++ .chancnt = 8, ++ .done_int_reg = GDMA_RT305X_STATUS_INT, ++ .init = rt305x_gdma_init, ++ .start_transfer = rt305x_gdma_start_transfer, ++}; ++ ++static struct gdma_data rt3883_gdma_data = { ++ .chancnt = 16, ++ .done_int_reg = GDMA_REG_DONE_INT, ++ .init = rt3883_gdma_init, ++ .start_transfer = rt3883_gdma_start_transfer, ++}; ++ ++static const struct of_device_id gdma_of_match_table[] = { ++ { .compatible = "ralink,rt305x-gdma", .data = &rt305x_gdma_data }, ++ { .compatible = "ralink,rt3883-gdma", .data = &rt3883_gdma_data }, ++ { }, ++}; ++ ++static int gdma_dma_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct gdma_dmaengine_chan *chan; ++ struct gdma_dma_dev *dma_dev; ++ struct dma_device *dd; ++ unsigned int i; ++ struct resource *res; ++ int ret; ++ int irq; ++ void __iomem *base; ++ struct gdma_data *data; ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) ++ return ret; ++ ++ match = of_match_device(gdma_of_match_table, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ data = (struct gdma_data *) match->data; ++ ++ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev) + ++ (sizeof(struct gdma_dmaengine_chan) * data->chancnt), ++ GFP_KERNEL); ++ if (!dma_dev) { ++ dev_err(&pdev->dev, "alloc dma device failed\n"); ++ return -EINVAL; ++ } ++ dma_dev->data = data; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ dma_dev->base = base; ++ tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, ++ 0, dev_name(&pdev->dev), dma_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++ ++ device_reset(&pdev->dev); ++ ++ dd = &dma_dev->ddev; ++ dma_cap_set(DMA_MEMCPY, dd->cap_mask); ++ dma_cap_set(DMA_SLAVE, dd->cap_mask); ++ dma_cap_set(DMA_CYCLIC, dd->cap_mask); ++ dd->device_free_chan_resources = gdma_dma_free_chan_resources; ++ dd->device_prep_dma_memcpy = gdma_dma_prep_dma_memcpy; ++ dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; ++ dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; ++ dd->device_config = gdma_dma_config; ++ dd->device_terminate_all = gdma_dma_terminate_all; ++ dd->device_tx_status = gdma_dma_tx_status; ++ dd->device_issue_pending = gdma_dma_issue_pending; ++ ++ dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); ++ dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); ++ dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); ++ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; ++ ++ dd->dev = &pdev->dev; ++ dd->dev->dma_parms = &dma_dev->dma_parms; ++ dma_set_max_seg_size(dd->dev, GDMA_REG_CTRL0_TX_MASK); ++ INIT_LIST_HEAD(&dd->channels); ++ ++ for (i = 0; i < data->chancnt; i++) { ++ chan = &dma_dev->chan[i]; ++ chan->id = i; ++ chan->vchan.desc_free = gdma_dma_desc_free; ++ vchan_init(&chan->vchan, dd); ++ } ++ ++ /* init hardware */ ++ data->init(dma_dev); ++ ++ ret = dma_async_device_register(dd); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register dma device\n"); ++ return ret; ++ } ++ ++ ret = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, dma_dev); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register of dma controller\n"); ++ goto err_unregister; ++ } ++ ++ platform_set_drvdata(pdev, dma_dev); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ return ret; ++} ++ ++static int gdma_dma_remove(struct platform_device *pdev) ++{ ++ struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); ++ ++ tasklet_kill(&dma_dev->task); ++ of_dma_controller_free(pdev->dev.of_node); ++ dma_async_device_unregister(&dma_dev->ddev); ++ ++ return 0; ++} ++ ++static struct platform_driver gdma_dma_driver = { ++ .probe = gdma_dma_probe, ++ .remove = gdma_dma_remove, ++ .driver = { ++ .name = "gdma-rt2880", ++ .of_match_table = gdma_of_match_table, ++ }, ++}; ++module_platform_driver(gdma_dma_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen "); ++MODULE_DESCRIPTION("Ralink/MTK DMA driver"); ++MODULE_LICENSE("GPL v2"); +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -525,6 +525,7 @@ static inline void dma_set_unmap(struct + struct dmaengine_unmap_data * + dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags); + void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap); ++struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); + #else + static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, + struct dmaengine_unmap_data *unmap) +--- /dev/null ++++ b/drivers/dma/mtk-hsdma.c +@@ -0,0 +1,767 @@ ++/* ++ * Copyright (C) 2015, Michael Lee ++ * MTK HSDMA support ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "virt-dma.h" ++ ++#define HSDMA_BASE_OFFSET 0x800 ++ ++#define HSDMA_REG_TX_BASE 0x00 ++#define HSDMA_REG_TX_CNT 0x04 ++#define HSDMA_REG_TX_CTX 0x08 ++#define HSDMA_REG_TX_DTX 0x0c ++#define HSDMA_REG_RX_BASE 0x100 ++#define HSDMA_REG_RX_CNT 0x104 ++#define HSDMA_REG_RX_CRX 0x108 ++#define HSDMA_REG_RX_DRX 0x10c ++#define HSDMA_REG_INFO 0x200 ++#define HSDMA_REG_GLO_CFG 0x204 ++#define HSDMA_REG_RST_CFG 0x208 ++#define HSDMA_REG_DELAY_INT 0x20c ++#define HSDMA_REG_FREEQ_THRES 0x210 ++#define HSDMA_REG_INT_STATUS 0x220 ++#define HSDMA_REG_INT_MASK 0x228 ++#define HSDMA_REG_SCH_Q01 0x280 ++#define HSDMA_REG_SCH_Q23 0x284 ++ ++#define HSDMA_DESCS_MAX 0xfff ++#define HSDMA_DESCS_NUM 8 ++#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1) ++#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK) ++ ++/* HSDMA_REG_INFO */ ++#define HSDMA_INFO_INDEX_MASK 0xf ++#define HSDMA_INFO_INDEX_SHIFT 24 ++#define HSDMA_INFO_BASE_MASK 0xff ++#define HSDMA_INFO_BASE_SHIFT 16 ++#define HSDMA_INFO_RX_MASK 0xff ++#define HSDMA_INFO_RX_SHIFT 8 ++#define HSDMA_INFO_TX_MASK 0xff ++#define HSDMA_INFO_TX_SHIFT 0 ++ ++/* HSDMA_REG_GLO_CFG */ ++#define HSDMA_GLO_TX_2B_OFFSET BIT(31) ++#define HSDMA_GLO_CLK_GATE BIT(30) ++#define HSDMA_GLO_BYTE_SWAP BIT(29) ++#define HSDMA_GLO_MULTI_DMA BIT(10) ++#define HSDMA_GLO_TWO_BUF BIT(9) ++#define HSDMA_GLO_32B_DESC BIT(8) ++#define HSDMA_GLO_BIG_ENDIAN BIT(7) ++#define HSDMA_GLO_TX_DONE BIT(6) ++#define HSDMA_GLO_BT_MASK 0x3 ++#define HSDMA_GLO_BT_SHIFT 4 ++#define HSDMA_GLO_RX_BUSY BIT(3) ++#define HSDMA_GLO_RX_DMA BIT(2) ++#define HSDMA_GLO_TX_BUSY BIT(1) ++#define HSDMA_GLO_TX_DMA BIT(0) ++ ++#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT) ++#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT) ++ ++#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \ ++ HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES) ++ ++/* HSDMA_REG_RST_CFG */ ++#define HSDMA_RST_RX_SHIFT 16 ++#define HSDMA_RST_TX_SHIFT 0 ++ ++/* HSDMA_REG_DELAY_INT */ ++#define HSDMA_DELAY_INT_EN BIT(15) ++#define HSDMA_DELAY_PEND_OFFSET 8 ++#define HSDMA_DELAY_TIME_OFFSET 0 ++#define HSDMA_DELAY_TX_OFFSET 16 ++#define HSDMA_DELAY_RX_OFFSET 0 ++ ++#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \ ++ ((x) << HSDMA_DELAY_PEND_OFFSET)) ++#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \ ++ HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x)) ++ ++/* HSDMA_REG_INT_STATUS */ ++#define HSDMA_INT_DELAY_RX_COH BIT(31) ++#define HSDMA_INT_DELAY_RX_INT BIT(30) ++#define HSDMA_INT_DELAY_TX_COH BIT(29) ++#define HSDMA_INT_DELAY_TX_INT BIT(28) ++#define HSDMA_INT_RX_MASK 0x3 ++#define HSDMA_INT_RX_SHIFT 16 ++#define HSDMA_INT_RX_Q0 BIT(16) ++#define HSDMA_INT_TX_MASK 0xf ++#define HSDMA_INT_TX_SHIFT 0 ++#define HSDMA_INT_TX_Q0 BIT(0) ++ ++/* tx/rx dma desc flags */ ++#define HSDMA_PLEN_MASK 0x3fff ++#define HSDMA_DESC_DONE BIT(31) ++#define HSDMA_DESC_LS0 BIT(30) ++#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16) ++#define HSDMA_DESC_TAG BIT(15) ++#define HSDMA_DESC_LS1 BIT(14) ++#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK) ++ ++/* align 4 bytes */ ++#define HSDMA_ALIGN_SIZE 3 ++/* align size 128bytes */ ++#define HSDMA_MAX_PLEN 0x3f80 ++ ++struct hsdma_desc { ++ u32 addr0; ++ u32 flags; ++ u32 addr1; ++ u32 unused; ++}; ++ ++struct mtk_hsdma_sg { ++ dma_addr_t src_addr; ++ dma_addr_t dst_addr; ++ u32 len; ++}; ++ ++struct mtk_hsdma_desc { ++ struct virt_dma_desc vdesc; ++ unsigned int num_sgs; ++ struct mtk_hsdma_sg sg[1]; ++}; ++ ++struct mtk_hsdma_chan { ++ struct virt_dma_chan vchan; ++ unsigned int id; ++ dma_addr_t desc_addr; ++ int tx_idx; ++ int rx_idx; ++ struct hsdma_desc *tx_ring; ++ struct hsdma_desc *rx_ring; ++ struct mtk_hsdma_desc *desc; ++ unsigned int next_sg; ++}; ++ ++struct mtk_hsdam_engine { ++ struct dma_device ddev; ++ struct device_dma_parameters dma_parms; ++ void __iomem *base; ++ struct tasklet_struct task; ++ volatile unsigned long chan_issued; ++ ++ struct mtk_hsdma_chan chan[1]; ++}; ++ ++static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev( ++ struct mtk_hsdma_chan *chan) ++{ ++ return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine, ++ ddev); ++} ++ ++static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c) ++{ ++ return container_of(c, struct mtk_hsdma_chan, vchan.chan); ++} ++ ++static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc( ++ struct virt_dma_desc *vdesc) ++{ ++ return container_of(vdesc, struct mtk_hsdma_desc, vdesc); ++} ++ ++static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg) ++{ ++ return readl(hsdma->base + reg); ++} ++ ++static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma, ++ unsigned reg, u32 val) ++{ ++ writel(val, hsdma->base + reg); ++} ++ ++static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ chan->tx_idx = 0; ++ chan->rx_idx = HSDMA_DESCS_NUM - 1; ++ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); ++ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, ++ 0x1 << (chan->id + HSDMA_RST_TX_SHIFT)); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, ++ 0x1 << (chan->id + HSDMA_RST_RX_SHIFT)); ++} ++ ++static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma) ++{ ++ dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \ ++ "tctx %08x, tdtx: %08x, rbase %08x, " \ ++ "rcnt %08x, rctx %08x, rdtx %08x\n", ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX), ++ mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX)); ++ ++ dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \ ++ "intr_stat %08x, intr_mask %08x\n", ++ mtk_hsdma_read(hsdma, HSDMA_REG_INFO), ++ mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG), ++ mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT), ++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS), ++ mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK)); ++} ++ ++static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ struct hsdma_desc *tx_desc; ++ struct hsdma_desc *rx_desc; ++ int i; ++ ++ dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n", ++ chan->tx_idx, chan->rx_idx); ++ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ tx_desc = &chan->tx_ring[i]; ++ rx_desc = &chan->rx_ring[i]; ++ ++ dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \ ++ "tx addr1: %08x, rx addr0 %08x, flags %08x\n", ++ i, tx_desc->addr0, tx_desc->flags, \ ++ tx_desc->addr1, rx_desc->addr0, rx_desc->flags); ++ } ++} ++ ++static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ int i; ++ ++ /* disable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); ++ ++ /* disable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); ++ ++ /* init desc value */ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ chan->tx_ring[i].addr0 = 0; ++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | ++ HSDMA_DESC_DONE; ++ } ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) { ++ chan->rx_ring[i].addr0 = 0; ++ chan->rx_ring[i].flags = 0; ++ } ++ ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++ ++ /* enable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); ++ ++ /* enable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); ++} ++ ++static int mtk_hsdma_terminate_all(struct dma_chan *c) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); ++ unsigned long timeout; ++ LIST_HEAD(head); ++ ++ spin_lock_bh(&chan->vchan.lock); ++ chan->desc = NULL; ++ clear_bit(chan->id, &hsdma->chan_issued); ++ vchan_get_all_descriptors(&chan->vchan, &head); ++ spin_unlock_bh(&chan->vchan.lock); ++ ++ vchan_dma_desc_free_list(&chan->vchan, &head); ++ ++ /* wait dma transfer complete */ ++ timeout = jiffies + msecs_to_jiffies(2000); ++ while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) & ++ (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) { ++ if (time_after_eq(jiffies, timeout)) { ++ hsdma_dump_desc(hsdma, chan); ++ mtk_hsdma_reset(hsdma, chan); ++ dev_err(hsdma->ddev.dev, "timeout, reset it\n"); ++ break; ++ } ++ cpu_relax(); ++ } ++ ++ return 0; ++} ++ ++static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ dma_addr_t src, dst; ++ size_t len, tlen; ++ struct hsdma_desc *tx_desc, *rx_desc; ++ struct mtk_hsdma_sg *sg; ++ unsigned int i; ++ int rx_idx; ++ ++ sg = &chan->desc->sg[0]; ++ len = sg->len; ++ chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN); ++ ++ /* tx desc */ ++ src = sg->src_addr; ++ for (i = 0; i < chan->desc->num_sgs; i++) { ++ if (len > HSDMA_MAX_PLEN) ++ tlen = HSDMA_MAX_PLEN; ++ else ++ tlen = len; ++ ++ if (i & 0x1) { ++ tx_desc->addr1 = src; ++ tx_desc->flags |= HSDMA_DESC_PLEN1(tlen); ++ } else { ++ tx_desc = &chan->tx_ring[chan->tx_idx]; ++ tx_desc->addr0 = src; ++ tx_desc->flags = HSDMA_DESC_PLEN0(tlen); ++ ++ /* update index */ ++ chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx); ++ } ++ ++ src += tlen; ++ len -= tlen; ++ } ++ if (i & 0x1) ++ tx_desc->flags |= HSDMA_DESC_LS0; ++ else ++ tx_desc->flags |= HSDMA_DESC_LS1; ++ ++ /* rx desc */ ++ rx_idx = HSDMA_NEXT_DESC(chan->rx_idx); ++ len = sg->len; ++ dst = sg->dst_addr; ++ for (i = 0; i < chan->desc->num_sgs; i++) { ++ rx_desc = &chan->rx_ring[rx_idx]; ++ if (len > HSDMA_MAX_PLEN) ++ tlen = HSDMA_MAX_PLEN; ++ else ++ tlen = len; ++ ++ rx_desc->addr0 = dst; ++ rx_desc->flags = HSDMA_DESC_PLEN0(tlen); ++ ++ dst += tlen; ++ len -= tlen; ++ ++ /* update index */ ++ rx_idx = HSDMA_NEXT_DESC(rx_idx); ++ } ++ ++ /* make sure desc and index all up to date */ ++ wmb(); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); ++ ++ return 0; ++} ++ ++static int gdma_next_desc(struct mtk_hsdma_chan *chan) ++{ ++ struct virt_dma_desc *vdesc; ++ ++ vdesc = vchan_next_desc(&chan->vchan); ++ if (!vdesc) { ++ chan->desc = NULL; ++ return 0; ++ } ++ chan->desc = to_mtk_hsdma_desc(vdesc); ++ chan->next_sg = 0; ++ ++ return 1; ++} ++ ++static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ struct mtk_hsdma_desc *desc; ++ int chan_issued; ++ ++ chan_issued = 0; ++ spin_lock_bh(&chan->vchan.lock); ++ desc = chan->desc; ++ if (likely(desc)) { ++ if (chan->next_sg == desc->num_sgs) { ++ list_del(&desc->vdesc.node); ++ vchan_cookie_complete(&desc->vdesc); ++ chan_issued = gdma_next_desc(chan); ++ } ++ } else ++ dev_dbg(hsdma->ddev.dev, "no desc to complete\n"); ++ ++ if (chan_issued) ++ set_bit(chan->id, &hsdma->chan_issued); ++ spin_unlock_bh(&chan->vchan.lock); ++} ++ ++static irqreturn_t mtk_hsdma_irq(int irq, void *devid) ++{ ++ struct mtk_hsdam_engine *hsdma = devid; ++ u32 status; ++ ++ status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS); ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ if (likely(status & HSDMA_INT_RX_Q0)) ++ tasklet_schedule(&hsdma->task); ++ else ++ dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", ++ status); ++ /* clean intr bits */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status); ++ ++ return IRQ_HANDLED; ++} ++ ++static void mtk_hsdma_issue_pending(struct dma_chan *c) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); ++ ++ spin_lock_bh(&chan->vchan.lock); ++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { ++ if (gdma_next_desc(chan)) { ++ set_bit(chan->id, &hsdma->chan_issued); ++ tasklet_schedule(&hsdma->task); ++ } else ++ dev_dbg(hsdma->ddev.dev, "no desc to issue\n"); ++ } ++ spin_unlock_bh(&chan->vchan.lock); ++} ++ ++static struct dma_async_tx_descriptor * mtk_hsdma_prep_dma_memcpy( ++ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, ++ size_t len, unsigned long flags) ++{ ++ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); ++ struct mtk_hsdma_desc *desc; ++ ++ if (len <= 0) ++ return NULL; ++ ++ desc = kzalloc(sizeof(struct mtk_hsdma_desc), GFP_ATOMIC); ++ if (!desc) { ++ dev_err(c->device->dev, "alloc memcpy decs error\n"); ++ return NULL; ++ } ++ ++ desc->sg[0].src_addr = src; ++ desc->sg[0].dst_addr = dest; ++ desc->sg[0].len = len; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ return dma_cookie_status(c, cookie, state); ++} ++ ++static void mtk_hsdma_free_chan_resources(struct dma_chan *c) ++{ ++ vchan_free_chan_resources(to_virt_chan(c)); ++} ++ ++static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc) ++{ ++ kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc)); ++} ++ ++static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ ++ if (test_and_clear_bit(0, &hsdma->chan_issued)) { ++ chan = &hsdma->chan[0]; ++ if (chan->desc) { ++ mtk_hsdma_start_transfer(hsdma, chan); ++ } else ++ dev_dbg(hsdma->ddev.dev,"chan 0 no desc to issue\n"); ++ } ++} ++ ++static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ int next_idx, drx_idx, cnt; ++ ++ chan = &hsdma->chan[0]; ++ next_idx = HSDMA_NEXT_DESC(chan->rx_idx); ++ drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX); ++ ++ cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK; ++ if (!cnt) ++ return; ++ ++ chan->next_sg += cnt; ++ chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK; ++ ++ /* update rx crx */ ++ wmb(); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); ++ ++ mtk_hsdma_chan_done(hsdma, chan); ++} ++ ++static void mtk_hsdma_tasklet(unsigned long arg) ++{ ++ struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg; ++ ++ mtk_hsdma_rx(hsdma); ++ mtk_hsdma_tx(hsdma); ++} ++ ++static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ int i; ++ ++ chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev, ++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), ++ &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO); ++ if (!chan->tx_ring) ++ goto no_mem; ++ ++ chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM]; ++ ++ /* init tx ring value */ ++ for (i = 0; i < HSDMA_DESCS_NUM; i++) ++ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; ++ ++ return 0; ++no_mem: ++ return -ENOMEM; ++} ++ ++static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma, ++ struct mtk_hsdma_chan *chan) ++{ ++ if (chan->tx_ring) { ++ dma_free_coherent(hsdma->ddev.dev, ++ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), ++ chan->tx_ring, chan->desc_addr); ++ chan->tx_ring = NULL; ++ chan->rx_ring = NULL; ++ } ++} ++ ++static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ int ret; ++ u32 reg; ++ ++ /* init desc */ ++ chan = &hsdma->chan[0]; ++ ret = mtk_hsdam_alloc_desc(hsdma, chan); ++ if (ret) ++ return ret; ++ ++ /* tx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM); ++ /* rx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr + ++ (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM)); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM); ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++ ++ /* enable rx intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); ++ ++ /* enable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); ++ ++ /* hardware info */ ++ reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO); ++ dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n", ++ (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK, ++ (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK); ++ ++ hsdma_dump_reg(hsdma); ++ ++ return ret; ++} ++ ++static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma) ++{ ++ struct mtk_hsdma_chan *chan; ++ ++ /* disable dma */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); ++ ++ /* disable intr */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); ++ ++ /* free desc */ ++ chan = &hsdma->chan[0]; ++ mtk_hsdam_free_desc(hsdma, chan); ++ ++ /* tx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0); ++ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0); ++ /* rx */ ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0); ++ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0); ++ /* reset */ ++ mtk_hsdma_reset_chan(hsdma, chan); ++} ++ ++static const struct of_device_id mtk_hsdma_of_match[] = { ++ { .compatible = "mediatek,mt7621-hsdma" }, ++ { }, ++}; ++ ++static int mtk_hsdma_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct mtk_hsdma_chan *chan; ++ struct mtk_hsdam_engine *hsdma; ++ struct dma_device *dd; ++ struct resource *res; ++ int ret; ++ int irq; ++ void __iomem *base; ++ ++ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); ++ if (ret) ++ return ret; ++ ++ match = of_match_device(mtk_hsdma_of_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ++ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); ++ if (!hsdma) { ++ dev_err(&pdev->dev, "alloc dma device failed\n"); ++ return -EINVAL; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ hsdma->base = base + HSDMA_BASE_OFFSET; ++ tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, ++ 0, dev_name(&pdev->dev), hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++ ++ device_reset(&pdev->dev); ++ ++ dd = &hsdma->ddev; ++ dma_cap_set(DMA_MEMCPY, dd->cap_mask); ++ dd->copy_align = HSDMA_ALIGN_SIZE; ++ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; ++ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; ++ dd->device_terminate_all = mtk_hsdma_terminate_all; ++ dd->device_tx_status = mtk_hsdma_tx_status; ++ dd->device_issue_pending = mtk_hsdma_issue_pending; ++ dd->dev = &pdev->dev; ++ dd->dev->dma_parms = &hsdma->dma_parms; ++ dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN); ++ INIT_LIST_HEAD(&dd->channels); ++ ++ chan = &hsdma->chan[0]; ++ chan->id = 0; ++ chan->vchan.desc_free = mtk_hsdma_desc_free; ++ vchan_init(&chan->vchan, dd); ++ ++ /* init hardware */ ++ ret = mtk_hsdma_init(hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to alloc ring descs\n"); ++ return ret; ++ } ++ ++ ret = dma_async_device_register(dd); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register dma device\n"); ++ return ret; ++ } ++ ++ ret = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, hsdma); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to register of dma controller\n"); ++ goto err_unregister; ++ } ++ ++ platform_set_drvdata(pdev, hsdma); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ return ret; ++} ++ ++static int mtk_hsdma_remove(struct platform_device *pdev) ++{ ++ struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev); ++ ++ mtk_hsdma_uninit(hsdma); ++ ++ of_dma_controller_free(pdev->dev.of_node); ++ dma_async_device_unregister(&hsdma->ddev); ++ ++ return 0; ++} ++ ++static struct platform_driver mtk_hsdma_driver = { ++ .probe = mtk_hsdma_probe, ++ .remove = mtk_hsdma_remove, ++ .driver = { ++ .name = "hsdma-mt7621", ++ .of_match_table = mtk_hsdma_of_match, ++ }, ++}; ++module_platform_driver(mtk_hsdma_driver); ++ ++MODULE_AUTHOR("Michael Lee "); ++MODULE_DESCRIPTION("MTK HSDMA driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch new file mode 100644 index 0000000000..1834e88538 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch @@ -0,0 +1,1046 @@ +From 7f29222b1731e8182ba94a331531dec18865a1e4 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sun, 27 Jul 2014 09:31:47 +0100 +Subject: [PATCH 48/53] asoc: add mt7620 support + +Signed-off-by: John Crispin +--- + arch/mips/ralink/of.c | 2 + + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/ralink/Kconfig | 15 ++ + sound/soc/ralink/Makefile | 11 + + sound/soc/ralink/mt7620-i2s.c | 436 ++++++++++++++++++++++++++++++++++++++ + sound/soc/ralink/mt7620-wm8960.c | 233 ++++++++++++++++++++ + 7 files changed, 699 insertions(+) + create mode 100644 sound/soc/ralink/Kconfig + create mode 100644 sound/soc/ralink/Makefile + create mode 100644 sound/soc/ralink/mt7620-i2s.c + create mode 100644 sound/soc/ralink/mt7620-wm8960.c + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -26,6 +27,7 @@ + #include "common.h" + + __iomem void *rt_sysc_membase; ++EXPORT_SYMBOL(rt_sysc_membase); + __iomem void *rt_memc_membase; + + __iomem void *plat_of_remap_node(const char *node) +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -59,6 +59,7 @@ source "sound/soc/mxs/Kconfig" + source "sound/soc/pxa/Kconfig" + source "sound/soc/qcom/Kconfig" + source "sound/soc/rockchip/Kconfig" ++source "sound/soc/ralink/Kconfig" + source "sound/soc/samsung/Kconfig" + source "sound/soc/sh/Kconfig" + source "sound/soc/sirf/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -40,6 +40,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ + obj-$(CONFIG_SND_SOC) += pxa/ + obj-$(CONFIG_SND_SOC) += qcom/ + obj-$(CONFIG_SND_SOC) += rockchip/ ++obj-$(CONFIG_SND_SOC) += ralink/ + obj-$(CONFIG_SND_SOC) += samsung/ + obj-$(CONFIG_SND_SOC) += sh/ + obj-$(CONFIG_SND_SOC) += sirf/ +--- /dev/null ++++ b/sound/soc/ralink/Kconfig +@@ -0,0 +1,8 @@ ++config SND_RALINK_SOC_I2S ++ depends on RALINK && SND_SOC && !SOC_RT288X ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ select REGMAP_MMIO ++ tristate "SoC Audio (I2S protocol) for Ralink SoC" ++ help ++ Say Y if you want to use I2S protocol and I2S codec on Ralink/MediaTek ++ based boards. +--- /dev/null ++++ b/sound/soc/ralink/Makefile +@@ -0,0 +1,6 @@ ++# ++# Ralink/MediaTek Platform Support ++# ++snd-soc-ralink-i2s-objs := ralink-i2s.o ++ ++obj-$(CONFIG_SND_RALINK_SOC_I2S) += snd-soc-ralink-i2s.o +--- /dev/null ++++ b/sound/soc/ralink/ralink-i2s.c +@@ -0,0 +1,965 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen ++ * Copyright (C) 2016 Michael Lee ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define DRV_NAME "ralink-i2s" ++ ++#define I2S_REG_CFG0 0x00 ++#define I2S_REG_INT_STATUS 0x04 ++#define I2S_REG_INT_EN 0x08 ++#define I2S_REG_FF_STATUS 0x0c ++#define I2S_REG_WREG 0x10 ++#define I2S_REG_RREG 0x14 ++#define I2S_REG_CFG1 0x18 ++#define I2S_REG_DIVCMP 0x20 ++#define I2S_REG_DIVINT 0x24 ++ ++/* I2S_REG_CFG0 */ ++#define I2S_REG_CFG0_EN BIT(31) ++#define I2S_REG_CFG0_DMA_EN BIT(30) ++#define I2S_REG_CFG0_BYTE_SWAP BIT(28) ++#define I2S_REG_CFG0_TX_EN BIT(24) ++#define I2S_REG_CFG0_RX_EN BIT(20) ++#define I2S_REG_CFG0_SLAVE BIT(16) ++#define I2S_REG_CFG0_RX_THRES 12 ++#define I2S_REG_CFG0_TX_THRES 4 ++#define I2S_REG_CFG0_THRES_MASK (0xf << I2S_REG_CFG0_RX_THRES) | \ ++ (4 << I2S_REG_CFG0_TX_THRES) ++#define I2S_REG_CFG0_DFT_THRES (4 << I2S_REG_CFG0_RX_THRES) | \ ++ (4 << I2S_REG_CFG0_TX_THRES) ++/* RT305x */ ++#define I2S_REG_CFG0_CLK_DIS BIT(8) ++#define I2S_REG_CFG0_TXCH_SWAP BIT(3) ++#define I2S_REG_CFG0_TXCH1_OFF BIT(2) ++#define I2S_REG_CFG0_TXCH0_OFF BIT(1) ++#define I2S_REG_CFG0_SLAVE_EN BIT(0) ++/* RT3883 */ ++#define I2S_REG_CFG0_RXCH_SWAP BIT(11) ++#define I2S_REG_CFG0_RXCH1_OFF BIT(10) ++#define I2S_REG_CFG0_RXCH0_OFF BIT(9) ++#define I2S_REG_CFG0_WS_INV BIT(0) ++/* MT7628 */ ++#define I2S_REG_CFG0_FMT_LE BIT(29) ++#define I2S_REG_CFG0_SYS_BE BIT(28) ++#define I2S_REG_CFG0_NORM_24 BIT(18) ++#define I2S_REG_CFG0_DATA_24 BIT(17) ++ ++/* I2S_REG_INT_STATUS */ ++#define I2S_REG_INT_RX_FAULT BIT(7) ++#define I2S_REG_INT_RX_OVRUN BIT(6) ++#define I2S_REG_INT_RX_UNRUN BIT(5) ++#define I2S_REG_INT_RX_THRES BIT(4) ++#define I2S_REG_INT_TX_FAULT BIT(3) ++#define I2S_REG_INT_TX_OVRUN BIT(2) ++#define I2S_REG_INT_TX_UNRUN BIT(1) ++#define I2S_REG_INT_TX_THRES BIT(0) ++#define I2S_REG_INT_TX_MASK 0xf ++#define I2S_REG_INT_RX_MASK 0xf0 ++ ++/* I2S_REG_INT_STATUS */ ++#define I2S_RX_AVCNT(x) ((x >> 4) & 0xf) ++#define I2S_TX_AVCNT(x) (x & 0xf) ++/* MT7628 */ ++#define MT7628_I2S_RX_AVCNT(x) ((x >> 8) & 0x1f) ++#define MT7628_I2S_TX_AVCNT(x) (x & 0x1f) ++ ++/* I2S_REG_CFG1 */ ++#define I2S_REG_CFG1_LBK BIT(31) ++#define I2S_REG_CFG1_EXTLBK BIT(30) ++/* RT3883 */ ++#define I2S_REG_CFG1_LEFT_J BIT(0) ++#define I2S_REG_CFG1_RIGHT_J BIT(1) ++#define I2S_REG_CFG1_FMT_MASK 0x3 ++ ++/* I2S_REG_DIVCMP */ ++#define I2S_REG_DIVCMP_CLKEN BIT(31) ++#define I2S_REG_DIVCMP_DIVCOMP_MASK 0x1ff ++ ++/* I2S_REG_DIVINT */ ++#define I2S_REG_DIVINT_MASK 0x3ff ++ ++/* BCLK dividers */ ++#define RALINK_I2S_DIVCMP 0 ++#define RALINK_I2S_DIVINT 1 ++ ++/* FIFO */ ++#define RALINK_I2S_FIFO_SIZE 32 ++ ++/* feature flags */ ++#define RALINK_FLAGS_TXONLY BIT(0) ++#define RALINK_FLAGS_LEFT_J BIT(1) ++#define RALINK_FLAGS_RIGHT_J BIT(2) ++#define RALINK_FLAGS_ENDIAN BIT(3) ++#define RALINK_FLAGS_24BIT BIT(4) ++ ++#define RALINK_I2S_INT_EN 0 ++ ++struct ralink_i2s_stats { ++ u32 dmafault; ++ u32 overrun; ++ u32 underrun; ++ u32 belowthres; ++}; ++ ++struct ralink_i2s { ++ struct device *dev; ++ void __iomem *regs; ++ struct clk *clk; ++ struct regmap *regmap; ++ u32 flags; ++ unsigned int fmt; ++ u16 txdma_req; ++ u16 rxdma_req; ++ ++ struct snd_dmaengine_dai_dma_data playback_dma_data; ++ struct snd_dmaengine_dai_dma_data capture_dma_data; ++ ++ struct dentry *dbg_dir; ++ struct dentry *dbg_stats; ++ struct ralink_i2s_stats txstats; ++ struct ralink_i2s_stats rxstats; ++}; ++ ++static void ralink_i2s_dump_regs(struct ralink_i2s *i2s) ++{ ++ u32 buf[10]; ++ int ret; ++ ++ ret = regmap_bulk_read(i2s->regmap, I2S_REG_CFG0, ++ buf, ARRAY_SIZE(buf)); ++ ++ dev_dbg(i2s->dev, "CFG0: %08x, INTSTAT: %08x, INTEN: %08x, " \ ++ "FFSTAT: %08x, WREG: %08x, RREG: %08x, " \ ++ "CFG1: %08x, DIVCMP: %08x, DIVINT: %08x\n", ++ buf[0], buf[1], buf[2], buf[3], buf[4], ++ buf[5], buf[6], buf[8], buf[9]); ++} ++ ++static int ralink_i2s_set_sysclk(struct snd_soc_dai *dai, ++ int clk_id, unsigned int freq, int dir) ++{ ++ return 0; ++} ++ ++static int ralink_i2s_set_sys_bclk(struct snd_soc_dai *dai, int width, int rate) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned long clk = clk_get_rate(i2s->clk); ++ int div; ++ uint32_t data; ++ ++ /* disable clock at slave mode */ ++ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == ++ SND_SOC_DAIFMT_CBM_CFM) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_CLK_DIS, ++ I2S_REG_CFG0_CLK_DIS); ++ return 0; ++ } ++ ++ /* FREQOUT = FREQIN / (I2S_CLK_DIV + 1) */ ++ div = (clk / rate ) - 1; ++ ++ data = rt_sysc_r32(0x30); ++ data &= (0xff << 8); ++ data |= (0x1 << 15) | (div << 8); ++ rt_sysc_w32(data, 0x30); ++ ++ /* enable clock */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_CLK_DIS, 0); ++ ++ dev_dbg(i2s->dev, "clk: %lu, rate: %u, div: %d\n", ++ clk, rate, div); ++ ++ return 0; ++} ++ ++static int ralink_i2s_set_bclk(struct snd_soc_dai *dai, int width, int rate) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned long clk = clk_get_rate(i2s->clk); ++ int divint, divcomp; ++ ++ /* disable clock at slave mode */ ++ if ((i2s->fmt & SND_SOC_DAIFMT_MASTER_MASK) == ++ SND_SOC_DAIFMT_CBM_CFM) { ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, ++ I2S_REG_DIVCMP_CLKEN, 0); ++ return 0; ++ } ++ ++ /* FREQOUT = FREQIN * (1/2) * (1/(DIVINT + DIVCOMP/512)) */ ++ clk = clk / (2 * 2 * width); ++ divint = clk / rate; ++ divcomp = ((clk % rate) * 512) / rate; ++ ++ if ((divint > I2S_REG_DIVINT_MASK) || ++ (divcomp > I2S_REG_DIVCMP_DIVCOMP_MASK)) ++ return -EINVAL; ++ ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVINT, ++ I2S_REG_DIVINT_MASK, divint); ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, ++ I2S_REG_DIVCMP_DIVCOMP_MASK, divcomp); ++ ++ /* enable clock */ ++ regmap_update_bits(i2s->regmap, I2S_REG_DIVCMP, I2S_REG_DIVCMP_CLKEN, ++ I2S_REG_DIVCMP_CLKEN); ++ ++ dev_dbg(i2s->dev, "clk: %lu, rate: %u, int: %d, comp: %d\n", ++ clk_get_rate(i2s->clk), rate, divint, divcomp); ++ ++ return 0; ++} ++ ++static int ralink_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned int cfg0 = 0, cfg1 = 0; ++ ++ /* set master/slave audio interface */ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBM_CFM: ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ cfg0 |= I2S_REG_CFG0_SLAVE_EN; ++ else ++ cfg0 |= I2S_REG_CFG0_SLAVE; ++ break; ++ case SND_SOC_DAIFMT_CBS_CFS: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* interface format */ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ break; ++ case SND_SOC_DAIFMT_RIGHT_J: ++ if (i2s->flags & RALINK_FLAGS_RIGHT_J) { ++ cfg1 |= I2S_REG_CFG1_RIGHT_J; ++ break; ++ } ++ return -EINVAL; ++ case SND_SOC_DAIFMT_LEFT_J: ++ if (i2s->flags & RALINK_FLAGS_LEFT_J) { ++ cfg1 |= I2S_REG_CFG1_LEFT_J; ++ break; ++ } ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ } ++ ++ /* clock inversion */ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SLAVE_EN, cfg0); ++ } else { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SLAVE, cfg0); ++ } ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG1, ++ I2S_REG_CFG1_FMT_MASK, cfg1); ++ i2s->fmt = fmt; ++ ++ return 0; ++} ++ ++static int ralink_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ if (dai->active) ++ return 0; ++ ++ /* setup status interrupt */ ++#if (RALINK_I2S_INT_EN) ++ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0xff); ++#else ++ regmap_write(i2s->regmap, I2S_REG_INT_EN, 0x0); ++#endif ++ ++ /* enable */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | ++ I2S_REG_CFG0_THRES_MASK, ++ I2S_REG_CFG0_EN | I2S_REG_CFG0_DMA_EN | ++ I2S_REG_CFG0_DFT_THRES); ++ ++ return 0; ++} ++ ++static void ralink_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ /* If both streams are stopped, disable module and clock */ ++ if (dai->active) ++ return; ++ ++ /* ++ * datasheet mention when disable all control regs are cleared ++ * to initial values. need reinit at startup. ++ */ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, I2S_REG_CFG0_EN, 0); ++} ++ ++static int ralink_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ int width; ++ int ret; ++ ++ width = params_width(params); ++ switch (width) { ++ case 16: ++ if (i2s->flags & RALINK_FLAGS_24BIT) ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_DATA_24, 0); ++ break; ++ case 24: ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_DATA_24, ++ I2S_REG_CFG0_DATA_24); ++ break; ++ } ++ return -EINVAL; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (params_channels(params)) { ++ case 2: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (i2s->flags & RALINK_FLAGS_ENDIAN) { ++ /* system endian */ ++#ifdef SNDRV_LITTLE_ENDIAN ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SYS_BE, 0); ++#else ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_SYS_BE, ++ I2S_REG_CFG0_SYS_BE); ++#endif ++ ++ /* data endian */ ++ switch (params_format(params)) { ++ case SNDRV_PCM_FORMAT_S16_LE: ++ case SNDRV_PCM_FORMAT_S24_LE: ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_FMT_LE, ++ I2S_REG_CFG0_FMT_LE); ++ break; ++ case SNDRV_PCM_FORMAT_S16_BE: ++ case SNDRV_PCM_FORMAT_S24_BE: ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, ++ I2S_REG_CFG0_FMT_LE, 0); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ /* setup bclk rate */ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ ret = ralink_i2s_set_sys_bclk(dai, width, params_rate(params)); ++ else ++ ret = ralink_i2s_set_bclk(dai, width, params_rate(params)); ++ ++ return ret; ++} ++ ++static int ralink_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ unsigned int mask, val; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ mask = I2S_REG_CFG0_TX_EN; ++ else ++ mask = I2S_REG_CFG0_RX_EN; ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ val = mask; ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ val = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(i2s->regmap, I2S_REG_CFG0, mask, val); ++ ++ return 0; ++} ++ ++static void ralink_i2s_init_dma_data(struct ralink_i2s *i2s, ++ struct resource *res) ++{ ++ struct snd_dmaengine_dai_dma_data *dma_data; ++ ++ /* Playback */ ++ dma_data = &i2s->playback_dma_data; ++ dma_data->addr = res->start + I2S_REG_WREG; ++ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_data->maxburst = 1; ++ dma_data->slave_id = i2s->txdma_req; ++ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ return; ++ ++ /* Capture */ ++ dma_data = &i2s->capture_dma_data; ++ dma_data->addr = res->start + I2S_REG_RREG; ++ dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ++ dma_data->maxburst = 1; ++ dma_data->slave_id = i2s->rxdma_req; ++} ++ ++static int ralink_i2s_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct ralink_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, ++ &i2s->capture_dma_data); ++ ++ return 0; ++} ++ ++static int ralink_i2s_dai_remove(struct snd_soc_dai *dai) ++{ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops ralink_i2s_dai_ops = { ++ .set_sysclk = ralink_i2s_set_sysclk, ++ .set_fmt = ralink_i2s_set_fmt, ++ .startup = ralink_i2s_startup, ++ .shutdown = ralink_i2s_shutdown, ++ .hw_params = ralink_i2s_hw_params, ++ .trigger = ralink_i2s_trigger, ++}; ++ ++static struct snd_soc_dai_driver ralink_i2s_dai = { ++ .name = DRV_NAME, ++ .probe = ralink_i2s_dai_probe, ++ .remove = ralink_i2s_dai_remove, ++ .ops = &ralink_i2s_dai_ops, ++ .capture = { ++ .stream_name = "I2S Capture", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = 5512, ++ .rate_max = 192000, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .playback = { ++ .stream_name = "I2S Playback", ++ .channels_min = 2, ++ .channels_max = 2, ++ .rate_min = 5512, ++ .rate_max = 192000, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ }, ++ .symmetric_rates = 1, ++}; ++ ++static struct snd_pcm_hardware ralink_pcm_hardware = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .channels_min = 2, ++ .channels_max = 2, ++ .period_bytes_min = PAGE_SIZE, ++ .period_bytes_max = PAGE_SIZE * 2, ++ .periods_min = 2, ++ .periods_max = 128, ++ .buffer_bytes_max = 128 * 1024, ++ .fifo_size = RALINK_I2S_FIFO_SIZE, ++}; ++ ++static const struct snd_dmaengine_pcm_config ralink_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &ralink_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ ++static const struct snd_soc_component_driver ralink_i2s_component = { ++ .name = DRV_NAME, ++}; ++ ++static bool ralink_i2s_readable_reg(struct device *dev, unsigned int reg) ++{ ++ return true; ++} ++ ++static bool ralink_i2s_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case I2S_REG_INT_STATUS: ++ case I2S_REG_FF_STATUS: ++ return true; ++ } ++ return false; ++} ++ ++static bool ralink_i2s_writeable_reg(struct device *dev, unsigned int reg) ++{ ++ switch (reg) { ++ case I2S_REG_FF_STATUS: ++ case I2S_REG_RREG: ++ return false; ++ } ++ return true; ++} ++ ++static const struct regmap_config ralink_i2s_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .writeable_reg = ralink_i2s_writeable_reg, ++ .readable_reg = ralink_i2s_readable_reg, ++ .volatile_reg = ralink_i2s_volatile_reg, ++ .max_register = I2S_REG_DIVINT, ++}; ++ ++#if (RALINK_I2S_INT_EN) ++static irqreturn_t ralink_i2s_irq(int irq, void *devid) ++{ ++ struct ralink_i2s *i2s = devid; ++ u32 status; ++ ++ regmap_read(i2s->regmap, I2S_REG_INT_STATUS, &status); ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ /* tx stats */ ++ if (status & I2S_REG_INT_TX_MASK) { ++ if (status & I2S_REG_INT_TX_THRES) ++ i2s->txstats.belowthres++; ++ if (status & I2S_REG_INT_TX_UNRUN) ++ i2s->txstats.underrun++; ++ if (status & I2S_REG_INT_TX_OVRUN) ++ i2s->txstats.overrun++; ++ if (status & I2S_REG_INT_TX_FAULT) ++ i2s->txstats.dmafault++; ++ } ++ ++ /* rx stats */ ++ if (status & I2S_REG_INT_RX_MASK) { ++ if (status & I2S_REG_INT_RX_THRES) ++ i2s->rxstats.belowthres++; ++ if (status & I2S_REG_INT_RX_UNRUN) ++ i2s->rxstats.underrun++; ++ if (status & I2S_REG_INT_RX_OVRUN) ++ i2s->rxstats.overrun++; ++ if (status & I2S_REG_INT_RX_FAULT) ++ i2s->rxstats.dmafault++; ++ } ++ ++ /* clean status bits */ ++ regmap_write(i2s->regmap, I2S_REG_INT_STATUS, status); ++ ++ return IRQ_HANDLED; ++} ++#endif ++ ++#if IS_ENABLED(CONFIG_DEBUG_FS) ++static int ralink_i2s_stats_show(struct seq_file *s, void *unused) ++{ ++ struct ralink_i2s *i2s = s->private; ++ ++ seq_printf(s, "tx stats\n"); ++ seq_printf(s, "\tbelow threshold\t%u\n", i2s->txstats.belowthres); ++ seq_printf(s, "\tunder run\t%u\n", i2s->txstats.underrun); ++ seq_printf(s, "\tover run\t%u\n", i2s->txstats.overrun); ++ seq_printf(s, "\tdma fault\t%u\n", i2s->txstats.dmafault); ++ ++ seq_printf(s, "rx stats\n"); ++ seq_printf(s, "\tbelow threshold\t%u\n", i2s->rxstats.belowthres); ++ seq_printf(s, "\tunder run\t%u\n", i2s->rxstats.underrun); ++ seq_printf(s, "\tover run\t%u\n", i2s->rxstats.overrun); ++ seq_printf(s, "\tdma fault\t%u\n", i2s->rxstats.dmafault); ++ ++ ralink_i2s_dump_regs(i2s); ++ ++ return 0; ++} ++ ++static int ralink_i2s_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, ralink_i2s_stats_show, inode->i_private); ++} ++ ++static const struct file_operations ralink_i2s_stats_ops = { ++ .open = ralink_i2s_stats_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) ++{ ++ i2s->dbg_dir = debugfs_create_dir(dev_name(i2s->dev), NULL); ++ if (!i2s->dbg_dir) ++ return -ENOMEM; ++ ++ i2s->dbg_stats = debugfs_create_file("stats", S_IRUGO, ++ i2s->dbg_dir, i2s, &ralink_i2s_stats_ops); ++ if (!i2s->dbg_stats) { ++ debugfs_remove(i2s->dbg_dir); ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++static inline void ralink_i2s_debugfs_remove(struct ralink_i2s *i2s) ++{ ++ debugfs_remove(i2s->dbg_stats); ++ debugfs_remove(i2s->dbg_dir); ++} ++#else ++static inline int ralink_i2s_debugfs_create(struct ralink_i2s *i2s) ++{ ++ return 0; ++} ++ ++static inline void ralink_i2s_debugfs_remove(struct fsl_ssi_dbg *ssi_dbg) ++{ ++} ++#endif ++ ++/* ++ * TODO: these refclk setup functions should use ++ * clock framework instead. hardcode it now. ++ */ ++static void rt3350_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data |= (0x1 << 8); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void rt3883_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x3 << 13); ++ data |= (0x1 << 13); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void rt3552_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0xf << 8); ++ data |= (0x3 << 8); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7620_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x7 << 9); ++ data |= 0x1 << 9; ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7621_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x1f << 18); ++ data |= (0x19 << 18); ++ data &= ~(0x1f << 12); ++ data |= (0x1 << 12); ++ data &= ~(0x7 << 9); ++ data |= (0x5 << 9); ++ rt_sysc_w32(data, 0x2c); ++} ++ ++static void mt7628_refclk_setup(void) ++{ ++ uint32_t data; ++ ++ /* set i2s and refclk digital pad */ ++ data = rt_sysc_r32(0x3c); ++ data |= 0x1f; ++ rt_sysc_w32(data, 0x3c); ++ ++ /* Adjust REFCLK0's driving strength */ ++ data = rt_sysc_r32(0x1354); ++ data &= ~(0x1 << 5); ++ rt_sysc_w32(data, 0x1354); ++ data = rt_sysc_r32(0x1364); ++ data |= ~(0x1 << 5); ++ rt_sysc_w32(data, 0x1364); ++ ++ /* set refclk output 12Mhz clock */ ++ data = rt_sysc_r32(0x2c); ++ data &= ~(0x7 << 9); ++ data |= 0x1 << 9; ++ rt_sysc_w32(data, 0x2c); ++} ++ ++struct rt_i2s_data { ++ u32 flags; ++ void (*refclk_setup)(void); ++}; ++ ++struct rt_i2s_data rt3050_i2s_data = { .flags = RALINK_FLAGS_TXONLY }; ++struct rt_i2s_data rt3350_i2s_data = { .flags = RALINK_FLAGS_TXONLY, ++ .refclk_setup = rt3350_refclk_setup }; ++struct rt_i2s_data rt3883_i2s_data = { ++ .flags = (RALINK_FLAGS_LEFT_J | RALINK_FLAGS_RIGHT_J), ++ .refclk_setup = rt3883_refclk_setup }; ++struct rt_i2s_data rt3352_i2s_data = { .refclk_setup = rt3552_refclk_setup}; ++struct rt_i2s_data mt7620_i2s_data = { .refclk_setup = mt7620_refclk_setup}; ++struct rt_i2s_data mt7621_i2s_data = { .refclk_setup = mt7621_refclk_setup}; ++struct rt_i2s_data mt7628_i2s_data = { ++ .flags = (RALINK_FLAGS_ENDIAN | RALINK_FLAGS_24BIT | ++ RALINK_FLAGS_LEFT_J), ++ .refclk_setup = mt7628_refclk_setup}; ++ ++static const struct of_device_id ralink_i2s_match_table[] = { ++ { .compatible = "ralink,rt3050-i2s", ++ .data = (void *)&rt3050_i2s_data }, ++ { .compatible = "ralink,rt3350-i2s", ++ .data = (void *)&rt3350_i2s_data }, ++ { .compatible = "ralink,rt3883-i2s", ++ .data = (void *)&rt3883_i2s_data }, ++ { .compatible = "ralink,rt3352-i2s", ++ .data = (void *)&rt3352_i2s_data }, ++ { .compatible = "mediatek,mt7620-i2s", ++ .data = (void *)&mt7620_i2s_data }, ++ { .compatible = "mediatek,mt7621-i2s", ++ .data = (void *)&mt7621_i2s_data }, ++ { .compatible = "mediatek,mt7628-i2s", ++ .data = (void *)&mt7628_i2s_data }, ++}; ++MODULE_DEVICE_TABLE(of, ralink_i2s_match_table); ++ ++static int ralink_i2s_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct device_node *np = pdev->dev.of_node; ++ struct ralink_i2s *i2s; ++ struct resource *res; ++ int irq, ret; ++ u32 dma_req; ++ struct rt_i2s_data *data; ++ ++ i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); ++ if (!i2s) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, i2s); ++ i2s->dev = &pdev->dev; ++ ++ match = of_match_device(ralink_i2s_match_table, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ data = (struct rt_i2s_data *)match->data; ++ i2s->flags = data->flags; ++ /* setup out 12Mhz refclk to codec as mclk */ ++ if (data->refclk_setup) ++ data->refclk_setup(); ++ ++ if (of_property_read_u32(np, "txdma-req", &dma_req)) { ++ dev_err(&pdev->dev, "no txdma-req define\n"); ++ return -EINVAL; ++ } ++ i2s->txdma_req = (u16)dma_req; ++ if (!(i2s->flags & RALINK_FLAGS_TXONLY)) { ++ if (of_property_read_u32(np, "rxdma-req", &dma_req)) { ++ dev_err(&pdev->dev, "no rxdma-req define\n"); ++ return -EINVAL; ++ } ++ i2s->rxdma_req = (u16)dma_req; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ i2s->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(i2s->regs)) ++ return PTR_ERR(i2s->regs); ++ ++ i2s->regmap = devm_regmap_init_mmio(&pdev->dev, i2s->regs, ++ &ralink_i2s_regmap_config); ++ if (IS_ERR(i2s->regmap)) { ++ dev_err(&pdev->dev, "regmap init failed\n"); ++ return PTR_ERR(i2s->regmap); ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ++#if (RALINK_I2S_INT_EN) ++ ret = devm_request_irq(&pdev->dev, irq, ralink_i2s_irq, ++ 0, dev_name(&pdev->dev), i2s); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return ret; ++ } ++#endif ++ ++ i2s->clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(i2s->clk)) { ++ dev_err(&pdev->dev, "no clock defined\n"); ++ return PTR_ERR(i2s->clk); ++ } ++ ++ ret = clk_prepare_enable(i2s->clk); ++ if (ret) ++ return ret; ++ ++ ralink_i2s_init_dma_data(i2s, res); ++ ++ device_reset(&pdev->dev); ++ ++ ret = ralink_i2s_debugfs_create(i2s); ++ if (ret) { ++ dev_err(&pdev->dev, "create debugfs failed\n"); ++ goto err_clk_disable; ++ } ++ ++ /* enable 24bits support */ ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S24_LE; ++ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S24_LE; ++ } ++ ++ /* enable big endian support */ ++ if (i2s->flags & RALINK_FLAGS_ENDIAN) { ++ ralink_i2s_dai.capture.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ ralink_i2s_dai.playback.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ ralink_pcm_hardware.formats |= SNDRV_PCM_FMTBIT_S16_BE; ++ if (i2s->flags & RALINK_FLAGS_24BIT) { ++ ralink_i2s_dai.capture.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ ralink_i2s_dai.playback.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ ralink_pcm_hardware.formats |= ++ SNDRV_PCM_FMTBIT_S24_BE; ++ } ++ } ++ ++ /* disable capture support */ ++ if (i2s->flags & RALINK_FLAGS_TXONLY) ++ memset(&ralink_i2s_dai.capture, sizeof(ralink_i2s_dai.capture), ++ 0); ++ ++ ret = devm_snd_soc_register_component(&pdev->dev, &ralink_i2s_component, ++ &ralink_i2s_dai, 1); ++ if (ret) ++ goto err_debugfs; ++ ++ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, ++ &ralink_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ if (ret) ++ goto err_debugfs; ++ ++ dev_info(i2s->dev, "mclk %luMHz\n", clk_get_rate(i2s->clk) / 1000000); ++ ++ return 0; ++ ++err_debugfs: ++ ralink_i2s_debugfs_remove(i2s); ++ ++err_clk_disable: ++ clk_disable_unprepare(i2s->clk); ++ ++ return ret; ++} ++ ++static int ralink_i2s_remove(struct platform_device *pdev) ++{ ++ struct ralink_i2s *i2s = platform_get_drvdata(pdev); ++ ++ ralink_i2s_debugfs_remove(i2s); ++ clk_disable_unprepare(i2s->clk); ++ ++ return 0; ++} ++ ++static struct platform_driver ralink_i2s_driver = { ++ .probe = ralink_i2s_probe, ++ .remove = ralink_i2s_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .of_match_table = ralink_i2s_match_table, ++ }, ++}; ++module_platform_driver(ralink_i2s_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen, "); ++MODULE_DESCRIPTION("Ralink/MediaTek I2S driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:" DRV_NAME); diff --git a/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch b/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch new file mode 100644 index 0000000000..2ad1f6f9f8 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch @@ -0,0 +1,22 @@ +From a7eb46e0ea4a11e4dfb56ab129bf816d1059a6c5 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:31:08 +0100 +Subject: [PATCH 51/53] serial: add ugly custom baud rate hack + +Signed-off-by: John Crispin +--- + drivers/tty/serial/serial_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -428,6 +428,9 @@ uart_get_baud_rate(struct uart_port *por + break; + } + ++ if (tty_termios_baud_rate(termios) == 2500000) ++ return 250000; ++ + for (try = 0; try < 2; try++) { + baud = tty_termios_baud_rate(termios); + diff --git a/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch b/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch new file mode 100644 index 0000000000..6eb7f16b9d --- /dev/null +++ b/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch @@ -0,0 +1,217 @@ +From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 7 Dec 2015 17:16:50 +0100 +Subject: [PATCH 52/53] pwm: add mediatek support + +Signed-off-by: John Crispin +--- + drivers/pwm/Kconfig | 9 +++ + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-mediatek.c | 173 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 183 insertions(+) + create mode 100644 drivers/pwm/pwm-mediatek.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -302,6 +302,15 @@ config PWM_MEDIATEK + To compile this driver as a module, choose M here: the module + will be called pwm-mediatek. + ++config PWM_MEDIATEK_RAMIPS ++ tristate "Mediatek PWM support" ++ depends on RALINK && OF ++ help ++ Generic PWM framework driver for Mediatek ARM SoC. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-mxs. ++ + config PWM_MXS + tristate "Freescale MXS PWM support" + depends on ARCH_MXS && OF +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p + obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o + obj-$(CONFIG_PWM_MESON) += pwm-meson.o + obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o ++obj-$(CONFIG_PWM_MEDIATEK_RAMIPS) += pwm-mediatek-ramips.o + obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o + obj-$(CONFIG_PWM_MXS) += pwm-mxs.o + obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o +--- /dev/null ++++ b/drivers/pwm/pwm-mediatek-ramips.c +@@ -0,0 +1,173 @@ ++/* ++ * Mediatek Pulse Width Modulator driver ++ * ++ * Copyright (C) 2015 John Crispin ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NUM_PWM 4 ++ ++/* PWM registers and bits definitions */ ++#define PWMCON 0x00 ++#define PWMHDUR 0x04 ++#define PWMLDUR 0x08 ++#define PWMGDUR 0x0c ++#define PWMWAVENUM 0x28 ++#define PWMDWIDTH 0x2c ++#define PWMTHRES 0x30 ++ ++/** ++ * struct mtk_pwm_chip - struct representing pwm chip ++ * ++ * @mmio_base: base address of pwm chip ++ * @chip: linux pwm chip representation ++ */ ++struct mtk_pwm_chip { ++ void __iomem *mmio_base; ++ struct pwm_chip chip; ++}; ++ ++static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct mtk_pwm_chip, chip); ++} ++ ++static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, ++ unsigned long offset) ++{ ++ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, ++ unsigned int num, unsigned long offset, ++ unsigned long val) ++{ ++ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 resolution = 100 / 4; ++ u32 clkdiv = 0; ++ ++ while (period_ns / resolution > 8191) { ++ clkdiv++; ++ resolution *= 2; ++ } ++ ++ if (clkdiv > 7) ++ return -1; ++ ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); ++ return 0; ++} ++ ++static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val |= BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++ ++ return 0; ++} ++ ++static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val &= ~BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++} ++ ++static const struct pwm_ops mtk_pwm_ops = { ++ .config = mtk_pwm_config, ++ .enable = mtk_pwm_enable, ++ .disable = mtk_pwm_disable, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_pwm_probe(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc; ++ struct resource *r; ++ int ret; ++ ++ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(pc->mmio_base)) ++ return PTR_ERR(pc->mmio_base); ++ ++ platform_set_drvdata(pdev, pc); ++ ++ pc->chip.dev = &pdev->dev; ++ pc->chip.ops = &mtk_pwm_ops; ++ pc->chip.base = -1; ++ pc->chip.npwm = NUM_PWM; ++ ++ ret = pwmchip_add(&pc->chip); ++ if (ret < 0) ++ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int mtk_pwm_remove(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < NUM_PWM; i++) ++ pwm_disable(&pc->chip.pwms[i]); ++ ++ return pwmchip_remove(&pc->chip); ++} ++ ++static const struct of_device_id mtk_pwm_of_match[] = { ++ { .compatible = "mediatek,mt7628-pwm" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); ++ ++static struct platform_driver mtk_pwm_driver = { ++ .driver = { ++ .name = "mtk-pwm", ++ .owner = THIS_MODULE, ++ .of_match_table = mtk_pwm_of_match, ++ }, ++ .probe = mtk_pwm_probe, ++ .remove = mtk_pwm_remove, ++}; ++ ++module_platform_driver(mtk_pwm_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("John Crispin "); ++MODULE_ALIAS("platform:mtk-pwm"); diff --git a/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch new file mode 100644 index 0000000000..aa2fb60a2b --- /dev/null +++ b/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch @@ -0,0 +1,214 @@ +mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash + +On some devices the flash chip needs to be in 3-byte addressing mode during +reboot, otherwise the boot loader will fail to start. +This mode however does not allow regular reads/writes onto the upper 16M +half. W25Q256 has separate read commands for reading from >16M, however +it does not have any separate write commands. +This patch changes the code to leave the chip in 3-byte mode most of the +time and only switch during erase/write cycles that go to >16M +addresses. + +Signed-off-by: Felix Fietkau +--- +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -89,6 +89,10 @@ struct flash_info { + #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ + #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ + #define USE_CLSR BIT(14) /* use CLSR command */ ++#define SPI_NOR_4B_READ_OP BIT(15) /* ++ * Like SPI_NOR_4B_OPCODES, but for read ++ * op code only. ++ */ + }; + + #define JEDEC_MFR(info) ((info)->id[0]) +@@ -240,6 +244,15 @@ static inline u8 spi_nor_convert_3to4_er + ARRAY_SIZE(spi_nor_3to4_erase)); + } + ++static void spi_nor_set_4byte_read(struct spi_nor *nor, ++ const struct flash_info *info) ++{ ++ nor->addr_width = 3; ++ nor->ext_addr = 0; ++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); ++ nor->flags |= SNOR_F_4B_EXT_ADDR; ++} ++ + static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, + const struct flash_info *info) + { +@@ -467,6 +480,36 @@ static int spi_nor_erase_sector(struct s + return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); + } + ++static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr) ++{ ++ bool ext_addr; ++ int ret; ++ u8 cmd; ++ ++ if (!(nor->flags & SNOR_F_4B_EXT_ADDR)) ++ return 0; ++ ++ ext_addr = !!(addr & 0xff000000); ++ if (nor->ext_addr == ext_addr) ++ return 0; ++ ++ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; ++ write_enable(nor); ++ ret = nor->write_reg(nor, cmd, NULL, 0); ++ if (ret) ++ return ret; ++ ++ cmd = 0; ++ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1); ++ if (ret) ++ return ret; ++ ++ nor->addr_width = 3 + ext_addr; ++ nor->ext_addr = ext_addr; ++ write_disable(nor); ++ return 0; ++} ++ + /* + * Erase an address range on the nor chip. The address range may extend + * one or more erase sectors. Return an error is there is a problem erasing. +@@ -492,6 +535,10 @@ static int spi_nor_erase(struct mtd_info + if (ret) + return ret; + ++ ret = spi_nor_check_ext_addr(nor, addr + len); ++ if (ret) ++ return ret; ++ + /* whole-chip erase? */ + if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { + unsigned long timeout; +@@ -542,6 +589,7 @@ static int spi_nor_erase(struct mtd_info + write_disable(nor); + + erase_err: ++ spi_nor_check_ext_addr(nor, 0); + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); + + instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE; +@@ -834,7 +882,9 @@ static int spi_nor_lock(struct mtd_info + if (ret) + return ret; + ++ spi_nor_check_ext_addr(nor, ofs + len); + ret = nor->flash_lock(nor, ofs, len); ++ spi_nor_check_ext_addr(nor, 0); + + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); + return ret; +@@ -849,7 +899,9 @@ static int spi_nor_unlock(struct mtd_inf + if (ret) + return ret; + ++ spi_nor_check_ext_addr(nor, ofs + len); + ret = nor->flash_unlock(nor, ofs, len); ++ spi_nor_check_ext_addr(nor, 0); + + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); + return ret; +@@ -1182,7 +1234,7 @@ static const struct flash_info spi_nor_i + { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, + { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, +- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_READ_OP) }, + { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, + SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, + +@@ -1245,6 +1297,9 @@ static int spi_nor_read(struct mtd_info + if (ret) + return ret; + ++ if (nor->flags & SNOR_F_4B_EXT_ADDR) ++ nor->addr_width = 4; ++ + while (len) { + loff_t addr = from; + +@@ -1269,6 +1324,18 @@ static int spi_nor_read(struct mtd_info + ret = 0; + + read_err: ++ if (nor->flags & SNOR_F_4B_EXT_ADDR) { ++ u8 val = 0; ++ ++ if ((from + len) & 0xff000000) { ++ write_enable(nor); ++ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1); ++ write_disable(nor); ++ } ++ ++ nor->addr_width = 3; ++ } ++ + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); + return ret; + } +@@ -1370,6 +1437,10 @@ static int spi_nor_write(struct mtd_info + if (ret) + return ret; + ++ ret = spi_nor_check_ext_addr(nor, to + len); ++ if (ret < 0) ++ return ret; ++ + for (i = 0; i < len; ) { + ssize_t written; + loff_t addr = to + i; +@@ -1410,6 +1481,7 @@ static int spi_nor_write(struct mtd_info + } + + write_err: ++ spi_nor_check_ext_addr(nor, 0); + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); + return ret; + } +@@ -2826,8 +2898,10 @@ int spi_nor_scan(struct spi_nor *nor, co + } else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || +- info->flags & SPI_NOR_4B_OPCODES) ++ if (info->flags & SPI_NOR_4B_READ_OP) ++ spi_nor_set_4byte_read(nor, info); ++ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || ++ info->flags & SPI_NOR_4B_OPCODES) + spi_nor_set_4byte_opcodes(nor, info); + else + set_4byte(nor, info, 1); +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -102,6 +102,7 @@ + /* Used for Macronix and Winbond flashes. */ + #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ + #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ ++#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ + + /* Used for Spansion flashes only. */ + #define SPINOR_OP_BRWR 0x17 /* Bank register write */ +@@ -229,6 +230,7 @@ enum spi_nor_option_flags { + SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), + SNOR_F_READY_XSR_RDY = BIT(4), + SNOR_F_USE_CLSR = BIT(5), ++ SNOR_F_4B_EXT_ADDR = BIT(6), + }; + + /** +@@ -280,6 +282,7 @@ struct spi_nor { + enum spi_nor_protocol reg_proto; + bool sst_write_second; + u32 flags; ++ u8 ext_addr; + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; + + int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); diff --git a/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch b/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch new file mode 100644 index 0000000000..a686937989 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch @@ -0,0 +1,73 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -142,20 +142,29 @@ static int read_fsr(struct spi_nor *nor) + * location. Return the configuration register value. + * Returns negative if error occurred. + */ +-static int read_cr(struct spi_nor *nor) ++static int _read_cr(struct spi_nor *nor, u8 reg) + { + int ret; + u8 val; + +- ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); ++ ret = nor->read_reg(nor, reg, &val, 1); + if (ret < 0) { +- dev_err(nor->dev, "error %d reading CR\n", ret); ++ dev_err(nor->dev, "error %d reading %s\n", ret, ++ (reg==SPINOR_OP_RDCR)?"CR":"XCR"); + return ret; + } + + return val; + } + ++static inline int read_cr(struct spi_nor *nor) { ++ return _read_cr(nor, SPINOR_OP_RDCR); ++} ++ ++static inline int read_xcr(struct spi_nor *nor) { ++ return _read_cr(nor, SPINOR_OP_RDXCR); ++} ++ + /* + * Write status register 1 byte + * Returns negative if error occurred. +@@ -2898,9 +2907,16 @@ int spi_nor_scan(struct spi_nor *nor, co + } else if (mtd->size > 0x1000000) { + /* enable 4-byte addressing if the device exceeds 16MiB */ + nor->addr_width = 4; +- if (info->flags & SPI_NOR_4B_READ_OP) +- spi_nor_set_4byte_read(nor, info); +- else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || ++ if (info->flags & SPI_NOR_4B_READ_OP) { ++ if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) { ++ ret = read_xcr(nor); ++ if (!(ret > 0 && (ret & XCR_DEF_4B_ADDR_MODE))) ++ spi_nor_set_4byte_read(nor, info); ++ else ++ set_4byte(nor, info, 1); ++ } else ++ spi_nor_set_4byte_read(nor, info); ++ } else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || + info->flags & SPI_NOR_4B_OPCODES) + spi_nor_set_4byte_opcodes(nor, info); + else +--- a/include/linux/mtd/spi-nor.h ++++ b/include/linux/mtd/spi-nor.h +@@ -103,6 +103,7 @@ + #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ + #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ + #define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ ++#define SPINOR_OP_RDXCR 0x15 /* Read extended configuration register */ + + /* Used for Spansion flashes only. */ + #define SPINOR_OP_BRWR 0x17 /* Bank register write */ +@@ -135,6 +136,7 @@ + + /* Configuration Register bits. */ + #define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ ++#define XCR_DEF_4B_ADDR_MODE BIT(1) /* Winbond 4B mode default */ + + /* Status Register 2 bits. */ + #define SR2_QUAD_EN_BIT7 BIT(7) diff --git a/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch b/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch new file mode 100644 index 0000000000..0e09e1d4e0 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch @@ -0,0 +1,15 @@ +--- a/drivers/usb/dwc2/platform.c ++++ b/drivers/usb/dwc2/platform.c +@@ -406,6 +406,12 @@ static int dwc2_driver_probe(struct plat + if (retval) + return retval; + ++ /* Enable USB port before any regs access */ ++ if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) { ++ dwc2_writel(0x00, hsotg->regs + PCGCTL); ++ /* TODO: mdelay(25) here? vendor driver don't use it */ ++ } ++ + retval = dwc2_get_dr_mode(hsotg); + if (retval) + goto error; diff --git a/target/linux/ramips/patches-5.4/0070-weak_reordering.patch b/target/linux/ramips/patches-5.4/0070-weak_reordering.patch new file mode 100644 index 0000000000..52e6641324 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0070-weak_reordering.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -58,6 +58,7 @@ choice + select COMMON_CLK + select CLKSRC_MIPS_GIC + select HW_HAS_PCI ++ select WEAK_REORDERING_BEYOND_LLSC + endchoice + + choice diff --git a/target/linux/ramips/patches-5.4/0098-disable_cm.patch b/target/linux/ramips/patches-5.4/0098-disable_cm.patch new file mode 100644 index 0000000000..bc00619dff --- /dev/null +++ b/target/linux/ramips/patches-5.4/0098-disable_cm.patch @@ -0,0 +1,19 @@ +--- a/arch/mips/kernel/mips-cm.c ++++ b/arch/mips/kernel/mips-cm.c +@@ -237,6 +237,7 @@ int mips_cm_probe(void) + + /* disable CM regions */ + write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR); ++ /* + write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK); + write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR); + write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK); +@@ -244,7 +245,7 @@ int mips_cm_probe(void) + write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK); + write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR); + write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK); +- ++*/ + /* probe for an L2-only sync region */ + mips_cm_probe_l2sync(); + diff --git a/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch b/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch new file mode 100644 index 0000000000..997fb6a2b3 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -33,7 +33,6 @@ + #define RALINK_GPIOMODE 0x60 + + #define PPLL_CFG1 0x9c +-#define PDRV_SW_SET BIT(23) + + #define PPLL_DRV 0xa0 + #define PDRV_SW_SET (1<<31) diff --git a/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch b/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch new file mode 100644 index 0000000000..cd1462fbcf --- /dev/null +++ b/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch @@ -0,0 +1,97 @@ +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/ + obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o + obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o + obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o ++obj-$(CONFIG_SOC_MT7620) += linkit.o + + lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o + lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o +--- /dev/null ++++ b/drivers/misc/linkit.c +@@ -0,0 +1,84 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2015 John Crispin ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define LINKIT_LATCH_GPIO 11 ++ ++struct linkit_hw_data { ++ char board[16]; ++ char rev[16]; ++}; ++ ++static void sanify_string(char *s) ++{ ++ int i; ++ ++ for (i = 0; i < 15; i++) ++ if (s[i] <= 0x20) ++ s[i] = '\0'; ++ s[15] = '\0'; ++} ++ ++static int linkit_probe(struct platform_device *pdev) ++{ ++ struct linkit_hw_data hw; ++ struct mtd_info *mtd; ++ size_t retlen; ++ int ret; ++ ++ mtd = get_mtd_device_nm("factory"); ++ if (IS_ERR(mtd)) ++ return PTR_ERR(mtd); ++ ++ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw); ++ put_mtd_device(mtd); ++ ++ sanify_string(hw.board); ++ sanify_string(hw.rev); ++ ++ dev_info(&pdev->dev, "Version : %s\n", hw.board); ++ dev_info(&pdev->dev, "Revision : %s\n", hw.rev); ++ ++ if (!strcmp(hw.board, "LINKITS7688")) { ++ dev_info(&pdev->dev, "setting up bootstrap latch\n"); ++ ++ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) { ++ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n"); ++ return -1; ++ } ++ gpio_direction_output(LINKIT_LATCH_GPIO, 0); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id linkit_match[] = { ++ { .compatible = "mediatek,linkit" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, linkit_match); ++ ++static struct platform_driver linkit_driver = { ++ .probe = linkit_probe, ++ .driver = { ++ .name = "mtk-linkit", ++ .owner = THIS_MODULE, ++ .of_match_table = linkit_match, ++ }, ++}; ++ ++int __init linkit_init(void) ++{ ++ return platform_driver_register(&linkit_driver); ++} ++late_initcall_sync(linkit_init); diff --git a/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch b/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch new file mode 100644 index 0000000000..991e19b6df --- /dev/null +++ b/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch @@ -0,0 +1,61 @@ +There is a variant of MT7621 which contains only one CPU core instead of 2. +This is not reflected in the config register, so the kernel detects more +physical cores, which leads to a hang on SMP bringup. +Add a hack to detect missing cores. + +Signed-off-by: Felix Fietkau + +--- a/arch/mips/kernel/smp-cps.c ++++ b/arch/mips/kernel/smp-cps.c +@@ -47,6 +47,11 @@ static unsigned core_vpe_count(unsigned + return mips_cps_numvps(cluster, core); + } + ++bool __weak plat_cpu_core_present(int core) ++{ ++ return true; ++} ++ + static void __init cps_smp_setup(void) + { + unsigned int nclusters, ncores, nvpes, core_vpes; +@@ -64,6 +69,8 @@ static void __init cps_smp_setup(void) + + ncores = mips_cps_numcores(cl); + for (c = 0; c < ncores; c++) { ++ if (!plat_cpu_core_present(c)) ++ continue; + core_vpes = core_vpe_count(cl, c); + + if (c > 0) +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + +@@ -162,6 +163,20 @@ void __init ralink_of_remap(void) + panic("Failed to remap core resources"); + } + ++bool plat_cpu_core_present(int core) ++{ ++ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); ++ ++ if (!core) ++ return true; ++ launch += core * 2; /* 2 VPEs per core */ ++ if (!(launch->flags & LAUNCH_FREADY)) ++ return false; ++ if (launch->flags & (LAUNCH_FGO | LAUNCH_FGONE)) ++ return false; ++ return true; ++} ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); diff --git a/target/linux/ramips/patches-5.4/101-mt7621-timer.patch b/target/linux/ramips/patches-5.4/101-mt7621-timer.patch new file mode 100644 index 0000000000..10edafd412 --- /dev/null +++ b/target/linux/ramips/patches-5.4/101-mt7621-timer.patch @@ -0,0 +1,87 @@ +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -9,6 +9,7 @@ + + #include + #include ++#include + + #include + #include +@@ -16,6 +17,7 @@ + #include + #include + #include ++#include + + #include + +@@ -177,6 +179,58 @@ bool plat_cpu_core_present(int core) + return true; + } + ++#define LPS_PREC 8 ++/* ++* Re-calibration lpj(loop-per-jiffy). ++* (derived from kernel/calibrate.c) ++*/ ++static int udelay_recal(void) ++{ ++ unsigned int i, lpj = 0; ++ unsigned long ticks, loopbit; ++ int lps_precision = LPS_PREC; ++ ++ lpj = (1<<12); ++ ++ while ((lpj <<= 1) != 0) { ++ /* wait for "start of" clock tick */ ++ ticks = jiffies; ++ while (ticks == jiffies) ++ /* nothing */; ++ ++ /* Go .. */ ++ ticks = jiffies; ++ __delay(lpj); ++ ticks = jiffies - ticks; ++ if (ticks) ++ break; ++ } ++ ++ /* ++ * Do a binary approximation to get lpj set to ++ * equal one clock (up to lps_precision bits) ++ */ ++ lpj >>= 1; ++ loopbit = lpj; ++ while (lps_precision-- && (loopbit >>= 1)) { ++ lpj |= loopbit; ++ ticks = jiffies; ++ while (ticks == jiffies) ++ /* nothing */; ++ ticks = jiffies; ++ __delay(lpj); ++ if (jiffies != ticks) /* longer than 1 tick */ ++ lpj &= ~loopbit; ++ } ++ printk(KERN_INFO "%d CPUs re-calibrate udelay(lpj = %d)\n", NR_CPUS, lpj); ++ ++ for(i=0; i< NR_CPUS; i++) ++ cpu_data[i].udelay_val = lpj; ++ ++ return 0; ++} ++device_initcall(udelay_recal); ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -59,6 +59,7 @@ choice + select CLKSRC_MIPS_GIC + select HW_HAS_PCI + select WEAK_REORDERING_BEYOND_LLSC ++ select GENERIC_CLOCKEVENTS_BROADCAST + endchoice + + choice diff --git a/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch b/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch new file mode 100644 index 0000000000..e647a2f4c8 --- /dev/null +++ b/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch @@ -0,0 +1,224 @@ +--- a/arch/mips/include/asm/mach-ralink/mt7621.h ++++ b/arch/mips/include/asm/mach-ralink/mt7621.h +@@ -19,6 +19,10 @@ + #define SYSC_REG_CHIP_REV 0x0c + #define SYSC_REG_SYSTEM_CONFIG0 0x10 + #define SYSC_REG_SYSTEM_CONFIG1 0x14 ++#define SYSC_REG_CLKCFG0 0x2c ++#define SYSC_REG_CUR_CLK_STS 0x44 ++ ++#define MEMC_REG_CPU_PLL 0x648 + + #define CHIP_REV_PKG_MASK 0x1 + #define CHIP_REV_PKG_SHIFT 16 +@@ -26,6 +30,22 @@ + #define CHIP_REV_VER_SHIFT 8 + #define CHIP_REV_ECO_MASK 0xf + ++#define XTAL_MODE_SEL_MASK 0x7 ++#define XTAL_MODE_SEL_SHIFT 6 ++ ++#define CPU_CLK_SEL_MASK 0x3 ++#define CPU_CLK_SEL_SHIFT 30 ++ ++#define CUR_CPU_FDIV_MASK 0x1f ++#define CUR_CPU_FDIV_SHIFT 8 ++#define CUR_CPU_FFRAC_MASK 0x1f ++#define CUR_CPU_FFRAC_SHIFT 0 ++ ++#define CPU_PLL_PREDIV_MASK 0x3 ++#define CPU_PLL_PREDIV_SHIFT 12 ++#define CPU_PLL_FBDIV_MASK 0x7f ++#define CPU_PLL_FBDIV_SHIFT 4 ++ + #define MT7621_DRAM_BASE 0x0 + #define MT7621_DDR2_SIZE_MIN 32 + #define MT7621_DDR2_SIZE_MAX 256 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -10,6 +10,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + + #include + #include +@@ -18,16 +22,12 @@ + #include + #include + #include ++#include + + #include + + #include "common.h" + +-#define SYSC_REG_SYSCFG 0x10 +-#define SYSC_REG_CPLL_CLKCFG0 0x2c +-#define SYSC_REG_CUR_CLK_STS 0x44 +-#define CPU_CLK_SEL (BIT(30) | BIT(31)) +- + #define MT7621_GPIO_MODE_UART1 1 + #define MT7621_GPIO_MODE_I2C 2 + #define MT7621_GPIO_MODE_UART3_MASK 0x3 +@@ -113,49 +113,89 @@ static struct rt2880_pmx_group mt7621_pi + { 0 } + }; + ++static struct clk *clks[MT7621_CLK_MAX]; ++static struct clk_onecell_data clk_data = { ++ .clks = clks, ++ .clk_num = ARRAY_SIZE(clks), ++}; ++ + phys_addr_t mips_cpc_default_phys_base(void) + { + panic("Cannot detect cpc address"); + } + +-void __init ralink_clk_init(void) ++static struct clk *__init mt7621_add_sys_clkdev( ++ const char *id, unsigned long rate) + { +- int cpu_fdiv = 0; +- int cpu_ffrac = 0; +- int fbdiv = 0; +- u32 clk_sts, syscfg; +- u8 clk_sel = 0, xtal_mode; +- u32 cpu_clk; ++ struct clk *clk; ++ int err; ++ ++ clk = clk_register_fixed_rate(NULL, id, NULL, 0, rate); ++ if (IS_ERR(clk)) ++ panic("failed to allocate %s clock structure", id); ++ ++ err = clk_register_clkdev(clk, id, NULL); ++ if (err) ++ panic("unable to register %s clock device", id); + +- if ((rt_sysc_r32(SYSC_REG_CPLL_CLKCFG0) & CPU_CLK_SEL) != 0) +- clk_sel = 1; ++ return clk; ++} ++ ++void __init ralink_clk_init(void) ++{ ++ u32 syscfg, xtal_sel, clkcfg, clk_sel, curclk, ffiv, ffrac; ++ u32 pll, prediv, fbdiv; ++ u32 xtal_clk, cpu_clk, bus_clk; ++ const static u32 prediv_tbl[] = {0, 1, 2, 2}; ++ ++ syscfg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); ++ xtal_sel = (syscfg >> XTAL_MODE_SEL_SHIFT) & XTAL_MODE_SEL_MASK; ++ ++ clkcfg = rt_sysc_r32(SYSC_REG_CLKCFG0); ++ clk_sel = (clkcfg >> CPU_CLK_SEL_SHIFT) & CPU_CLK_SEL_MASK; ++ ++ curclk = rt_sysc_r32(SYSC_REG_CUR_CLK_STS); ++ ffiv = (curclk >> CUR_CPU_FDIV_SHIFT) & CUR_CPU_FDIV_MASK; ++ ffrac = (curclk >> CUR_CPU_FFRAC_SHIFT) & CUR_CPU_FFRAC_MASK; ++ ++ if (xtal_sel <= 2) ++ xtal_clk = 20 * 1000 * 1000; ++ else if (xtal_sel <= 5) ++ xtal_clk = 40 * 1000 * 1000; ++ else ++ xtal_clk = 25 * 1000 * 1000; + + switch (clk_sel) { + case 0: +- clk_sts = rt_sysc_r32(SYSC_REG_CUR_CLK_STS); +- cpu_fdiv = ((clk_sts >> 8) & 0x1F); +- cpu_ffrac = (clk_sts & 0x1F); +- cpu_clk = (500 * cpu_ffrac / cpu_fdiv) * 1000 * 1000; ++ cpu_clk = 500 * 1000 * 1000; + break; +- + case 1: +- fbdiv = ((rt_sysc_r32(0x648) >> 4) & 0x7F) + 1; +- syscfg = rt_sysc_r32(SYSC_REG_SYSCFG); +- xtal_mode = (syscfg >> 6) & 0x7; +- if (xtal_mode >= 6) { +- /* 25Mhz Xtal */ +- cpu_clk = 25 * fbdiv * 1000 * 1000; +- } else if (xtal_mode >= 3) { +- /* 40Mhz Xtal */ +- cpu_clk = 40 * fbdiv * 1000 * 1000; +- } else { +- /* 20Mhz Xtal */ +- cpu_clk = 20 * fbdiv * 1000 * 1000; +- } ++ pll = rt_memc_r32(MEMC_REG_CPU_PLL); ++ fbdiv = (pll >> CPU_PLL_FBDIV_SHIFT) & CPU_PLL_FBDIV_MASK; ++ prediv = (pll >> CPU_PLL_PREDIV_SHIFT) & CPU_PLL_PREDIV_MASK; ++ cpu_clk = ((fbdiv + 1) * xtal_clk) >> prediv_tbl[prediv]; + break; ++ default: ++ cpu_clk = xtal_clk; + } ++ ++ cpu_clk = cpu_clk / ffiv * ffrac; ++ bus_clk = cpu_clk / 4; ++ ++ clks[MT7621_CLK_CPU] = mt7621_add_sys_clkdev("cpu", cpu_clk); ++ clks[MT7621_CLK_BUS] = mt7621_add_sys_clkdev("bus", bus_clk); ++ ++ pr_info("CPU Clock: %dMHz\n", cpu_clk / 1000000); ++ mips_hpt_frequency = cpu_clk / 2; + } + ++static void __init mt7621_clocks_init_dt(struct device_node *np) ++{ ++ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); ++} ++ ++CLK_OF_DECLARE(ar7100, "mediatek,mt7621-pll", mt7621_clocks_init_dt); ++ + void __init ralink_of_remap(void) + { + rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc"); +--- a/arch/mips/ralink/timer-gic.c ++++ b/arch/mips/ralink/timer-gic.c +@@ -11,14 +11,14 @@ + + #include + #include +-#include ++#include + + #include "common.h" + + void __init plat_time_init(void) + { + ralink_of_remap(); +- ++ ralink_clk_init(); + of_clk_init(NULL); + timer_probe(); + } +--- /dev/null ++++ b/include/dt-bindings/clock/mt7621-clk.h +@@ -0,0 +1,18 @@ ++/* ++ * Copyright (C) 2018 Weijie Gao ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __DT_BINDINGS_MT7621_CLK_H ++#define __DT_BINDINGS_MT7621_CLK_H ++ ++#define MT7621_CLK_CPU 0 ++#define MT7621_CLK_BUS 1 ++ ++#define MT7621_CLK_MAX 2 ++ ++#endif /* __DT_BINDINGS_MT7621_CLK_H */ diff --git a/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch b/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch new file mode 100644 index 0000000000..b19b57fd66 --- /dev/null +++ b/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch @@ -0,0 +1,125 @@ +From b5a52351a66f3c2a7a207548aa87d78ff2d336c0 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Wed, 10 Jul 2019 00:24:48 +0800 +Subject: [PATCH] MIPS: ralink: mt7621: add memory detection support + +mt7621 has the following memory map: +0x0-0x1c000000: lower 448m memory +0x1c000000-0x2000000: peripheral registers +0x20000000-0x2400000: higher 64m memory + +detect_memory_region in arch/mips/kernel/setup.c only add the first +memory region and isn't suitable for 512m memory detection because +it may accidentally read the memory area for peripheral registers. + +This commit adds memory detection capability for mt7621: +1. add the highmem area when 512m is detected. +2. guard memcmp from accessing peripheral registers: + This only happens when some weird user decided to change + kernel load address to 256m or higher address. Since this + is a quite unusual case, we just skip 512m testing and return + 256m as memory size. + +Signed-off-by: Chuanhong Guo +--- + arch/mips/include/asm/mach-ralink/mt7621.h | 7 ++--- + arch/mips/ralink/mt7621.c | 30 +++++++++++++++++++--- + 2 files changed, 30 insertions(+), 7 deletions(-) + +--- a/arch/mips/include/asm/mach-ralink/mt7621.h ++++ b/arch/mips/include/asm/mach-ralink/mt7621.h +@@ -46,9 +46,10 @@ + #define CPU_PLL_FBDIV_MASK 0x7f + #define CPU_PLL_FBDIV_SHIFT 4 + +-#define MT7621_DRAM_BASE 0x0 +-#define MT7621_DDR2_SIZE_MIN 32 +-#define MT7621_DDR2_SIZE_MAX 256 ++#define MT7621_LOWMEM_BASE 0x0 ++#define MT7621_LOWMEM_MAX_SIZE 0x1C000000 ++#define MT7621_HIGHMEM_BASE 0x20000000 ++#define MT7621_HIGHMEM_SIZE 0x4000000 + + #define MT7621_CHIP_NAME0 0x3637544D + #define MT7621_CHIP_NAME1 0x20203132 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -15,6 +15,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -57,6 +58,8 @@ + #define MT7621_GPIO_MODE_SDHCI_SHIFT 18 + #define MT7621_GPIO_MODE_SDHCI_GPIO 1 + ++static void *detect_magic __initdata = detect_memory_region; ++ + static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) }; + static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) }; + static struct rt2880_pmx_func uart3_grp[] = { +@@ -141,6 +144,28 @@ static struct clk *__init mt7621_add_sys + return clk; + } + ++void __init mt7621_memory_detect(void) ++{ ++ void *dm = &detect_magic; ++ phys_addr_t size; ++ ++ for (size = 32 * SZ_1M; size < 256 * SZ_1M; size <<= 1) { ++ if (!memcmp(dm, dm + size, sizeof(detect_magic))) ++ break; ++ } ++ ++ if ((size == 256 * SZ_1M) && ++ (CPHYSADDR(dm + size) < MT7621_LOWMEM_MAX_SIZE) && ++ memcmp(dm, dm + size, sizeof(detect_magic))) { ++ add_memory_region(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE, ++ BOOT_MEM_RAM); ++ add_memory_region(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE, ++ BOOT_MEM_RAM); ++ } else { ++ add_memory_region(MT7621_LOWMEM_BASE, size, BOOT_MEM_RAM); ++ } ++} ++ + void __init ralink_clk_init(void) + { + u32 syscfg, xtal_sel, clkcfg, clk_sel, curclk, ffiv, ffrac; +@@ -319,10 +344,7 @@ void prom_soc_init(struct ralink_soc_inf + (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, + (rev & CHIP_REV_ECO_MASK)); + +- soc_info->mem_size_min = MT7621_DDR2_SIZE_MIN; +- soc_info->mem_size_max = MT7621_DDR2_SIZE_MAX; +- soc_info->mem_base = MT7621_DRAM_BASE; +- ++ soc_info->mem_detect = mt7621_memory_detect; + rt2880_pinmux_data = mt7621_pinmux_data; + + +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -19,6 +19,7 @@ struct ralink_soc_info { + unsigned long mem_size; + unsigned long mem_size_min; + unsigned long mem_size_max; ++ void (*mem_detect)(void); + }; + extern struct ralink_soc_info soc_info; + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -89,6 +89,8 @@ void __init plat_mem_setup(void) + of_scan_flat_dt(early_init_dt_find_memory, NULL); + if (memory_dtb) + of_scan_flat_dt(early_init_dt_scan_memory, NULL); ++ else if (soc_info.mem_detect) ++ soc_info.mem_detect(); + else if (soc_info.mem_size) + add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, + BOOT_MEM_RAM); diff --git a/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch b/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch new file mode 100644 index 0000000000..4c40e65ab9 --- /dev/null +++ b/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch @@ -0,0 +1,15 @@ +--- a/arch/mips/ralink/irq-gic.c ++++ b/arch/mips/ralink/irq-gic.c +@@ -15,6 +15,12 @@ + + int get_c0_perfcount_int(void) + { ++ /* ++ * Performance counter events are routed through GIC. ++ * Prevent them from firing on CPU IRQ7 as well ++ */ ++ clear_c0_status(IE_SW0 << 7); ++ + return gic_get_c0_perfcount_int(); + } + EXPORT_SYMBOL_GPL(get_c0_perfcount_int); diff --git a/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch b/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch new file mode 100644 index 0000000000..0cb1fede30 --- /dev/null +++ b/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch @@ -0,0 +1,19 @@ +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -137,4 +137,16 @@ static inline int mt7620_get_eco(void) + return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK; + } + ++static inline int mt7620_get_chipver(void) ++{ ++ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_VER_SHIFT) & ++ CHIP_REV_VER_MASK; ++} ++ ++static inline int mt7620_get_pkg(void) ++{ ++ return (rt_sysc_r32(SYSC_REG_CHIP_REV) >> CHIP_REV_PKG_SHIFT) & ++ CHIP_REV_PKG_MASK; ++} ++ + #endif diff --git a/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch b/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch new file mode 100644 index 0000000000..0a3a65d70a --- /dev/null +++ b/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch @@ -0,0 +1,14 @@ +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1066,6 +1066,11 @@ static const struct flash_info spi_nor_i + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, ++ { ++ "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | ++ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES) ++ }, + + /* Intel/Numonyx -- xxxs33b */ + { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, diff --git a/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch b/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch new file mode 100644 index 0000000000..8b59a106e1 --- /dev/null +++ b/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch @@ -0,0 +1,72 @@ +This hack can be dropped after the next stable release from +v5.x-tree. + +The problem was fixed upstream by + +commit 2bffa65da43e ("mtd: spi-nor: Add a post BFPT fixup for MX25L25635E") + +For reference see: + + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -1103,6 +1103,7 @@ static const struct flash_info spi_nor_i + { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, + { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, + { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, + { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, + { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, +@@ -1275,11 +1276,12 @@ static const struct flash_info spi_nor_i + { }, + }; + +-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) ++static const struct flash_info *spi_nor_read_id(struct spi_nor *nor, ++ const char *name) + { + int tmp; + u8 id[SPI_NOR_MAX_ID_LEN]; +- const struct flash_info *info; ++ const struct flash_info *info, *first_match = NULL; + + tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); + if (tmp < 0) { +@@ -1290,10 +1292,16 @@ static const struct flash_info *spi_nor_ + for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { + info = &spi_nor_ids[tmp]; + if (info->id_len) { +- if (!memcmp(info->id, id, info->id_len)) +- return &spi_nor_ids[tmp]; ++ if (!memcmp(info->id, id, info->id_len)) { ++ if (!name || !strcmp(name, info->name)) ++ return info; ++ if (!first_match) ++ first_match = info; ++ } + } + } ++ if (first_match) ++ return first_match; + dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return ERR_PTR(-ENODEV); +@@ -2773,7 +2781,7 @@ int spi_nor_scan(struct spi_nor *nor, co + info = spi_nor_match_id(name); + /* Try to auto-detect if chip name wasn't specified or not found */ + if (!info) +- info = spi_nor_read_id(nor); ++ info = spi_nor_read_id(nor, NULL); + if (IS_ERR_OR_NULL(info)) + return -ENOENT; + +@@ -2784,7 +2792,7 @@ int spi_nor_scan(struct spi_nor *nor, co + if (name && info->id_len) { + const struct flash_info *jinfo; + +- jinfo = spi_nor_read_id(nor); ++ jinfo = spi_nor_read_id(nor, name); + if (IS_ERR(jinfo)) { + return PTR_ERR(jinfo); + } else if (jinfo != info) { diff --git a/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch b/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch new file mode 100644 index 0000000000..3310a6bdba --- /dev/null +++ b/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch @@ -0,0 +1,21 @@ +--- a/arch/mips/pci/pci-mt7620.c ++++ b/arch/mips/pci/pci-mt7620.c +@@ -35,6 +35,7 @@ + #define PPLL_CFG1 0x9c + + #define PPLL_DRV 0xa0 ++#define PPLL_LD (1<<23) + #define PDRV_SW_SET (1<<31) + #define LC_CKDRVPD (1<<19) + #define LC_CKDRVOHZ (1<<18) +@@ -242,8 +243,8 @@ static int mt7620_pci_hw_init(struct pla + rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); + mdelay(100); + +- if (!(rt_sysc_r32(PPLL_CFG1) & PDRV_SW_SET)) { +- dev_err(&pdev->dev, "MT7620 PPLL unlock\n"); ++ if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) { ++ dev_err(&pdev->dev, "MT7620 PPLL is unlocked, aborting init\n"); + reset_control_assert(rstpcie0); + rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); + return -1; From d4903b572071470416c51afa8f8c6b3891be4c2e Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:02:06 +0800 Subject: [PATCH 02/35] ramips: move MTK MMC driver to files directory Move MTK MMC driver from "files-4.14" to "files" so kernel 5.4 can use it Signed-off-by: DENG Qingfang --- .../ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/Kconfig | 0 .../{files-4.14 => files}/drivers/mmc/host/mtk-mmc/Makefile | 0 .../ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/board.h | 0 .../ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/dbg.c | 0 .../ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/dbg.h | 0 .../{files-4.14 => files}/drivers/mmc/host/mtk-mmc/mt6575_sd.h | 0 .../ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/sd.c | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/Kconfig (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/Makefile (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/board.h (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/dbg.c (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/dbg.h (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/mt6575_sd.h (100%) rename target/linux/ramips/{files-4.14 => files}/drivers/mmc/host/mtk-mmc/sd.c (100%) diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Kconfig b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/Kconfig similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Kconfig rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/Kconfig diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Makefile b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/Makefile similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/Makefile rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/Makefile diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/board.h b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/board.h similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/board.h rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/board.h diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.c b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/dbg.c similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.c rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/dbg.c diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.h b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/dbg.h similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/dbg.h rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/dbg.h diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/mt6575_sd.h b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/mt6575_sd.h similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/mt6575_sd.h rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/mt6575_sd.h diff --git a/target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/sd.c b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c similarity index 100% rename from target/linux/ramips/files-4.14/drivers/mmc/host/mtk-mmc/sd.c rename to target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c From d75c9b8f81b1a4f65132a5fed81f0a3fbbbd8fee Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Fri, 17 Jan 2020 16:04:14 +0800 Subject: [PATCH 03/35] ramips: mtk-mmc: set correct DMA mask Since commit f8c55dc ("MIPS: use generic dma noncoherent ops for simple noncoherent platforms") changed MIPS dma handling, the mmc driver fails because it doesn't have a dma mask is set. So set the correct dma mask. Signed-off-by: NeilBrown Signed-off-by: DENG Qingfang --- target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c index cb0aa4231a..8cbc87da3a 100644 --- a/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c +++ b/target/linux/ramips/files/drivers/mmc/host/mtk-mmc/sd.c @@ -2284,7 +2284,7 @@ static int msdc_drv_probe(struct platform_device *pdev) host->mrq = NULL; //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ - mmc_dev(mmc)->dma_mask = NULL; + dma_coerce_mask_and_coherent(mmc_dev(mmc), DMA_BIT_MASK(32)); /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ host->dma.gpd = dma_alloc_coherent(&pdev->dev, From 6be0da90a165912da7bd56e7bd4d7b2d978b4706 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:06:45 +0800 Subject: [PATCH 04/35] ramips: refresh patches Removed upstreamed/solved elsewhere upstream: - 0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch - 0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch - 0004-MIPS-ralink-add-MT7621-pcie-driver.patch - 0009-PCI-MIPS-enable-PCIe-on-MT7688.patch - 0025-pinctrl-ralink-add-pinctrl-driver.patch - 0028-GPIO-ralink-add-mt7621-gpio-controller.patch - 0043-spi-add-mt7621-support.patch - 0045-i2c-add-mt7621-driver.patch - 0047-DMA-ralink-add-rt2880-dma-engine.patch - 0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch - 0054-mtd-spi-nor-w25q256-respect-default-mode.patch - 0099-pci-mt7620.patch - 304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch Removed because of the new NAND driver: - 0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch - 0039-mtd-add-mt7621-nand-support.patch - 0040-nand-hack.patch Remove patch that no longer applies (needs rework): - 0034-NET-multi-phy-support.patch Signed-off-by: DENG Qingfang --- ...IPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch | 45 - ...ci-rt2880-set-pci-controller-of_node.patch | 32 - ...reservation-in-bootmem_init-for-cert.patch | 24 +- ...4-MIPS-ralink-add-MT7621-pcie-driver.patch | 861 ---- ...IPS-ralink-add-cpu-frequency-scaling.patch | 6 +- ...-the-commandline-from-the-devicetree.patch | 2 +- .../0009-PCI-MIPS-enable-PCIe-on-MT7688.patch | 28 - ...013-owrt-hack-fix-mt7688-cache-issue.patch | 8 +- .../0024-GPIO-add-named-gpio-exports.patch | 18 +- ...25-pinctrl-ralink-add-pinctrl-driver.patch | 524 -- ...alink-add-gpio-driver-for-ralink-SoC.patch | 42 +- ...IO-ralink-add-mt7621-gpio-controller.patch | 405 -- ...0031-uvc-add-iPassion-iP2970-support.patch | 40 +- .../0032-USB-dwc2-add-device_reset.patch | 6 +- .../0034-NET-multi-phy-support.patch | 59 - ...mtd-cfi-cmdset-0002-force-word-write.patch | 50 - ...d-Remove-unused-chip-write_page-hook.patch | 67 - .../0039-mtd-add-mt7621-nand-support.patch | 4437 ----------------- .../ramips/patches-5.4/0040-nand-hack.patch | 32 - ...SPI-ralink-add-Ralink-SoC-spi-driver.patch | 6 +- .../0043-spi-add-mt7621-support.patch | 487 -- ...0044-i2c-MIPS-adds-ralink-I2C-driver.patch | 6 +- .../0045-i2c-add-mt7621-driver.patch | 473 -- ...IPS-ralink-add-sdhci-for-mt7620a-SoC.patch | 4 +- ...047-DMA-ralink-add-rt2880-dma-engine.patch | 1757 ------- .../0048-asoc-add-mt7620-support.patch | 10 +- ...erial-add-ugly-custom-baud-rate-hack.patch | 2 +- .../0052-pwm-add-mediatek-support.patch | 4 +- ...d-spi-nor-add-w25q256-3b-mode-switch.patch | 214 - ...spi-nor-w25q256-respect-default-mode.patch | 73 - .../0069-awake-rt305x-dwc2-controller.patch | 10 +- .../patches-5.4/0070-weak_reordering.patch | 4 +- .../ramips/patches-5.4/0098-disable_cm.patch | 4 +- .../ramips/patches-5.4/0099-pci-mt7620.patch | 10 - .../patches-5.4/0200-linkit_bootstrap.patch | 12 +- .../100-mt7621-core-detect-hack.patch | 8 +- .../ramips/patches-5.4/101-mt7621-timer.patch | 10 +- .../102-mt7621-fix-cpu-clk-add-clkdev.patch | 12 +- .../105-mt7621-memory-detect.patch | 14 +- .../patches-5.4/110-mt7621-perfctr-fix.patch | 2 +- ...0-mt7620-export-chip-version-and-pkg.patch | 2 +- .../302-spi-nor-add-gd25q512.patch | 6 +- ...or-enable-4B-opcodes-for-mx25l25635f.patch | 72 - .../patches-5.4/999-fix-pci-init-mt7620.patch | 12 +- 44 files changed, 130 insertions(+), 9770 deletions(-) delete mode 100644 target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch delete mode 100644 target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch delete mode 100644 target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch delete mode 100644 target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch delete mode 100644 target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch delete mode 100644 target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch delete mode 100644 target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch delete mode 100644 target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch delete mode 100644 target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch delete mode 100644 target/linux/ramips/patches-5.4/0040-nand-hack.patch delete mode 100644 target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch delete mode 100644 target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch delete mode 100644 target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch delete mode 100644 target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch delete mode 100644 target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch delete mode 100644 target/linux/ramips/patches-5.4/0099-pci-mt7620.patch delete mode 100644 target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch diff --git a/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch b/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch deleted file mode 100644 index 4f803dfd0d..0000000000 --- a/target/linux/ramips/patches-5.4/0001-MIPS-ralink-Add-rt3352-SPI_CS1-pinmux.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 35d017947401d9f449a7e55e52506744e0c62577 Mon Sep 17 00:00:00 2001 -From: Mathias Kresin -Date: Wed, 22 Aug 2018 22:38:06 +0200 -Subject: [PATCH] MIPS: ralink: Add rt3352 SPI_CS1 pinmux - -The rt3352 has a pin that can be used as second spi chip select, -watchdog reset or GPIO. The pinmux setup was missing the definition of -said pin. - -The pin is configured via the same bit on rt5350, so reuse the existing -macro. - -Signed-off-by: Mathias Kresin -Signed-off-by: Paul Burton -Patchwork: https://patchwork.linux-mips.org/patch/20301/ -Cc: John Crispin -Cc: Ralf Baechle -Cc: James Hogan -Cc: linux-mips@linux-mips.org -Cc: linux-kernel@vger.kernel.org ---- - arch/mips/ralink/rt305x.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/mips/ralink/rt305x.c -+++ b/arch/mips/ralink/rt305x.c -@@ -49,6 +49,10 @@ static struct rt2880_pmx_func rgmii_func - static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; - static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; - static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; -+static struct rt2880_pmx_func rt3352_cs1_func[] = { -+ FUNC("spi_cs1", 0, 45, 1), -+ FUNC("wdg_cs1", 1, 45, 1), -+}; - - static struct rt2880_pmx_group rt3050_pinmux_data[] = { - GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), -@@ -75,6 +79,7 @@ static struct rt2880_pmx_group rt3352_pi - GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA), - GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA), - GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED), -+ GRP("spi_cs1", rt3352_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1), - { 0 } - }; - diff --git a/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch b/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch deleted file mode 100644 index 7ac092cfb0..0000000000 --- a/target/linux/ramips/patches-5.4/0002-MIPS-pci-rt2880-set-pci-controller-of_node.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0eb1cfffd5433d8dce3e4163a5cd9accc6000856 Mon Sep 17 00:00:00 2001 -From: Tobias Wolf -Date: Wed, 5 Sep 2018 08:51:26 +0200 -Subject: [PATCH] MIPS: pci-rt2880: set pci controller of_node - -Set the PCI controller of_node such that PCI devices can be -instantiated via device tree. - -Signed-off-by: Tobias Wolf -Signed-off-by: Mathias Kresin -Acked-by: John Crispin -Signed-off-by: Paul Burton -Patchwork: https://patchwork.linux-mips.org/patch/20423/ -Cc: Ralf Baechle -Cc: James Hogan -Cc: linux-mips@linux-mips.org -Cc: linux-kernel@vger.kernel.org ---- - arch/mips/pci/pci-rt2880.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/mips/pci/pci-rt2880.c -+++ b/arch/mips/pci/pci-rt2880.c -@@ -246,6 +246,8 @@ static int rt288x_pci_probe(struct platf - rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); - (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); - -+ rt2880_pci_controller.of_node = pdev->dev.of_node; -+ - register_pci_controller(&rt2880_pci_controller); - return 0; - } diff --git a/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch b/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch index 77f2622b9d..fa923f1829 100644 --- a/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch +++ b/target/linux/ramips/patches-5.4/0003-MIPS-Fix-memory-reservation-in-bootmem_init-for-cert.patch @@ -16,27 +16,27 @@ Signed-off-by: Tobias Wolf --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c -@@ -369,6 +369,8 @@ static unsigned long __init bootmap_byte - return ALIGN(bytes, sizeof(long)); - } - +@@ -285,6 +285,8 @@ static unsigned long __init init_initrd( + * Initialize the bootmem allocator. It also setup initrd related data + * if needed. + */ +static int usermem __initdata; + + #if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA)) + static void __init bootmem_init(void) - { - unsigned long reserved_end; -@@ -442,7 +444,7 @@ static void __init bootmem_init(void) +@@ -323,7 +325,7 @@ static void __init bootmem_init(void) /* * Reserve any memory between the start of RAM and PHYS_OFFSET */ - if (ramstart > PHYS_OFFSET) + if (usermem && ramstart > PHYS_OFFSET) - add_memory_region(PHYS_OFFSET, ramstart - PHYS_OFFSET, - BOOT_MEM_RESERVED); + memblock_reserve(PHYS_OFFSET, ramstart - PHYS_OFFSET); -@@ -652,8 +654,6 @@ static void __init bootmem_init(void) - * initialization hook for anything else was introduced. - */ + if (PFN_UP(ramstart) > ARCH_PFN_OFFSET) { +@@ -384,8 +386,6 @@ static void __init bootmem_init(void) + + #endif /* CONFIG_SGI_IP27 */ -static int usermem __initdata; - diff --git a/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch b/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch deleted file mode 100644 index b6f1ce93f4..0000000000 --- a/target/linux/ramips/patches-5.4/0004-MIPS-ralink-add-MT7621-pcie-driver.patch +++ /dev/null @@ -1,861 +0,0 @@ -From fec11d4e8dc5cc79bcd7c8fd55038ac21ac39965 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 16 Mar 2014 05:22:39 +0000 -Subject: [PATCH 04/53] MIPS: ralink: add MT7621 pcie driver - -Signed-off-by: John Crispin ---- - arch/mips/pci/Makefile | 1 + - arch/mips/pci/pci-mt7621.c | 813 ++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 814 insertions(+) - create mode 100644 arch/mips/pci/pci-mt7621.c - ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -47,6 +47,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops - obj-$(CONFIG_LANTIQ) += fixup-lantiq.o - obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o - obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o -+obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o - obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o - obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o - obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o ---- /dev/null -+++ b/arch/mips/pci/pci-mt7621.c -@@ -0,0 +1,836 @@ -+/************************************************************************** -+ * -+ * BRIEF MODULE DESCRIPTION -+ * PCI init for Ralink RT2880 solution -+ * -+ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ * -+ ************************************************************************** -+ * May 2007 Bruce Chang -+ * Initial Release -+ * -+ * May 2009 Bruce Chang -+ * support RT2880/RT3883 PCIe -+ * -+ * May 2011 Bruce Chang -+ * support RT6855/MT7620 PCIe -+ * -+ ************************************************************************** -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+extern void pcie_phy_init(void); -+extern void chk_phy_pll(void); -+ -+/* -+ * These functions and structures provide the BIOS scan and mapping of the PCI -+ * devices. -+ */ -+ -+#define CONFIG_PCIE_PORT0 -+#define CONFIG_PCIE_PORT1 -+#define CONFIG_PCIE_PORT2 -+#define RALINK_PCIE0_CLK_EN (1<<24) -+#define RALINK_PCIE1_CLK_EN (1<<25) -+#define RALINK_PCIE2_CLK_EN (1<<26) -+ -+#define RALINK_PCI_CONFIG_ADDR 0x20 -+#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24 -+#define RALINK_INT_PCIE0 pcie_irq[0] -+#define RALINK_INT_PCIE1 pcie_irq[1] -+#define RALINK_INT_PCIE2 pcie_irq[2] -+#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028) -+#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C) -+#define RALINK_PCIE0_RST (1<<24) -+#define RALINK_PCIE1_RST (1<<25) -+#define RALINK_PCIE2_RST (1<<26) -+#define RALINK_SYSCTL_BASE 0xBE000000 -+ -+#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000) -+#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C) -+#define RALINK_PCI_BASE 0xBE140000 -+ -+#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) -+#define RT6855_PCIE0_OFFSET 0x2000 -+#define RT6855_PCIE1_OFFSET 0x3000 -+#define RT6855_PCIE2_OFFSET 0x4000 -+ -+#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010) -+#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018) -+#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030) -+#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034) -+#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038) -+#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050) -+#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060) -+#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064) -+ -+#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010) -+#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018) -+#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030) -+#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034) -+#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038) -+#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050) -+#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060) -+#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064) -+ -+#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010) -+#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018) -+#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030) -+#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034) -+#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038) -+#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050) -+#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060) -+#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064) -+ -+#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) -+#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000) -+ -+ -+#define MV_WRITE(ofs, data) \ -+ *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data) -+#define MV_READ(ofs, data) \ -+ *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) -+#define MV_READ_DATA(ofs) \ -+ le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) -+ -+#define MV_WRITE_16(ofs, data) \ -+ *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data) -+#define MV_READ_16(ofs, data) \ -+ *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs))) -+ -+#define MV_WRITE_8(ofs, data) \ -+ *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data -+#define MV_READ_8(ofs, data) \ -+ *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) -+ -+ -+ -+#define RALINK_PCI_MM_MAP_BASE 0x60000000 -+#define RALINK_PCI_IO_MAP_BASE 0x1e160000 -+ -+#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000 -+#define GPIO_PERST -+#define ASSERT_SYSRST_PCIE(val) do { \ -+ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ -+ RALINK_RSTCTRL |= val; \ -+ else \ -+ RALINK_RSTCTRL &= ~val; \ -+ } while(0) -+#define DEASSERT_SYSRST_PCIE(val) do { \ -+ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ -+ RALINK_RSTCTRL &= ~val; \ -+ else \ -+ RALINK_RSTCTRL |= val; \ -+ } while(0) -+#define RALINK_SYSCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14) -+#define RALINK_CLKCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30) -+#define RALINK_RSTCTRL *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34) -+#define RALINK_GPIOMODE *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60) -+#define RALINK_PCIE_CLK_GEN *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c) -+#define RALINK_PCIE_CLK_GEN1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80) -+#define PPLL_CFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c) -+#define PPLL_DRV *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0) -+//RALINK_SYSCFG1 bit -+#define RALINK_PCI_HOST_MODE_EN (1<<7) -+#define RALINK_PCIE_RC_MODE_EN (1<<8) -+//RALINK_RSTCTRL bit -+#define RALINK_PCIE_RST (1<<23) -+#define RALINK_PCI_RST (1<<24) -+//RALINK_CLKCFG1 bit -+#define RALINK_PCI_CLK_EN (1<<19) -+#define RALINK_PCIE_CLK_EN (1<<21) -+//RALINK_GPIOMODE bit -+#define PCI_SLOTx2 (1<<11) -+#define PCI_SLOTx1 (2<<11) -+//MTK PCIE PLL bit -+#define PDRV_SW_SET (1<<31) -+#define LC_CKDRVPD_ (1<<19) -+ -+#define MEMORY_BASE 0x0 -+static int pcie_link_status = 0; -+ -+#define PCI_ACCESS_READ_1 0 -+#define PCI_ACCESS_READ_2 1 -+#define PCI_ACCESS_READ_4 2 -+#define PCI_ACCESS_WRITE_1 3 -+#define PCI_ACCESS_WRITE_2 4 -+#define PCI_ACCESS_WRITE_4 5 -+ -+static int pcie_irq[3]; -+ -+static int config_access(unsigned char access_type, struct pci_bus *bus, -+ unsigned int devfn, unsigned int where, u32 * data) -+{ -+ unsigned int slot = PCI_SLOT(devfn); -+ u8 func = PCI_FUNC(devfn); -+ uint32_t address_reg, data_reg; -+ unsigned int address; -+ -+ address_reg = RALINK_PCI_CONFIG_ADDR; -+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; -+ -+ address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; -+ MV_WRITE(address_reg, address); -+ -+ switch(access_type) { -+ case PCI_ACCESS_WRITE_1: -+ MV_WRITE_8(data_reg+(where&0x3), *data); -+ break; -+ case PCI_ACCESS_WRITE_2: -+ MV_WRITE_16(data_reg+(where&0x3), *data); -+ break; -+ case PCI_ACCESS_WRITE_4: -+ MV_WRITE(data_reg, *data); -+ break; -+ case PCI_ACCESS_READ_1: -+ MV_READ_8( data_reg+(where&0x3), data); -+ break; -+ case PCI_ACCESS_READ_2: -+ MV_READ_16(data_reg+(where&0x3), data); -+ break; -+ case PCI_ACCESS_READ_4: -+ MV_READ(data_reg, data); -+ break; -+ default: -+ printk("no specify access type\n"); -+ break; -+ } -+ return 0; -+} -+ -+static int -+read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) -+{ -+ return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val); -+} -+ -+static int -+read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) -+{ -+ return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val); -+} -+ -+static int -+read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) -+{ -+ return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val); -+} -+ -+static int -+write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) -+{ -+ if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val)) -+ return -1; -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int -+write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) -+{ -+ if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val)) -+ return -1; -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int -+write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) -+{ -+ if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val)) -+ return -1; -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+ -+static int -+pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -+{ -+ switch (size) { -+ case 1: -+ return read_config_byte(bus, devfn, where, (u8 *) val); -+ case 2: -+ return read_config_word(bus, devfn, where, (u16 *) val); -+ default: -+ return read_config_dword(bus, devfn, where, val); -+ } -+} -+ -+static int -+pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -+{ -+ switch (size) { -+ case 1: -+ return write_config_byte(bus, devfn, where, (u8) val); -+ case 2: -+ return write_config_word(bus, devfn, where, (u16) val); -+ default: -+ return write_config_dword(bus, devfn, where, val); -+ } -+} -+ -+struct pci_ops mt7621_pci_ops= { -+ .read = pci_config_read, -+ .write = pci_config_write, -+}; -+ -+static struct resource mt7621_res_pci_mem1 = { -+ .name = "PCI MEM1", -+ .start = RALINK_PCI_MM_MAP_BASE, -+ .end = (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), -+ .flags = IORESOURCE_MEM, -+}; -+static struct resource mt7621_res_pci_io1 = { -+ .name = "PCI I/O1", -+ .start = RALINK_PCI_IO_MAP_BASE, -+ .end = (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), -+ .flags = IORESOURCE_IO, -+}; -+ -+static struct pci_controller mt7621_controller = { -+ .pci_ops = &mt7621_pci_ops, -+ .mem_resource = &mt7621_res_pci_mem1, -+ .io_resource = &mt7621_res_pci_io1, -+ .mem_offset = 0x00000000UL, -+ .io_offset = 0x00000000UL, -+ .io_map_base = 0xa0000000, -+}; -+ -+static void -+read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val) -+{ -+ unsigned int address_reg, data_reg, address; -+ -+ address_reg = RALINK_PCI_CONFIG_ADDR; -+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; -+ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; -+ MV_WRITE(address_reg, address); -+ MV_READ(data_reg, val); -+ return; -+} -+ -+static void -+write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val) -+{ -+ unsigned int address_reg, data_reg, address; -+ -+ address_reg = RALINK_PCI_CONFIG_ADDR; -+ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; -+ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; -+ MV_WRITE(address_reg, address); -+ MV_WRITE(data_reg, val); -+ return; -+} -+ -+ -+int -+pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ u16 cmd; -+ u32 val; -+ int irq = 0; -+ -+ if ((dev->bus->number == 0) && (slot == 0)) { -+ write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); -+ read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); -+ printk("BAR0 at slot 0 = %x\n", val); -+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); -+ } else if((dev->bus->number == 0) && (slot == 0x1)) { -+ write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); -+ read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); -+ printk("BAR0 at slot 1 = %x\n", val); -+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); -+ } else if((dev->bus->number == 0) && (slot == 0x2)) { -+ write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); -+ read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); -+ printk("BAR0 at slot 2 = %x\n", val); -+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); -+ } else if ((dev->bus->number == 1) && (slot == 0x0)) { -+ switch (pcie_link_status) { -+ case 2: -+ case 6: -+ irq = RALINK_INT_PCIE1; -+ break; -+ case 4: -+ irq = RALINK_INT_PCIE2; -+ break; -+ default: -+ irq = RALINK_INT_PCIE0; -+ } -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else if ((dev->bus->number == 2) && (slot == 0x0)) { -+ switch (pcie_link_status) { -+ case 5: -+ case 6: -+ irq = RALINK_INT_PCIE2; -+ break; -+ default: -+ irq = RALINK_INT_PCIE1; -+ } -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else if ((dev->bus->number == 2) && (slot == 0x1)) { -+ switch (pcie_link_status) { -+ case 5: -+ case 6: -+ irq = RALINK_INT_PCIE2; -+ break; -+ default: -+ irq = RALINK_INT_PCIE1; -+ } -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else if ((dev->bus->number ==3) && (slot == 0x0)) { -+ irq = RALINK_INT_PCIE2; -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else if ((dev->bus->number ==3) && (slot == 0x1)) { -+ irq = RALINK_INT_PCIE2; -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else if ((dev->bus->number ==3) && (slot == 0x2)) { -+ irq = RALINK_INT_PCIE2; -+ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); -+ } else { -+ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); -+ return 0; -+ } -+ -+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 -+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; -+ pci_write_config_word(dev, PCI_COMMAND, cmd); -+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -+ return irq; -+} -+ -+void -+set_pcie_phy(u32 *addr, int start_b, int bits, int val) -+{ -+// printk("0x%p:", addr); -+// printk(" %x", *addr); -+ *(unsigned int *)(addr) &= ~(((1< %x\n", *addr); -+} -+ -+void -+bypass_pipe_rst(void) -+{ -+#if defined (CONFIG_PCIE_PORT0) -+ /* PCIe Port 0 */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ /* PCIe Port 1 */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ /* PCIe Port 2 */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] -+#endif -+} -+ -+void -+set_phy_for_ssc(void) -+{ -+ unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)); -+ -+ reg = (reg >> 6) & 0x7; -+#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1) -+ /* Set PCIe Port0 & Port1 PHY to disable SSC */ -+ /* Debug Xtal Type */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable -+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) -+ printk("***** Xtal 40MHz *****\n"); -+ } else { // 25MHz | 20MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) -+ if (reg >= 6) { -+ printk("***** Xtal 25MHz *****\n"); -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial -+ } else { -+ printk("***** Xtal 20MHz *****\n"); -+ } -+ } -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN -+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv -+ } -+ /* Enable PHY and disable force mode */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ /* Set PCIe Port2 PHY to disable SSC */ -+ /* Debug Xtal Type */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable -+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) -+ } else { // 25MHz | 20MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) -+ if (reg >= 6) { // 25MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial -+ } -+ } -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN -+ if(reg <= 5 && reg >= 3) { // 40MHz Xtal -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv -+ } -+ /* Enable PHY and disable force mode */ -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable -+ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control -+#endif -+} -+ -+void setup_cm_memory_region(struct resource *mem_resource) -+{ -+ resource_size_t mask; -+ if (mips_cps_numiocu(0)) { -+ /* FIXME: hardware doesn't accept mask values with 1s after -+ 0s (e.g. 0xffef), so it would be great to warn if that's -+ about to happen */ -+ mask = ~(mem_resource->end - mem_resource->start); -+ -+ write_gcr_reg1_base(mem_resource->start); -+ write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); -+ printk("PCI coherence region base: 0x%08lx, mask/settings: 0x%08lx\n", -+ read_gcr_reg1_base(), -+ read_gcr_reg1_mask()); -+ } -+} -+ -+static int mt7621_pci_probe(struct platform_device *pdev) -+{ -+ unsigned long val = 0; -+ int i; -+ -+ for (i = 0; i < 3; i++) -+ pcie_irq[i] = irq_of_parse_and_map(pdev->dev.of_node, i); -+ -+ iomem_resource.start = 0; -+ iomem_resource.end= ~0; -+ ioport_resource.start= 0; -+ ioport_resource.end = ~0; -+ -+#if defined (CONFIG_PCIE_PORT0) -+ val = RALINK_PCIE0_RST; -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ val |= RALINK_PCIE1_RST; -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ val |= RALINK_PCIE2_RST; -+#endif -+ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST); -+ printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); -+#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ -+ *(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3); -+ *(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3; -+ mdelay(100); -+ *(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3) -+ mdelay(100); -+ *(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7); // clear DATA -+ -+ mdelay(100); -+#else -+ *(unsigned int *)(0xbe000060) &= ~0x00000c00; -+#endif -+#if defined (CONFIG_PCIE_PORT0) -+ val = RALINK_PCIE0_RST; -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ val |= RALINK_PCIE1_RST; -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ val |= RALINK_PCIE2_RST; -+#endif -+ DEASSERT_SYSRST_PCIE(val); -+ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); -+ -+ if ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2 -+ bypass_pipe_rst(); -+ set_phy_for_ssc(); -+ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); -+ -+#if defined (CONFIG_PCIE_PORT0) -+ read_config(0, 0, 0, 0x70c, &val); -+ printk("Port 0 N_FTS = %x\n", (unsigned int)val); -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ read_config(0, 1, 0, 0x70c, &val); -+ printk("Port 1 N_FTS = %x\n", (unsigned int)val); -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ read_config(0, 2, 0, 0x70c, &val); -+ printk("Port 2 N_FTS = %x\n", (unsigned int)val); -+#endif -+ -+ RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST); -+ RALINK_SYSCFG1 &= ~(0x30); -+ RALINK_SYSCFG1 |= (2<<4); -+ RALINK_PCIE_CLK_GEN &= 0x7fffffff; -+ RALINK_PCIE_CLK_GEN1 &= 0x80ffffff; -+ RALINK_PCIE_CLK_GEN1 |= 0xa << 24; -+ RALINK_PCIE_CLK_GEN |= 0x80000000; -+ mdelay(50); -+ RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST); -+ -+ -+#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ -+ *(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // set DATA -+ mdelay(100); -+#else -+ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST -+#endif -+ mdelay(500); -+ -+ -+ mdelay(500); -+#if defined (CONFIG_PCIE_PORT0) -+ if(( RALINK_PCI0_STATUS & 0x1) == 0) -+ { -+ printk("PCIE0 no card, disable it(RST&CLK)\n"); -+ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST); -+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN); -+ pcie_link_status &= ~(1<<0); -+ } else { -+ pcie_link_status |= 1<<0; -+ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt -+ } -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ if(( RALINK_PCI1_STATUS & 0x1) == 0) -+ { -+ printk("PCIE1 no card, disable it(RST&CLK)\n"); -+ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST); -+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN); -+ pcie_link_status &= ~(1<<1); -+ } else { -+ pcie_link_status |= 1<<1; -+ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt -+ } -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ if (( RALINK_PCI2_STATUS & 0x1) == 0) { -+ printk("PCIE2 no card, disable it(RST&CLK)\n"); -+ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST); -+ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN); -+ pcie_link_status &= ~(1<<2); -+ } else { -+ pcie_link_status |= 1<<2; -+ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt -+ } -+#endif -+ if (pcie_link_status == 0) -+ return 0; -+ -+/* -+pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num -+3'b000 x x x -+3'b001 x x 0 -+3'b010 x 0 x -+3'b011 x 1 0 -+3'b100 0 x x -+3'b101 1 x 0 -+3'b110 1 0 x -+3'b111 2 1 0 -+*/ -+ switch(pcie_link_status) { -+ case 2: -+ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000; -+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 -+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 -+ break; -+ case 4: -+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; -+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 -+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 -+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 24; //port2 -+ break; -+ case 5: -+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; -+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 16; //port0 -+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 -+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 -+ break; -+ case 6: -+ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; -+ RALINK_PCI_PCICFG_ADDR |= 0x2 << 16; //port0 -+ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 -+ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 -+ break; -+ } -+ printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR); -+ //printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL); -+ -+/* -+ ioport_resource.start = mt7621_res_pci_io1.start; -+ ioport_resource.end = mt7621_res_pci_io1.end; -+*/ -+ -+ RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE; -+ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; -+ -+#if defined (CONFIG_PCIE_PORT0) -+ //PCIe0 -+ if((pcie_link_status & 0x1) != 0) { -+ RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE -+ RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE; -+ RALINK_PCI0_CLASS = 0x06040001; -+ printk("PCIE0 enabled\n"); -+ } -+#endif -+#if defined (CONFIG_PCIE_PORT1) -+ //PCIe1 -+ if ((pcie_link_status & 0x2) != 0) { -+ RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE -+ RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE; -+ RALINK_PCI1_CLASS = 0x06040001; -+ printk("PCIE1 enabled\n"); -+ } -+#endif -+#if defined (CONFIG_PCIE_PORT2) -+ //PCIe2 -+ if ((pcie_link_status & 0x4) != 0) { -+ RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE -+ RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE; -+ RALINK_PCI2_CLASS = 0x06040001; -+ printk("PCIE2 enabled\n"); -+ } -+#endif -+ -+ -+ switch(pcie_link_status) { -+ case 7: -+ read_config(0, 2, 0, 0x4, &val); -+ write_config(0, 2, 0, 0x4, val|0x4); -+ // write_config(0, 1, 0, 0x4, val|0x7); -+ read_config(0, 2, 0, 0x70c, &val); -+ val &= ~(0xff)<<8; -+ val |= 0x50<<8; -+ write_config(0, 2, 0, 0x70c, val); -+ case 3: -+ case 5: -+ case 6: -+ read_config(0, 1, 0, 0x4, &val); -+ write_config(0, 1, 0, 0x4, val|0x4); -+ // write_config(0, 1, 0, 0x4, val|0x7); -+ read_config(0, 1, 0, 0x70c, &val); -+ val &= ~(0xff)<<8; -+ val |= 0x50<<8; -+ write_config(0, 1, 0, 0x70c, val); -+ default: -+ read_config(0, 0, 0, 0x4, &val); -+ write_config(0, 0, 0, 0x4, val|0x4); //bus master enable -+ // write_config(0, 0, 0, 0x4, val|0x7); //bus master enable -+ read_config(0, 0, 0, 0x70c, &val); -+ val &= ~(0xff)<<8; -+ val |= 0x50<<8; -+ write_config(0, 0, 0, 0x70c, val); -+ } -+ -+ pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node); -+ setup_cm_memory_region(mt7621_controller.mem_resource); -+ register_pci_controller(&mt7621_controller); -+ return 0; -+ -+} -+ -+int pcibios_plat_dev_init(struct pci_dev *dev) -+{ -+ return 0; -+} -+ -+static const struct of_device_id mt7621_pci_ids[] = { -+ { .compatible = "mediatek,mt7621-pci" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mt7621_pci_ids); -+ -+static struct platform_driver mt7621_pci_driver = { -+ .probe = mt7621_pci_probe, -+ .driver = { -+ .name = "mt7621-pci", -+ .owner = THIS_MODULE, -+ .of_match_table = of_match_ptr(mt7621_pci_ids), -+ }, -+}; -+ -+static int __init mt7621_pci_init(void) -+{ -+ return platform_driver_register(&mt7621_pci_driver); -+} -+ -+arch_initcall(mt7621_pci_init); diff --git a/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch b/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch index 90215fbf86..a3b8e4d250 100644 --- a/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch +++ b/target/linux/ramips/patches-5.4/0006-MIPS-ralink-add-cpu-frequency-scaling.patch @@ -179,7 +179,7 @@ Signed-off-by: John Crispin + /* register clock event */ systick.dev.irq = irq_of_parse_and_map(np, 0); if (!systick.dev.irq) { - pr_err("%s: request_irq failed", np->name); + pr_err("%pOFn: request_irq failed", np); return -EINVAL; } @@ -196,5 +196,5 @@ Signed-off-by: John Crispin + systick.dev.cpumask = cpumask_of(0); + clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); - pr_info("%s: running - mult: %d, shift: %d\n", - np->name, systick.dev.mult, systick.dev.shift); + pr_info("%pOFn: running - mult: %d, shift: %d\n", + np, systick.dev.mult, systick.dev.shift); diff --git a/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch b/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch index c05ee8018d..54af571d85 100644 --- a/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch +++ b/target/linux/ramips/patches-5.4/0007-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c -@@ -82,6 +82,8 @@ void __init plat_mem_setup(void) +@@ -80,6 +80,8 @@ void __init plat_mem_setup(void) __dt_setup_arch(dtb); diff --git a/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch b/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch deleted file mode 100644 index 6ca15fe32e..0000000000 --- a/target/linux/ramips/patches-5.4/0009-PCI-MIPS-enable-PCIe-on-MT7688.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7768798964eb0e4f95eaecffb93b5d0ca28a38af Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sat, 3 Jun 2017 20:00:03 +0200 -Subject: [PATCH] MIPS: pci-mt7620: enabled PCIe on MT7688 -To: linux-mips@linux-mips.org, - John Crispin -Cc: Wei Yongjun , - Ralf Baechle , - linux-mediatek@lists.infradead.org - -Use PCIe support for MT7628AN also on MT7688. -Tested on WRTNODE2R. - -Signed-off-by: Daniel Golle ---- - arch/mips/pci/pci-mt7620.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/mips/pci/pci-mt7620.c -+++ b/arch/mips/pci/pci-mt7620.c -@@ -316,6 +316,7 @@ static int mt7620_pci_probe(struct platf - break; - - case MT762X_SOC_MT7628AN: -+ case MT762X_SOC_MT7688: - if (mt7628_pci_hw_init(pdev)) - return -1; - break; diff --git a/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch b/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch index 442f3180a3..75c93c7e50 100644 --- a/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch +++ b/target/linux/ramips/patches-5.4/0013-owrt-hack-fix-mt7688-cache-issue.patch @@ -10,15 +10,15 @@ Signed-off-by: John Crispin --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c -@@ -910,7 +910,6 @@ static void __init arch_mem_init(char ** - crashk_res.end - crashk_res.start + 1, - BOOTMEM_DEFAULT); +@@ -652,7 +652,6 @@ static void __init arch_mem_init(char ** + memblock_reserve(crashk_res.start, + crashk_res.end - crashk_res.start + 1); #endif - device_tree_init(); sparse_init(); plat_swiotlb_setup(); -@@ -1026,6 +1025,7 @@ void __init setup_arch(char **cmdline_p) +@@ -760,6 +759,7 @@ void __init setup_arch(char **cmdline_p) cpu_cache_init(); paging_init(); diff --git a/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch b/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch index 61ed9ea784..d4ea379159 100644 --- a/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch +++ b/target/linux/ramips/patches-5.4/0024-GPIO-add-named-gpio-exports.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c -@@ -23,6 +23,8 @@ +@@ -19,6 +19,8 @@ #include #include #include @@ -21,9 +21,9 @@ Signed-off-by: John Crispin +#include #include "gpiolib.h" - -@@ -513,3 +515,68 @@ void of_gpiochip_remove(struct gpio_chip - gpiochip_remove_pin_ranges(chip); + #include "gpiolib-of.h" +@@ -915,3 +917,68 @@ void of_gpiochip_remove(struct gpio_chip + { of_node_put(chip->of_node); } + @@ -93,7 +93,7 @@ Signed-off-by: John Crispin +module_platform_driver(gpio_export_driver); --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c -@@ -553,7 +553,7 @@ static struct class gpio_class = { +@@ -563,7 +563,7 @@ static struct class gpio_class = { * * Returns zero on success, else an error. */ @@ -102,7 +102,7 @@ Signed-off-by: John Crispin { struct gpio_chip *chip; struct gpio_device *gdev; -@@ -615,6 +615,8 @@ int gpiod_export(struct gpio_desc *desc, +@@ -625,6 +625,8 @@ int gpiod_export(struct gpio_desc *desc, offset = gpio_chip_hwgpio(desc); if (chip->names && chip->names[offset]) ioname = chip->names[offset]; @@ -111,7 +111,7 @@ Signed-off-by: John Crispin dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, -@@ -636,6 +638,12 @@ err_unlock: +@@ -646,6 +648,12 @@ err_unlock: gpiod_dbg(desc, "%s: status %d\n", __func__, status); return status; } @@ -141,7 +141,7 @@ Signed-off-by: John Crispin { --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h -@@ -451,6 +451,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_ +@@ -668,6 +668,7 @@ static inline void devm_acpi_dev_remove_ #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) @@ -149,7 +149,7 @@ Signed-off-by: John Crispin int gpiod_export(struct gpio_desc *desc, bool direction_may_change); int gpiod_export_link(struct device *dev, const char *name, struct gpio_desc *desc); -@@ -458,6 +459,13 @@ void gpiod_unexport(struct gpio_desc *de +@@ -675,6 +676,13 @@ void gpiod_unexport(struct gpio_desc *de #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ diff --git a/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch b/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch deleted file mode 100644 index a374e01b59..0000000000 --- a/target/linux/ramips/patches-5.4/0025-pinctrl-ralink-add-pinctrl-driver.patch +++ /dev/null @@ -1,524 +0,0 @@ -From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:34:05 +0100 -Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver - -Signed-off-by: John Crispin ---- - arch/mips/Kconfig | 2 + - drivers/pinctrl/Kconfig | 5 + - drivers/pinctrl/Makefile | 1 + - drivers/pinctrl/pinctrl-rt2880.c | 474 ++++++++++++++++++++++++++++++++++++++ - 4 files changed, 482 insertions(+) - create mode 100644 drivers/pinctrl/pinctrl-rt2880.c - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -629,6 +629,8 @@ config RALINK - select CLKDEV_LOOKUP - select ARCH_HAS_RESET_CONTROLLER - select RESET_CONTROLLER -+ select PINCTRL -+ select PINCTRL_RT2880 - - config SGI_IP22 - bool "SGI IP22 (Indy/Indigo2)" ---- a/drivers/pinctrl/Kconfig -+++ b/drivers/pinctrl/Kconfig -@@ -143,6 +143,11 @@ config PINCTRL_LPC18XX - help - Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU). - -+config PINCTRL_RT2880 -+ bool -+ depends on RALINK -+ select PINMUX -+ - config PINCTRL_FALCON - bool - depends on SOC_FALCON ---- a/drivers/pinctrl/Makefile -+++ b/drivers/pinctrl/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl- - obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o - obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o - obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o -+obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o - obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o - obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o - obj-$(CONFIG_PINCTRL_SIRF) += sirf/ ---- /dev/null -+++ b/drivers/pinctrl/pinctrl-rt2880.c -@@ -0,0 +1,472 @@ -+/* -+ * linux/drivers/pinctrl/pinctrl-rt2880.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * publishhed by the Free Software Foundation. -+ * -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "core.h" -+ -+#define SYSC_REG_GPIO_MODE 0x60 -+#define SYSC_REG_GPIO_MODE2 0x64 -+ -+struct rt2880_priv { -+ struct device *dev; -+ -+ struct pinctrl_pin_desc *pads; -+ struct pinctrl_desc *desc; -+ -+ struct rt2880_pmx_func **func; -+ int func_count; -+ -+ struct rt2880_pmx_group *groups; -+ const char **group_names; -+ int group_count; -+ -+ uint8_t *gpio; -+ int max_pins; -+}; -+ -+static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ return p->group_count; -+} -+ -+static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, -+ unsigned group) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ if (group >= p->group_count) -+ return NULL; -+ -+ return p->group_names[group]; -+} -+ -+static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, -+ unsigned group, -+ const unsigned **pins, -+ unsigned *num_pins) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ if (group >= p->group_count) -+ return -EINVAL; -+ -+ *pins = p->groups[group].func[0].pins; -+ *num_pins = p->groups[group].func[0].pin_count; -+ -+ return 0; -+} -+ -+static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, -+ struct pinctrl_map *map, unsigned num_maps) -+{ -+ int i; -+ -+ for (i = 0; i < num_maps; i++) -+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || -+ map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) -+ kfree(map[i].data.configs.configs); -+ kfree(map); -+} -+ -+static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, -+ struct seq_file *s, -+ unsigned offset) -+{ -+ seq_printf(s, "ralink pio"); -+} -+ -+static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, -+ struct device_node *np, -+ struct pinctrl_map **map) -+{ -+ const char *function; -+ int func = of_property_read_string(np, "ralink,function", &function); -+ int grps = of_property_count_strings(np, "ralink,group"); -+ int i; -+ -+ if (func || !grps) -+ return; -+ -+ for (i = 0; i < grps; i++) { -+ const char *group; -+ -+ of_property_read_string_index(np, "ralink,group", i, &group); -+ -+ (*map)->type = PIN_MAP_TYPE_MUX_GROUP; -+ (*map)->name = function; -+ (*map)->data.mux.group = group; -+ (*map)->data.mux.function = function; -+ (*map)++; -+ } -+} -+ -+static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, -+ struct device_node *np_config, -+ struct pinctrl_map **map, -+ unsigned *num_maps) -+{ -+ int max_maps = 0; -+ struct pinctrl_map *tmp; -+ struct device_node *np; -+ -+ for_each_child_of_node(np_config, np) { -+ int ret = of_property_count_strings(np, "ralink,group"); -+ -+ if (ret >= 0) -+ max_maps += ret; -+ } -+ -+ if (!max_maps) -+ return -EINVAL; -+ -+ *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); -+ if (!*map) -+ return -ENOMEM; -+ -+ tmp = *map; -+ -+ for_each_child_of_node(np_config, np) -+ rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); -+ *num_maps = max_maps; -+ -+ return 0; -+} -+ -+static const struct pinctrl_ops rt2880_pctrl_ops = { -+ .get_groups_count = rt2880_get_group_count, -+ .get_group_name = rt2880_get_group_name, -+ .get_group_pins = rt2880_get_group_pins, -+ .pin_dbg_show = rt2880_pinctrl_pin_dbg_show, -+ .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, -+ .dt_free_map = rt2880_pinctrl_dt_free_map, -+}; -+ -+static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ return p->func_count; -+} -+ -+static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, -+ unsigned func) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ return p->func[func]->name; -+} -+ -+static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, -+ unsigned func, -+ const char * const **groups, -+ unsigned * const num_groups) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ if (p->func[func]->group_count == 1) -+ *groups = &p->group_names[p->func[func]->groups[0]]; -+ else -+ *groups = p->group_names; -+ -+ *num_groups = p->func[func]->group_count; -+ -+ return 0; -+} -+ -+static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, -+ unsigned func, -+ unsigned group) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ u32 mode = 0; -+ u32 reg = SYSC_REG_GPIO_MODE; -+ int i; -+ int shift; -+ -+ /* dont allow double use */ -+ if (p->groups[group].enabled) { -+ dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); -+ return -EBUSY; -+ } -+ -+ p->groups[group].enabled = 1; -+ p->func[func]->enabled = 1; -+ -+ shift = p->groups[group].shift; -+ if (shift >= 32) { -+ shift -= 32; -+ reg = SYSC_REG_GPIO_MODE2; -+ } -+ mode = rt_sysc_r32(reg); -+ mode &= ~(p->groups[group].mask << shift); -+ -+ /* mark the pins as gpio */ -+ for (i = 0; i < p->groups[group].func[0].pin_count; i++) -+ p->gpio[p->groups[group].func[0].pins[i]] = 1; -+ -+ /* function 0 is gpio and needs special handling */ -+ if (func == 0) { -+ mode |= p->groups[group].gpio << shift; -+ } else { -+ for (i = 0; i < p->func[func]->pin_count; i++) -+ p->gpio[p->func[func]->pins[i]] = 0; -+ mode |= p->func[func]->value << shift; -+ } -+ rt_sysc_w32(mode, reg); -+ -+ return 0; -+} -+ -+static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, -+ struct pinctrl_gpio_range *range, -+ unsigned pin) -+{ -+ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); -+ -+ if (!p->gpio[pin]) { -+ dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static const struct pinmux_ops rt2880_pmx_group_ops = { -+ .get_functions_count = rt2880_pmx_func_count, -+ .get_function_name = rt2880_pmx_func_name, -+ .get_function_groups = rt2880_pmx_group_get_groups, -+ .set_mux = rt2880_pmx_group_enable, -+ .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, -+}; -+ -+static struct pinctrl_desc rt2880_pctrl_desc = { -+ .owner = THIS_MODULE, -+ .name = "rt2880-pinmux", -+ .pctlops = &rt2880_pctrl_ops, -+ .pmxops = &rt2880_pmx_group_ops, -+}; -+ -+static struct rt2880_pmx_func gpio_func = { -+ .name = "gpio", -+}; -+ -+static int rt2880_pinmux_index(struct rt2880_priv *p) -+{ -+ struct rt2880_pmx_func **f; -+ struct rt2880_pmx_group *mux = p->groups; -+ int i, j, c = 0; -+ -+ /* count the mux functions */ -+ while (mux->name) { -+ p->group_count++; -+ mux++; -+ } -+ -+ /* allocate the group names array needed by the gpio function */ -+ p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); -+ if (!p->group_names) -+ return -1; -+ -+ for (i = 0; i < p->group_count; i++) { -+ p->group_names[i] = p->groups[i].name; -+ p->func_count += p->groups[i].func_count; -+ } -+ -+ /* we have a dummy function[0] for gpio */ -+ p->func_count++; -+ -+ /* allocate our function and group mapping index buffers */ -+ f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); -+ gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); -+ if (!f || !gpio_func.groups) -+ return -1; -+ -+ /* add a backpointer to the function so it knows its group */ -+ gpio_func.group_count = p->group_count; -+ for (i = 0; i < gpio_func.group_count; i++) -+ gpio_func.groups[i] = i; -+ -+ f[c] = &gpio_func; -+ c++; -+ -+ /* add remaining functions */ -+ for (i = 0; i < p->group_count; i++) { -+ for (j = 0; j < p->groups[i].func_count; j++) { -+ f[c] = &p->groups[i].func[j]; -+ f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); -+ f[c]->groups[0] = i; -+ f[c]->group_count = 1; -+ c++; -+ } -+ } -+ return 0; -+} -+ -+static int rt2880_pinmux_pins(struct rt2880_priv *p) -+{ -+ int i, j; -+ -+ /* loop over the functions and initialize the pins array. also work out the highest pin used */ -+ for (i = 0; i < p->func_count; i++) { -+ int pin; -+ -+ if (!p->func[i]->pin_count) -+ continue; -+ -+ p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); -+ for (j = 0; j < p->func[i]->pin_count; j++) -+ p->func[i]->pins[j] = p->func[i]->pin_first + j; -+ -+ pin = p->func[i]->pin_first + p->func[i]->pin_count; -+ if (pin > p->max_pins) -+ p->max_pins = pin; -+ } -+ -+ /* the buffer that tells us which pins are gpio */ -+ p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, -+ GFP_KERNEL); -+ /* the pads needed to tell pinctrl about our pins */ -+ p->pads = devm_kzalloc(p->dev, -+ sizeof(struct pinctrl_pin_desc) * p->max_pins, -+ GFP_KERNEL); -+ if (!p->pads || !p->gpio ) { -+ dev_err(p->dev, "Failed to allocate gpio data\n"); -+ return -ENOMEM; -+ } -+ -+ memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); -+ for (i = 0; i < p->func_count; i++) { -+ if (!p->func[i]->pin_count) -+ continue; -+ -+ for (j = 0; j < p->func[i]->pin_count; j++) -+ p->gpio[p->func[i]->pins[j]] = 0; -+ } -+ -+ /* pin 0 is always a gpio */ -+ p->gpio[0] = 1; -+ -+ /* set the pads */ -+ for (i = 0; i < p->max_pins; i++) { -+ /* strlen("ioXY") + 1 = 5 */ -+ char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); -+ -+ if (!name) { -+ dev_err(p->dev, "Failed to allocate pad name\n"); -+ return -ENOMEM; -+ } -+ snprintf(name, 5, "io%d", i); -+ p->pads[i].number = i; -+ p->pads[i].name = name; -+ } -+ p->desc->pins = p->pads; -+ p->desc->npins = p->max_pins; -+ -+ return 0; -+} -+ -+static int rt2880_pinmux_probe(struct platform_device *pdev) -+{ -+ struct rt2880_priv *p; -+ struct pinctrl_dev *dev; -+ struct device_node *np; -+ -+ if (!rt2880_pinmux_data) -+ return -ENOSYS; -+ -+ /* setup the private data */ -+ p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); -+ if (!p) -+ return -ENOMEM; -+ -+ p->dev = &pdev->dev; -+ p->desc = &rt2880_pctrl_desc; -+ p->groups = rt2880_pinmux_data; -+ platform_set_drvdata(pdev, p); -+ -+ /* init the device */ -+ if (rt2880_pinmux_index(p)) { -+ dev_err(&pdev->dev, "failed to load index\n"); -+ return -EINVAL; -+ } -+ if (rt2880_pinmux_pins(p)) { -+ dev_err(&pdev->dev, "failed to load pins\n"); -+ return -EINVAL; -+ } -+ dev = pinctrl_register(p->desc, &pdev->dev, p); -+ if (IS_ERR(dev)) -+ return PTR_ERR(dev); -+ -+ /* finalize by adding gpio ranges for enables gpio controllers */ -+ for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { -+ const __be32 *ngpio, *gpiobase; -+ struct pinctrl_gpio_range *range; -+ char *name; -+ -+ if (!of_device_is_available(np)) -+ continue; -+ -+ ngpio = of_get_property(np, "ralink,nr-gpio", NULL); -+ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); -+ if (!ngpio || !gpiobase) { -+ dev_err(&pdev->dev, "failed to load chip info\n"); -+ return -EINVAL; -+ } -+ -+ range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); -+ range->name = name = (char *) &range[1]; -+ sprintf(name, "pio"); -+ range->npins = __be32_to_cpu(*ngpio); -+ range->base = __be32_to_cpu(*gpiobase); -+ range->pin_base = range->base; -+ pinctrl_add_gpio_range(dev, range); -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id rt2880_pinmux_match[] = { -+ { .compatible = "ralink,rt2880-pinmux" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); -+ -+static struct platform_driver rt2880_pinmux_driver = { -+ .probe = rt2880_pinmux_probe, -+ .driver = { -+ .name = "rt2880-pinmux", -+ .owner = THIS_MODULE, -+ .of_match_table = rt2880_pinmux_match, -+ }, -+}; -+ -+int __init rt2880_pinmux_init(void) -+{ -+ return platform_driver_register(&rt2880_pinmux_driver); -+} -+ -+core_initcall_sync(rt2880_pinmux_init); diff --git a/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch index eaae0d3d02..3d78ef40c6 100644 --- a/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch +++ b/target/linux/ramips/patches-5.4/0027-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch @@ -47,9 +47,9 @@ Cc: linux-gpio@vger.kernel.org +#endif /* __ASM_MACH_RALINK_GPIO_H */ --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig -@@ -398,6 +398,12 @@ config GPIO_REG - A 32-bit single register GPIO fixed in/out implementation. This - can be used to represent any register as a set of GPIO signals. +@@ -471,6 +471,12 @@ config GPIO_SNPS_CREG + where only several fields in register belong to GPIO lines and + each GPIO line owns a field with different length and on/off value. +config GPIO_RALINK + bool "Ralink GPIO Support" @@ -62,17 +62,17 @@ Cc: linux-gpio@vger.kernel.org depends on PLAT_SPEAR --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile -@@ -98,6 +98,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-p - obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o - obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o - obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o -+obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o - obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o - obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o - obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +@@ -112,6 +112,7 @@ obj-$(CONFIG_GPIO_PISOSR) += gpio-pisos + obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o + obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o ++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o + obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o --- /dev/null +++ b/drivers/gpio/gpio-ralink.c -@@ -0,0 +1,355 @@ +@@ -0,0 +1,341 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published @@ -328,20 +328,6 @@ Cc: linux-gpio@vger.kernel.org + dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio); +} + -+static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset) -+{ -+ int gpio = chip->base + offset; -+ -+ return pinctrl_request_gpio(gpio); -+} -+ -+static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset) -+{ -+ int gpio = chip->base + offset; -+ -+ pinctrl_free_gpio(gpio); -+} -+ +static int ralink_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; @@ -393,9 +379,9 @@ Cc: linux-gpio@vger.kernel.org + rg->chip.direction_output = ralink_gpio_direction_output; + rg->chip.get = ralink_gpio_get; + rg->chip.set = ralink_gpio_set; -+ rg->chip.request = ralink_gpio_request; ++ rg->chip.request = gpiochip_generic_request; + rg->chip.to_irq = ralink_gpio_to_irq; -+ rg->chip.free = ralink_gpio_free; ++ rg->chip.free = gpiochip_generic_free; + + /* set polarity to low for all lines */ + rt_gpio_w32(rg, GPIO_REG_POL, 0); diff --git a/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch b/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch deleted file mode 100644 index debeae2806..0000000000 --- a/target/linux/ramips/patches-5.4/0028-GPIO-ralink-add-mt7621-gpio-controller.patch +++ /dev/null @@ -1,405 +0,0 @@ -From 61ac7d9b4228de8c332900902c2b93189b042eab Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 11:00:32 +0100 -Subject: [PATCH 28/53] GPIO: ralink: add mt7621 gpio controller - -Signed-off-by: John Crispin ---- - arch/mips/Kconfig | 3 + - drivers/gpio/Kconfig | 6 + - drivers/gpio/Makefile | 1 + - drivers/gpio/gpio-mt7621.c | 354 ++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 364 insertions(+) - create mode 100644 drivers/gpio/gpio-mt7621.c - ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -631,6 +631,9 @@ config RALINK - select RESET_CONTROLLER - select PINCTRL - select PINCTRL_RT2880 -+ select ARCH_HAS_RESET_CONTROLLER -+ select RESET_CONTROLLER -+ select ARCH_REQUIRE_GPIOLIB - - config SGI_IP22 - bool "SGI IP22 (Indy/Indigo2)" ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -298,6 +298,12 @@ config GPIO_MENZ127 - help - Say yes here to support the MEN 16Z127 GPIO Controller - -+config GPIO_MT7621 -+ bool "Mediatek GPIO Support" -+ depends on SOC_MT7620 || SOC_MT7621 -+ help -+ Say yes here to support the Mediatek SoC GPIO device -+ - config GPIO_MM_LANTIQ - bool "Lantiq Memory mapped GPIOs" - depends on LANTIQ && SOC_XWAY ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -152,3 +152,4 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o - obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o - obj-$(CONFIG_GPIO_ZX) += gpio-zx.o - obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o -+obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o ---- /dev/null -+++ b/drivers/gpio/gpio-mt7621.c -@@ -0,0 +1,354 @@ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ * -+ * Copyright (C) 2009-2011 Gabor Juhos -+ * Copyright (C) 2013 John Crispin -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define MTK_MAX_BANK 3 -+#define MTK_BANK_WIDTH 32 -+ -+enum mediatek_gpio_reg { -+ GPIO_REG_CTRL = 0, -+ GPIO_REG_POL, -+ GPIO_REG_DATA, -+ GPIO_REG_DSET, -+ GPIO_REG_DCLR, -+ GPIO_REG_REDGE, -+ GPIO_REG_FEDGE, -+ GPIO_REG_HLVL, -+ GPIO_REG_LLVL, -+ GPIO_REG_STAT, -+ GPIO_REG_EDGE, -+}; -+ -+static void __iomem *mediatek_gpio_membase; -+static int mediatek_gpio_irq; -+static struct irq_domain *mediatek_gpio_irq_domain; -+static atomic_t irq_refcount = ATOMIC_INIT(0); -+ -+struct mtk_gc { -+ struct gpio_chip chip; -+ spinlock_t lock; -+ int bank; -+ u32 rising; -+ u32 falling; -+} *gc_map[MTK_MAX_BANK]; -+ -+static inline struct mtk_gc -+*to_mediatek_gpio(struct gpio_chip *chip) -+{ -+ struct mtk_gc *mgc; -+ -+ mgc = container_of(chip, struct mtk_gc, chip); -+ -+ return mgc; -+} -+ -+static inline void -+mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val) -+{ -+ iowrite32(val, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); -+} -+ -+static inline u32 -+mtk_gpio_r32(struct mtk_gc *rg, u8 reg) -+{ -+ return ioread32(mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); -+} -+ -+static void -+mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ -+ mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset)); -+} -+ -+static int -+mediatek_gpio_get(struct gpio_chip *chip, unsigned offset) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ -+ return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); -+} -+ -+static int -+mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); -+ t &= ~BIT(offset); -+ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int -+mediatek_gpio_direction_output(struct gpio_chip *chip, -+ unsigned offset, int value) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); -+ t |= BIT(offset); -+ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); -+ mediatek_gpio_set(chip, offset, value); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ return 0; -+} -+ -+static int -+mediatek_gpio_get_direction(struct gpio_chip *chip, unsigned offset) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ unsigned long flags; -+ u32 t; -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); -+ spin_unlock_irqrestore(&rg->lock, flags); -+ -+ if (t & BIT(offset)) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin) -+{ -+ struct mtk_gc *rg = to_mediatek_gpio(chip); -+ -+ return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH)); -+} -+ -+static int -+mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank) -+{ -+ const __be32 *id = of_get_property(bank, "reg", NULL); -+ struct mtk_gc *rg = devm_kzalloc(&pdev->dev, -+ sizeof(struct mtk_gc), GFP_KERNEL); -+ -+ if (!rg || !id || be32_to_cpu(*id) > MTK_MAX_BANK) -+ return -ENOMEM; -+ -+ gc_map[be32_to_cpu(*id)] = rg; -+ -+ memset(rg, 0, sizeof(struct mtk_gc)); -+ -+ spin_lock_init(&rg->lock); -+ -+ rg->chip.parent = &pdev->dev; -+ rg->chip.label = dev_name(&pdev->dev); -+ rg->chip.of_node = bank; -+ rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id); -+ rg->chip.ngpio = MTK_BANK_WIDTH; -+ rg->chip.direction_input = mediatek_gpio_direction_input; -+ rg->chip.direction_output = mediatek_gpio_direction_output; -+ rg->chip.get_direction = mediatek_gpio_get_direction; -+ rg->chip.get = mediatek_gpio_get; -+ rg->chip.set = mediatek_gpio_set; -+ if (mediatek_gpio_irq_domain) -+ rg->chip.to_irq = mediatek_gpio_to_irq; -+ rg->bank = be32_to_cpu(*id); -+ -+ /* set polarity to low for all gpios */ -+ mtk_gpio_w32(rg, GPIO_REG_POL, 0); -+ -+ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); -+ -+ return gpiochip_add(&rg->chip); -+} -+ -+static void -+mediatek_gpio_irq_handler(struct irq_desc *desc) -+{ -+ int i; -+ -+ for (i = 0; i < MTK_MAX_BANK; i++) { -+ struct mtk_gc *rg = gc_map[i]; -+ unsigned long pending; -+ int bit; -+ -+ if (!rg) -+ continue; -+ -+ pending = mtk_gpio_r32(rg, GPIO_REG_STAT); -+ -+ for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { -+ u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit); -+ -+ generic_handle_irq(map); -+ mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); -+ } -+ } -+} -+ -+static void -+mediatek_gpio_irq_unmask(struct irq_data *d) -+{ -+ int pin = d->hwirq; -+ int bank = pin / 32; -+ struct mtk_gc *rg = gc_map[bank]; -+ unsigned long flags; -+ u32 rise, fall; -+ -+ if (!rg) -+ return; -+ -+ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); -+ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising)); -+ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling)); -+ spin_unlock_irqrestore(&rg->lock, flags); -+} -+ -+static void -+mediatek_gpio_irq_mask(struct irq_data *d) -+{ -+ int pin = d->hwirq; -+ int bank = pin / 32; -+ struct mtk_gc *rg = gc_map[bank]; -+ unsigned long flags; -+ u32 rise, fall; -+ -+ if (!rg) -+ return; -+ -+ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); -+ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); -+ -+ spin_lock_irqsave(&rg->lock, flags); -+ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq)); -+ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq)); -+ spin_unlock_irqrestore(&rg->lock, flags); -+} -+ -+static int -+mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) -+{ -+ int pin = d->hwirq; -+ int bank = pin / 32; -+ struct mtk_gc *rg = gc_map[bank]; -+ u32 mask = BIT(d->hwirq); -+ -+ if (!rg) -+ return -1; -+ -+ if (type == IRQ_TYPE_PROBE) { -+ if ((rg->rising | rg->falling) & mask) -+ return 0; -+ -+ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; -+ } -+ -+ if (type & IRQ_TYPE_EDGE_RISING) -+ rg->rising |= mask; -+ else -+ rg->rising &= ~mask; -+ -+ if (type & IRQ_TYPE_EDGE_FALLING) -+ rg->falling |= mask; -+ else -+ rg->falling &= ~mask; -+ -+ return 0; -+} -+ -+static struct irq_chip mediatek_gpio_irq_chip = { -+ .name = "GPIO", -+ .irq_unmask = mediatek_gpio_irq_unmask, -+ .irq_mask = mediatek_gpio_irq_mask, -+ .irq_mask_ack = mediatek_gpio_irq_mask, -+ .irq_set_type = mediatek_gpio_irq_type, -+}; -+ -+static int -+mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) -+{ -+ irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq); -+ irq_set_handler_data(irq, d); -+ -+ return 0; -+} -+ -+static const struct irq_domain_ops irq_domain_ops = { -+ .xlate = irq_domain_xlate_onecell, -+ .map = mediatek_gpio_gpio_map, -+}; -+ -+static int -+mediatek_gpio_probe(struct platform_device *pdev) -+{ -+ struct device_node *bank, *np = pdev->dev.of_node; -+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ -+ mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(mediatek_gpio_membase)) -+ return PTR_ERR(mediatek_gpio_membase); -+ -+ mediatek_gpio_irq = irq_of_parse_and_map(np, 0); -+ if (mediatek_gpio_irq) { -+ mediatek_gpio_irq_domain = irq_domain_add_linear(np, -+ MTK_MAX_BANK * MTK_BANK_WIDTH, -+ &irq_domain_ops, NULL); -+ if (!mediatek_gpio_irq_domain) -+ dev_err(&pdev->dev, "irq_domain_add_linear failed\n"); -+ } -+ -+ for_each_child_of_node(np, bank) -+ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank")) -+ mediatek_gpio_bank_probe(pdev, bank); -+ -+ if (mediatek_gpio_irq_domain) -+ irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler); -+ -+ return 0; -+} -+ -+static const struct of_device_id mediatek_gpio_match[] = { -+ { .compatible = "mtk,mt7621-gpio" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mediatek_gpio_match); -+ -+static struct platform_driver mediatek_gpio_driver = { -+ .probe = mediatek_gpio_probe, -+ .driver = { -+ .name = "mt7621_gpio", -+ .owner = THIS_MODULE, -+ .of_match_table = mediatek_gpio_match, -+ }, -+}; -+ -+static int __init -+mediatek_gpio_init(void) -+{ -+ return platform_driver_register(&mediatek_gpio_driver); -+} -+ -+subsys_initcall(mediatek_gpio_init); diff --git a/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch index 7ed1a616f6..084b655483 100644 --- a/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch +++ b/target/linux/ramips/patches-5.4/0031-uvc-add-iPassion-iP2970-support.patch @@ -13,10 +13,10 @@ Signed-off-by: John Crispin --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c -@@ -2749,6 +2749,18 @@ static const struct usb_device_id uvc_id +@@ -2908,6 +2908,18 @@ static const struct usb_device_id uvc_id .bInterfaceSubClass = 1, .bInterfaceProtocol = 0, - .driver_info = UVC_QUIRK_FORCE_Y8 }, + .driver_info = UVC_INFO_META(V4L2_META_FMT_D4XX) }, + /* iPassion iP2970 */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, @@ -34,15 +34,15 @@ Signed-off-by: John Crispin { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, --- a/drivers/media/usb/uvc/uvc_status.c +++ b/drivers/media/usb/uvc/uvc_status.c -@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u - switch (dev->status[0] & 0x0f) { - case UVC_STATUS_TYPE_CONTROL: - uvc_event_control(dev, dev->status, len); +@@ -223,6 +223,7 @@ static void uvc_status_complete(struct u + if (uvc_event_control(urb, status, len)) + /* The URB will be resubmitted in work context. */ + return; + dev->motion = 1; break; + } - case UVC_STATUS_TYPE_STREAMING: -@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d +@@ -271,6 +272,7 @@ int uvc_status_init(struct uvc_device *d } pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); @@ -52,7 +52,7 @@ Signed-off-by: John Crispin * an exponent of two. Some developers forgot about it. --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c -@@ -21,6 +21,11 @@ +@@ -16,6 +16,11 @@ #include #include #include @@ -64,8 +64,8 @@ Signed-off-by: John Crispin #include -@@ -1101,9 +1106,149 @@ static void uvc_video_decode_data(struct - } +@@ -1156,9 +1161,149 @@ static void uvc_video_decode_data(struct + uvc_urb->async_operations++; } +struct bh_priv { @@ -196,7 +196,7 @@ Signed-off-by: John Crispin + +#define MOTION_FLAG_OFFSET 4 static void uvc_video_decode_end(struct uvc_streaming *stream, - struct uvc_buffer *buf, const __u8 *data, int len) + struct uvc_buffer *buf, const u8 *data, int len) { + if ((stream->dev->quirks & UVC_QUIRK_MOTION) && + (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { @@ -214,7 +214,7 @@ Signed-off-by: John Crispin /* Mark the buffer as done if the EOF marker is set. */ if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); -@@ -1518,6 +1663,8 @@ static int uvc_init_video_isoc(struct uv +@@ -1715,6 +1860,8 @@ static int uvc_init_video_isoc(struct uv if (npackets == 0) return -ENOMEM; @@ -222,13 +222,13 @@ Signed-off-by: John Crispin + npackets = 1; size = npackets * psize; - for (i = 0; i < UVC_URBS; ++i) { + for_each_uvc_urb(uvc_urb, stream) { --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h -@@ -186,7 +186,9 @@ - #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 +@@ -199,7 +199,9 @@ #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400 #define UVC_QUIRK_FORCE_Y8 0x00000800 + #define UVC_QUIRK_FORCE_BPP 0x00001000 - +#define UVC_QUIRK_MOTION 0x00001000 +#define UVC_QUIRK_SINGLE_ISO 0x00002000 @@ -236,11 +236,11 @@ Signed-off-by: John Crispin /* Format flags */ #define UVC_FMT_FLAG_COMPRESSED 0x00000001 #define UVC_FMT_FLAG_STREAM 0x00000002 -@@ -584,6 +586,7 @@ struct uvc_device { - __u8 *status; +@@ -666,6 +668,7 @@ struct uvc_device { + u8 *status; struct input_dev *input; char input_phys[64]; + int motion; - }; - enum uvc_handle_state { + struct uvc_ctrl_work { + struct work_struct work; diff --git a/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch b/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch index c04e2db661..ec837cda93 100644 --- a/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch +++ b/target/linux/ramips/patches-5.4/0032-USB-dwc2-add-device_reset.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c -@@ -48,6 +48,7 @@ +@@ -49,6 +49,7 @@ #include #include #include @@ -18,12 +18,12 @@ Signed-off-by: John Crispin #include #include -@@ -5215,6 +5216,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso +@@ -5023,6 +5024,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso retval = -ENOMEM; + device_reset(hsotg->dev); + - hcfg = dwc2_readl(hsotg->regs + HCFG); + hcfg = dwc2_readl(hsotg, HCFG); dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); diff --git a/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch b/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch deleted file mode 100644 index 5536e3f61c..0000000000 --- a/target/linux/ramips/patches-5.4/0034-NET-multi-phy-support.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:38:50 +0100 -Subject: [PATCH 34/53] NET: multi phy support - -Signed-off-by: John Crispin ---- - drivers/net/phy/phy.c | 9 ++++++--- - include/linux/phy.h | 1 + - 2 files changed, 7 insertions(+), 3 deletions(-) - ---- a/drivers/net/phy/phy.c -+++ b/drivers/net/phy/phy.c -@@ -913,7 +913,10 @@ void phy_state_machine(struct work_struc - /* If the link is down, give up on negotiation for now */ - if (!phydev->link) { - phydev->state = PHY_NOLINK; -- phy_link_down(phydev, true); -+ if (!phydev->no_auto_carrier_off) -+ phy_link_down(phydev, true); -+ else -+ phy_link_down(phydev, false); - break; - } - -@@ -1000,7 +1003,10 @@ void phy_state_machine(struct work_struc - phy_link_up(phydev); - } else { - phydev->state = PHY_NOLINK; -- phy_link_down(phydev, true); -+ if (!phydev->no_auto_carrier_off) -+ phy_link_down(phydev, true); -+ else -+ phy_link_down(phydev, false); - } - - if (phy_interrupt_is_valid(phydev)) -@@ -1010,7 +1016,10 @@ void phy_state_machine(struct work_struc - case PHY_HALTED: - if (phydev->link) { - phydev->link = 0; -- phy_link_down(phydev, true); -+ if (!phydev->no_auto_carrier_off) -+ phy_link_down(phydev, true); -+ else -+ phy_link_down(phydev, false); - do_suspend = true; - } - break; ---- a/include/linux/phy.h -+++ b/include/linux/phy.h -@@ -412,6 +412,7 @@ struct phy_device { - bool suspended; - bool sysfs_links; - bool loopback_enabled; -+ bool no_auto_carrier_off; - - enum phy_state state; - diff --git a/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch b/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch index 478af4cbc9..7011bbe50b 100644 --- a/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch +++ b/target/linux/ramips/patches-5.4/0037-mtd-cfi-cmdset-0002-force-word-write.patch @@ -18,53 +18,3 @@ Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write #define MAX_RETRIES 3 -@@ -51,7 +51,9 @@ - - static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+#if !FORCE_WORD_WRITE - static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -+#endif - static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); - static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); - static void cfi_amdstd_sync (struct mtd_info *); -@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m - } - #endif - -+#if !FORCE_WORD_WRITE - static void fixup_use_write_buffers(struct mtd_info *mtd) - { - struct map_info *map = mtd->priv; -@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru - mtd->_write = cfi_amdstd_write_buffers; - } - } -+#endif /* !FORCE_WORD_WRITE */ - - /* Atmel chips don't use the same PRI format as AMD chips */ - static void fixup_convert_atmel_pri(struct mtd_info *mtd) -@@ -1798,6 +1802,7 @@ static int cfi_amdstd_write_words(struct - /* - * FIXME: interleaved mode not tested, and probably not supported! - */ -+#if !FORCE_WORD_WRITE - static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, - unsigned long adr, const u_char *buf, - int len) -@@ -1926,7 +1931,6 @@ static int __xipram do_write_buffer(stru - return ret; - } - -- - static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) - { -@@ -2001,6 +2005,7 @@ static int cfi_amdstd_write_buffers(stru - - return 0; - } -+#endif /* !FORCE_WORD_WRITE */ - - /* - * Wait for the flash chip to become ready to write data diff --git a/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch b/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch deleted file mode 100644 index 4758f18558..0000000000 --- a/target/linux/ramips/patches-5.4/0038-Revert-mtd-nand-Remove-unused-chip-write_page-hook.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -Subject: [PATCH] Revert "mtd: nand: Remove unused chip->write_page() hook" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This reverts commit f107d7a43923a83d837b3ea3c7b7de58cd014bbd. - -OpenWrt's downstream driver mtk_nand2 still uses that callback. - -Signed-off-by: Rafał Miłecki ---- - ---- a/drivers/mtd/nand/nand_base.c -+++ b/drivers/mtd/nand/nand_base.c -@@ -2577,7 +2577,7 @@ static int nand_write_page_syndrome(stru - } - - /** -- * nand_write_page - write one page -+ * nand_write_page - [REPLACEABLE] write one page - * @mtd: MTD device structure - * @chip: NAND chip descriptor - * @offset: address offset within the page -@@ -2761,9 +2761,9 @@ static int nand_do_write_ops(struct mtd_ - memset(chip->oob_poi, 0xff, mtd->oobsize); - } - -- ret = nand_write_page(mtd, chip, column, bytes, wbuf, -- oob_required, page, -- (ops->mode == MTD_OPS_RAW)); -+ ret = chip->write_page(mtd, chip, column, bytes, wbuf, -+ oob_required, page, -+ (ops->mode == MTD_OPS_RAW)); - if (ret) - break; - -@@ -4719,6 +4719,9 @@ int nand_scan_tail(struct mtd_info *mtd) - } - } - -+ if (!chip->write_page) -+ chip->write_page = nand_write_page; -+ - /* - * Check ECC mode, default to software if 3byte/512byte hardware ECC is - * selected and we have 256 byte pagesize fallback to software ECC ---- a/include/linux/mtd/rawnand.h -+++ b/include/linux/mtd/rawnand.h -@@ -862,6 +862,7 @@ struct nand_manufacturer_ops { - * structure which is shared among multiple independent - * devices. - * @priv: [OPTIONAL] pointer to private chip data -+ * @write_page: [REPLACEABLE] High-level page write function - * @manufacturer: [INTERN] Contains manufacturer information - */ - -@@ -885,6 +886,9 @@ struct nand_chip { - int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this); - int (*erase)(struct mtd_info *mtd, int page); - int (*scan_bbt)(struct mtd_info *mtd); -+ int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, -+ uint32_t offset, int data_len, const uint8_t *buf, -+ int oob_required, int page, int raw); - int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip, - int feature_addr, uint8_t *subfeature_para); - int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip, diff --git a/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch b/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch deleted file mode 100644 index 3c6a59b863..0000000000 --- a/target/linux/ramips/patches-5.4/0039-mtd-add-mt7621-nand-support.patch +++ /dev/null @@ -1,4437 +0,0 @@ -From 0e1c4e3c97b83b4e7da65b1c56f0a7d40736ac53 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 11:05:17 +0100 -Subject: [PATCH 39/53] mtd: add mt7621 nand support - -Signed-off-by: John Crispin ---- - drivers/mtd/nand/Kconfig | 6 + - drivers/mtd/nand/Makefile | 1 + - drivers/mtd/nand/bmt.c | 750 ++++++++++++ - drivers/mtd/nand/bmt.h | 80 ++ - drivers/mtd/nand/dev-nand.c | 63 + - drivers/mtd/nand/mt6575_typedefs.h | 340 ++++++ - drivers/mtd/nand/mtk_nand2.c | 2304 +++++++++++++++++++++++++++++++++++ - drivers/mtd/nand/mtk_nand2.h | 452 +++++++ - drivers/mtd/nand/nand_base.c | 6 +- - drivers/mtd/nand/nand_def.h | 123 ++ - drivers/mtd/nand/nand_device_list.h | 55 + - drivers/mtd/nand/partition.h | 115 ++ - 13 files changed, 4311 insertions(+), 3 deletions(-) - create mode 100644 drivers/mtd/nand/bmt.c - create mode 100644 drivers/mtd/nand/bmt.h - create mode 100644 drivers/mtd/nand/dev-nand.c - create mode 100644 drivers/mtd/nand/mt6575_typedefs.h - create mode 100644 drivers/mtd/nand/mtk_nand2.c - create mode 100644 drivers/mtd/nand/mtk_nand2.h - create mode 100644 drivers/mtd/nand/nand_def.h - create mode 100644 drivers/mtd/nand/nand_device_list.h - create mode 100644 drivers/mtd/nand/partition.h - ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -563,4 +563,10 @@ config MTD_NAND_MTK - Enables support for NAND controller on MTK SoCs. - This controller is found on mt27xx, mt81xx, mt65xx SoCs. - -+config MTK_MTD_NAND -+ tristate "Support for MTK SoC NAND controller" -+ depends on SOC_MT7621 -+ select MTD_NAND_IDS -+ select MTD_NAND_ECC -+ - endif # MTD_NAND ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -60,6 +60,7 @@ obj-$(CONFIG_MTD_NAND_HISI504) + - obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ - obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o - obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o -+obj-$(CONFIG_MTK_MTD_NAND) += mtk_nand2.o bmt.o - - nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o - nand-objs += nand_amd.o ---- /dev/null -+++ b/drivers/mtd/nand/bmt.c -@@ -0,0 +1,750 @@ -+#include "bmt.h" -+ -+typedef struct -+{ -+ char signature[3]; -+ u8 version; -+ u8 bad_count; // bad block count in pool -+ u8 mapped_count; // mapped block count in pool -+ u8 checksum; -+ u8 reseverd[13]; -+} phys_bmt_header; -+ -+typedef struct -+{ -+ phys_bmt_header header; -+ bmt_entry table[MAX_BMT_SIZE]; -+} phys_bmt_struct; -+ -+typedef struct -+{ -+ char signature[3]; -+} bmt_oob_data; -+ -+static char MAIN_SIGNATURE[] = "BMT"; -+static char OOB_SIGNATURE[] = "bmt"; -+#define SIGNATURE_SIZE (3) -+ -+#define MAX_DAT_SIZE 0x1000 -+#define MAX_OOB_SIZE 0x80 -+ -+static struct mtd_info *mtd_bmt; -+static struct nand_chip *nand_chip_bmt; -+#define BLOCK_SIZE_BMT (1 << nand_chip_bmt->phys_erase_shift) -+#define PAGE_SIZE_BMT (1 << nand_chip_bmt->page_shift) -+ -+#define OFFSET(block) ((block) * BLOCK_SIZE_BMT) -+#define PAGE_ADDR(block) ((block) * BLOCK_SIZE_BMT / PAGE_SIZE_BMT) -+ -+/********************************************************************* -+* Flash is splited into 2 parts, system part is for normal system * -+* system usage, size is system_block_count, another is replace pool * -+* +-------------------------------------------------+ * -+* | system_block_count | bmt_block_count | * -+* +-------------------------------------------------+ * -+*********************************************************************/ -+static u32 total_block_count; // block number in flash -+static u32 system_block_count; -+static int bmt_block_count; // bmt table size -+// static int bmt_count; // block used in bmt -+static int page_per_block; // page per count -+ -+static u32 bmt_block_index; // bmt block index -+static bmt_struct bmt; // dynamic created global bmt table -+ -+static u8 dat_buf[MAX_DAT_SIZE]; -+static u8 oob_buf[MAX_OOB_SIZE]; -+static bool pool_erased; -+ -+/*************************************************************** -+* -+* Interface adaptor for preloader/uboot/kernel -+* These interfaces operate on physical address, read/write -+* physical data. -+* -+***************************************************************/ -+int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob) -+{ -+ return mtk_nand_exec_read_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob); -+} -+ -+bool nand_block_bad_bmt(u32 offset) -+{ -+ return mtk_nand_block_bad_hw(mtd_bmt, offset); -+} -+ -+bool nand_erase_bmt(u32 offset) -+{ -+ int status; -+ if (offset < 0x20000) -+ { -+ MSG(INIT, "erase offset: 0x%x\n", offset); -+ } -+ -+ status = mtk_nand_erase_hw(mtd_bmt, offset / PAGE_SIZE_BMT); // as nand_chip structure doesn't have a erase function defined -+ if (status & NAND_STATUS_FAIL) -+ return false; -+ else -+ return true; -+} -+ -+int mark_block_bad_bmt(u32 offset) -+{ -+ return mtk_nand_block_markbad_hw(mtd_bmt, offset); //mark_block_bad_hw(offset); -+} -+ -+bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob) -+{ -+ if (mtk_nand_exec_write_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob)) -+ return false; -+ else -+ return true; -+} -+ -+/*************************************************************** -+* * -+* static internal function * -+* * -+***************************************************************/ -+static void dump_bmt_info(bmt_struct * bmt) -+{ -+ int i; -+ -+ MSG(INIT, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count); -+ for (i = 0; i < bmt->mapped_count; i++) -+ { -+ MSG(INIT, "\t0x%x -> 0x%x\n", bmt->table[i].bad_index, bmt->table[i].mapped_index); -+ } -+} -+ -+static bool match_bmt_signature(u8 * dat, u8 * oob) -+{ -+ -+ if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE)) -+ { -+ return false; -+ } -+ -+ if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE)) -+ { -+ MSG(INIT, "main signature match, oob signature doesn't match, but ignore\n"); -+ } -+ return true; -+} -+ -+static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size) -+{ -+ int i; -+ u8 checksum = 0; -+ u8 *dat = (u8 *) phys_table; -+ -+ checksum += phys_table->header.version; -+ checksum += phys_table->header.mapped_count; -+ -+ dat += sizeof(phys_bmt_header); -+ for (i = 0; i < bmt_size * sizeof(bmt_entry); i++) -+ { -+ checksum += dat[i]; -+ } -+ -+ return checksum; -+} -+ -+ -+static int is_block_mapped(int index) -+{ -+ int i; -+ for (i = 0; i < bmt.mapped_count; i++) -+ { -+ if (index == bmt.table[i].mapped_index) -+ return i; -+ } -+ return -1; -+} -+ -+static bool is_page_used(u8 * dat, u8 * oob) -+{ -+ return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF)); -+} -+ -+static bool valid_bmt_data(phys_bmt_struct * phys_table) -+{ -+ int i; -+ u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count); -+ -+ // checksum correct? -+ if (phys_table->header.checksum != checksum) -+ { -+ MSG(INIT, "BMT Data checksum error: %x %x\n", phys_table->header.checksum, checksum); -+ return false; -+ } -+ -+ MSG(INIT, "BMT Checksum is: 0x%x\n", phys_table->header.checksum); -+ -+ // block index correct? -+ for (i = 0; i < phys_table->header.mapped_count; i++) -+ { -+ if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count) -+ { -+ MSG(INIT, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index); -+ return false; -+ } -+ } -+ -+ // pass check, valid bmt. -+ MSG(INIT, "Valid BMT, version v%d\n", phys_table->header.version); -+ return true; -+} -+ -+static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob) -+{ -+ phys_bmt_struct phys_bmt; -+ -+ dump_bmt_info(bmt); -+ -+ // fill phys_bmt_struct structure with bmt_struct -+ memset(&phys_bmt, 0xFF, sizeof(phys_bmt)); -+ -+ memcpy(phys_bmt.header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE); -+ phys_bmt.header.version = BMT_VERSION; -+ // phys_bmt.header.bad_count = bmt->bad_count; -+ phys_bmt.header.mapped_count = bmt->mapped_count; -+ memcpy(phys_bmt.table, bmt->table, sizeof(bmt_entry) * bmt_block_count); -+ -+ phys_bmt.header.checksum = cal_bmt_checksum(&phys_bmt, bmt_block_count); -+ -+ memcpy(dat + MAIN_SIGNATURE_OFFSET, &phys_bmt, sizeof(phys_bmt)); -+ memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE); -+} -+ -+// return valid index if found BMT, else return 0 -+static int load_bmt_data(int start, int pool_size) -+{ -+ int bmt_index = start + pool_size - 1; // find from the end -+ phys_bmt_struct phys_table; -+ int i; -+ -+ MSG(INIT, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index); -+ -+ for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--) -+ { -+ if (nand_block_bad_bmt(OFFSET(bmt_index))) -+ { -+ MSG(INIT, "Skip bad block: %d\n", bmt_index); -+ continue; -+ } -+ -+ if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf)) -+ { -+ MSG(INIT, "Error found when read block %d\n", bmt_index); -+ continue; -+ } -+ -+ if (!match_bmt_signature(dat_buf, oob_buf)) -+ { -+ continue; -+ } -+ -+ MSG(INIT, "Match bmt signature @ block: 0x%x\n", bmt_index); -+ -+ memcpy(&phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_table)); -+ -+ if (!valid_bmt_data(&phys_table)) -+ { -+ MSG(INIT, "BMT data is not correct %d\n", bmt_index); -+ continue; -+ } else -+ { -+ bmt.mapped_count = phys_table.header.mapped_count; -+ bmt.version = phys_table.header.version; -+ // bmt.bad_count = phys_table.header.bad_count; -+ memcpy(bmt.table, phys_table.table, bmt.mapped_count * sizeof(bmt_entry)); -+ -+ MSG(INIT, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count); -+ -+ for (i = 0; i < bmt.mapped_count; i++) -+ { -+ if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index))) -+ { -+ MSG(INIT, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index); -+ mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index)); -+ } -+ } -+ -+ return bmt_index; -+ } -+ } -+ -+ MSG(INIT, "bmt block not found!\n"); -+ return 0; -+} -+ -+/************************************************************************* -+* Find an available block and erase. * -+* start_from_end: if true, find available block from end of flash. * -+* else, find from the beginning of the pool * -+* need_erase: if true, all unmapped blocks in the pool will be erased * -+*************************************************************************/ -+static int find_available_block(bool start_from_end) -+{ -+ int i; // , j; -+ int block = system_block_count; -+ int direction; -+ // int avail_index = 0; -+ MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased); -+ -+ // erase all un-mapped blocks in pool when finding avaliable block -+ if (!pool_erased) -+ { -+ MSG(INIT, "Erase all un-mapped blocks in pool\n"); -+ for (i = 0; i < bmt_block_count; i++) -+ { -+ if (block == bmt_block_index) -+ { -+ MSG(INIT, "Skip bmt block 0x%x\n", block); -+ continue; -+ } -+ -+ if (nand_block_bad_bmt(OFFSET(block + i))) -+ { -+ MSG(INIT, "Skip bad block 0x%x\n", block + i); -+ continue; -+ } -+//if(block==4095) -+//{ -+// continue; -+//} -+ -+ if (is_block_mapped(block + i) >= 0) -+ { -+ MSG(INIT, "Skip mapped block 0x%x\n", block + i); -+ continue; -+ } -+ -+ if (!nand_erase_bmt(OFFSET(block + i))) -+ { -+ MSG(INIT, "Erase block 0x%x failed\n", block + i); -+ mark_block_bad_bmt(OFFSET(block + i)); -+ } -+ } -+ -+ pool_erased = 1; -+ } -+ -+ if (start_from_end) -+ { -+ block = total_block_count - 1; -+ direction = -1; -+ } else -+ { -+ block = system_block_count; -+ direction = 1; -+ } -+ -+ for (i = 0; i < bmt_block_count; i++, block += direction) -+ { -+ if (block == bmt_block_index) -+ { -+ MSG(INIT, "Skip bmt block 0x%x\n", block); -+ continue; -+ } -+ -+ if (nand_block_bad_bmt(OFFSET(block))) -+ { -+ MSG(INIT, "Skip bad block 0x%x\n", block); -+ continue; -+ } -+ -+ if (is_block_mapped(block) >= 0) -+ { -+ MSG(INIT, "Skip mapped block 0x%x\n", block); -+ continue; -+ } -+ -+ MSG(INIT, "Find block 0x%x available\n", block); -+ return block; -+ } -+ -+ return 0; -+} -+ -+static unsigned short get_bad_index_from_oob(u8 * oob_buf) -+{ -+ unsigned short index; -+ memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE); -+ -+ return index; -+} -+ -+void set_bad_index_to_oob(u8 * oob, u16 index) -+{ -+ memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index)); -+} -+ -+static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob) -+{ -+ int page; -+ int error_block = offset / BLOCK_SIZE_BMT; -+ int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; -+ int to_index; -+ -+ memcpy(oob_buf, write_oob, MAX_OOB_SIZE); -+ -+ to_index = find_available_block(false); -+ -+ if (!to_index) -+ { -+ MSG(INIT, "Cannot find an available block for BMT\n"); -+ return 0; -+ } -+ -+ { // migrate error page first -+ MSG(INIT, "Write error page: 0x%x\n", error_page); -+ if (!write_dat) -+ { -+ nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL); -+ write_dat = dat_buf; -+ } -+ // memcpy(oob_buf, write_oob, MAX_OOB_SIZE); -+ -+ if (error_block < system_block_count) -+ set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. -+ -+ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) -+ { -+ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page); -+ mark_block_bad_bmt(to_index); -+ return migrate_from_bad(offset, write_dat, write_oob); -+ } -+ } -+ -+ for (page = 0; page < page_per_block; page++) -+ { -+ if (page != error_page) -+ { -+ nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); -+ if (is_page_used(dat_buf, oob_buf)) -+ { -+ if (error_block < system_block_count) -+ { -+ set_bad_index_to_oob(oob_buf, error_block); -+ } -+ MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page); -+ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) -+ { -+ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page); -+ mark_block_bad_bmt(to_index); -+ return migrate_from_bad(offset, write_dat, write_oob); -+ } -+ } -+ } -+ } -+ -+ MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index); -+ -+ return to_index; -+} -+ -+static bool write_bmt_to_flash(u8 * dat, u8 * oob) -+{ -+ bool need_erase = true; -+ MSG(INIT, "Try to write BMT\n"); -+ -+ if (bmt_block_index == 0) -+ { -+ // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() -+ need_erase = false; -+ if (!(bmt_block_index = find_available_block(true))) -+ { -+ MSG(INIT, "Cannot find an available block for BMT\n"); -+ return false; -+ } -+ } -+ -+ MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index); -+ -+ // write bmt to flash -+ if (need_erase) -+ { -+ if (!nand_erase_bmt(OFFSET(bmt_block_index))) -+ { -+ MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); -+ mark_block_bad_bmt(OFFSET(bmt_block_index)); -+ // bmt.bad_count++; -+ -+ bmt_block_index = 0; -+ return write_bmt_to_flash(dat, oob); // recursive call -+ } -+ } -+ -+ if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob)) -+ { -+ MSG(INIT, "Write BMT data fail, need to write again\n"); -+ mark_block_bad_bmt(OFFSET(bmt_block_index)); -+ // bmt.bad_count++; -+ -+ bmt_block_index = 0; -+ return write_bmt_to_flash(dat, oob); // recursive call -+ } -+ -+ MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index); -+ return true; -+} -+ -+/******************************************************************* -+* Reconstruct bmt, called when found bmt info doesn't match bad -+* block info in flash. -+* -+* Return NULL for failure -+*******************************************************************/ -+bmt_struct *reconstruct_bmt(bmt_struct * bmt) -+{ -+ int i; -+ int index = system_block_count; -+ unsigned short bad_index; -+ int mapped; -+ -+ // init everything in BMT struct -+ bmt->version = BMT_VERSION; -+ bmt->bad_count = 0; -+ bmt->mapped_count = 0; -+ -+ memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry)); -+ -+ for (i = 0; i < bmt_block_count; i++, index++) -+ { -+ if (nand_block_bad_bmt(OFFSET(index))) -+ { -+ MSG(INIT, "Skip bad block: 0x%x\n", index); -+ // bmt->bad_count++; -+ continue; -+ } -+ -+ MSG(INIT, "read page: 0x%x\n", PAGE_ADDR(index)); -+ nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf); -+ /* if (mtk_nand_read_page_hw(PAGE_ADDR(index), dat_buf)) -+ { -+ MSG(INIT, "Error when read block %d\n", bmt_block_index); -+ continue; -+ } */ -+ -+ if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count) -+ { -+ MSG(INIT, "get bad index: 0x%x\n", bad_index); -+ if (bad_index != 0xFFFF) -+ MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index); -+ continue; -+ } -+ -+ MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index); -+ -+ if (!nand_block_bad_bmt(OFFSET(bad_index))) -+ { -+ MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index); -+ continue; // no need to erase here, it will be erased later when trying to write BMT -+ } -+ -+ if ((mapped = is_block_mapped(bad_index)) >= 0) -+ { -+ MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index); -+ bmt->table[mapped].mapped_index = index; // use new one instead. -+ } else -+ { -+ // add mapping to BMT -+ bmt->table[bmt->mapped_count].bad_index = bad_index; -+ bmt->table[bmt->mapped_count].mapped_index = index; -+ bmt->mapped_count++; -+ } -+ -+ MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index); -+ -+ } -+ -+ MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count); -+ // dump_bmt_info(bmt); -+ -+ // fill NAND BMT buffer -+ memset(oob_buf, 0xFF, sizeof(oob_buf)); -+ fill_nand_bmt_buffer(bmt, dat_buf, oob_buf); -+ -+ // write BMT back -+ if (!write_bmt_to_flash(dat_buf, oob_buf)) -+ { -+ MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n"); -+ } -+ -+ return bmt; -+} -+ -+/******************************************************************* -+* [BMT Interface] -+* -+* Description: -+* Init bmt from nand. Reconstruct if not found or data error -+* -+* Parameter: -+* size: size of bmt and replace pool -+* -+* Return: -+* NULL for failure, and a bmt struct for success -+*******************************************************************/ -+bmt_struct *init_bmt(struct nand_chip * chip, int size) -+{ -+ struct mtk_nand_host *host; -+ -+ if (size > 0 && size < MAX_BMT_SIZE) -+ { -+ MSG(INIT, "Init bmt table, size: %d\n", size); -+ bmt_block_count = size; -+ } else -+ { -+ MSG(INIT, "Invalid bmt table size: %d\n", size); -+ return NULL; -+ } -+ nand_chip_bmt = chip; -+ system_block_count = chip->chipsize >> chip->phys_erase_shift; -+ total_block_count = bmt_block_count + system_block_count; -+ page_per_block = BLOCK_SIZE_BMT / PAGE_SIZE_BMT; -+ host = (struct mtk_nand_host *)chip->priv; -+ mtd_bmt = host->mtd; -+ -+ MSG(INIT, "mtd_bmt: %p, nand_chip_bmt: %p\n", mtd_bmt, nand_chip_bmt); -+ MSG(INIT, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count); -+ -+ // set this flag, and unmapped block in pool will be erased. -+ pool_erased = 0; -+ memset(bmt.table, 0, size * sizeof(bmt_entry)); -+ if ((bmt_block_index = load_bmt_data(system_block_count, size))) -+ { -+ MSG(INIT, "Load bmt data success @ block 0x%x\n", bmt_block_index); -+ dump_bmt_info(&bmt); -+ return &bmt; -+ } else -+ { -+ MSG(INIT, "Load bmt data fail, need re-construct!\n"); -+#ifndef __UBOOT_NAND__ // BMT is not re-constructed in UBOOT. -+ if (reconstruct_bmt(&bmt)) -+ return &bmt; -+ else -+#endif -+ return NULL; -+ } -+} -+ -+/******************************************************************* -+* [BMT Interface] -+* -+* Description: -+* Update BMT. -+* -+* Parameter: -+* offset: update block/page offset. -+* reason: update reason, see update_reason_t for reason. -+* dat/oob: data and oob buffer for write fail. -+* -+* Return: -+* Return true for success, and false for failure. -+*******************************************************************/ -+bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob) -+{ -+ int map_index; -+ int orig_bad_block = -1; -+ // int bmt_update_index; -+ int i; -+ int bad_index = offset / BLOCK_SIZE_BMT; -+ -+#ifndef MTK_NAND_BMT -+ return false; -+#endif -+ if (reason == UPDATE_WRITE_FAIL) -+ { -+ MSG(INIT, "Write fail, need to migrate\n"); -+ if (!(map_index = migrate_from_bad(offset, dat, oob))) -+ { -+ MSG(INIT, "migrate fail\n"); -+ return false; -+ } -+ } else -+ { -+ if (!(map_index = find_available_block(false))) -+ { -+ MSG(INIT, "Cannot find block in pool\n"); -+ return false; -+ } -+ } -+ -+ // now let's update BMT -+ if (bad_index >= system_block_count) // mapped block become bad, find original bad block -+ { -+ for (i = 0; i < bmt_block_count; i++) -+ { -+ if (bmt.table[i].mapped_index == bad_index) -+ { -+ orig_bad_block = bmt.table[i].bad_index; -+ break; -+ } -+ } -+ // bmt.bad_count++; -+ MSG(INIT, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block); -+ -+ bmt.table[i].mapped_index = map_index; -+ } else -+ { -+ bmt.table[bmt.mapped_count].mapped_index = map_index; -+ bmt.table[bmt.mapped_count].bad_index = bad_index; -+ bmt.mapped_count++; -+ } -+ -+ memset(oob_buf, 0xFF, sizeof(oob_buf)); -+ fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf); -+ if (!write_bmt_to_flash(dat_buf, oob_buf)) -+ return false; -+ -+ mark_block_bad_bmt(offset); -+ -+ return true; -+} -+ -+/******************************************************************* -+* [BMT Interface] -+* -+* Description: -+* Given an block index, return mapped index if it's mapped, else -+* return given index. -+* -+* Parameter: -+* index: given an block index. This value cannot exceed -+* system_block_count. -+* -+* Return NULL for failure -+*******************************************************************/ -+u16 get_mapping_block_index(int index) -+{ -+ int i; -+#ifndef MTK_NAND_BMT -+ return index; -+#endif -+ if (index > system_block_count) -+ { -+ return index; -+ } -+ -+ for (i = 0; i < bmt.mapped_count; i++) -+ { -+ if (bmt.table[i].bad_index == index) -+ { -+ return bmt.table[i].mapped_index; -+ } -+ } -+ -+ return index; -+} -+#ifdef __KERNEL_NAND__ -+EXPORT_SYMBOL_GPL(init_bmt); -+EXPORT_SYMBOL_GPL(update_bmt); -+EXPORT_SYMBOL_GPL(get_mapping_block_index); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("MediaTek"); -+MODULE_DESCRIPTION("Bad Block mapping management for MediaTek NAND Flash Driver"); -+#endif ---- /dev/null -+++ b/drivers/mtd/nand/bmt.h -@@ -0,0 +1,80 @@ -+#ifndef __BMT_H__ -+#define __BMT_H__ -+ -+#include "nand_def.h" -+ -+#if defined(__PRELOADER_NAND__) -+ -+#include "nand.h" -+ -+#elif defined(__UBOOT_NAND__) -+ -+#include -+#include "mtk_nand2.h" -+ -+#elif defined(__KERNEL_NAND__) -+ -+#include -+#include -+#include -+#include "mtk_nand2.h" -+ -+#endif -+ -+ -+#define MAX_BMT_SIZE (0x80) -+#define BMT_VERSION (1) // initial version -+ -+#define MAIN_SIGNATURE_OFFSET (0) -+#define OOB_SIGNATURE_OFFSET (1) -+#define OOB_INDEX_OFFSET (29) -+#define OOB_INDEX_SIZE (2) -+#define FAKE_INDEX (0xAAAA) -+ -+typedef struct _bmt_entry_ -+{ -+ u16 bad_index; // bad block index -+ u16 mapped_index; // mapping block index in the replace pool -+} bmt_entry; -+ -+typedef enum -+{ -+ UPDATE_ERASE_FAIL, -+ UPDATE_WRITE_FAIL, -+ UPDATE_UNMAPPED_BLOCK, -+ UPDATE_REASON_COUNT, -+} update_reason_t; -+ -+typedef struct -+{ -+ bmt_entry table[MAX_BMT_SIZE]; -+ u8 version; -+ u8 mapped_count; // mapped block count in pool -+ u8 bad_count; // bad block count in pool. Not used in V1 -+} bmt_struct; -+ -+/*************************************************************** -+* * -+* Interface BMT need to use * -+* * -+***************************************************************/ -+extern bool mtk_nand_exec_read_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); -+extern int mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs); -+extern int mtk_nand_erase_hw(struct mtd_info *mtd, int page); -+extern int mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t ofs); -+extern int mtk_nand_exec_write_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); -+ -+ -+/*************************************************************** -+* * -+* Different function interface for preloader/uboot/kernel * -+* * -+***************************************************************/ -+void set_bad_index_to_oob(u8 * oob, u16 index); -+ -+ -+bmt_struct *init_bmt(struct nand_chip *nand, int size); -+bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob); -+unsigned short get_mapping_block_index(int index); -+ -+#endif // #ifndef __BMT_H__ ---- /dev/null -+++ b/drivers/mtd/nand/dev-nand.c -@@ -0,0 +1,63 @@ -+#include -+#include -+#include -+ -+#include "mt6575_typedefs.h" -+ -+#define RALINK_NAND_CTRL_BASE 0xBE003000 -+#define NFI_base RALINK_NAND_CTRL_BASE -+#define RALINK_NANDECC_CTRL_BASE 0xBE003800 -+#define NFIECC_base RALINK_NANDECC_CTRL_BASE -+#define MT7621_NFI_IRQ_ID SURFBOARDINT_NAND -+#define MT7621_NFIECC_IRQ_ID SURFBOARDINT_NAND_ECC -+ -+#define SURFBOARDINT_NAND 22 -+#define SURFBOARDINT_NAND_ECC 23 -+ -+static struct resource MT7621_resource_nand[] = { -+ { -+ .start = NFI_base, -+ .end = NFI_base + 0x1A0, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = NFIECC_base, -+ .end = NFIECC_base + 0x150, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = MT7621_NFI_IRQ_ID, -+ .flags = IORESOURCE_IRQ, -+ }, -+ { -+ .start = MT7621_NFIECC_IRQ_ID, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct platform_device MT7621_nand_dev = { -+ .name = "MT7621-NAND", -+ .id = 0, -+ .num_resources = ARRAY_SIZE(MT7621_resource_nand), -+ .resource = MT7621_resource_nand, -+ .dev = { -+ .platform_data = &mt7621_nand_hw, -+ }, -+}; -+ -+ -+int __init mtk_nand_register(void) -+{ -+ -+ int retval = 0; -+ -+ retval = platform_device_register(&MT7621_nand_dev); -+ if (retval != 0) { -+ printk(KERN_ERR "register nand device fail\n"); -+ return retval; -+ } -+ -+ -+ return retval; -+} -+arch_initcall(mtk_nand_register); ---- /dev/null -+++ b/drivers/mtd/nand/mt6575_typedefs.h -@@ -0,0 +1,340 @@ -+/* Copyright Statement: -+ * -+ * This software/firmware and related documentation ("MediaTek Software") are -+ * protected under relevant copyright laws. The information contained herein -+ * is confidential and proprietary to MediaTek Inc. and/or its licensors. -+ * Without the prior written permission of MediaTek inc. and/or its licensors, -+ * any reproduction, modification, use or disclosure of MediaTek Software, -+ * and information contained herein, in whole or in part, shall be strictly prohibited. -+ */ -+/* MediaTek Inc. (C) 2010. All rights reserved. -+ * -+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES -+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") -+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON -+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. -+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE -+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR -+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH -+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES -+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES -+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK -+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR -+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND -+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, -+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, -+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO -+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. -+ * -+ * The following software/firmware and/or related documentation ("MediaTek Software") -+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's -+ * applicable license agreements with MediaTek Inc. -+ */ -+ -+/***************************************************************************** -+* Copyright Statement: -+* -------------------- -+* This software is protected by Copyright and the information contained -+* herein is confidential. The software may not be copied and the information -+* contained herein may not be used or disclosed except with the written -+* permission of MediaTek Inc. (C) 2008 -+* -+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES -+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") -+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON -+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, -+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF -+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. -+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE -+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR -+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH -+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO -+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S -+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. -+* -+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE -+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, -+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, -+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO -+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. -+* -+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE -+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF -+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND -+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER -+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). -+* -+*****************************************************************************/ -+ -+#ifndef _MT6575_TYPEDEFS_H -+#define _MT6575_TYPEDEFS_H -+ -+#if defined (__KERNEL_NAND__) -+#include -+#else -+#define true 1 -+#define false 0 -+#define bool u8 -+#endif -+ -+// --------------------------------------------------------------------------- -+// Basic Type Definitions -+// --------------------------------------------------------------------------- -+ -+typedef volatile unsigned char *P_kal_uint8; -+typedef volatile unsigned short *P_kal_uint16; -+typedef volatile unsigned int *P_kal_uint32; -+ -+typedef long LONG; -+typedef unsigned char UBYTE; -+typedef short SHORT; -+ -+typedef signed char kal_int8; -+typedef signed short kal_int16; -+typedef signed int kal_int32; -+typedef long long kal_int64; -+typedef unsigned char kal_uint8; -+typedef unsigned short kal_uint16; -+typedef unsigned int kal_uint32; -+typedef unsigned long long kal_uint64; -+typedef char kal_char; -+ -+typedef unsigned int *UINT32P; -+typedef volatile unsigned short *UINT16P; -+typedef volatile unsigned char *UINT8P; -+typedef unsigned char *U8P; -+ -+typedef volatile unsigned char *P_U8; -+typedef volatile signed char *P_S8; -+typedef volatile unsigned short *P_U16; -+typedef volatile signed short *P_S16; -+typedef volatile unsigned int *P_U32; -+typedef volatile signed int *P_S32; -+typedef unsigned long long *P_U64; -+typedef signed long long *P_S64; -+ -+typedef unsigned char U8; -+typedef signed char S8; -+typedef unsigned short U16; -+typedef signed short S16; -+typedef unsigned int U32; -+typedef signed int S32; -+typedef unsigned long long U64; -+typedef signed long long S64; -+//typedef unsigned char bool; -+ -+typedef unsigned char UINT8; -+typedef unsigned short UINT16; -+typedef unsigned int UINT32; -+typedef unsigned short USHORT; -+typedef signed char INT8; -+typedef signed short INT16; -+typedef signed int INT32; -+typedef unsigned int DWORD; -+typedef void VOID; -+typedef unsigned char BYTE; -+typedef float FLOAT; -+ -+typedef char *LPCSTR; -+typedef short *LPWSTR; -+ -+ -+// --------------------------------------------------------------------------- -+// Constants -+// --------------------------------------------------------------------------- -+ -+#define IMPORT EXTERN -+#ifndef __cplusplus -+ #define EXTERN extern -+#else -+ #define EXTERN extern "C" -+#endif -+#define LOCAL static -+#define GLOBAL -+#define EXPORT GLOBAL -+ -+#define EQ == -+#define NEQ != -+#define AND && -+#define OR || -+#define XOR(A,B) ((!(A) AND (B)) OR ((A) AND !(B))) -+ -+#ifndef FALSE -+ #define FALSE (0) -+#endif -+ -+#ifndef TRUE -+ #define TRUE (1) -+#endif -+ -+#ifndef NULL -+ #define NULL (0) -+#endif -+ -+//enum boolean {false, true}; -+enum {RX, TX, NONE}; -+ -+#ifndef BOOL -+typedef unsigned char BOOL; -+#endif -+ -+typedef enum { -+ KAL_FALSE = 0, -+ KAL_TRUE = 1, -+} kal_bool; -+ -+ -+// --------------------------------------------------------------------------- -+// Type Casting -+// --------------------------------------------------------------------------- -+ -+#define AS_INT32(x) (*(INT32 *)((void*)x)) -+#define AS_INT16(x) (*(INT16 *)((void*)x)) -+#define AS_INT8(x) (*(INT8 *)((void*)x)) -+ -+#define AS_UINT32(x) (*(UINT32 *)((void*)x)) -+#define AS_UINT16(x) (*(UINT16 *)((void*)x)) -+#define AS_UINT8(x) (*(UINT8 *)((void*)x)) -+ -+ -+// --------------------------------------------------------------------------- -+// Register Manipulations -+// --------------------------------------------------------------------------- -+ -+#define READ_REGISTER_UINT32(reg) \ -+ (*(volatile UINT32 * const)(reg)) -+ -+#define WRITE_REGISTER_UINT32(reg, val) \ -+ (*(volatile UINT32 * const)(reg)) = (val) -+ -+#define READ_REGISTER_UINT16(reg) \ -+ (*(volatile UINT16 * const)(reg)) -+ -+#define WRITE_REGISTER_UINT16(reg, val) \ -+ (*(volatile UINT16 * const)(reg)) = (val) -+ -+#define READ_REGISTER_UINT8(reg) \ -+ (*(volatile UINT8 * const)(reg)) -+ -+#define WRITE_REGISTER_UINT8(reg, val) \ -+ (*(volatile UINT8 * const)(reg)) = (val) -+ -+#define INREG8(x) READ_REGISTER_UINT8((UINT8*)((void*)(x))) -+#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8*)((void*)(x)), (UINT8)(y)) -+#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) -+#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) -+#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) -+ -+#define INREG16(x) READ_REGISTER_UINT16((UINT16*)((void*)(x))) -+#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16*)((void*)(x)),(UINT16)(y)) -+#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) -+#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) -+#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) -+ -+#define INREG32(x) READ_REGISTER_UINT32((UINT32*)((void*)(x))) -+#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32*)((void*)(x)), (UINT32)(y)) -+#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) -+#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) -+#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) -+ -+ -+#define DRV_Reg8(addr) INREG8(addr) -+#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) -+#define DRV_SetReg8(addr, data) SETREG8(addr, data) -+#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) -+ -+#define DRV_Reg16(addr) INREG16(addr) -+#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) -+#define DRV_SetReg16(addr, data) SETREG16(addr, data) -+#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) -+ -+#define DRV_Reg32(addr) INREG32(addr) -+#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) -+#define DRV_SetReg32(addr, data) SETREG32(addr, data) -+#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) -+ -+// !!! DEPRECATED, WILL BE REMOVED LATER !!! -+#define DRV_Reg(addr) DRV_Reg16(addr) -+#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) -+#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) -+#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) -+ -+ -+// --------------------------------------------------------------------------- -+// Compiler Time Deduction Macros -+// --------------------------------------------------------------------------- -+ -+#define _MASK_OFFSET_1(x, n) ((x) & 0x1) ? (n) : -+#define _MASK_OFFSET_2(x, n) _MASK_OFFSET_1((x), (n)) _MASK_OFFSET_1((x) >> 1, (n) + 1) -+#define _MASK_OFFSET_4(x, n) _MASK_OFFSET_2((x), (n)) _MASK_OFFSET_2((x) >> 2, (n) + 2) -+#define _MASK_OFFSET_8(x, n) _MASK_OFFSET_4((x), (n)) _MASK_OFFSET_4((x) >> 4, (n) + 4) -+#define _MASK_OFFSET_16(x, n) _MASK_OFFSET_8((x), (n)) _MASK_OFFSET_8((x) >> 8, (n) + 8) -+#define _MASK_OFFSET_32(x, n) _MASK_OFFSET_16((x), (n)) _MASK_OFFSET_16((x) >> 16, (n) + 16) -+ -+#define MASK_OFFSET_ERROR (0xFFFFFFFF) -+ -+#define MASK_OFFSET(x) (_MASK_OFFSET_32(x, 0) MASK_OFFSET_ERROR) -+ -+ -+// --------------------------------------------------------------------------- -+// Assertions -+// --------------------------------------------------------------------------- -+ -+#ifndef ASSERT -+ #define ASSERT(expr) BUG_ON(!(expr)) -+#endif -+ -+#ifndef NOT_IMPLEMENTED -+ #define NOT_IMPLEMENTED() BUG_ON(1) -+#endif -+ -+#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) -+#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) -+#define STATIC_ASSERT_XX(pred, line) \ -+ extern char assertion_failed_at_##line[(pred) ? 1 : -1] -+ -+// --------------------------------------------------------------------------- -+// Resolve Compiler Warnings -+// --------------------------------------------------------------------------- -+ -+#define NOT_REFERENCED(x) { (x) = (x); } -+ -+ -+// --------------------------------------------------------------------------- -+// Utilities -+// --------------------------------------------------------------------------- -+ -+#define MAXIMUM(A,B) (((A)>(B))?(A):(B)) -+#define MINIMUM(A,B) (((A)<(B))?(A):(B)) -+ -+#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) -+#define DVT_DELAYMACRO(u4Num) \ -+{ \ -+ UINT32 u4Count = 0 ; \ -+ for (u4Count = 0; u4Count < u4Num; u4Count++ ); \ -+} \ -+ -+#define A68351B 0 -+#define B68351B 1 -+#define B68351D 2 -+#define B68351E 3 -+#define UNKNOWN_IC_VERSION 0xFF -+ -+/* NAND driver */ -+struct mtk_nand_host_hw { -+ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ -+ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ -+ unsigned int nfi_cs_num; /* NFI_CS_NUM */ -+ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ -+ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ -+ unsigned int nand_ecc_size; -+ unsigned int nand_ecc_bytes; -+ unsigned int nand_ecc_mode; -+}; -+extern struct mtk_nand_host_hw mt7621_nand_hw; -+extern unsigned int CFG_BLOCKSIZE; -+ -+#endif // _MT6575_TYPEDEFS_H -+ ---- /dev/null -+++ b/drivers/mtd/nand/mtk_nand2.c -@@ -0,0 +1,2345 @@ -+/****************************************************************************** -+* mtk_nand2.c - MTK NAND Flash Device Driver -+ * -+* Copyright 2009-2012 MediaTek Co.,Ltd. -+ * -+* DESCRIPTION: -+* This file provid the other drivers nand relative functions -+ * -+* modification history -+* ---------------------------------------- -+* v3.0, 11 Feb 2010, mtk -+* ---------------------------------------- -+******************************************************************************/ -+#include "nand_def.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "mtk_nand2.h" -+#include "nand_device_list.h" -+ -+#include "bmt.h" -+#include "partition.h" -+ -+unsigned int CFG_BLOCKSIZE; -+ -+static int shift_on_bbt = 0; -+int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page); -+ -+static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL }; -+ -+#define NAND_CMD_STATUS_MULTI 0x71 -+ -+void show_stack(struct task_struct *tsk, unsigned long *sp); -+extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); -+extern void mt_irq_set_polarity(unsigned int irq,unsigned int polarity); -+ -+struct mtk_nand_host mtk_nand_host; /* include mtd_info and nand_chip structs */ -+struct mtk_nand_host_hw mt7621_nand_hw = { -+ .nfi_bus_width = 8, -+ .nfi_access_timing = NFI_DEFAULT_ACCESS_TIMING, -+ .nfi_cs_num = NFI_CS_NUM, -+ .nand_sec_size = 512, -+ .nand_sec_shift = 9, -+ .nand_ecc_size = 2048, -+ .nand_ecc_bytes = 32, -+ .nand_ecc_mode = NAND_ECC_HW, -+}; -+ -+ -+/******************************************************************************* -+ * Gloable Varible Definition -+ *******************************************************************************/ -+ -+#define NFI_ISSUE_COMMAND(cmd, col_addr, row_addr, col_num, row_num) \ -+ do { \ -+ DRV_WriteReg(NFI_CMD_REG16,cmd);\ -+ while (DRV_Reg32(NFI_STA_REG32) & STA_CMD_STATE);\ -+ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);\ -+ DRV_WriteReg32(NFI_ROWADDR_REG32, row_addr);\ -+ DRV_WriteReg(NFI_ADDRNOB_REG16, col_num | (row_num<priv; -+ int block; -+ -+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); -+ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6)); -+ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6); -+} -+ -+static int nand_bbt_get(struct mtd_info *mtd, int page) -+{ -+ struct nand_chip *this = mtd->priv; -+ int block; -+ -+ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); -+ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; -+} -+ -+void nand_enable_clock(void) -+{ -+ //enable_clock(MT65XX_PDN_PERI_NFI, "NAND"); -+} -+ -+void nand_disable_clock(void) -+{ -+ //disable_clock(MT65XX_PDN_PERI_NFI, "NAND"); -+} -+ -+struct nand_ecclayout { -+ __u32 eccbytes; -+ __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE]; -+ __u32 oobavail; -+ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE]; -+}; -+ -+static struct nand_ecclayout *layout; -+ -+static struct nand_ecclayout nand_oob_16 = { -+ .eccbytes = 8, -+ .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, -+ .oobfree = {{1, 6}, {0, 0}} -+}; -+ -+struct nand_ecclayout nand_oob_64 = { -+ .eccbytes = 32, -+ .eccpos = {32, 33, 34, 35, 36, 37, 38, 39, -+ 40, 41, 42, 43, 44, 45, 46, 47, -+ 48, 49, 50, 51, 52, 53, 54, 55, -+ 56, 57, 58, 59, 60, 61, 62, 63}, -+ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 6}, {0, 0}} -+}; -+ -+struct nand_ecclayout nand_oob_128 = { -+ .eccbytes = 64, -+ .eccpos = { -+ 64, 65, 66, 67, 68, 69, 70, 71, -+ 72, 73, 74, 75, 76, 77, 78, 79, -+ 80, 81, 82, 83, 84, 85, 86, 86, -+ 88, 89, 90, 91, 92, 93, 94, 95, -+ 96, 97, 98, 99, 100, 101, 102, 103, -+ 104, 105, 106, 107, 108, 109, 110, 111, -+ 112, 113, 114, 115, 116, 117, 118, 119, -+ 120, 121, 122, 123, 124, 125, 126, 127}, -+ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 7}, {33, 7}, {41, 7}, {49, 7}, {57, 6}} -+}; -+ -+flashdev_info devinfo; -+ -+void dump_nfi(void) -+{ -+} -+ -+void dump_ecc(void) -+{ -+} -+ -+u32 -+nand_virt_to_phys_add(u32 va) -+{ -+ u32 pageOffset = (va & (PAGE_SIZE - 1)); -+ pgd_t *pgd; -+ pmd_t *pmd; -+ pte_t *pte; -+ u32 pa; -+ -+ if (virt_addr_valid(va)) -+ return __virt_to_phys(va); -+ -+ if (NULL == current) { -+ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR ,current is NULL! \n"); -+ return 0; -+ } -+ -+ if (NULL == current->mm) { -+ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR current->mm is NULL! tgid=0x%x, name=%s \n", current->tgid, current->comm); -+ return 0; -+ } -+ -+ pgd = pgd_offset(current->mm, va); /* what is tsk->mm */ -+ if (pgd_none(*pgd) || pgd_bad(*pgd)) { -+ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pgd invalid! \n", va); -+ return 0; -+ } -+ -+ pmd = pmd_offset((pud_t *)pgd, va); -+ if (pmd_none(*pmd) || pmd_bad(*pmd)) { -+ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pmd invalid! \n", va); -+ return 0; -+ } -+ -+ pte = pte_offset_map(pmd, va); -+ if (pte_present(*pte)) { -+ pa = (pte_val(*pte) & (PAGE_MASK)) | pageOffset; -+ return pa; -+ } -+ -+ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR va=0x%x, pte invalid! \n", va); -+ return 0; -+} -+EXPORT_SYMBOL(nand_virt_to_phys_add); -+ -+bool -+get_device_info(u16 id, u32 ext_id, flashdev_info * pdevinfo) -+{ -+ u32 index; -+ for (index = 0; gen_FlashTable[index].id != 0; index++) { -+ if (id == gen_FlashTable[index].id && ext_id == gen_FlashTable[index].ext_id) { -+ pdevinfo->id = gen_FlashTable[index].id; -+ pdevinfo->ext_id = gen_FlashTable[index].ext_id; -+ pdevinfo->blocksize = gen_FlashTable[index].blocksize; -+ pdevinfo->addr_cycle = gen_FlashTable[index].addr_cycle; -+ pdevinfo->iowidth = gen_FlashTable[index].iowidth; -+ pdevinfo->timmingsetting = gen_FlashTable[index].timmingsetting; -+ pdevinfo->advancedmode = gen_FlashTable[index].advancedmode; -+ pdevinfo->pagesize = gen_FlashTable[index].pagesize; -+ pdevinfo->sparesize = gen_FlashTable[index].sparesize; -+ pdevinfo->totalsize = gen_FlashTable[index].totalsize; -+ memcpy(pdevinfo->devciename, gen_FlashTable[index].devciename, sizeof(pdevinfo->devciename)); -+ printk(KERN_INFO "Device found in MTK table, ID: %x, EXT_ID: %x\n", id, ext_id); -+ -+ goto find; -+ } -+ } -+ -+find: -+ if (0 == pdevinfo->id) { -+ printk(KERN_INFO "Device not found, ID: %x\n", id); -+ return false; -+ } else { -+ return true; -+ } -+} -+ -+static void -+ECC_Config(struct mtk_nand_host_hw *hw,u32 ecc_bit) -+{ -+ u32 u4ENCODESize; -+ u32 u4DECODESize; -+ u32 ecc_bit_cfg = ECC_CNFG_ECC4; -+ -+ switch(ecc_bit){ -+ case 4: -+ ecc_bit_cfg = ECC_CNFG_ECC4; -+ break; -+ case 8: -+ ecc_bit_cfg = ECC_CNFG_ECC8; -+ break; -+ case 10: -+ ecc_bit_cfg = ECC_CNFG_ECC10; -+ break; -+ case 12: -+ ecc_bit_cfg = ECC_CNFG_ECC12; -+ break; -+ default: -+ break; -+ } -+ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); -+ do { -+ } while (!DRV_Reg16(ECC_DECIDLE_REG16)); -+ -+ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); -+ do { -+ } while (!DRV_Reg32(ECC_ENCIDLE_REG32)); -+ -+ /* setup FDM register base */ -+ DRV_WriteReg32(ECC_FDMADDR_REG32, NFI_FDM0L_REG32); -+ -+ /* Sector + FDM */ -+ u4ENCODESize = (hw->nand_sec_size + 8) << 3; -+ /* Sector + FDM + YAFFS2 meta data bits */ -+ u4DECODESize = ((hw->nand_sec_size + 8) << 3) + ecc_bit * 13; -+ -+ /* configure ECC decoder && encoder */ -+ DRV_WriteReg32(ECC_DECCNFG_REG32, ecc_bit_cfg | DEC_CNFG_NFI | DEC_CNFG_EMPTY_EN | (u4DECODESize << DEC_CNFG_CODE_SHIFT)); -+ -+ DRV_WriteReg32(ECC_ENCCNFG_REG32, ecc_bit_cfg | ENC_CNFG_NFI | (u4ENCODESize << ENC_CNFG_MSG_SHIFT)); -+ NFI_SET_REG32(ECC_DECCNFG_REG32, DEC_CNFG_EL); -+} -+ -+static void -+ECC_Decode_Start(void) -+{ -+ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) -+ ; -+ DRV_WriteReg16(ECC_DECCON_REG16, DEC_EN); -+} -+ -+static void -+ECC_Decode_End(void) -+{ -+ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) -+ ; -+ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); -+} -+ -+static void -+ECC_Encode_Start(void) -+{ -+ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) -+ ; -+ mb(); -+ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_EN); -+} -+ -+static void -+ECC_Encode_End(void) -+{ -+ /* wait for device returning idle */ -+ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ; -+ mb(); -+ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); -+} -+ -+static bool -+mtk_nand_check_bch_error(struct mtd_info *mtd, u8 * pDataBuf, u32 u4SecIndex, u32 u4PageAddr) -+{ -+ bool bRet = true; -+ u16 u2SectorDoneMask = 1 << u4SecIndex; -+ u32 u4ErrorNumDebug, i, u4ErrNum; -+ u32 timeout = 0xFFFF; -+ // int el; -+ u32 au4ErrBitLoc[6]; -+ u32 u4ErrByteLoc, u4BitOffset; -+ u32 u4ErrBitLoc1th, u4ErrBitLoc2nd; -+ -+ //4 // Wait for Decode Done -+ while (0 == (u2SectorDoneMask & DRV_Reg16(ECC_DECDONE_REG16))) { -+ timeout--; -+ if (0 == timeout) -+ return false; -+ } -+ /* We will manually correct the error bits in the last sector, not all the sectors of the page! */ -+ memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc)); -+ u4ErrorNumDebug = DRV_Reg32(ECC_DECENUM_REG32); -+ u4ErrNum = DRV_Reg32(ECC_DECENUM_REG32) >> (u4SecIndex << 2); -+ u4ErrNum &= 0xF; -+ -+ if (u4ErrNum) { -+ if (0xF == u4ErrNum) { -+ mtd->ecc_stats.failed++; -+ bRet = false; -+ printk(KERN_ERR"mtk_nand: UnCorrectable at PageAddr=%d\n", u4PageAddr); -+ } else { -+ for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) { -+ au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i); -+ u4ErrBitLoc1th = au4ErrBitLoc[i] & 0x1FFF; -+ if (u4ErrBitLoc1th < 0x1000) { -+ u4ErrByteLoc = u4ErrBitLoc1th / 8; -+ u4BitOffset = u4ErrBitLoc1th % 8; -+ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); -+ mtd->ecc_stats.corrected++; -+ } else { -+ mtd->ecc_stats.failed++; -+ } -+ u4ErrBitLoc2nd = (au4ErrBitLoc[i] >> 16) & 0x1FFF; -+ if (0 != u4ErrBitLoc2nd) { -+ if (u4ErrBitLoc2nd < 0x1000) { -+ u4ErrByteLoc = u4ErrBitLoc2nd / 8; -+ u4BitOffset = u4ErrBitLoc2nd % 8; -+ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); -+ mtd->ecc_stats.corrected++; -+ } else { -+ mtd->ecc_stats.failed++; -+ //printk(KERN_ERR"UnCorrectable High ErrLoc=%d\n", au4ErrBitLoc[i]); -+ } -+ } -+ } -+ } -+ if (0 == (DRV_Reg16(ECC_DECFER_REG16) & (1 << u4SecIndex))) -+ bRet = false; -+ } -+ return bRet; -+} -+ -+static bool -+mtk_nand_RFIFOValidSize(u16 u2Size) -+{ -+ u32 timeout = 0xFFFF; -+ while (FIFO_RD_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) < u2Size) { -+ timeout--; -+ if (0 == timeout) -+ return false; -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_WFIFOValidSize(u16 u2Size) -+{ -+ u32 timeout = 0xFFFF; -+ -+ while (FIFO_WR_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) > u2Size) { -+ timeout--; -+ if (0 == timeout) -+ return false; -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_status_ready(u32 u4Status) -+{ -+ u32 timeout = 0xFFFF; -+ -+ while ((DRV_Reg32(NFI_STA_REG32) & u4Status) != 0) { -+ timeout--; -+ if (0 == timeout) -+ return false; -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_reset(void) -+{ -+ int timeout = 0xFFFF; -+ if (DRV_Reg16(NFI_MASTERSTA_REG16)) { -+ mb(); -+ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); -+ while (DRV_Reg16(NFI_MASTERSTA_REG16)) { -+ timeout--; -+ if (!timeout) -+ MSG(INIT, "Wait for NFI_MASTERSTA timeout\n"); -+ } -+ } -+ /* issue reset operation */ -+ mb(); -+ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); -+ -+ return mtk_nand_status_ready(STA_NFI_FSM_MASK | STA_NAND_BUSY) && mtk_nand_RFIFOValidSize(0) && mtk_nand_WFIFOValidSize(0); -+} -+ -+static void -+mtk_nand_set_mode(u16 u2OpMode) -+{ -+ u16 u2Mode = DRV_Reg16(NFI_CNFG_REG16); -+ u2Mode &= ~CNFG_OP_MODE_MASK; -+ u2Mode |= u2OpMode; -+ DRV_WriteReg16(NFI_CNFG_REG16, u2Mode); -+} -+ -+static void -+mtk_nand_set_autoformat(bool bEnable) -+{ -+ if (bEnable) -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); -+ else -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); -+} -+ -+static void -+mtk_nand_configure_fdm(u16 u2FDMSize) -+{ -+ NFI_CLN_REG16(NFI_PAGEFMT_REG16, PAGEFMT_FDM_MASK | PAGEFMT_FDM_ECC_MASK); -+ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_SHIFT); -+ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_ECC_SHIFT); -+} -+ -+static void -+mtk_nand_configure_lock(void) -+{ -+ u32 u4WriteColNOB = 2; -+ u32 u4WriteRowNOB = 3; -+ u32 u4EraseColNOB = 0; -+ u32 u4EraseRowNOB = 3; -+ DRV_WriteReg16(NFI_LOCKANOB_REG16, -+ (u4WriteColNOB << PROG_CADD_NOB_SHIFT) | (u4WriteRowNOB << PROG_RADD_NOB_SHIFT) | (u4EraseColNOB << ERASE_CADD_NOB_SHIFT) | (u4EraseRowNOB << ERASE_RADD_NOB_SHIFT)); -+ -+ if (CHIPVER_ECO_1 == g_u4ChipVer) { -+ int i; -+ for (i = 0; i < 16; ++i) { -+ DRV_WriteReg32(NFI_LOCK00ADD_REG32 + (i << 1), 0xFFFFFFFF); -+ DRV_WriteReg32(NFI_LOCK00FMT_REG32 + (i << 1), 0xFFFFFFFF); -+ } -+ //DRV_WriteReg16(NFI_LOCKANOB_REG16, 0x0); -+ DRV_WriteReg32(NFI_LOCKCON_REG32, 0xFFFFFFFF); -+ DRV_WriteReg16(NFI_LOCK_REG16, NFI_LOCK_ON); -+ } -+} -+ -+static bool -+mtk_nand_pio_ready(void) -+{ -+ int count = 0; -+ while (!(DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)) { -+ count++; -+ if (count > 0xffff) { -+ printk("PIO_DIRDY timeout\n"); -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+static bool -+mtk_nand_set_command(u16 command) -+{ -+ mb(); -+ DRV_WriteReg16(NFI_CMD_REG16, command); -+ return mtk_nand_status_ready(STA_CMD_STATE); -+} -+ -+static bool -+mtk_nand_set_address(u32 u4ColAddr, u32 u4RowAddr, u16 u2ColNOB, u16 u2RowNOB) -+{ -+ mb(); -+ DRV_WriteReg32(NFI_COLADDR_REG32, u4ColAddr); -+ DRV_WriteReg32(NFI_ROWADDR_REG32, u4RowAddr); -+ DRV_WriteReg16(NFI_ADDRNOB_REG16, u2ColNOB | (u2RowNOB << ADDR_ROW_NOB_SHIFT)); -+ return mtk_nand_status_ready(STA_ADDR_STATE); -+} -+ -+static void mtk_nfc_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) -+{ -+ if (ctrl & NAND_ALE) { -+ mtk_nand_set_address(dat, 0, 1, 0); -+ } else if (ctrl & NAND_CLE) { -+ mtk_nand_reset(); -+ mtk_nand_set_mode(0x6000); -+ mtk_nand_set_command(dat); -+ } -+} -+ -+static bool -+mtk_nand_check_RW_count(u16 u2WriteSize) -+{ -+ u32 timeout = 0xFFFF; -+ u16 u2SecNum = u2WriteSize >> 9; -+ -+ while (ADDRCNTR_CNTR(DRV_Reg16(NFI_ADDRCNTR_REG16)) < u2SecNum) { -+ timeout--; -+ if (0 == timeout) { -+ printk(KERN_INFO "[%s] timeout\n", __FUNCTION__); -+ return false; -+ } -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_ready_for_read(struct nand_chip *nand, u32 u4RowAddr, u32 u4ColAddr, bool full, u8 * buf) -+{ -+ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ -+ bool bRet = false; -+ u16 sec_num = 1 << (nand->page_shift - 9); -+ u32 col_addr = u4ColAddr; -+ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; -+ if (nand->options & NAND_BUSWIDTH_16) -+ col_addr /= 2; -+ -+ if (!mtk_nand_reset()) -+ goto cleanup; -+ if (g_bHwEcc) { -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } else { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } -+ -+ mtk_nand_set_mode(CNFG_OP_READ); -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); -+ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); -+ -+ if (full) { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ -+ if (g_bHwEcc) -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ else -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } else { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ } -+ -+ mtk_nand_set_autoformat(full); -+ if (full) -+ if (g_bHwEcc) -+ ECC_Decode_Start(); -+ if (!mtk_nand_set_command(NAND_CMD_READ0)) -+ goto cleanup; -+ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) -+ goto cleanup; -+ if (!mtk_nand_set_command(NAND_CMD_READSTART)) -+ goto cleanup; -+ if (!mtk_nand_status_ready(STA_NAND_BUSY)) -+ goto cleanup; -+ -+ bRet = true; -+ -+cleanup: -+ return bRet; -+} -+ -+static bool -+mtk_nand_ready_for_write(struct nand_chip *nand, u32 u4RowAddr, u32 col_addr, bool full, u8 * buf) -+{ -+ bool bRet = false; -+ u32 sec_num = 1 << (nand->page_shift - 9); -+ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; -+ if (nand->options & NAND_BUSWIDTH_16) -+ col_addr /= 2; -+ -+ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ -+ if (!mtk_nand_reset()) -+ return false; -+ -+ mtk_nand_set_mode(CNFG_OP_PRGM); -+ -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_READ_EN); -+ -+ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); -+ -+ if (full) { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ if (g_bHwEcc) -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ else -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } else { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ } -+ -+ mtk_nand_set_autoformat(full); -+ -+ if (full) -+ if (g_bHwEcc) -+ ECC_Encode_Start(); -+ -+ if (!mtk_nand_set_command(NAND_CMD_SEQIN)) -+ goto cleanup; -+ //1 FIXED ME: For Any Kind of AddrCycle -+ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) -+ goto cleanup; -+ -+ if (!mtk_nand_status_ready(STA_NAND_BUSY)) -+ goto cleanup; -+ -+ bRet = true; -+ -+cleanup: -+ return bRet; -+} -+ -+static bool -+mtk_nand_check_dececc_done(u32 u4SecNum) -+{ -+ u32 timeout, dec_mask; -+ -+ timeout = 0xffff; -+ dec_mask = (1 << u4SecNum) - 1; -+ while ((dec_mask != DRV_Reg(ECC_DECDONE_REG16)) && timeout > 0) -+ timeout--; -+ if (timeout == 0) { -+ MSG(VERIFY, "ECC_DECDONE: timeout\n"); -+ return false; -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_mcu_read_data(u8 * buf, u32 length) -+{ -+ int timeout = 0xffff; -+ u32 i; -+ u32 *buf32 = (u32 *) buf; -+ if ((u32) buf % 4 || length % 4) -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ else -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ -+ //DRV_WriteReg32(NFI_STRADDR_REG32, 0); -+ mb(); -+ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BRD); -+ -+ if ((u32) buf % 4 || length % 4) { -+ for (i = 0; (i < (length)) && (timeout > 0);) { -+ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { -+ *buf++ = (u8) DRV_Reg32(NFI_DATAR_REG32); -+ i++; -+ } else { -+ timeout--; -+ } -+ if (0 == timeout) { -+ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); -+ dump_nfi(); -+ return false; -+ } -+ } -+ } else { -+ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { -+ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { -+ *buf32++ = DRV_Reg32(NFI_DATAR_REG32); -+ i++; -+ } else { -+ timeout--; -+ } -+ if (0 == timeout) { -+ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); -+ dump_nfi(); -+ return false; -+ } -+ } -+ } -+ return true; -+} -+ -+static bool -+mtk_nand_read_page_data(struct mtd_info *mtd, u8 * pDataBuf, u32 u4Size) -+{ -+ return mtk_nand_mcu_read_data(pDataBuf, u4Size); -+} -+ -+static bool -+mtk_nand_mcu_write_data(struct mtd_info *mtd, const u8 * buf, u32 length) -+{ -+ u32 timeout = 0xFFFF; -+ u32 i; -+ u32 *pBuf32; -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ mb(); -+ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BWR); -+ pBuf32 = (u32 *) buf; -+ -+ if ((u32) buf % 4 || length % 4) -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ else -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ -+ if ((u32) buf % 4 || length % 4) { -+ for (i = 0; (i < (length)) && (timeout > 0);) { -+ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { -+ DRV_WriteReg32(NFI_DATAW_REG32, *buf++); -+ i++; -+ } else { -+ timeout--; -+ } -+ if (0 == timeout) { -+ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); -+ dump_nfi(); -+ return false; -+ } -+ } -+ } else { -+ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { -+ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { -+ DRV_WriteReg32(NFI_DATAW_REG32, *pBuf32++); -+ i++; -+ } else { -+ timeout--; -+ } -+ if (0 == timeout) { -+ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); -+ dump_nfi(); -+ return false; -+ } -+ } -+ } -+ -+ return true; -+} -+ -+static bool -+mtk_nand_write_page_data(struct mtd_info *mtd, u8 * buf, u32 size) -+{ -+ return mtk_nand_mcu_write_data(mtd, buf, size); -+} -+ -+static void -+mtk_nand_read_fdm_data(u8 * pDataBuf, u32 u4SecNum) -+{ -+ u32 i; -+ u32 *pBuf32 = (u32 *) pDataBuf; -+ -+ if (pBuf32) { -+ for (i = 0; i < u4SecNum; ++i) { -+ *pBuf32++ = DRV_Reg32(NFI_FDM0L_REG32 + (i << 1)); -+ *pBuf32++ = DRV_Reg32(NFI_FDM0M_REG32 + (i << 1)); -+ } -+ } -+} -+ -+static u8 fdm_buf[64]; -+static void -+mtk_nand_write_fdm_data(struct nand_chip *chip, u8 * pDataBuf, u32 u4SecNum) -+{ -+ u32 i, j; -+ u8 checksum = 0; -+ bool empty = true; -+ struct nand_oobfree *free_entry; -+ u32 *pBuf32; -+ -+ memcpy(fdm_buf, pDataBuf, u4SecNum * 8); -+ -+ free_entry = layout->oobfree; -+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free_entry[i].length; i++) { -+ for (j = 0; j < free_entry[i].length; j++) { -+ if (pDataBuf[free_entry[i].offset + j] != 0xFF) -+ empty = false; -+ checksum ^= pDataBuf[free_entry[i].offset + j]; -+ } -+ } -+ -+ if (!empty) { -+ fdm_buf[free_entry[i - 1].offset + free_entry[i - 1].length] = checksum; -+ } -+ -+ pBuf32 = (u32 *) fdm_buf; -+ for (i = 0; i < u4SecNum; ++i) { -+ DRV_WriteReg32(NFI_FDM0L_REG32 + (i << 1), *pBuf32++); -+ DRV_WriteReg32(NFI_FDM0M_REG32 + (i << 1), *pBuf32++); -+ } -+} -+ -+static void -+mtk_nand_stop_read(void) -+{ -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); -+ mtk_nand_reset(); -+ if (g_bHwEcc) -+ ECC_Decode_End(); -+ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); -+} -+ -+static void -+mtk_nand_stop_write(void) -+{ -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); -+ if (g_bHwEcc) -+ ECC_Encode_End(); -+ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); -+} -+ -+bool -+mtk_nand_exec_read_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) -+{ -+ u8 *buf; -+ bool bRet = true; -+ struct nand_chip *nand = mtd->priv; -+ u32 u4SecNum = u4PageSize >> 9; -+ -+ buf = pPageBuf; -+ if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) { -+ int j; -+ for (j = 0 ; j < u4SecNum; j++) { -+ if (!mtk_nand_read_page_data(mtd, buf+j*512, 512)) -+ bRet = false; -+ if(g_bHwEcc && !mtk_nand_check_dececc_done(j+1)) -+ bRet = false; -+ if(g_bHwEcc && !mtk_nand_check_bch_error(mtd, buf+j*512, j, u4RowAddr)) -+ bRet = false; -+ } -+ if (!mtk_nand_status_ready(STA_NAND_BUSY)) -+ bRet = false; -+ -+ mtk_nand_read_fdm_data(pFDMBuf, u4SecNum); -+ mtk_nand_stop_read(); -+ } -+ -+ return bRet; -+} -+ -+int -+mtk_nand_exec_write_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) -+{ -+ struct nand_chip *chip = mtd->priv; -+ u32 u4SecNum = u4PageSize >> 9; -+ u8 *buf; -+ u8 status; -+ -+ MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr); -+ -+ buf = pPageBuf; -+ -+ if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) { -+ mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum); -+ (void)mtk_nand_write_page_data(mtd, buf, u4PageSize); -+ (void)mtk_nand_check_RW_count(u4PageSize); -+ mtk_nand_stop_write(); -+ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); -+ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ; -+ } -+ -+ status = chip->waitfunc(mtd, chip); -+ if (status & NAND_STATUS_FAIL) -+ return -EIO; -+ return 0; -+} -+ -+static int -+get_start_end_block(struct mtd_info *mtd, int block, int *start_blk, int *end_blk) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int i; -+ -+ *start_blk = 0; -+ for (i = 0; i <= part_num; i++) -+ { -+ if (i == part_num) -+ { -+ // try the last reset partition -+ *end_blk = (chip->chipsize >> chip->phys_erase_shift) - 1; -+ if (*start_blk <= *end_blk) -+ { -+ if ((block >= *start_blk) && (block <= *end_blk)) -+ break; -+ } -+ } -+ // skip All partition entry -+ else if (g_pasStatic_Partition[i].size == MTDPART_SIZ_FULL) -+ { -+ continue; -+ } -+ *end_blk = *start_blk + (g_pasStatic_Partition[i].size >> chip->phys_erase_shift) - 1; -+ if ((block >= *start_blk) && (block <= *end_blk)) -+ break; -+ *start_blk = *end_blk + 1; -+ } -+ if (*start_blk > *end_blk) -+ { -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+block_remap(struct mtd_info *mtd, int block) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int start_blk, end_blk; -+ int j, block_offset; -+ int bad_block = 0; -+ -+ if (chip->bbt == NULL) { -+ printk("ERROR!! no bbt table for block_remap\n"); -+ return -1; -+ } -+ -+ if (get_start_end_block(mtd, block, &start_blk, &end_blk) < 0) { -+ printk("ERROR!! can not find start_blk and end_blk\n"); -+ return -1; -+ } -+ -+ block_offset = block - start_blk; -+ for (j = start_blk; j <= end_blk;j++) { -+ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) == 0x0) { -+ if (!block_offset) -+ break; -+ block_offset--; -+ } else { -+ bad_block++; -+ } -+ } -+ if (j <= end_blk) { -+ return j; -+ } else { -+ // remap to the bad block -+ for (j = end_blk; bad_block > 0; j--) -+ { -+ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) != 0x0) -+ { -+ bad_block--; -+ if (bad_block <= block_offset) -+ return j; -+ } -+ } -+ } -+ -+ printk("Error!! block_remap error\n"); -+ return -1; -+} -+ -+int -+check_block_remap(struct mtd_info *mtd, int block) -+{ -+ if (shift_on_bbt) -+ return block_remap(mtd, block); -+ else -+ return block; -+} -+EXPORT_SYMBOL(check_block_remap); -+ -+ -+static int -+write_next_on_fail(struct mtd_info *mtd, char *write_buf, int page, int * to_blk) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int i, j, to_page = 0, first_page; -+ char *buf, *oob; -+ int start_blk = 0, end_blk; -+ int mapped_block; -+ int page_per_block_bit = chip->phys_erase_shift - chip->page_shift; -+ int block = page >> page_per_block_bit; -+ -+ // find next available block in the same MTD partition -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ -+ get_start_end_block(mtd, block, &start_blk, &end_blk); -+ -+ buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL | GFP_DMA); -+ if (buf == NULL) -+ return -1; -+ -+ oob = buf + mtd->writesize; -+ for ((*to_blk) = block + 1; (*to_blk) <= end_blk ; (*to_blk)++) { -+ if (nand_bbt_get(mtd, (*to_blk) << page_per_block_bit) == 0) { -+ int status; -+ status = mtk_nand_erase_hw(mtd, (*to_blk) << page_per_block_bit); -+ if (status & NAND_STATUS_FAIL) { -+ mtk_nand_block_markbad_hw(mtd, (*to_blk) << chip->phys_erase_shift); -+ nand_bbt_set(mtd, (*to_blk) << page_per_block_bit, 0x3); -+ } else { -+ /* good block */ -+ to_page = (*to_blk) << page_per_block_bit; -+ break; -+ } -+ } -+ } -+ -+ if (!to_page) { -+ kfree(buf); -+ return -1; -+ } -+ -+ first_page = (page >> page_per_block_bit) << page_per_block_bit; -+ for (i = 0; i < (1 << page_per_block_bit); i++) { -+ if ((first_page + i) != page) { -+ mtk_nand_read_oob_hw(mtd, chip, (first_page+i)); -+ for (j = 0; j < mtd->oobsize; j++) -+ if (chip->oob_poi[j] != (unsigned char)0xff) -+ break; -+ if (j < mtd->oobsize) { -+ mtk_nand_exec_read_page(mtd, (first_page+i), mtd->writesize, buf, oob); -+ memset(oob, 0xff, mtd->oobsize); -+ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)buf, oob) != 0) { -+ int ret, new_blk = 0; -+ nand_bbt_set(mtd, to_page, 0x3); -+ ret = write_next_on_fail(mtd, buf, to_page + i, &new_blk); -+ if (ret) { -+ kfree(buf); -+ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); -+ return ret; -+ } -+ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); -+ *to_blk = new_blk; -+ to_page = ((*to_blk) << page_per_block_bit); -+ } -+ } -+ } else { -+ memset(chip->oob_poi, 0xff, mtd->oobsize); -+ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)write_buf, chip->oob_poi) != 0) { -+ int ret, new_blk = 0; -+ nand_bbt_set(mtd, to_page, 0x3); -+ ret = write_next_on_fail(mtd, write_buf, to_page + i, &new_blk); -+ if (ret) { -+ kfree(buf); -+ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); -+ return ret; -+ } -+ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); -+ *to_blk = new_blk; -+ to_page = ((*to_blk) << page_per_block_bit); -+ } -+ } -+ } -+ -+ kfree(buf); -+ -+ return 0; -+} -+ -+static int -+mtk_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset, -+ int data_len, const u8 * buf, int oob_required, int page, int raw) -+{ -+ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ int block = page / page_per_block; -+ u16 page_in_block = page % page_per_block; -+ int mapped_block = block; -+ -+#if defined(MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+ // write bad index into oob -+ if (mapped_block != block) -+ set_bad_index_to_oob(chip->oob_poi, block); -+ else -+ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } -+#endif -+ do { -+ if (mtk_nand_exec_write_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, (u8 *)buf, chip->oob_poi)) { -+ MSG(INIT, "write fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); -+#if defined(MTK_NAND_BMT) -+ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, UPDATE_WRITE_FAIL, (u8 *) buf, chip->oob_poi)) { -+ MSG(INIT, "Update BMT success\n"); -+ return 0; -+ } else { -+ MSG(INIT, "Update BMT fail\n"); -+ return -EIO; -+ } -+#else -+ { -+ int new_blk; -+ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); -+ if (write_next_on_fail(mtd, (char *)buf, page_in_block + mapped_block * page_per_block, &new_blk) != 0) -+ { -+ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); -+ return NAND_STATUS_FAIL; -+ } -+ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); -+ break; -+ } -+#endif -+ } else -+ break; -+ } while(1); -+ -+ return 0; -+} -+ -+static void -+mtk_nand_command_bp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) -+{ -+ struct nand_chip *nand = mtd->priv; -+ -+ switch (command) { -+ case NAND_CMD_SEQIN: -+ memset(g_kCMD.au1OOB, 0xFF, sizeof(g_kCMD.au1OOB)); -+ g_kCMD.pDataBuf = NULL; -+ g_kCMD.u4RowAddr = page_addr; -+ g_kCMD.u4ColAddr = column; -+ break; -+ -+ case NAND_CMD_PAGEPROG: -+ if (g_kCMD.pDataBuf || (0xFF != g_kCMD.au1OOB[nand_badblock_offset])) { -+ u8 *pDataBuf = g_kCMD.pDataBuf ? g_kCMD.pDataBuf : nand->buffers->databuf; -+ mtk_nand_exec_write_page(mtd, g_kCMD.u4RowAddr, mtd->writesize, pDataBuf, g_kCMD.au1OOB); -+ g_kCMD.u4RowAddr = (u32) - 1; -+ g_kCMD.u4OOBRowAddr = (u32) - 1; -+ } -+ break; -+ -+ case NAND_CMD_READOOB: -+ g_kCMD.u4RowAddr = page_addr; -+ g_kCMD.u4ColAddr = column + mtd->writesize; -+ break; -+ -+ case NAND_CMD_READ0: -+ g_kCMD.u4RowAddr = page_addr; -+ g_kCMD.u4ColAddr = column; -+ break; -+ -+ case NAND_CMD_ERASE1: -+ nand->state=FL_ERASING; -+ (void)mtk_nand_reset(); -+ mtk_nand_set_mode(CNFG_OP_ERASE); -+ (void)mtk_nand_set_command(NAND_CMD_ERASE1); -+ (void)mtk_nand_set_address(0, page_addr, 0, devinfo.addr_cycle - 2); -+ break; -+ -+ case NAND_CMD_ERASE2: -+ (void)mtk_nand_set_command(NAND_CMD_ERASE2); -+ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) -+ ; -+ break; -+ -+ case NAND_CMD_STATUS: -+ (void)mtk_nand_reset(); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); -+ mtk_nand_set_mode(CNFG_OP_SRD); -+ mtk_nand_set_mode(CNFG_READ_EN); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ (void)mtk_nand_set_command(NAND_CMD_STATUS); -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); -+ mb(); -+ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD | (1 << CON_NFI_NOB_SHIFT)); -+ g_bcmdstatus = true; -+ break; -+ -+ case NAND_CMD_RESET: -+ (void)mtk_nand_reset(); -+ DRV_WriteReg16(NFI_INTR_EN_REG16, INTR_RST_DONE_EN); -+ (void)mtk_nand_set_command(NAND_CMD_RESET); -+ DRV_WriteReg16(NFI_BASE+0x44, 0xF1); -+ while(!(DRV_Reg16(NFI_INTR_REG16)&INTR_RST_DONE_EN)) -+ ; -+ break; -+ -+ case NAND_CMD_READID: -+ mtk_nand_reset(); -+ /* Disable HW ECC */ -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN | CNFG_BYTE_RW); -+ (void)mtk_nand_reset(); -+ mb(); -+ mtk_nand_set_mode(CNFG_OP_SRD); -+ (void)mtk_nand_set_command(NAND_CMD_READID); -+ (void)mtk_nand_set_address(0, 0, 1, 0); -+ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD); -+ while (DRV_Reg32(NFI_STA_REG32) & STA_DATAR_STATE) -+ ; -+ break; -+ -+ default: -+ BUG(); -+ break; -+ } -+} -+ -+static void -+mtk_nand_select_chip(struct mtd_info *mtd, int chip) -+{ -+ if ((chip == -1) && (false == g_bInitDone)) { -+ struct nand_chip *nand = mtd->priv; -+ struct mtk_nand_host *host = nand->priv; -+ struct mtk_nand_host_hw *hw = host->hw; -+ u32 spare_per_sector = mtd->oobsize / (mtd->writesize / 512); -+ u32 ecc_bit = 4; -+ u32 spare_bit = PAGEFMT_SPARE_16; -+ -+ if (spare_per_sector >= 28) { -+ spare_bit = PAGEFMT_SPARE_28; -+ ecc_bit = 12; -+ spare_per_sector = 28; -+ } else if (spare_per_sector >= 27) { -+ spare_bit = PAGEFMT_SPARE_27; -+ ecc_bit = 8; -+ spare_per_sector = 27; -+ } else if (spare_per_sector >= 26) { -+ spare_bit = PAGEFMT_SPARE_26; -+ ecc_bit = 8; -+ spare_per_sector = 26; -+ } else if (spare_per_sector >= 16) { -+ spare_bit = PAGEFMT_SPARE_16; -+ ecc_bit = 4; -+ spare_per_sector = 16; -+ } else { -+ MSG(INIT, "[NAND]: NFI not support oobsize: %x\n", spare_per_sector); -+ ASSERT(0); -+ } -+ mtd->oobsize = spare_per_sector*(mtd->writesize/512); -+ MSG(INIT, "[NAND]select ecc bit:%d, sparesize :%d spare_per_sector=%d\n",ecc_bit,mtd->oobsize,spare_per_sector); -+ /* Setup PageFormat */ -+ if (4096 == mtd->writesize) { -+ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_4K); -+ nand->cmdfunc = mtk_nand_command_bp; -+ } else if (2048 == mtd->writesize) { -+ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K); -+ nand->cmdfunc = mtk_nand_command_bp; -+ } -+ ECC_Config(hw,ecc_bit); -+ g_bInitDone = true; -+ } -+ switch (chip) { -+ case -1: -+ break; -+ case 0: -+ case 1: -+ /* Jun Shen, 2011.04.13 */ -+ /* Note: MT6577 EVB NAND is mounted on CS0, but FPGA is CS1 */ -+ DRV_WriteReg16(NFI_CSEL_REG16, chip); -+ /* Jun Shen, 2011.04.13 */ -+ break; -+ } -+} -+ -+static uint8_t -+mtk_nand_read_byte(struct mtd_info *mtd) -+{ -+ uint8_t retval = 0; -+ -+ if (!mtk_nand_pio_ready()) { -+ printk("pio ready timeout\n"); -+ retval = false; -+ } -+ -+ if (g_bcmdstatus) { -+ retval = DRV_Reg8(NFI_DATAR_REG32); -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); -+ mtk_nand_reset(); -+ if (g_bHwEcc) { -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } else { -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ } -+ g_bcmdstatus = false; -+ } else -+ retval = DRV_Reg8(NFI_DATAR_REG32); -+ -+ return retval; -+} -+ -+static void -+mtk_nand_read_buf(struct mtd_info *mtd, uint8_t * buf, int len) -+{ -+ struct nand_chip *nand = (struct nand_chip *)mtd->priv; -+ struct NAND_CMD *pkCMD = &g_kCMD; -+ u32 u4ColAddr = pkCMD->u4ColAddr; -+ u32 u4PageSize = mtd->writesize; -+ -+ if (u4ColAddr < u4PageSize) { -+ if ((u4ColAddr == 0) && (len >= u4PageSize)) { -+ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, pkCMD->au1OOB); -+ if (len > u4PageSize) { -+ u32 u4Size = min(len - u4PageSize, sizeof(pkCMD->au1OOB)); -+ memcpy(buf + u4PageSize, pkCMD->au1OOB, u4Size); -+ } -+ } else { -+ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); -+ memcpy(buf, nand->buffers->databuf + u4ColAddr, len); -+ } -+ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; -+ } else { -+ u32 u4Offset = u4ColAddr - u4PageSize; -+ u32 u4Size = min(len - u4Offset, sizeof(pkCMD->au1OOB)); -+ if (pkCMD->u4OOBRowAddr != pkCMD->u4RowAddr) { -+ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); -+ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; -+ } -+ memcpy(buf, pkCMD->au1OOB + u4Offset, u4Size); -+ } -+ pkCMD->u4ColAddr += len; -+} -+ -+static void -+mtk_nand_write_buf(struct mtd_info *mtd, const uint8_t * buf, int len) -+{ -+ struct NAND_CMD *pkCMD = &g_kCMD; -+ u32 u4ColAddr = pkCMD->u4ColAddr; -+ u32 u4PageSize = mtd->writesize; -+ int i4Size, i; -+ -+ if (u4ColAddr >= u4PageSize) { -+ u32 u4Offset = u4ColAddr - u4PageSize; -+ u8 *pOOB = pkCMD->au1OOB + u4Offset; -+ i4Size = min(len, (int)(sizeof(pkCMD->au1OOB) - u4Offset)); -+ for (i = 0; i < i4Size; i++) { -+ pOOB[i] &= buf[i]; -+ } -+ } else { -+ pkCMD->pDataBuf = (u8 *) buf; -+ } -+ -+ pkCMD->u4ColAddr += len; -+} -+ -+static int -+mtk_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, int oob_required, int page) -+{ -+ mtk_nand_write_buf(mtd, buf, mtd->writesize); -+ mtk_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); -+ return 0; -+} -+ -+static int -+mtk_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, int oob_required, int page) -+{ -+ struct NAND_CMD *pkCMD = &g_kCMD; -+ u32 u4ColAddr = pkCMD->u4ColAddr; -+ u32 u4PageSize = mtd->writesize; -+ -+ if (u4ColAddr == 0) { -+ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, chip->oob_poi); -+ pkCMD->u4ColAddr += u4PageSize + mtd->oobsize; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, u8 * buf, int page) -+{ -+ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ int block = page / page_per_block; -+ u16 page_in_block = page % page_per_block; -+ int mapped_block = block; -+ -+#if defined (MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, -+ mtd->writesize, buf, chip->oob_poi)) -+ return 0; -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } -+ -+ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, buf, chip->oob_poi)) -+ return 0; -+ else -+ return -EIO; -+#endif -+} -+ -+int -+mtk_nand_erase_hw(struct mtd_info *mtd, int page) -+{ -+ struct nand_chip *chip = (struct nand_chip *)mtd->priv; -+ -+ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); -+ chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); -+ -+ return chip->waitfunc(mtd, chip); -+} -+ -+static int -+mtk_nand_erase(struct mtd_info *mtd, int page) -+{ -+ // get mapping -+ struct nand_chip *chip = mtd->priv; -+ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ int page_in_block = page % page_per_block; -+ int block = page / page_per_block; -+ int mapped_block = block; -+ -+#if defined(MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } -+#endif -+ -+ do { -+ int status = mtk_nand_erase_hw(mtd, page_in_block + page_per_block * mapped_block); -+ -+ if (status & NAND_STATUS_FAIL) { -+#if defined (MTK_NAND_BMT) -+ if (update_bmt( (page_in_block + mapped_block * page_per_block) << chip->page_shift, -+ UPDATE_ERASE_FAIL, NULL, NULL)) -+ { -+ MSG(INIT, "Erase fail at block: 0x%x, update BMT success\n", mapped_block); -+ return 0; -+ } else { -+ MSG(INIT, "Erase fail at block: 0x%x, update BMT fail\n", mapped_block); -+ return NAND_STATUS_FAIL; -+ } -+#else -+ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); -+ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } else -+ return NAND_STATUS_FAIL; -+#endif -+ } else -+ break; -+ } while(1); -+ -+ return 0; -+} -+ -+static int -+mtk_nand_read_oob_raw(struct mtd_info *mtd, uint8_t * buf, int page_addr, int len) -+{ -+ struct nand_chip *chip = (struct nand_chip *)mtd->priv; -+ u32 col_addr = 0; -+ u32 sector = 0; -+ int res = 0; -+ u32 colnob = 2, rawnob = devinfo.addr_cycle - 2; -+ int randomread = 0; -+ int read_len = 0; -+ int sec_num = 1<<(chip->page_shift-9); -+ int spare_per_sector = mtd->oobsize/sec_num; -+ -+ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { -+ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); -+ return -EINVAL; -+ } -+ if (len > spare_per_sector) -+ randomread = 1; -+ if (!randomread || !(devinfo.advancedmode & RAMDOM_READ)) { -+ while (len > 0) { -+ read_len = min(len, spare_per_sector); -+ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); // TODO: Fix this hard-code 16 -+ if (!mtk_nand_ready_for_read(chip, page_addr, col_addr, false, NULL)) { -+ printk(KERN_WARNING "mtk_nand_ready_for_read return failed\n"); -+ res = -EIO; -+ goto error; -+ } -+ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { -+ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed\n"); -+ res = -EIO; -+ goto error; -+ } -+ mtk_nand_check_RW_count(read_len); -+ mtk_nand_stop_read(); -+ sector++; -+ len -= read_len; -+ } -+ } else { -+ col_addr = NAND_SECTOR_SIZE; -+ if (chip->options & NAND_BUSWIDTH_16) -+ col_addr /= 2; -+ if (!mtk_nand_reset()) -+ goto error; -+ mtk_nand_set_mode(0x6000); -+ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); -+ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); -+ -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); -+ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ -+ mtk_nand_set_autoformat(false); -+ -+ if (!mtk_nand_set_command(NAND_CMD_READ0)) -+ goto error; -+ //1 FIXED ME: For Any Kind of AddrCycle -+ if (!mtk_nand_set_address(col_addr, page_addr, colnob, rawnob)) -+ goto error; -+ if (!mtk_nand_set_command(NAND_CMD_READSTART)) -+ goto error; -+ if (!mtk_nand_status_ready(STA_NAND_BUSY)) -+ goto error; -+ read_len = min(len, spare_per_sector); -+ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { -+ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); -+ res = -EIO; -+ goto error; -+ } -+ sector++; -+ len -= read_len; -+ mtk_nand_stop_read(); -+ while (len > 0) { -+ read_len = min(len, spare_per_sector); -+ if (!mtk_nand_set_command(0x05)) -+ goto error; -+ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); -+ if (chip->options & NAND_BUSWIDTH_16) -+ col_addr /= 2; -+ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr); -+ DRV_WriteReg16(NFI_ADDRNOB_REG16, 2); -+ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); -+ if (!mtk_nand_status_ready(STA_ADDR_STATE)) -+ goto error; -+ if (!mtk_nand_set_command(0xE0)) -+ goto error; -+ if (!mtk_nand_status_ready(STA_NAND_BUSY)) -+ goto error; -+ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { -+ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); -+ res = -EIO; -+ goto error; -+ } -+ mtk_nand_stop_read(); -+ sector++; -+ len -= read_len; -+ } -+ } -+error: -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); -+ return res; -+} -+ -+static int -+mtk_nand_write_oob_raw(struct mtd_info *mtd, const uint8_t * buf, int page_addr, int len) -+{ -+ struct nand_chip *chip = mtd->priv; -+ u32 col_addr = 0; -+ u32 sector = 0; -+ int write_len = 0; -+ int status; -+ int sec_num = 1<<(chip->page_shift-9); -+ int spare_per_sector = mtd->oobsize/sec_num; -+ -+ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { -+ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); -+ return -EINVAL; -+ } -+ -+ while (len > 0) { -+ write_len = min(len, spare_per_sector); -+ col_addr = sector * (NAND_SECTOR_SIZE + spare_per_sector) + NAND_SECTOR_SIZE; -+ if (!mtk_nand_ready_for_write(chip, page_addr, col_addr, false, NULL)) -+ return -EIO; -+ if (!mtk_nand_mcu_write_data(mtd, buf + sector * spare_per_sector, write_len)) -+ return -EIO; -+ (void)mtk_nand_check_RW_count(write_len); -+ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); -+ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); -+ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) -+ ; -+ status = chip->waitfunc(mtd, chip); -+ if (status & NAND_STATUS_FAIL) { -+ printk(KERN_INFO "status: %d\n", status); -+ return -EIO; -+ } -+ len -= write_len; -+ sector++; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_nand_write_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) -+{ -+ int i, iter; -+ int sec_num = 1<<(chip->page_shift-9); -+ int spare_per_sector = mtd->oobsize/sec_num; -+ -+ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); -+ -+ // copy ecc data -+ for (i = 0; i < layout->eccbytes; i++) { -+ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); -+ local_oob_buf[iter] = chip->oob_poi[layout->eccpos[i]]; -+ } -+ -+ // copy FDM data -+ for (i = 0; i < sec_num; i++) -+ memcpy(&local_oob_buf[i * spare_per_sector], &chip->oob_poi[i * OOB_AVAI_PER_SECTOR], OOB_AVAI_PER_SECTOR); -+ -+ return mtk_nand_write_oob_raw(mtd, local_oob_buf, page, mtd->oobsize); -+} -+ -+static int mtk_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) -+{ -+ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ int block = page / page_per_block; -+ u16 page_in_block = page % page_per_block; -+ int mapped_block = block; -+ -+#if defined(MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+ // write bad index into oob -+ if (mapped_block != block) -+ set_bad_index_to_oob(chip->oob_poi, block); -+ else -+ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); -+#else -+ if (shift_on_bbt) -+ { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } -+#endif -+ do { -+ if (mtk_nand_write_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block /* page */)) { -+ MSG(INIT, "write oob fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); -+#if defined(MTK_NAND_BMT) -+ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, -+ UPDATE_WRITE_FAIL, NULL, chip->oob_poi)) -+ { -+ MSG(INIT, "Update BMT success\n"); -+ return 0; -+ } else { -+ MSG(INIT, "Update BMT fail\n"); -+ return -EIO; -+ } -+#else -+ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); -+ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, mapped_block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) -+ return NAND_STATUS_FAIL; -+ } else { -+ return NAND_STATUS_FAIL; -+ } -+#endif -+ } else -+ break; -+ } while (1); -+ -+ return 0; -+} -+ -+int -+mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t offset) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int block = (int)offset >> chip->phys_erase_shift; -+ int page = block * (1 << (chip->phys_erase_shift - chip->page_shift)); -+ u8 buf[8]; -+ -+ memset(buf, 0xFF, 8); -+ buf[0] = 0; -+ return mtk_nand_write_oob_raw(mtd, buf, page, 8); -+} -+ -+static int -+mtk_nand_block_markbad(struct mtd_info *mtd, loff_t offset) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int block = (int)offset >> chip->phys_erase_shift; -+ int ret; -+ int mapped_block = block; -+ -+ nand_get_device(chip, mtd, FL_WRITING); -+ -+#if defined(MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) { -+ printk("NAND mark bad failed\n"); -+ nand_release_device(mtd); -+ return NAND_STATUS_FAIL; -+ } -+ } -+ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); -+#endif -+ nand_release_device(mtd); -+ -+ return ret; -+} -+ -+int -+mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) -+{ -+ int i; -+ u8 iter = 0; -+ -+ int sec_num = 1<<(chip->page_shift-9); -+ int spare_per_sector = mtd->oobsize/sec_num; -+ -+ if (mtk_nand_read_oob_raw(mtd, chip->oob_poi, page, mtd->oobsize)) { -+ printk(KERN_ERR "[%s]mtk_nand_read_oob_raw return failed\n", __FUNCTION__); -+ return -EIO; -+ } -+ -+ // adjust to ecc physical layout to memory layout -+ /*********************************************************/ -+ /* FDM0 | ECC0 | FDM1 | ECC1 | FDM2 | ECC2 | FDM3 | ECC3 */ -+ /* 8B | 8B | 8B | 8B | 8B | 8B | 8B | 8B */ -+ /*********************************************************/ -+ -+ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); -+ // copy ecc data -+ for (i = 0; i < layout->eccbytes; i++) { -+ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); -+ chip->oob_poi[layout->eccpos[i]] = local_oob_buf[iter]; -+ } -+ -+ // copy FDM data -+ for (i = 0; i < sec_num; i++) { -+ memcpy(&chip->oob_poi[i * OOB_AVAI_PER_SECTOR], &local_oob_buf[i * spare_per_sector], OOB_AVAI_PER_SECTOR); -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) -+{ -+ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ int block = page / page_per_block; -+ u16 page_in_block = page % page_per_block; -+ int mapped_block = block; -+ -+#if defined (MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+ mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block); -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ if (mapped_block == -1) -+ return NAND_STATUS_FAIL; -+ // allow to read oob even if the block is bad -+ } -+ if (mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block)!=0) -+ return -1; -+#endif -+ return 0; -+} -+ -+int -+mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct nand_chip *chip = (struct nand_chip *)mtd->priv; -+ int page_addr = (int)(ofs >> chip->page_shift); -+ unsigned int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); -+ unsigned char oob_buf[8]; -+ -+ page_addr &= ~(page_per_block - 1); -+ if (mtk_nand_read_oob_raw(mtd, oob_buf, page_addr, sizeof(oob_buf))) { -+ printk(KERN_WARNING "mtk_nand_read_oob_raw return error\n"); -+ return 1; -+ } -+ -+ if (oob_buf[0] != 0xff) { -+ printk(KERN_WARNING "Bad block detected at 0x%x, oob_buf[0] is 0x%x\n", page_addr, oob_buf[0]); -+ // dump_nfi(); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int -+mtk_nand_block_bad(struct mtd_info *mtd, loff_t ofs) -+{ -+ struct nand_chip *chip = (struct nand_chip *)mtd->priv; -+ int block = (int)ofs >> chip->phys_erase_shift; -+ int mapped_block = block; -+ int ret; -+ -+#if defined(MTK_NAND_BMT) -+ mapped_block = get_mapping_block_index(block); -+#else -+ if (shift_on_bbt) { -+ mapped_block = block_remap(mtd, block); -+ } -+#endif -+ -+ ret = mtk_nand_block_bad_hw(mtd, mapped_block << chip->phys_erase_shift); -+#if defined (MTK_NAND_BMT) -+ if (ret) { -+ MSG(INIT, "Unmapped bad block: 0x%x\n", mapped_block); -+ if (update_bmt(mapped_block << chip->phys_erase_shift, UPDATE_UNMAPPED_BLOCK, NULL, NULL)) { -+ MSG(INIT, "Update BMT success\n"); -+ ret = 0; -+ } else { -+ MSG(INIT, "Update BMT fail\n"); -+ ret = 1; -+ } -+ } -+#endif -+ -+ return ret; -+} -+ -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+char gacBuf[4096 + 288]; -+ -+static int -+mtk_nand_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len) -+{ -+ struct nand_chip *chip = (struct nand_chip *)mtd->priv; -+ struct NAND_CMD *pkCMD = &g_kCMD; -+ u32 u4PageSize = mtd->writesize; -+ u32 *pSrc, *pDst; -+ int i; -+ -+ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, gacBuf, gacBuf + u4PageSize); -+ -+ pSrc = (u32 *) buf; -+ pDst = (u32 *) gacBuf; -+ len = len / sizeof(u32); -+ for (i = 0; i < len; ++i) { -+ if (*pSrc != *pDst) { -+ MSG(VERIFY, "mtk_nand_verify_buf page fail at page %d\n", pkCMD->u4RowAddr); -+ return -1; -+ } -+ pSrc++; -+ pDst++; -+ } -+ -+ pSrc = (u32 *) chip->oob_poi; -+ pDst = (u32 *) (gacBuf + u4PageSize); -+ -+ if ((pSrc[0] != pDst[0]) || (pSrc[1] != pDst[1]) || (pSrc[2] != pDst[2]) || (pSrc[3] != pDst[3]) || (pSrc[4] != pDst[4]) || (pSrc[5] != pDst[5])) { -+ // TODO: Ask Designer Why? -+ //(pSrc[6] != pDst[6]) || (pSrc[7] != pDst[7])) -+ MSG(VERIFY, "mtk_nand_verify_buf oob fail at page %d\n", pkCMD->u4RowAddr); -+ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5], pSrc[6], pSrc[7]); -+ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pDst[0], pDst[1], pDst[2], pDst[3], pDst[4], pDst[5], pDst[6], pDst[7]); -+ return -1; -+ } -+ return 0; -+} -+#endif -+ -+static void -+mtk_nand_init_hw(struct mtk_nand_host *host) { -+ struct mtk_nand_host_hw *hw = host->hw; -+ u32 data; -+ -+ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); -+ data &= ~((0x3<<18)|(0x3<<16)); -+ data |= ((0x2<<18) |(0x2<<16)); -+ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); -+ -+ MSG(INIT, "Enable NFI Clock\n"); -+ nand_enable_clock(); -+ -+ g_bInitDone = false; -+ g_kCMD.u4OOBRowAddr = (u32) - 1; -+ -+ /* Set default NFI access timing control */ -+ DRV_WriteReg32(NFI_ACCCON_REG32, hw->nfi_access_timing); -+ DRV_WriteReg16(NFI_CNFG_REG16, 0); -+ DRV_WriteReg16(NFI_PAGEFMT_REG16, 0); -+ -+ /* Reset the state machine and data FIFO, because flushing FIFO */ -+ (void)mtk_nand_reset(); -+ -+ /* Set the ECC engine */ -+ if (hw->nand_ecc_mode == NAND_ECC_HW) { -+ MSG(INIT, "%s : Use HW ECC\n", MODULE_NAME); -+ if (g_bHwEcc) -+ NFI_SET_REG32(NFI_CNFG_REG16, CNFG_HW_ECC_EN); -+ ECC_Config(host->hw,4); -+ mtk_nand_configure_fdm(8); -+ mtk_nand_configure_lock(); -+ } -+ -+ NFI_SET_REG16(NFI_IOCON_REG16, 0x47); -+} -+ -+static int mtk_nand_dev_ready(struct mtd_info *mtd) -+{ -+ return !(DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY); -+} -+ -+#define FACT_BBT_BLOCK_NUM 32 // use the latest 32 BLOCK for factory bbt table -+#define FACT_BBT_OOB_SIGNATURE 1 -+#define FACT_BBT_SIGNATURE_LEN 7 -+const u8 oob_signature[] = "mtknand"; -+static u8 *fact_bbt = 0; -+static u32 bbt_size = 0; -+ -+static int -+read_fact_bbt(struct mtd_info *mtd, unsigned int page) -+{ -+ struct nand_chip *chip = mtd->priv; -+ -+ // read oob -+ if (mtk_nand_read_oob_hw(mtd, chip, page)==0) -+ { -+ if (chip->oob_poi[nand_badblock_offset] != 0xFF) -+ { -+ printk("Bad Block on Page %x\n", page); -+ return -1; -+ } -+ if (memcmp(&chip->oob_poi[FACT_BBT_OOB_SIGNATURE], oob_signature, FACT_BBT_SIGNATURE_LEN) != 0) -+ { -+ printk("compare signature failed %x\n", page); -+ return -1; -+ } -+ if (mtk_nand_exec_read_page(mtd, page, mtd->writesize, chip->buffers->databuf, chip->oob_poi)) -+ { -+ printk("Signature matched and data read!\n"); -+ memcpy(fact_bbt, chip->buffers->databuf, (bbt_size <= mtd->writesize)? bbt_size:mtd->writesize); -+ return 0; -+ } -+ -+ } -+ printk("failed at page %x\n", page); -+ return -1; -+} -+ -+static int -+load_fact_bbt(struct mtd_info *mtd) -+{ -+ struct nand_chip *chip = mtd->priv; -+ int i; -+ u32 total_block; -+ -+ total_block = 1 << (chip->chip_shift - chip->phys_erase_shift); -+ bbt_size = total_block >> 2; -+ -+ if ((!fact_bbt) && (bbt_size)) -+ fact_bbt = (u8 *)kmalloc(bbt_size, GFP_KERNEL); -+ if (!fact_bbt) -+ return -1; -+ -+ for (i = total_block - 1; i >= (total_block - FACT_BBT_BLOCK_NUM); i--) -+ { -+ if (read_fact_bbt(mtd, i << (chip->phys_erase_shift - chip->page_shift)) == 0) -+ { -+ printk("load_fact_bbt success %d\n", i); -+ return 0; -+ } -+ -+ } -+ printk("load_fact_bbt failed\n"); -+ return -1; -+} -+ -+static int oob_mtk_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) -+{ -+ oobregion->length = 8; -+ oobregion->offset = layout->eccpos[section * 8]; -+ -+ return 0; -+} -+ -+static int oob_mtk_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *oobregion) -+{ -+ if (section >= (layout->eccbytes / 8)) { -+ return -ERANGE; -+ } -+ oobregion->offset = layout->oobfree[section].offset; -+ oobregion->length = layout->oobfree[section].length; -+ -+ return 0; -+} -+ -+ -+static const struct mtd_ooblayout_ops oob_mtk_ops = { -+ .ecc = oob_mtk_ooblayout_ecc, -+ .free = oob_mtk_ooblayout_free, -+}; -+ -+static int -+mtk_nand_probe(struct platform_device *pdev) -+{ -+ struct mtd_part_parser_data ppdata; -+ struct mtk_nand_host_hw *hw; -+ struct nand_chip *nand_chip; -+ struct mtd_info *mtd; -+ u8 ext_id1, ext_id2, ext_id3; -+ int err = 0; -+ int id; -+ u32 ext_id; -+ int i; -+ u32 data; -+ -+ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); -+ data &= ~((0x3<<18)|(0x3<<16)); -+ data |= ((0x2<<18) |(0x2<<16)); -+ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); -+ -+ hw = &mt7621_nand_hw; -+ BUG_ON(!hw); -+ /* Allocate memory for the device structure (and zero it) */ -+ host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL); -+ if (!host) { -+ MSG(INIT, "mtk_nand: failed to allocate device structure.\n"); -+ return -ENOMEM; -+ } -+ -+ host->hw = hw; -+ -+ /* init mtd data structure */ -+ nand_chip = &host->nand_chip; -+ nand_chip->priv = host; /* link the private data structures */ -+ -+ mtd = host->mtd = &nand_chip->mtd; -+ mtd->priv = nand_chip; -+ mtd->owner = THIS_MODULE; -+ mtd->name = "MT7621-NAND"; -+ -+ hw->nand_ecc_mode = NAND_ECC_HW; -+ -+ /* Set address of NAND IO lines */ -+ nand_chip->IO_ADDR_R = (void __iomem *)NFI_DATAR_REG32; -+ nand_chip->IO_ADDR_W = (void __iomem *)NFI_DATAW_REG32; -+ nand_chip->chip_delay = 20; /* 20us command delay time */ -+ nand_chip->ecc.mode = hw->nand_ecc_mode; /* enable ECC */ -+ nand_chip->ecc.strength = 1; -+ nand_chip->read_byte = mtk_nand_read_byte; -+ nand_chip->read_buf = mtk_nand_read_buf; -+ nand_chip->write_buf = mtk_nand_write_buf; -+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE -+ nand_chip->verify_buf = mtk_nand_verify_buf; -+#endif -+ nand_chip->select_chip = mtk_nand_select_chip; -+ nand_chip->dev_ready = mtk_nand_dev_ready; -+ nand_chip->cmdfunc = mtk_nand_command_bp; -+ nand_chip->ecc.read_page = mtk_nand_read_page_hwecc; -+ nand_chip->ecc.write_page = mtk_nand_write_page_hwecc; -+ -+ mtd_set_ooblayout(mtd, &oob_mtk_ops); -+ nand_chip->ecc.size = hw->nand_ecc_size; //2048 -+ nand_chip->ecc.bytes = hw->nand_ecc_bytes; //32 -+ -+ // For BMT, we need to revise driver architecture -+ nand_chip->write_page = mtk_nand_write_page; -+ nand_chip->ecc.write_oob = mtk_nand_write_oob; -+ nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device(). -+ nand_chip->read_page = mtk_nand_read_page; -+ nand_chip->ecc.read_oob = mtk_nand_read_oob; -+ nand_chip->block_bad = mtk_nand_block_bad; -+ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; -+ -+ //Qwert:Add for Uboot -+ mtk_nand_init_hw(host); -+ /* Select the device */ -+ nand_chip->select_chip(mtd, NFI_DEFAULT_CS); -+ -+ /* -+ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) -+ * after power-up -+ */ -+ nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); -+ -+ memset(&devinfo, 0 , sizeof(flashdev_info)); -+ -+ /* Send the command for reading device ID */ -+ -+ nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); -+ -+ /* Read manufacturer and device IDs */ -+ manu_id = nand_chip->read_byte(mtd); -+ dev_id = nand_chip->read_byte(mtd); -+ id = dev_id | (manu_id << 8); -+ ext_id1 = nand_chip->read_byte(mtd); -+ ext_id2 = nand_chip->read_byte(mtd); -+ ext_id3 = nand_chip->read_byte(mtd); -+ ext_id = ext_id1 << 16 | ext_id2 << 8 | ext_id3; -+ if (!get_device_info(id, ext_id, &devinfo)) { -+ u32 chip_mode = RALINK_REG(RALINK_SYSCTL_BASE+0x010)&0x0F; -+ MSG(INIT, "Not Support this Device! \r\n"); -+ memset(&devinfo, 0 , sizeof(flashdev_info)); -+ MSG(INIT, "chip_mode=%08X\n",chip_mode); -+ -+ /* apply bootstrap first */ -+ devinfo.addr_cycle = 5; -+ devinfo.iowidth = 8; -+ -+ switch (chip_mode) { -+ case 10: -+ devinfo.pagesize = 2048; -+ devinfo.sparesize = 128; -+ devinfo.totalsize = 128; -+ devinfo.blocksize = 128; -+ break; -+ case 11: -+ devinfo.pagesize = 4096; -+ devinfo.sparesize = 128; -+ devinfo.totalsize = 1024; -+ devinfo.blocksize = 256; -+ break; -+ case 12: -+ devinfo.pagesize = 4096; -+ devinfo.sparesize = 224; -+ devinfo.totalsize = 2048; -+ devinfo.blocksize = 512; -+ break; -+ default: -+ case 1: -+ devinfo.pagesize = 2048; -+ devinfo.sparesize = 64; -+ devinfo.totalsize = 128; -+ devinfo.blocksize = 128; -+ break; -+ } -+ -+ devinfo.timmingsetting = NFI_DEFAULT_ACCESS_TIMING; -+ devinfo.devciename[0] = 'U'; -+ devinfo.advancedmode = 0; -+ } -+ mtd->writesize = devinfo.pagesize; -+ mtd->erasesize = (devinfo.blocksize<<10); -+ mtd->oobsize = devinfo.sparesize; -+ -+ nand_chip->chipsize = (devinfo.totalsize<<20); -+ nand_chip->page_shift = ffs(mtd->writesize) - 1; -+ nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1; -+ nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1; -+ nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1; -+ nand_chip->cmd_ctrl = mtk_nfc_cmd_ctrl; -+ -+ if (devinfo.pagesize == 4096) -+ layout = &nand_oob_128; -+ else if (devinfo.pagesize == 2048) -+ layout = &nand_oob_64; -+ else if (devinfo.pagesize == 512) -+ layout = &nand_oob_16; -+ -+ layout->eccbytes = devinfo.sparesize-OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE); -+ for (i = 0; i < layout->eccbytes; i++) -+ layout->eccpos[i]=OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE)+i; -+ -+ MSG(INIT, "Support this Device in MTK table! %x \r\n", id); -+ hw->nfi_bus_width = devinfo.iowidth; -+ DRV_WriteReg32(NFI_ACCCON_REG32, devinfo.timmingsetting); -+ -+ /* 16-bit bus width */ -+ if (hw->nfi_bus_width == 16) { -+ MSG(INIT, "%s : Set the 16-bit I/O settings!\n", MODULE_NAME); -+ nand_chip->options |= NAND_BUSWIDTH_16; -+ } -+ mtd->oobsize = devinfo.sparesize; -+ hw->nfi_cs_num = 1; -+ -+ nand_chip->options |= NAND_USE_BOUNCE_BUFFER; -+ nand_chip->buf_align = 16; -+ -+ /* Scan to find existance of the device */ -+ if (nand_scan(mtd, hw->nfi_cs_num)) { -+ MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME); -+ err = -ENXIO; -+ goto out; -+ } -+ -+ nand_chip->erase = mtk_nand_erase; -+ -+ g_page_size = mtd->writesize; -+ platform_set_drvdata(pdev, host); -+ if (hw->nfi_bus_width == 16) { -+ NFI_SET_REG16(NFI_PAGEFMT_REG16, PAGEFMT_DBYTE_EN); -+ } -+ -+ nand_chip->select_chip(mtd, 0); -+#if defined(MTK_NAND_BMT) -+ nand_chip->chipsize -= (BMT_POOL_SIZE) << nand_chip->phys_erase_shift; -+#endif -+ mtd->size = nand_chip->chipsize; -+ -+ CFG_BLOCKSIZE = mtd->erasesize; -+ -+#if defined(MTK_NAND_BMT) -+ if (!g_bmt) { -+ if (!(g_bmt = init_bmt(nand_chip, BMT_POOL_SIZE))) { -+ MSG(INIT, "Error: init bmt failed\n"); -+ return 0; -+ } -+ } -+#endif -+ -+ nand_set_flash_node(nand_chip, pdev->dev.of_node); -+ err = mtd_device_parse_register(mtd, probe_types, &ppdata, -+ NULL, 0); -+ if (!err) { -+ MSG(INIT, "[mtk_nand] probe successfully!\n"); -+ nand_disable_clock(); -+ shift_on_bbt = 0; -+ if (load_fact_bbt(mtd) == 0) { -+ int i; -+ for (i = 0; i < 0x100; i++) -+ nand_chip->bbt[i] |= fact_bbt[i]; -+ } -+ -+ return err; -+ } -+ -+out: -+ MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err); -+ nand_release(mtd); -+ platform_set_drvdata(pdev, NULL); -+ kfree(host); -+ nand_disable_clock(); -+ return err; -+} -+ -+static int -+mtk_nand_remove(struct platform_device *pdev) -+{ -+ struct mtk_nand_host *host = platform_get_drvdata(pdev); -+ struct mtd_info *mtd = host->mtd; -+ struct nand_chip *nand_chip = &host->nand_chip; -+ -+ nand_release(mtd); -+ kfree(host); -+ nand_disable_clock(); -+ -+ return 0; -+} -+ -+static const struct of_device_id mt7621_nand_match[] = { -+ { .compatible = "mtk,mt7621-nand" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mt7621_nand_match); -+ -+static struct platform_driver mtk_nand_driver = { -+ .probe = mtk_nand_probe, -+ .remove = mtk_nand_remove, -+ .driver = { -+ .name = "MT7621-NAND", -+ .owner = THIS_MODULE, -+ .of_match_table = mt7621_nand_match, -+ }, -+}; -+ -+static int __init -+mtk_nand_init(void) -+{ -+ printk("MediaTek Nand driver init, version %s\n", VERSION); -+ -+ return platform_driver_register(&mtk_nand_driver); -+} -+ -+static void __exit -+mtk_nand_exit(void) -+{ -+ platform_driver_unregister(&mtk_nand_driver); -+} -+ -+module_init(mtk_nand_init); -+module_exit(mtk_nand_exit); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/drivers/mtd/nand/mtk_nand2.h -@@ -0,0 +1,452 @@ -+#ifndef __MTK_NAND_H -+#define __MTK_NAND_H -+ -+#define RALINK_NAND_CTRL_BASE 0xBE003000 -+#define RALINK_SYSCTL_BASE 0xBE000000 -+#define RALINK_NANDECC_CTRL_BASE 0xBE003800 -+/******************************************************************************* -+ * NFI Register Definition -+ *******************************************************************************/ -+ -+#define NFI_CNFG_REG16 ((volatile P_U16)(NFI_BASE+0x0000)) -+#define NFI_PAGEFMT_REG16 ((volatile P_U16)(NFI_BASE+0x0004)) -+#define NFI_CON_REG16 ((volatile P_U16)(NFI_BASE+0x0008)) -+#define NFI_ACCCON_REG32 ((volatile P_U32)(NFI_BASE+0x000C)) -+#define NFI_INTR_EN_REG16 ((volatile P_U16)(NFI_BASE+0x0010)) -+#define NFI_INTR_REG16 ((volatile P_U16)(NFI_BASE+0x0014)) -+ -+#define NFI_CMD_REG16 ((volatile P_U16)(NFI_BASE+0x0020)) -+ -+#define NFI_ADDRNOB_REG16 ((volatile P_U16)(NFI_BASE+0x0030)) -+#define NFI_COLADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0034)) -+#define NFI_ROWADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0038)) -+ -+#define NFI_STRDATA_REG16 ((volatile P_U16)(NFI_BASE+0x0040)) -+ -+#define NFI_DATAW_REG32 ((volatile P_U32)(NFI_BASE+0x0050)) -+#define NFI_DATAR_REG32 ((volatile P_U32)(NFI_BASE+0x0054)) -+#define NFI_PIO_DIRDY_REG16 ((volatile P_U16)(NFI_BASE+0x0058)) -+ -+#define NFI_STA_REG32 ((volatile P_U32)(NFI_BASE+0x0060)) -+#define NFI_FIFOSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0064)) -+#define NFI_LOCKSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0068)) -+ -+#define NFI_ADDRCNTR_REG16 ((volatile P_U16)(NFI_BASE+0x0070)) -+ -+#define NFI_STRADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0080)) -+#define NFI_BYTELEN_REG16 ((volatile P_U16)(NFI_BASE+0x0084)) -+ -+#define NFI_CSEL_REG16 ((volatile P_U16)(NFI_BASE+0x0090)) -+#define NFI_IOCON_REG16 ((volatile P_U16)(NFI_BASE+0x0094)) -+ -+#define NFI_FDM0L_REG32 ((volatile P_U32)(NFI_BASE+0x00A0)) -+#define NFI_FDM0M_REG32 ((volatile P_U32)(NFI_BASE+0x00A4)) -+ -+#define NFI_LOCK_REG16 ((volatile P_U16)(NFI_BASE+0x0100)) -+#define NFI_LOCKCON_REG32 ((volatile P_U32)(NFI_BASE+0x0104)) -+#define NFI_LOCKANOB_REG16 ((volatile P_U16)(NFI_BASE+0x0108)) -+#define NFI_LOCK00ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0110)) -+#define NFI_LOCK00FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0114)) -+#define NFI_LOCK01ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0118)) -+#define NFI_LOCK01FMT_REG32 ((volatile P_U32)(NFI_BASE+0x011C)) -+#define NFI_LOCK02ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0120)) -+#define NFI_LOCK02FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0124)) -+#define NFI_LOCK03ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0128)) -+#define NFI_LOCK03FMT_REG32 ((volatile P_U32)(NFI_BASE+0x012C)) -+#define NFI_LOCK04ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0130)) -+#define NFI_LOCK04FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0134)) -+#define NFI_LOCK05ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0138)) -+#define NFI_LOCK05FMT_REG32 ((volatile P_U32)(NFI_BASE+0x013C)) -+#define NFI_LOCK06ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0140)) -+#define NFI_LOCK06FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0144)) -+#define NFI_LOCK07ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0148)) -+#define NFI_LOCK07FMT_REG32 ((volatile P_U32)(NFI_BASE+0x014C)) -+#define NFI_LOCK08ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0150)) -+#define NFI_LOCK08FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0154)) -+#define NFI_LOCK09ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0158)) -+#define NFI_LOCK09FMT_REG32 ((volatile P_U32)(NFI_BASE+0x015C)) -+#define NFI_LOCK10ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0160)) -+#define NFI_LOCK10FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0164)) -+#define NFI_LOCK11ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0168)) -+#define NFI_LOCK11FMT_REG32 ((volatile P_U32)(NFI_BASE+0x016C)) -+#define NFI_LOCK12ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0170)) -+#define NFI_LOCK12FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0174)) -+#define NFI_LOCK13ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0178)) -+#define NFI_LOCK13FMT_REG32 ((volatile P_U32)(NFI_BASE+0x017C)) -+#define NFI_LOCK14ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0180)) -+#define NFI_LOCK14FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0184)) -+#define NFI_LOCK15ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0188)) -+#define NFI_LOCK15FMT_REG32 ((volatile P_U32)(NFI_BASE+0x018C)) -+ -+#define NFI_FIFODATA0_REG32 ((volatile P_U32)(NFI_BASE+0x0190)) -+#define NFI_FIFODATA1_REG32 ((volatile P_U32)(NFI_BASE+0x0194)) -+#define NFI_FIFODATA2_REG32 ((volatile P_U32)(NFI_BASE+0x0198)) -+#define NFI_FIFODATA3_REG32 ((volatile P_U32)(NFI_BASE+0x019C)) -+#define NFI_MASTERSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0210)) -+ -+ -+/******************************************************************************* -+ * NFI Register Field Definition -+ *******************************************************************************/ -+ -+/* NFI_CNFG */ -+#define CNFG_AHB (0x0001) -+#define CNFG_READ_EN (0x0002) -+#define CNFG_DMA_BURST_EN (0x0004) -+#define CNFG_BYTE_RW (0x0040) -+#define CNFG_HW_ECC_EN (0x0100) -+#define CNFG_AUTO_FMT_EN (0x0200) -+#define CNFG_OP_IDLE (0x0000) -+#define CNFG_OP_READ (0x1000) -+#define CNFG_OP_SRD (0x2000) -+#define CNFG_OP_PRGM (0x3000) -+#define CNFG_OP_ERASE (0x4000) -+#define CNFG_OP_RESET (0x5000) -+#define CNFG_OP_CUST (0x6000) -+#define CNFG_OP_MODE_MASK (0x7000) -+#define CNFG_OP_MODE_SHIFT (12) -+ -+/* NFI_PAGEFMT */ -+#define PAGEFMT_512 (0x0000) -+#define PAGEFMT_2K (0x0001) -+#define PAGEFMT_4K (0x0002) -+ -+#define PAGEFMT_PAGE_MASK (0x0003) -+ -+#define PAGEFMT_DBYTE_EN (0x0008) -+ -+#define PAGEFMT_SPARE_16 (0x0000) -+#define PAGEFMT_SPARE_26 (0x0001) -+#define PAGEFMT_SPARE_27 (0x0002) -+#define PAGEFMT_SPARE_28 (0x0003) -+#define PAGEFMT_SPARE_MASK (0x0030) -+#define PAGEFMT_SPARE_SHIFT (4) -+ -+#define PAGEFMT_FDM_MASK (0x0F00) -+#define PAGEFMT_FDM_SHIFT (8) -+ -+#define PAGEFMT_FDM_ECC_MASK (0xF000) -+#define PAGEFMT_FDM_ECC_SHIFT (12) -+ -+/* NFI_CON */ -+#define CON_FIFO_FLUSH (0x0001) -+#define CON_NFI_RST (0x0002) -+#define CON_NFI_SRD (0x0010) -+ -+#define CON_NFI_NOB_MASK (0x0060) -+#define CON_NFI_NOB_SHIFT (5) -+ -+#define CON_NFI_BRD (0x0100) -+#define CON_NFI_BWR (0x0200) -+ -+#define CON_NFI_SEC_MASK (0xF000) -+#define CON_NFI_SEC_SHIFT (12) -+ -+/* NFI_ACCCON */ -+#define ACCCON_SETTING () -+ -+/* NFI_INTR_EN */ -+#define INTR_RD_DONE_EN (0x0001) -+#define INTR_WR_DONE_EN (0x0002) -+#define INTR_RST_DONE_EN (0x0004) -+#define INTR_ERASE_DONE_EN (0x0008) -+#define INTR_BSY_RTN_EN (0x0010) -+#define INTR_ACC_LOCK_EN (0x0020) -+#define INTR_AHB_DONE_EN (0x0040) -+#define INTR_ALL_INTR_DE (0x0000) -+#define INTR_ALL_INTR_EN (0x007F) -+ -+/* NFI_INTR */ -+#define INTR_RD_DONE (0x0001) -+#define INTR_WR_DONE (0x0002) -+#define INTR_RST_DONE (0x0004) -+#define INTR_ERASE_DONE (0x0008) -+#define INTR_BSY_RTN (0x0010) -+#define INTR_ACC_LOCK (0x0020) -+#define INTR_AHB_DONE (0x0040) -+ -+/* NFI_ADDRNOB */ -+#define ADDR_COL_NOB_MASK (0x0003) -+#define ADDR_COL_NOB_SHIFT (0) -+#define ADDR_ROW_NOB_MASK (0x0030) -+#define ADDR_ROW_NOB_SHIFT (4) -+ -+/* NFI_STA */ -+#define STA_READ_EMPTY (0x00001000) -+#define STA_ACC_LOCK (0x00000010) -+#define STA_CMD_STATE (0x00000001) -+#define STA_ADDR_STATE (0x00000002) -+#define STA_DATAR_STATE (0x00000004) -+#define STA_DATAW_STATE (0x00000008) -+ -+#define STA_NAND_FSM_MASK (0x1F000000) -+#define STA_NAND_BUSY (0x00000100) -+#define STA_NAND_BUSY_RETURN (0x00000200) -+#define STA_NFI_FSM_MASK (0x000F0000) -+#define STA_NFI_OP_MASK (0x0000000F) -+ -+/* NFI_FIFOSTA */ -+#define FIFO_RD_EMPTY (0x0040) -+#define FIFO_RD_FULL (0x0080) -+#define FIFO_WR_FULL (0x8000) -+#define FIFO_WR_EMPTY (0x4000) -+#define FIFO_RD_REMAIN(x) (0x1F&(x)) -+#define FIFO_WR_REMAIN(x) ((0x1F00&(x))>>8) -+ -+/* NFI_ADDRCNTR */ -+#define ADDRCNTR_CNTR(x) ((0xF000&(x))>>12) -+#define ADDRCNTR_OFFSET(x) (0x03FF&(x)) -+ -+/* NFI_LOCK */ -+#define NFI_LOCK_ON (0x0001) -+ -+/* NFI_LOCKANOB */ -+#define PROG_RADD_NOB_MASK (0x7000) -+#define PROG_RADD_NOB_SHIFT (12) -+#define PROG_CADD_NOB_MASK (0x0300) -+#define PROG_CADD_NOB_SHIFT (8) -+#define ERASE_RADD_NOB_MASK (0x0070) -+#define ERASE_RADD_NOB_SHIFT (4) -+#define ERASE_CADD_NOB_MASK (0x0007) -+#define ERASE_CADD_NOB_SHIFT (0) -+ -+/******************************************************************************* -+ * ECC Register Definition -+ *******************************************************************************/ -+ -+#define ECC_ENCCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0000)) -+#define ECC_ENCCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0004)) -+#define ECC_ENCDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0008)) -+#define ECC_ENCIDLE_REG32 ((volatile P_U32)(NFIECC_BASE+0x000C)) -+#define ECC_ENCPAR0_REG32 ((volatile P_U32)(NFIECC_BASE+0x0010)) -+#define ECC_ENCPAR1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0014)) -+#define ECC_ENCPAR2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0018)) -+#define ECC_ENCPAR3_REG32 ((volatile P_U32)(NFIECC_BASE+0x001C)) -+#define ECC_ENCPAR4_REG32 ((volatile P_U32)(NFIECC_BASE+0x0020)) -+#define ECC_ENCSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0024)) -+#define ECC_ENCIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0028)) -+#define ECC_ENCIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x002C)) -+ -+#define ECC_DECCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0100)) -+#define ECC_DECCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0104)) -+#define ECC_DECDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0108)) -+#define ECC_DECIDLE_REG16 ((volatile P_U16)(NFIECC_BASE+0x010C)) -+#define ECC_DECFER_REG16 ((volatile P_U16)(NFIECC_BASE+0x0110)) -+#define ECC_DECENUM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0114)) -+#define ECC_DECDONE_REG16 ((volatile P_U16)(NFIECC_BASE+0x0118)) -+#define ECC_DECEL0_REG32 ((volatile P_U32)(NFIECC_BASE+0x011C)) -+#define ECC_DECEL1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0120)) -+#define ECC_DECEL2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0124)) -+#define ECC_DECEL3_REG32 ((volatile P_U32)(NFIECC_BASE+0x0128)) -+#define ECC_DECEL4_REG32 ((volatile P_U32)(NFIECC_BASE+0x012C)) -+#define ECC_DECEL5_REG32 ((volatile P_U32)(NFIECC_BASE+0x0130)) -+#define ECC_DECIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0134)) -+#define ECC_DECIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x0138)) -+#define ECC_FDMADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x013C)) -+#define ECC_DECFSM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0140)) -+#define ECC_SYNSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0144)) -+#define ECC_DECNFIDI_REG32 ((volatile P_U32)(NFIECC_BASE+0x0148)) -+#define ECC_SYN0_REG32 ((volatile P_U32)(NFIECC_BASE+0x014C)) -+ -+/******************************************************************************* -+ * ECC register definition -+ *******************************************************************************/ -+/* ECC_ENCON */ -+#define ENC_EN (0x0001) -+#define ENC_DE (0x0000) -+ -+/* ECC_ENCCNFG */ -+#define ECC_CNFG_ECC4 (0x0000) -+#define ECC_CNFG_ECC6 (0x0001) -+#define ECC_CNFG_ECC8 (0x0002) -+#define ECC_CNFG_ECC10 (0x0003) -+#define ECC_CNFG_ECC12 (0x0004) -+#define ECC_CNFG_ECC_MASK (0x00000007) -+ -+#define ENC_CNFG_NFI (0x0010) -+#define ENC_CNFG_MODE_MASK (0x0010) -+ -+#define ENC_CNFG_META6 (0x10300000) -+#define ENC_CNFG_META8 (0x10400000) -+ -+#define ENC_CNFG_MSG_MASK (0x1FFF0000) -+#define ENC_CNFG_MSG_SHIFT (0x10) -+ -+/* ECC_ENCIDLE */ -+#define ENC_IDLE (0x0001) -+ -+/* ECC_ENCSTA */ -+#define STA_FSM (0x001F) -+#define STA_COUNT_PS (0xFF10) -+#define STA_COUNT_MS (0x3FFF0000) -+ -+/* ECC_ENCIRQEN */ -+#define ENC_IRQEN (0x0001) -+ -+/* ECC_ENCIRQSTA */ -+#define ENC_IRQSTA (0x0001) -+ -+/* ECC_DECCON */ -+#define DEC_EN (0x0001) -+#define DEC_DE (0x0000) -+ -+/* ECC_ENCCNFG */ -+#define DEC_CNFG_ECC4 (0x0000) -+//#define DEC_CNFG_ECC6 (0x0001) -+//#define DEC_CNFG_ECC12 (0x0002) -+#define DEC_CNFG_NFI (0x0010) -+//#define DEC_CNFG_META6 (0x10300000) -+//#define DEC_CNFG_META8 (0x10400000) -+ -+#define DEC_CNFG_FER (0x01000) -+#define DEC_CNFG_EL (0x02000) -+#define DEC_CNFG_CORRECT (0x03000) -+#define DEC_CNFG_TYPE_MASK (0x03000) -+ -+#define DEC_CNFG_EMPTY_EN (0x80000000) -+ -+#define DEC_CNFG_CODE_MASK (0x1FFF0000) -+#define DEC_CNFG_CODE_SHIFT (0x10) -+ -+/* ECC_DECIDLE */ -+#define DEC_IDLE (0x0001) -+ -+/* ECC_DECFER */ -+#define DEC_FER0 (0x0001) -+#define DEC_FER1 (0x0002) -+#define DEC_FER2 (0x0004) -+#define DEC_FER3 (0x0008) -+#define DEC_FER4 (0x0010) -+#define DEC_FER5 (0x0020) -+#define DEC_FER6 (0x0040) -+#define DEC_FER7 (0x0080) -+ -+/* ECC_DECENUM */ -+#define ERR_NUM0 (0x0000000F) -+#define ERR_NUM1 (0x000000F0) -+#define ERR_NUM2 (0x00000F00) -+#define ERR_NUM3 (0x0000F000) -+#define ERR_NUM4 (0x000F0000) -+#define ERR_NUM5 (0x00F00000) -+#define ERR_NUM6 (0x0F000000) -+#define ERR_NUM7 (0xF0000000) -+ -+/* ECC_DECDONE */ -+#define DEC_DONE0 (0x0001) -+#define DEC_DONE1 (0x0002) -+#define DEC_DONE2 (0x0004) -+#define DEC_DONE3 (0x0008) -+#define DEC_DONE4 (0x0010) -+#define DEC_DONE5 (0x0020) -+#define DEC_DONE6 (0x0040) -+#define DEC_DONE7 (0x0080) -+ -+/* ECC_DECIRQEN */ -+#define DEC_IRQEN (0x0001) -+ -+/* ECC_DECIRQSTA */ -+#define DEC_IRQSTA (0x0001) -+ -+#define CHIPVER_ECO_1 (0x8a00) -+#define CHIPVER_ECO_2 (0x8a01) -+ -+//#define NAND_PFM -+ -+/******************************************************************************* -+ * Data Structure Definition -+ *******************************************************************************/ -+struct mtk_nand_host -+{ -+ struct nand_chip nand_chip; -+ struct mtd_info *mtd; -+ struct mtk_nand_host_hw *hw; -+}; -+ -+struct NAND_CMD -+{ -+ u32 u4ColAddr; -+ u32 u4RowAddr; -+ u32 u4OOBRowAddr; -+ u8 au1OOB[288]; -+ u8* pDataBuf; -+#ifdef NAND_PFM -+ u32 pureReadOOB; -+ u32 pureReadOOBNum; -+#endif -+}; -+ -+/* -+ * ECC layout control structure. Exported to userspace for -+ * diagnosis and to allow creation of raw images -+struct nand_ecclayout { -+ uint32_t eccbytes; -+ uint32_t eccpos[64]; -+ uint32_t oobavail; -+ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; -+}; -+*/ -+#define __DEBUG_NAND 1 /* Debug information on/off */ -+ -+/* Debug message event */ -+#define DBG_EVT_NONE 0x00000000 /* No event */ -+#define DBG_EVT_INIT 0x00000001 /* Initial related event */ -+#define DBG_EVT_VERIFY 0x00000002 /* Verify buffer related event */ -+#define DBG_EVT_PERFORMANCE 0x00000004 /* Performance related event */ -+#define DBG_EVT_READ 0x00000008 /* Read related event */ -+#define DBG_EVT_WRITE 0x00000010 /* Write related event */ -+#define DBG_EVT_ERASE 0x00000020 /* Erase related event */ -+#define DBG_EVT_BADBLOCK 0x00000040 /* Badblock related event */ -+#define DBG_EVT_POWERCTL 0x00000080 /* Suspend/Resume related event */ -+ -+#define DBG_EVT_ALL 0xffffffff -+ -+#define DBG_EVT_MASK (DBG_EVT_INIT) -+ -+#if __DEBUG_NAND -+#define MSG(evt, fmt, args...) \ -+do { \ -+ if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \ -+ printk(fmt, ##args); \ -+ } \ -+} while(0) -+ -+#define MSG_FUNC_ENTRY(f) MSG(FUC, ": %s\n", __FUNCTION__) -+#else -+#define MSG(evt, fmt, args...) do{}while(0) -+#define MSG_FUNC_ENTRY(f) do{}while(0) -+#endif -+ -+#define RAMDOM_READ 1<<0 -+#define CACHE_READ 1<<1 -+ -+typedef struct -+{ -+ u16 id; //deviceid+menuid -+ u32 ext_id; -+ u8 addr_cycle; -+ u8 iowidth; -+ u16 totalsize; -+ u16 blocksize; -+ u16 pagesize; -+ u16 sparesize; -+ u32 timmingsetting; -+ char devciename[14]; -+ u32 advancedmode; // -+}flashdev_info,*pflashdev_info; -+ -+/* NAND driver */ -+#if 0 -+struct mtk_nand_host_hw { -+ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ -+ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ -+ unsigned int nfi_cs_num; /* NFI_CS_NUM */ -+ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ -+ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ -+ unsigned int nand_ecc_size; -+ unsigned int nand_ecc_bytes; -+ unsigned int nand_ecc_mode; -+}; -+extern struct mtk_nand_host_hw mt7621_nand_hw; -+extern u32 CFG_BLOCKSIZE; -+#endif -+#endif ---- a/drivers/mtd/nand/nand_base.c -+++ b/drivers/mtd/nand/nand_base.c -@@ -48,7 +48,7 @@ - #include - #include - --static int nand_get_device(struct mtd_info *mtd, int new_state); -+int nand_get_device(struct mtd_info *mtd, int new_state); - - static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, - struct mtd_oob_ops *ops); -@@ -240,7 +240,7 @@ static int check_offs_len(struct mtd_inf - * - * Release chip lock and wake up anyone waiting on the device. - */ --static void nand_release_device(struct mtd_info *mtd) -+void nand_release_device(struct mtd_info *mtd) - { - struct nand_chip *chip = mtd_to_nand(mtd); - -@@ -968,7 +968,7 @@ static void panic_nand_get_device(struct - * - * Get the device and lock it for exclusive access - */ --static int -+int - nand_get_device(struct mtd_info *mtd, int new_state) - { - struct nand_chip *chip = mtd_to_nand(mtd); ---- /dev/null -+++ b/drivers/mtd/nand/nand_def.h -@@ -0,0 +1,123 @@ -+#ifndef __NAND_DEF_H__ -+#define __NAND_DEF_H__ -+ -+#define VERSION "v2.1 Fix AHB virt2phys error" -+#define MODULE_NAME "# MTK NAND #" -+#define PROCNAME "driver/nand" -+ -+#undef TESTTIME -+//#define __UBOOT_NAND__ 1 -+#define __KERNEL_NAND__ 1 -+//#define __PRELOADER_NAND__ 1 -+//#define PMT 1 -+//#define _MTK_NAND_DUMMY_DRIVER -+//#define CONFIG_BADBLOCK_CHECK 1 -+//#ifdef CONFIG_BADBLOCK_CHECK -+//#define MTK_NAND_BMT 1 -+//#endif -+#define ECC_ENABLE 1 -+#define MANUAL_CORRECT 1 -+//#define __INTERNAL_USE_AHB_MODE__ (0) -+#define SKIP_BAD_BLOCK -+#define FACT_BBT -+ -+#ifndef NAND_OTP_SUPPORT -+#define NAND_OTP_SUPPORT 0 -+#endif -+ -+/******************************************************************************* -+ * Macro definition -+ *******************************************************************************/ -+//#define NFI_SET_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) | (value))) -+//#define NFI_SET_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) | (value))) -+//#define NFI_CLN_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) & (~(value)))) -+//#define NFI_CLN_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) & (~(value)))) -+ -+#if defined (__KERNEL_NAND__) -+#define NFI_SET_REG32(reg, value) \ -+do { \ -+ g_value = (DRV_Reg32(reg) | (value));\ -+ DRV_WriteReg32(reg, g_value); \ -+} while(0) -+ -+#define NFI_SET_REG16(reg, value) \ -+do { \ -+ g_value = (DRV_Reg16(reg) | (value));\ -+ DRV_WriteReg16(reg, g_value); \ -+} while(0) -+ -+#define NFI_CLN_REG32(reg, value) \ -+do { \ -+ g_value = (DRV_Reg32(reg) & (~(value)));\ -+ DRV_WriteReg32(reg, g_value); \ -+} while(0) -+ -+#define NFI_CLN_REG16(reg, value) \ -+do { \ -+ g_value = (DRV_Reg16(reg) & (~(value)));\ -+ DRV_WriteReg16(reg, g_value); \ -+} while(0) -+#endif -+ -+#define NFI_WAIT_STATE_DONE(state) do{;}while (__raw_readl(NFI_STA_REG32) & state) -+#define NFI_WAIT_TO_READY() do{;}while (!(__raw_readl(NFI_STA_REG32) & STA_BUSY2READY)) -+ -+ -+#define NAND_SECTOR_SIZE (512) -+#define OOB_PER_SECTOR (16) -+#define OOB_AVAI_PER_SECTOR (8) -+ -+#ifndef PART_SIZE_BMTPOOL -+#define BMT_POOL_SIZE (80) -+#else -+#define BMT_POOL_SIZE (PART_SIZE_BMTPOOL) -+#endif -+ -+#define PMT_POOL_SIZE (2) -+ -+#define TIMEOUT_1 0x1fff -+#define TIMEOUT_2 0x8ff -+#define TIMEOUT_3 0xffff -+#define TIMEOUT_4 0xffff//5000 //PIO -+ -+ -+/* temporarity definiation */ -+#if !defined (__KERNEL_NAND__) -+#define KERN_INFO -+#define KERN_WARNING -+#define KERN_ERR -+#define PAGE_SIZE (4096) -+#endif -+#define AddStorageTrace //AddStorageTrace -+#define STORAGE_LOGGER_MSG_NAND 0 -+#define NFI_BASE RALINK_NAND_CTRL_BASE -+#define NFIECC_BASE RALINK_NANDECC_CTRL_BASE -+ -+#ifdef __INTERNAL_USE_AHB_MODE__ -+#define MT65xx_POLARITY_LOW 0 -+#define MT65XX_PDN_PERI_NFI 0 -+#define MT65xx_EDGE_SENSITIVE 0 -+#define MT6575_NFI_IRQ_ID (58) -+#endif -+ -+#if defined (__KERNEL_NAND__) -+#define RALINK_REG(x) (*((volatile u32 *)(x))) -+#define __virt_to_phys(x) virt_to_phys((volatile void*)x) -+#else -+#define CONFIG_MTD_NAND_VERIFY_WRITE (1) -+#define printk printf -+#define ra_dbg printf -+#define BUG() //BUG() -+#define BUG_ON(x) //BUG_ON() -+#define NUM_PARTITIONS 1 -+#endif -+ -+#define NFI_DEFAULT_ACCESS_TIMING (0x30C77fff) //(0x44333) -+ -+//uboot only support 1 cs -+#define NFI_CS_NUM (1) -+#define NFI_DEFAULT_CS (0) -+ -+#include "mt6575_typedefs.h" -+ -+#endif /* __NAND_DEF_H__ */ ---- /dev/null -+++ b/drivers/mtd/nand/nand_device_list.h -@@ -0,0 +1,60 @@ -+/* Copyright Statement: -+ * -+ * This software/firmware and related documentation ("MediaTek Software") are -+ * protected under relevant copyright laws. The information contained herein -+ * is confidential and proprietary to MediaTek Inc. and/or its licensors. -+ * Without the prior written permission of MediaTek inc. and/or its licensors, -+ * any reproduction, modification, use or disclosure of MediaTek Software, -+ * and information contained herein, in whole or in part, shall be strictly prohibited. -+ */ -+/* MediaTek Inc. (C) 2010. All rights reserved. -+ * -+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES -+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") -+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON -+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. -+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE -+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR -+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH -+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES -+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES -+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK -+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR -+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND -+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, -+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, -+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO -+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. -+ * -+ * The following software/firmware and/or related documentation ("MediaTek Software") -+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's -+ * applicable license agreements with MediaTek Inc. -+ */ -+ -+#ifndef __NAND_DEVICE_LIST_H__ -+#define __NAND_DEVICE_LIST_H__ -+ -+static const flashdev_info gen_FlashTable[]={ -+ {0x20BC, 0x105554, 5, 16, 512, 128, 2048, 64, 0x1123, "EHD013151MA_5", 0}, -+ {0xECBC, 0x005554, 5, 16, 512, 128, 2048, 64, 0x1123, "K524G2GACB_A0", 0}, -+ {0x2CBC, 0x905556, 5, 16, 512, 128, 2048, 64, 0x21044333, "MT29C4G96MAZA", 0}, -+ {0x2CDA, 0x909506, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "MT29F2G08ABAE", 0}, -+ {0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0}, -+ {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0}, -+ {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0}, -+ {0xC8D1, 0x809540, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81MA", 0}, -+ {0xC8DA, 0x909544, 5, 8, 256, 128, 2048, 64, 0x30C77fff, "F59L2G81A", 0}, -+ {0xC8DC, 0x909554, 5, 8, 512, 128, 2048, 64, 0x30C77fff, "F59L4G81A", 0}, -+ {0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0}, -+ {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0}, -+ {0xC2F1, 0x809502, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G18AC", 0}, -+ {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0}, -+ {0x01DA, 0x909546, 5, 8, 256, 128, 2048, 128, 0x30C77fff, "S34ML02G200TF", 0}, -+ {0x01DC, 0x909556, 5, 8, 512, 128, 2048, 128, 0x30C77fff, "S34ML04G200TF", 0}, -+ {0x0000, 0x000000, 0, 0, 0, 0, 0, 0, 0, "xxxxxxxxxx", 0}, -+}; -+ -+ -+#endif ---- /dev/null -+++ b/drivers/mtd/nand/partition.h -@@ -0,0 +1,115 @@ -+/* Copyright Statement: -+ * -+ * This software/firmware and related documentation ("MediaTek Software") are -+ * protected under relevant copyright laws. The information contained herein -+ * is confidential and proprietary to MediaTek Inc. and/or its licensors. -+ * Without the prior written permission of MediaTek inc. and/or its licensors, -+ * any reproduction, modification, use or disclosure of MediaTek Software, -+ * and information contained herein, in whole or in part, shall be strictly prohibited. -+ */ -+/* MediaTek Inc. (C) 2010. All rights reserved. -+ * -+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES -+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") -+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON -+ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. -+ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE -+ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR -+ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH -+ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES -+ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES -+ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK -+ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR -+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND -+ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, -+ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, -+ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO -+ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. -+ * -+ * The following software/firmware and/or related documentation ("MediaTek Software") -+ * have been modified by MediaTek Inc. All revisions are subject to any receiver's -+ * applicable license agreements with MediaTek Inc. -+ */ -+ -+#include -+#include -+#include -+ -+#define RECONFIG_PARTITION_SIZE 1 -+ -+#define MTD_BOOT_PART_SIZE 0x80000 -+#define MTD_CONFIG_PART_SIZE 0x20000 -+#define MTD_FACTORY_PART_SIZE 0x20000 -+ -+extern unsigned int CFG_BLOCKSIZE; -+#define LARGE_MTD_BOOT_PART_SIZE (CFG_BLOCKSIZE<<2) -+#define LARGE_MTD_CONFIG_PART_SIZE (CFG_BLOCKSIZE<<2) -+#define LARGE_MTD_FACTORY_PART_SIZE (CFG_BLOCKSIZE<<1) -+ -+/*=======================================================================*/ -+/* NAND PARTITION Mapping */ -+/*=======================================================================*/ -+//#ifdef CONFIG_MTD_PARTITIONS -+static struct mtd_partition g_pasStatic_Partition[] = { -+ { -+ name: "ALL", -+ size: MTDPART_SIZ_FULL, -+ offset: 0, -+ }, -+ /* Put your own partition definitions here */ -+ { -+ name: "Bootloader", -+ size: MTD_BOOT_PART_SIZE, -+ offset: 0, -+ }, { -+ name: "Config", -+ size: MTD_CONFIG_PART_SIZE, -+ offset: MTDPART_OFS_APPEND -+ }, { -+ name: "Factory", -+ size: MTD_FACTORY_PART_SIZE, -+ offset: MTDPART_OFS_APPEND -+#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH -+ }, { -+ name: "Kernel", -+ size: MTD_KERN_PART_SIZE, -+ offset: MTDPART_OFS_APPEND, -+ }, { -+ name: "RootFS", -+ size: MTD_ROOTFS_PART_SIZE, -+ offset: MTDPART_OFS_APPEND, -+#ifdef CONFIG_ROOTFS_IN_FLASH_NO_PADDING -+ }, { -+ name: "Kernel_RootFS", -+ size: MTD_KERN_PART_SIZE + MTD_ROOTFS_PART_SIZE, -+ offset: MTD_BOOT_PART_SIZE + MTD_CONFIG_PART_SIZE + MTD_FACTORY_PART_SIZE, -+#endif -+#else //CONFIG_RT2880_ROOTFS_IN_RAM -+ }, { -+ name: "Kernel", -+ size: 0x10000, -+ offset: MTDPART_OFS_APPEND, -+#endif -+#ifdef CONFIG_DUAL_IMAGE -+ }, { -+ name: "Kernel2", -+ size: MTD_KERN2_PART_SIZE, -+ offset: MTD_KERN2_PART_OFFSET, -+#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH -+ }, { -+ name: "RootFS2", -+ size: MTD_ROOTFS2_PART_SIZE, -+ offset: MTD_ROOTFS2_PART_OFFSET, -+#endif -+#endif -+ } -+ -+}; -+ -+#define NUM_PARTITIONS ARRAY_SIZE(g_pasStatic_Partition) -+extern int part_num; // = NUM_PARTITIONS; -+//#endif -+#undef RECONFIG_PARTITION_SIZE -+ diff --git a/target/linux/ramips/patches-5.4/0040-nand-hack.patch b/target/linux/ramips/patches-5.4/0040-nand-hack.patch deleted file mode 100644 index 58cdf1bce7..0000000000 --- a/target/linux/ramips/patches-5.4/0040-nand-hack.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/drivers/mtd/nand/nand_base.c -+++ b/drivers/mtd/nand/nand_base.c -@@ -1908,6 +1908,9 @@ static int nand_do_read_ops(struct mtd_i - __func__, buf); - - read_retry: -+#ifdef CONFIG_MTK_MTD_NAND -+ ret = chip->read_page(mtd, chip, bufpoi, page); -+#else - if (nand_standard_page_accessors(&chip->ecc)) - chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); - -@@ -1927,6 +1930,7 @@ read_retry: - else - ret = chip->ecc.read_page(mtd, chip, bufpoi, - oob_required, page); -+#endif - if (ret < 0) { - if (use_bufpoi) - /* Invalidate page cache */ ---- a/include/linux/mtd/rawnand.h -+++ b/include/linux/mtd/rawnand.h -@@ -897,6 +897,9 @@ struct nand_chip { - int (*setup_data_interface)(struct mtd_info *mtd, int chipnr, - const struct nand_data_interface *conf); - -+#ifdef CONFIG_MTK_MTD_NAND -+ int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, u8 *buf, int page); -+#endif /* CONFIG_MTK_MTD_NAND */ - - int chip_delay; - unsigned int options; diff --git a/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch index 1dd9f40c39..652371617a 100644 --- a/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch +++ b/target/linux/ramips/patches-5.4/0042-SPI-ralink-add-Ralink-SoC-spi-driver.patch @@ -16,9 +16,9 @@ Acked-by: John Crispin --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -563,6 +563,12 @@ config SPI_QUP +@@ -605,6 +605,12 @@ config SPI_QCOM_GENI This driver can also be built as a module. If so, the module - will be called spi_qup. + will be called spi-geni-qcom. +config SPI_RT2880 + tristate "Ralink RT288x SPI Controller" @@ -31,7 +31,7 @@ Acked-by: John Crispin depends on ARCH_S3C24XX --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -81,6 +81,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o +@@ -87,6 +87,7 @@ obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o diff --git a/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch b/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch deleted file mode 100644 index b607f2bdf4..0000000000 --- a/target/linux/ramips/patches-5.4/0043-spi-add-mt7621-support.patch +++ /dev/null @@ -1,487 +0,0 @@ -From cbd66c626e16743b05af807ad48012c0a097b9fb Mon Sep 17 00:00:00 2001 -From: Stefan Roese -Date: Mon, 25 Mar 2019 09:29:25 +0100 -Subject: [PATCH] spi: mt7621: Move SPI driver out of staging - -This patch moves the MT7621 SPI driver, which is used on some Ralink / -MediaTek MT76xx MIPS SoC's, out of the staging directory. No changes to -the source code are done in this patch. - -This driver version was tested successfully on an MT7688 based platform -with an SPI NOR on CS0 and an SPI NAND on CS1 without any issues (so -far). - -This patch also documents the devicetree bindings for the MT7621 SPI -device driver. - -Signed-off-by: Stefan Roese -Cc: Rob Herring -Cc: Mark Brown -Cc: Greg Kroah-Hartman -Cc: NeilBrown -Cc: Sankalp Negi -Cc: Chuanhong Guo -Cc: John Crispin -Cc: Armando Miraglia -Signed-off-by: Mark Brown ---- - .../devicetree/bindings/spi/spi-mt7621.txt | 26 ++++++ - drivers/spi/Kconfig | 6 ++ - drivers/spi/Makefile | 1 + - .../{staging/mt7621-spi => spi}/spi-mt7621.c | 83 +++++++++---------- - drivers/staging/Kconfig | 2 - - drivers/staging/Makefile | 1 - - drivers/staging/mt7621-spi/Kconfig | 6 -- - drivers/staging/mt7621-spi/Makefile | 1 - - drivers/staging/mt7621-spi/TODO | 5 -- - 9 files changed, 74 insertions(+), 57 deletions(-) - create mode 100644 Documentation/devicetree/bindings/spi/spi-mt7621.txt - rename drivers/{staging/mt7621-spi => spi}/spi-mt7621.c (88%) - delete mode 100644 drivers/staging/mt7621-spi/Kconfig - delete mode 100644 drivers/staging/mt7621-spi/Makefile - delete mode 100644 drivers/staging/mt7621-spi/TODO - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -569,6 +569,12 @@ config SPI_RT2880 - help - This selects a driver for the Ralink RT288x/RT305x SPI Controller. - -+config SPI_MT7621 -+ tristate "MediaTek MT7621 SPI Controller" -+ depends on RALINK -+ help -+ This selects a driver for the MediaTek MT7621 SPI Controller. -+ - config SPI_S3C24XX - tristate "Samsung S3C24XX series SPI" - depends on ARCH_S3C24XX ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -60,6 +60,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mp - obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o - obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o - obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o -+obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o - obj-$(CONFIG_SPI_MXS) += spi-mxs.o - obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o - obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o ---- /dev/null -+++ b/drivers/spi/spi-mt7621.c -@@ -0,0 +1,416 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// -+// spi-mt7621.c -- MediaTek MT7621 SPI controller driver -+// -+// Copyright (C) 2011 Sergiy -+// Copyright (C) 2011-2013 Gabor Juhos -+// Copyright (C) 2014-2015 Felix Fietkau -+// -+// Some parts are based on spi-orion.c: -+// Author: Shadi Ammouri -+// Copyright (C) 2007-2008 Marvell Ltd. -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRIVER_NAME "spi-mt7621" -+ -+/* in usec */ -+#define RALINK_SPI_WAIT_MAX_LOOP 2000 -+ -+/* SPISTAT register bit field */ -+#define SPISTAT_BUSY BIT(0) -+ -+#define MT7621_SPI_TRANS 0x00 -+#define SPITRANS_BUSY BIT(16) -+ -+#define MT7621_SPI_OPCODE 0x04 -+#define MT7621_SPI_DATA0 0x08 -+#define MT7621_SPI_DATA4 0x18 -+#define SPI_CTL_TX_RX_CNT_MASK 0xff -+#define SPI_CTL_START BIT(8) -+ -+#define MT7621_SPI_MASTER 0x28 -+#define MASTER_MORE_BUFMODE BIT(2) -+#define MASTER_FULL_DUPLEX BIT(10) -+#define MASTER_RS_CLK_SEL GENMASK(27, 16) -+#define MASTER_RS_CLK_SEL_SHIFT 16 -+#define MASTER_RS_SLAVE_SEL GENMASK(31, 29) -+ -+#define MT7621_SPI_MOREBUF 0x2c -+#define MT7621_SPI_POLAR 0x38 -+#define MT7621_SPI_SPACE 0x3c -+ -+#define MT7621_CPHA BIT(5) -+#define MT7621_CPOL BIT(4) -+#define MT7621_LSB_FIRST BIT(3) -+ -+struct mt7621_spi { -+ struct spi_controller *master; -+ void __iomem *base; -+ unsigned int sys_freq; -+ unsigned int speed; -+ struct clk *clk; -+ int pending_write; -+}; -+ -+static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) -+{ -+ return spi_controller_get_devdata(spi->master); -+} -+ -+static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) -+{ -+ return ioread32(rs->base + reg); -+} -+ -+static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val) -+{ -+ iowrite32(val, rs->base + reg); -+} -+ -+static void mt7621_spi_set_cs(struct spi_device *spi, int enable) -+{ -+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); -+ int cs = spi->chip_select; -+ u32 polar = 0; -+ u32 master; -+ -+ /* -+ * Select SPI device 7, enable "more buffer mode" and disable -+ * full-duplex (only half-duplex really works on this chip -+ * reliably) -+ */ -+ master = mt7621_spi_read(rs, MT7621_SPI_MASTER); -+ master |= MASTER_RS_SLAVE_SEL | MASTER_MORE_BUFMODE; -+ master &= ~MASTER_FULL_DUPLEX; -+ mt7621_spi_write(rs, MT7621_SPI_MASTER, master); -+ -+ rs->pending_write = 0; -+ -+ if (enable) -+ polar = BIT(cs); -+ mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); -+} -+ -+static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed) -+{ -+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); -+ u32 rate; -+ u32 reg; -+ -+ dev_dbg(&spi->dev, "speed:%u\n", speed); -+ -+ rate = DIV_ROUND_UP(rs->sys_freq, speed); -+ dev_dbg(&spi->dev, "rate-1:%u\n", rate); -+ -+ if (rate > 4097) -+ return -EINVAL; -+ -+ if (rate < 2) -+ rate = 2; -+ -+ reg = mt7621_spi_read(rs, MT7621_SPI_MASTER); -+ reg &= ~MASTER_RS_CLK_SEL; -+ reg |= (rate - 2) << MASTER_RS_CLK_SEL_SHIFT; -+ rs->speed = speed; -+ -+ reg &= ~MT7621_LSB_FIRST; -+ if (spi->mode & SPI_LSB_FIRST) -+ reg |= MT7621_LSB_FIRST; -+ -+ /* -+ * This SPI controller seems to be tested on SPI flash only and some -+ * bits are swizzled under other SPI modes probably due to incorrect -+ * wiring inside the silicon. Only mode 0 works correctly. -+ */ -+ reg &= ~(MT7621_CPHA | MT7621_CPOL); -+ -+ mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); -+ -+ return 0; -+} -+ -+static inline int mt7621_spi_wait_till_ready(struct mt7621_spi *rs) -+{ -+ int i; -+ -+ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { -+ u32 status; -+ -+ status = mt7621_spi_read(rs, MT7621_SPI_TRANS); -+ if ((status & SPITRANS_BUSY) == 0) -+ return 0; -+ cpu_relax(); -+ udelay(1); -+ } -+ -+ return -ETIMEDOUT; -+} -+ -+static void mt7621_spi_read_half_duplex(struct mt7621_spi *rs, -+ int rx_len, u8 *buf) -+{ -+ int tx_len; -+ -+ /* -+ * Combine with any pending write, and perform one or more half-duplex -+ * transactions reading 'len' bytes. Data to be written is already in -+ * MT7621_SPI_DATA. -+ */ -+ tx_len = rs->pending_write; -+ rs->pending_write = 0; -+ -+ while (rx_len || tx_len) { -+ int i; -+ u32 val = (min(tx_len, 4) * 8) << 24; -+ int rx = min(rx_len, 32); -+ -+ if (tx_len > 4) -+ val |= (tx_len - 4) * 8; -+ val |= (rx * 8) << 12; -+ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); -+ -+ tx_len = 0; -+ -+ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); -+ val |= SPI_CTL_START; -+ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); -+ -+ mt7621_spi_wait_till_ready(rs); -+ -+ for (i = 0; i < rx; i++) { -+ if ((i % 4) == 0) -+ val = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); -+ *buf++ = val & 0xff; -+ val >>= 8; -+ } -+ -+ rx_len -= i; -+ } -+} -+ -+static inline void mt7621_spi_flush(struct mt7621_spi *rs) -+{ -+ mt7621_spi_read_half_duplex(rs, 0, NULL); -+} -+ -+static void mt7621_spi_write_half_duplex(struct mt7621_spi *rs, -+ int tx_len, const u8 *buf) -+{ -+ int len = rs->pending_write; -+ int val = 0; -+ -+ if (len & 3) { -+ val = mt7621_spi_read(rs, MT7621_SPI_OPCODE + (len & ~3)); -+ if (len < 4) { -+ val <<= (4 - len) * 8; -+ val = swab32(val); -+ } -+ } -+ -+ while (tx_len > 0) { -+ if (len >= 36) { -+ rs->pending_write = len; -+ mt7621_spi_flush(rs); -+ len = 0; -+ } -+ -+ val |= *buf++ << (8 * (len & 3)); -+ len++; -+ if ((len & 3) == 0) { -+ if (len == 4) -+ /* The byte-order of the opcode is weird! */ -+ val = swab32(val); -+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + len - 4, val); -+ val = 0; -+ } -+ tx_len -= 1; -+ } -+ -+ if (len & 3) { -+ if (len < 4) { -+ val = swab32(val); -+ val >>= (4 - len) * 8; -+ } -+ mt7621_spi_write(rs, MT7621_SPI_OPCODE + (len & ~3), val); -+ } -+ -+ rs->pending_write = len; -+} -+ -+static int mt7621_spi_transfer_one_message(struct spi_controller *master, -+ struct spi_message *m) -+{ -+ struct mt7621_spi *rs = spi_controller_get_devdata(master); -+ struct spi_device *spi = m->spi; -+ unsigned int speed = spi->max_speed_hz; -+ struct spi_transfer *t = NULL; -+ int status = 0; -+ -+ mt7621_spi_wait_till_ready(rs); -+ -+ list_for_each_entry(t, &m->transfers, transfer_list) -+ if (t->speed_hz < speed) -+ speed = t->speed_hz; -+ -+ if (mt7621_spi_prepare(spi, speed)) { -+ status = -EIO; -+ goto msg_done; -+ } -+ -+ /* Assert CS */ -+ mt7621_spi_set_cs(spi, 1); -+ -+ m->actual_length = 0; -+ list_for_each_entry(t, &m->transfers, transfer_list) { -+ if ((t->rx_buf) && (t->tx_buf)) { -+ /* -+ * This controller will shift some extra data out -+ * of spi_opcode if (mosi_bit_cnt > 0) && -+ * (cmd_bit_cnt == 0). So the claimed full-duplex -+ * support is broken since we have no way to read -+ * the MISO value during that bit. -+ */ -+ status = -EIO; -+ goto msg_done; -+ } else if (t->rx_buf) { -+ mt7621_spi_read_half_duplex(rs, t->len, t->rx_buf); -+ } else if (t->tx_buf) { -+ mt7621_spi_write_half_duplex(rs, t->len, t->tx_buf); -+ } -+ m->actual_length += t->len; -+ } -+ -+ /* Flush data and deassert CS */ -+ mt7621_spi_flush(rs); -+ mt7621_spi_set_cs(spi, 0); -+ -+msg_done: -+ m->status = status; -+ spi_finalize_current_message(master); -+ -+ return 0; -+} -+ -+static int mt7621_spi_setup(struct spi_device *spi) -+{ -+ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); -+ -+ if ((spi->max_speed_hz == 0) || -+ (spi->max_speed_hz > (rs->sys_freq / 2))) -+ spi->max_speed_hz = (rs->sys_freq / 2); -+ -+ if (spi->max_speed_hz < (rs->sys_freq / 4097)) { -+ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", -+ spi->max_speed_hz); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static const struct of_device_id mt7621_spi_match[] = { -+ { .compatible = "ralink,mt7621-spi" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, mt7621_spi_match); -+ -+static int mt7621_spi_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *match; -+ struct spi_controller *master; -+ struct mt7621_spi *rs; -+ void __iomem *base; -+ struct resource *r; -+ int status = 0; -+ struct clk *clk; -+ int ret; -+ -+ match = of_match_device(mt7621_spi_match, &pdev->dev); -+ if (!match) -+ return -EINVAL; -+ -+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, r); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ -+ clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(clk)) { -+ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", -+ status); -+ return PTR_ERR(clk); -+ } -+ -+ status = clk_prepare_enable(clk); -+ if (status) -+ return status; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); -+ if (!master) { -+ dev_info(&pdev->dev, "master allocation failed\n"); -+ return -ENOMEM; -+ } -+ -+ master->mode_bits = SPI_LSB_FIRST; -+ master->flags = SPI_CONTROLLER_HALF_DUPLEX; -+ master->setup = mt7621_spi_setup; -+ master->transfer_one_message = mt7621_spi_transfer_one_message; -+ master->bits_per_word_mask = SPI_BPW_MASK(8); -+ master->dev.of_node = pdev->dev.of_node; -+ master->num_chipselect = 2; -+ -+ dev_set_drvdata(&pdev->dev, master); -+ -+ rs = spi_controller_get_devdata(master); -+ rs->base = base; -+ rs->clk = clk; -+ rs->master = master; -+ rs->sys_freq = clk_get_rate(rs->clk); -+ rs->pending_write = 0; -+ dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); -+ -+ ret = device_reset(&pdev->dev); -+ if (ret) { -+ dev_err(&pdev->dev, "SPI reset failed!\n"); -+ return ret; -+ } -+ -+ return devm_spi_register_controller(&pdev->dev, master); -+} -+ -+static int mt7621_spi_remove(struct platform_device *pdev) -+{ -+ struct spi_controller *master; -+ struct mt7621_spi *rs; -+ -+ master = dev_get_drvdata(&pdev->dev); -+ rs = spi_controller_get_devdata(master); -+ -+ clk_disable_unprepare(rs->clk); -+ -+ return 0; -+} -+ -+MODULE_ALIAS("platform:" DRIVER_NAME); -+ -+static struct platform_driver mt7621_spi_driver = { -+ .driver = { -+ .name = DRIVER_NAME, -+ .of_match_table = mt7621_spi_match, -+ }, -+ .probe = mt7621_spi_probe, -+ .remove = mt7621_spi_remove, -+}; -+ -+module_platform_driver(mt7621_spi_driver); -+ -+MODULE_DESCRIPTION("MT7621 SPI driver"); -+MODULE_AUTHOR("Felix Fietkau "); -+MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch index 4905aba046..e3bb7f2488 100644 --- a/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch +++ b/target/linux/ramips/patches-5.4/0044-i2c-MIPS-adds-ralink-I2C-driver.patch @@ -45,7 +45,7 @@ Signed-off-by: John Crispin +}; --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig -@@ -864,6 +864,11 @@ config I2C_RK3X +@@ -922,6 +922,11 @@ config I2C_RK3X This driver can also be built as a module. If so, the module will be called i2c-rk3x. @@ -59,14 +59,14 @@ Signed-off-by: John Crispin help --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile -@@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o +@@ -91,6 +91,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o +obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o + obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o obj-$(CONFIG_I2C_QUP) += i2c-qup.o obj-$(CONFIG_I2C_RIIC) += i2c-riic.o - obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o --- /dev/null +++ b/drivers/i2c/busses/i2c-ralink.c @@ -0,0 +1,435 @@ diff --git a/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch b/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch deleted file mode 100644 index a848085520..0000000000 --- a/target/linux/ramips/patches-5.4/0045-i2c-add-mt7621-driver.patch +++ /dev/null @@ -1,473 +0,0 @@ -From d5c54ff3d1db0a4348fa04d8e78f3bf6063e3afc Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Mon, 7 Dec 2015 17:21:27 +0100 -Subject: [PATCH 45/53] i2c: add mt7621 driver - -Signed-off-by: John Crispin ---- - drivers/i2c/busses/Kconfig | 4 + - drivers/i2c/busses/Makefile | 1 + - drivers/i2c/busses/i2c-mt7621.c | 303 +++++++++++++++++++++++++++++++++++++++ - 3 files changed, 308 insertions(+) - create mode 100644 drivers/i2c/busses/i2c-mt7621.c - ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -869,6 +869,11 @@ config I2C_RALINK - depends on RALINK && !SOC_MT7621 - select OF_I2C - -+config I2C_MT7621 -+ tristate "MT7621/MT7628 I2C Controller" -+ depends on RALINK && (SOC_MT7620 || SOC_MT7621) -+ select OF_I2C -+ - config HAVE_S3C2410_I2C - bool - help ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -85,6 +85,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o - obj-$(CONFIG_I2C_PXA) += i2c-pxa.o - obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o - obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o -+obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o - obj-$(CONFIG_I2C_QUP) += i2c-qup.o - obj-$(CONFIG_I2C_RIIC) += i2c-riic.o - obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o ---- /dev/null -+++ b/drivers/i2c/busses/i2c-mt7621.c -@@ -0,0 +1,433 @@ -+/* -+ * drivers/i2c/busses/i2c-mt7621.c -+ * -+ * Copyright (C) 2013 Steven Liu -+ * Copyright (C) 2016 Michael Lee -+ * -+ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. -+ * (C) 2014 Sittisak -+ * -+ * This software is licensed under the terms of the GNU General Public -+ * License version 2, as published by the Free Software Foundation, and -+ * may be copied, distributed, and modified under those terms. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define REG_SM0CFG0 0x08 -+#define REG_SM0DOUT 0x10 -+#define REG_SM0DIN 0x14 -+#define REG_SM0ST 0x18 -+#define REG_SM0AUTO 0x1C -+#define REG_SM0CFG1 0x20 -+#define REG_SM0CFG2 0x28 -+#define REG_SM0CTL0 0x40 -+#define REG_SM0CTL1 0x44 -+#define REG_SM0D0 0x50 -+#define REG_SM0D1 0x54 -+#define REG_PINTEN 0x5C -+#define REG_PINTST 0x60 -+#define REG_PINTCL 0x64 -+ -+/* REG_SM0CFG0 */ -+#define I2C_DEVADDR_MASK 0x7f -+ -+/* REG_SM0ST */ -+#define I2C_DATARDY BIT(2) -+#define I2C_SDOEMPTY BIT(1) -+#define I2C_BUSY BIT(0) -+ -+/* REG_SM0AUTO */ -+#define READ_CMD BIT(0) -+ -+/* REG_SM0CFG1 */ -+#define BYTECNT_MAX 64 -+#define SET_BYTECNT(x) (x - 1) -+ -+/* REG_SM0CFG2 */ -+#define AUTOMODE_EN BIT(0) -+ -+/* REG_SM0CTL0 */ -+#define ODRAIN_HIGH_SM0 BIT(31) -+#define VSYNC_SHIFT 28 -+#define VSYNC_MASK 0x3 -+#define VSYNC_PULSE (0x1 << VSYNC_SHIFT) -+#define VSYNC_RISING (0x2 << VSYNC_SHIFT) -+#define CLK_DIV_SHIFT 16 -+#define CLK_DIV_MASK 0xfff -+#define DEG_CNT_SHIFT 8 -+#define DEG_CNT_MASK 0xff -+#define WAIT_HIGH BIT(6) -+#define DEG_EN BIT(5) -+#define CS_STATUA BIT(4) -+#define SCL_STATUS BIT(3) -+#define SDA_STATUS BIT(2) -+#define SM0_EN BIT(1) -+#define SCL_STRECH BIT(0) -+ -+/* REG_SM0CTL1 */ -+#define ACK_SHIFT 16 -+#define ACK_MASK 0xff -+#define PGLEN_SHIFT 8 -+#define PGLEN_MASK 0x7 -+#define SM0_MODE_SHIFT 4 -+#define SM0_MODE_MASK 0x7 -+#define SM0_MODE_START 0x1 -+#define SM0_MODE_WRITE 0x2 -+#define SM0_MODE_STOP 0x3 -+#define SM0_MODE_READ_NACK 0x4 -+#define SM0_MODE_READ_ACK 0x5 -+#define SM0_TRI_BUSY BIT(0) -+ -+/* timeout waiting for I2C devices to respond (clock streching) */ -+#define TIMEOUT_MS 1000 -+#define DELAY_INTERVAL_US 100 -+ -+struct mtk_i2c { -+ void __iomem *base; -+ struct clk *clk; -+ struct device *dev; -+ struct i2c_adapter adap; -+ u32 cur_clk; -+ u32 clk_div; -+ u32 flags; -+}; -+ -+static void mtk_i2c_w32(struct mtk_i2c *i2c, u32 val, unsigned reg) -+{ -+ iowrite32(val, i2c->base + reg); -+} -+ -+static u32 mtk_i2c_r32(struct mtk_i2c *i2c, unsigned reg) -+{ -+ return ioread32(i2c->base + reg); -+} -+ -+static int poll_down_timeout(void __iomem *addr, u32 mask) -+{ -+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); -+ -+ do { -+ if (!(readl_relaxed(addr) & mask)) -+ return 0; -+ -+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); -+ } while (time_before(jiffies, timeout)); -+ -+ return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; -+} -+ -+static int mtk_i2c_wait_idle(struct mtk_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_down_timeout(i2c->base + REG_SM0ST, I2C_BUSY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "idle err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static int poll_up_timeout(void __iomem *addr, u32 mask) -+{ -+ unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); -+ u32 status; -+ -+ do { -+ status = readl_relaxed(addr); -+ if (status & mask) -+ return 0; -+ usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); -+ } while (time_before(jiffies, timeout)); -+ -+ return -ETIMEDOUT; -+} -+ -+static int mtk_i2c_wait_rx_done(struct mtk_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_DATARDY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "rx err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static int mtk_i2c_wait_tx_done(struct mtk_i2c *i2c) -+{ -+ int ret; -+ -+ ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_SDOEMPTY); -+ if (ret < 0) -+ dev_dbg(i2c->dev, "tx err(%d)\n", ret); -+ -+ return ret; -+} -+ -+static void mtk_i2c_reset(struct mtk_i2c *i2c) -+{ -+ u32 reg; -+ device_reset(i2c->adap.dev.parent); -+ barrier(); -+ -+ /* ctrl0 */ -+ reg = ODRAIN_HIGH_SM0 | VSYNC_PULSE | (i2c->clk_div << CLK_DIV_SHIFT) | -+ WAIT_HIGH | SM0_EN; -+ mtk_i2c_w32(i2c, reg, REG_SM0CTL0); -+ -+ /* auto mode */ -+ mtk_i2c_w32(i2c, AUTOMODE_EN, REG_SM0CFG2); -+} -+ -+static void mtk_i2c_dump_reg(struct mtk_i2c *i2c) -+{ -+ dev_dbg(i2c->dev, "cfg0 %08x, dout %08x, din %08x, " \ -+ "status %08x, auto %08x, cfg1 %08x, " \ -+ "cfg2 %08x, ctl0 %08x, ctl1 %08x\n", -+ mtk_i2c_r32(i2c, REG_SM0CFG0), -+ mtk_i2c_r32(i2c, REG_SM0DOUT), -+ mtk_i2c_r32(i2c, REG_SM0DIN), -+ mtk_i2c_r32(i2c, REG_SM0ST), -+ mtk_i2c_r32(i2c, REG_SM0AUTO), -+ mtk_i2c_r32(i2c, REG_SM0CFG1), -+ mtk_i2c_r32(i2c, REG_SM0CFG2), -+ mtk_i2c_r32(i2c, REG_SM0CTL0), -+ mtk_i2c_r32(i2c, REG_SM0CTL1)); -+} -+ -+static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, -+ int num) -+{ -+ struct mtk_i2c *i2c; -+ struct i2c_msg *pmsg; -+ int i, j, ret; -+ u32 cmd; -+ -+ i2c = i2c_get_adapdata(adap); -+ -+ for (i = 0; i < num; i++) { -+ pmsg = &msgs[i]; -+ cmd = 0; -+ -+ dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x\n", -+ pmsg->addr, pmsg->len, pmsg->flags); -+ -+ /* wait hardware idle */ -+ if ((ret = mtk_i2c_wait_idle(i2c))) -+ goto err_timeout; -+ -+ if (pmsg->flags & I2C_M_TEN) { -+ dev_dbg(i2c->dev, "10 bits addr not supported\n"); -+ return -EINVAL; -+ } else { -+ /* 7 bits address */ -+ mtk_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, -+ REG_SM0CFG0); -+ } -+ -+ /* buffer length */ -+ if (pmsg->len == 0) { -+ dev_dbg(i2c->dev, "length is 0\n"); -+ return -EINVAL; -+ } else -+ mtk_i2c_w32(i2c, SET_BYTECNT(pmsg->len), -+ REG_SM0CFG1); -+ -+ j = 0; -+ if (pmsg->flags & I2C_M_RD) { -+ cmd |= READ_CMD; -+ /* start transfer */ -+ barrier(); -+ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); -+ do { -+ /* wait */ -+ if ((ret = mtk_i2c_wait_rx_done(i2c))) -+ goto err_timeout; -+ /* read data */ -+ if (pmsg->len) -+ pmsg->buf[j] = mtk_i2c_r32(i2c, -+ REG_SM0DIN); -+ j++; -+ } while (j < pmsg->len); -+ } else { -+ do { -+ /* write data */ -+ if (pmsg->len) -+ mtk_i2c_w32(i2c, pmsg->buf[j], -+ REG_SM0DOUT); -+ /* start transfer */ -+ if (j == 0) { -+ barrier(); -+ mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); -+ } -+ /* wait */ -+ if ((ret = mtk_i2c_wait_tx_done(i2c))) -+ goto err_timeout; -+ j++; -+ } while (j < pmsg->len); -+ } -+ } -+ /* the return value is number of executed messages */ -+ ret = i; -+ -+ return ret; -+ -+err_timeout: -+ mtk_i2c_dump_reg(i2c); -+ mtk_i2c_reset(i2c); -+ return ret; -+} -+ -+static u32 mtk_i2c_func(struct i2c_adapter *a) -+{ -+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm mtk_i2c_algo = { -+ .master_xfer = mtk_i2c_master_xfer, -+ .functionality = mtk_i2c_func, -+}; -+ -+static const struct of_device_id i2c_mtk_dt_ids[] = { -+ { .compatible = "mediatek,mt7621-i2c" }, -+ { /* sentinel */ } -+}; -+ -+MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids); -+ -+static struct i2c_adapter_quirks mtk_i2c_quirks = { -+ .max_write_len = BYTECNT_MAX, -+ .max_read_len = BYTECNT_MAX, -+}; -+ -+static void mtk_i2c_init(struct mtk_i2c *i2c) -+{ -+ i2c->clk_div = clk_get_rate(i2c->clk) / i2c->cur_clk; -+ if (i2c->clk_div > CLK_DIV_MASK) -+ i2c->clk_div = CLK_DIV_MASK; -+ -+ mtk_i2c_reset(i2c); -+} -+ -+static int mtk_i2c_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ struct mtk_i2c *i2c; -+ struct i2c_adapter *adap; -+ const struct of_device_id *match; -+ int ret; -+ -+ match = of_match_device(i2c_mtk_dt_ids, &pdev->dev); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) { -+ dev_err(&pdev->dev, "no memory resource found\n"); -+ return -ENODEV; -+ } -+ -+ i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); -+ if (!i2c) { -+ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); -+ return -ENOMEM; -+ } -+ -+ i2c->base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(i2c->base)) -+ return PTR_ERR(i2c->base); -+ -+ i2c->clk = devm_clk_get(&pdev->dev, NULL); -+ if (IS_ERR(i2c->clk)) { -+ dev_err(&pdev->dev, "no clock defined\n"); -+ return -ENODEV; -+ } -+ clk_prepare_enable(i2c->clk); -+ i2c->dev = &pdev->dev; -+ -+ if (of_property_read_u32(pdev->dev.of_node, -+ "clock-frequency", &i2c->cur_clk)) -+ i2c->cur_clk = 100000; -+ -+ adap = &i2c->adap; -+ adap->owner = THIS_MODULE; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; -+ adap->algo = &mtk_i2c_algo; -+ adap->retries = 3; -+ adap->dev.parent = &pdev->dev; -+ i2c_set_adapdata(adap, i2c); -+ adap->dev.of_node = pdev->dev.of_node; -+ strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); -+ adap->quirks = &mtk_i2c_quirks; -+ -+ platform_set_drvdata(pdev, i2c); -+ -+ mtk_i2c_init(i2c); -+ -+ ret = i2c_add_adapter(adap); -+ if (ret < 0) { -+ dev_err(&pdev->dev, "failed to add adapter\n"); -+ clk_disable_unprepare(i2c->clk); -+ return ret; -+ } -+ -+ dev_info(&pdev->dev, "clock %uKHz, re-start not support\n", -+ i2c->cur_clk/1000); -+ -+ return ret; -+} -+ -+static int mtk_i2c_remove(struct platform_device *pdev) -+{ -+ struct mtk_i2c *i2c = platform_get_drvdata(pdev); -+ -+ i2c_del_adapter(&i2c->adap); -+ clk_disable_unprepare(i2c->clk); -+ -+ return 0; -+} -+ -+static struct platform_driver mtk_i2c_driver = { -+ .probe = mtk_i2c_probe, -+ .remove = mtk_i2c_remove, -+ .driver = { -+ .owner = THIS_MODULE, -+ .name = "i2c-mt7621", -+ .of_match_table = i2c_mtk_dt_ids, -+ }, -+}; -+ -+static int __init i2c_mtk_init (void) -+{ -+ return platform_driver_register(&mtk_i2c_driver); -+} -+subsys_initcall(i2c_mtk_init); -+ -+static void __exit i2c_mtk_exit (void) -+{ -+ platform_driver_unregister(&mtk_i2c_driver); -+} -+module_exit(i2c_mtk_exit); -+ -+MODULE_AUTHOR("Steven Liu "); -+MODULE_DESCRIPTION("MT7621 I2c host driver"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:MT7621-I2C"); diff --git a/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch index 0535811ea3..f3912a1054 100644 --- a/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch +++ b/target/linux/ramips/patches-5.4/0046-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch @@ -25,9 +25,9 @@ Signed-off-by: John Crispin --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig -@@ -901,3 +901,5 @@ config MMC_SDHCI_XENON - This selects Marvell Xenon eMMC/SD/SDIO SDHCI. +@@ -1019,3 +1019,5 @@ config MMC_SDHCI_AM654 If you have a controller with this interface, say Y or M here. + If unsure, say N. + +source "drivers/mmc/host/mtk-mmc/Kconfig" diff --git a/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch b/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch deleted file mode 100644 index b74a48a220..0000000000 --- a/target/linux/ramips/patches-5.4/0047-DMA-ralink-add-rt2880-dma-engine.patch +++ /dev/null @@ -1,1757 +0,0 @@ -From f1c4d9e622c800e1f38b3818f933ec7597d1ccfb Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Sun, 27 Jul 2014 09:29:51 +0100 -Subject: [PATCH 47/53] DMA: ralink: add rt2880 dma engine - -Signed-off-by: John Crispin ---- - drivers/dma/Kconfig | 6 + - drivers/dma/Makefile | 1 + - drivers/dma/ralink-gdma.c | 577 +++++++++++++++++++++++++++++++++++++++++++++ - include/linux/dmaengine.h | 1 + - 4 files changed, 585 insertions(+) - create mode 100644 drivers/dma/ralink-gdma.c - ---- a/drivers/dma/Kconfig -+++ b/drivers/dma/Kconfig -@@ -40,6 +40,18 @@ config ASYNC_TX_ENABLE_CHANNEL_SWITCH - config ARCH_HAS_ASYNC_TX_FIND_CHANNEL - bool - -+config DMA_RALINK -+ tristate "RALINK DMA support" -+ depends on RALINK && !SOC_RT288X -+ select DMA_ENGINE -+ select DMA_VIRTUAL_CHANNELS -+ -+config MTK_HSDMA -+ tristate "MTK HSDMA support" -+ depends on RALINK && SOC_MT7621 -+ select DMA_ENGINE -+ select DMA_VIRTUAL_CHANNELS -+ - config DMA_ENGINE - bool - ---- a/drivers/dma/Makefile -+++ b/drivers/dma/Makefile -@@ -71,6 +71,8 @@ obj-$(CONFIG_TI_EDMA) += edma.o - obj-$(CONFIG_XGENE_DMA) += xgene-dma.o - obj-$(CONFIG_ZX_DMA) += zx_dma.o - obj-$(CONFIG_ST_FDMA) += st_fdma.o -+obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o -+obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o - - obj-y += qcom/ - obj-y += xilinx/ ---- /dev/null -+++ b/drivers/dma/ralink-gdma.c -@@ -0,0 +1,928 @@ -+/* -+ * Copyright (C) 2013, Lars-Peter Clausen -+ * GDMA4740 DMAC support -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "virt-dma.h" -+ -+#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) -+#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) -+ -+#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) -+#define GDMA_REG_CTRL0_TX_MASK 0xffff -+#define GDMA_REG_CTRL0_TX_SHIFT 16 -+#define GDMA_REG_CTRL0_CURR_MASK 0xff -+#define GDMA_REG_CTRL0_CURR_SHIFT 8 -+#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) -+#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) -+#define GDMA_REG_CTRL0_BURST_MASK 0x7 -+#define GDMA_REG_CTRL0_BURST_SHIFT 3 -+#define GDMA_REG_CTRL0_DONE_INT BIT(2) -+#define GDMA_REG_CTRL0_ENABLE BIT(1) -+#define GDMA_REG_CTRL0_SW_MODE BIT(0) -+ -+#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) -+#define GDMA_REG_CTRL1_SEG_MASK 0xf -+#define GDMA_REG_CTRL1_SEG_SHIFT 22 -+#define GDMA_REG_CTRL1_REQ_MASK 0x3f -+#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 -+#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 -+#define GDMA_REG_CTRL1_CONTINOUS BIT(14) -+#define GDMA_REG_CTRL1_NEXT_MASK 0x1f -+#define GDMA_REG_CTRL1_NEXT_SHIFT 3 -+#define GDMA_REG_CTRL1_COHERENT BIT(2) -+#define GDMA_REG_CTRL1_FAIL BIT(1) -+#define GDMA_REG_CTRL1_MASK BIT(0) -+ -+#define GDMA_REG_UNMASK_INT 0x200 -+#define GDMA_REG_DONE_INT 0x204 -+ -+#define GDMA_REG_GCT 0x220 -+#define GDMA_REG_GCT_CHAN_MASK 0x3 -+#define GDMA_REG_GCT_CHAN_SHIFT 3 -+#define GDMA_REG_GCT_VER_MASK 0x3 -+#define GDMA_REG_GCT_VER_SHIFT 1 -+#define GDMA_REG_GCT_ARBIT_RR BIT(0) -+ -+#define GDMA_REG_REQSTS 0x2a0 -+#define GDMA_REG_ACKSTS 0x2a4 -+#define GDMA_REG_FINSTS 0x2a8 -+ -+/* for RT305X gdma registers */ -+#define GDMA_RT305X_CTRL0_REQ_MASK 0xf -+#define GDMA_RT305X_CTRL0_SRC_REQ_SHIFT 12 -+#define GDMA_RT305X_CTRL0_DST_REQ_SHIFT 8 -+ -+#define GDMA_RT305X_CTRL1_FAIL BIT(4) -+#define GDMA_RT305X_CTRL1_NEXT_MASK 0x7 -+#define GDMA_RT305X_CTRL1_NEXT_SHIFT 1 -+ -+#define GDMA_RT305X_STATUS_INT 0x80 -+#define GDMA_RT305X_STATUS_SIGNAL 0x84 -+#define GDMA_RT305X_GCT 0x88 -+ -+/* for MT7621 gdma registers */ -+#define GDMA_REG_PERF_START(x) (0x230 + (x) * 0x8) -+#define GDMA_REG_PERF_END(x) (0x234 + (x) * 0x8) -+ -+enum gdma_dma_transfer_size { -+ GDMA_TRANSFER_SIZE_4BYTE = 0, -+ GDMA_TRANSFER_SIZE_8BYTE = 1, -+ GDMA_TRANSFER_SIZE_16BYTE = 2, -+ GDMA_TRANSFER_SIZE_32BYTE = 3, -+ GDMA_TRANSFER_SIZE_64BYTE = 4, -+}; -+ -+struct gdma_dma_sg { -+ dma_addr_t src_addr; -+ dma_addr_t dst_addr; -+ u32 len; -+}; -+ -+struct gdma_dma_desc { -+ struct virt_dma_desc vdesc; -+ -+ enum dma_transfer_direction direction; -+ bool cyclic; -+ -+ u32 residue; -+ unsigned int num_sgs; -+ struct gdma_dma_sg sg[]; -+}; -+ -+struct gdma_dmaengine_chan { -+ struct virt_dma_chan vchan; -+ unsigned int id; -+ unsigned int slave_id; -+ -+ dma_addr_t fifo_addr; -+ enum gdma_dma_transfer_size burst_size; -+ -+ struct gdma_dma_desc *desc; -+ unsigned int next_sg; -+}; -+ -+struct gdma_dma_dev { -+ struct dma_device ddev; -+ struct device_dma_parameters dma_parms; -+ struct gdma_data *data; -+ void __iomem *base; -+ struct tasklet_struct task; -+ volatile unsigned long chan_issued; -+ atomic_t cnt; -+ -+ struct gdma_dmaengine_chan chan[]; -+}; -+ -+struct gdma_data -+{ -+ int chancnt; -+ u32 done_int_reg; -+ void (*init)(struct gdma_dma_dev *dma_dev); -+ int (*start_transfer)(struct gdma_dmaengine_chan *chan); -+}; -+ -+static struct gdma_dma_dev *gdma_dma_chan_get_dev( -+ struct gdma_dmaengine_chan *chan) -+{ -+ return container_of(chan->vchan.chan.device, struct gdma_dma_dev, -+ ddev); -+} -+ -+static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) -+{ -+ return container_of(c, struct gdma_dmaengine_chan, vchan.chan); -+} -+ -+static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) -+{ -+ return container_of(vdesc, struct gdma_dma_desc, vdesc); -+} -+ -+static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, -+ unsigned int reg) -+{ -+ return readl(dma_dev->base + reg); -+} -+ -+static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, -+ unsigned reg, uint32_t val) -+{ -+ writel(val, dma_dev->base + reg); -+} -+ -+static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) -+{ -+ return kzalloc(sizeof(struct gdma_dma_desc) + -+ sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); -+} -+ -+static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) -+{ -+ if (maxburst < 2) -+ return GDMA_TRANSFER_SIZE_4BYTE; -+ else if (maxburst < 4) -+ return GDMA_TRANSFER_SIZE_8BYTE; -+ else if (maxburst < 8) -+ return GDMA_TRANSFER_SIZE_16BYTE; -+ else if (maxburst < 16) -+ return GDMA_TRANSFER_SIZE_32BYTE; -+ else -+ return GDMA_TRANSFER_SIZE_64BYTE; -+} -+ -+static int gdma_dma_config(struct dma_chan *c, -+ struct dma_slave_config *config) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); -+ -+ if (config->device_fc) { -+ dev_err(dma_dev->ddev.dev, "not support flow controller\n"); -+ return -EINVAL; -+ } -+ -+ switch (config->direction) { -+ case DMA_MEM_TO_DEV: -+ if (config->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { -+ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); -+ return -EINVAL; -+ } -+ chan->slave_id = config->slave_id; -+ chan->fifo_addr = config->dst_addr; -+ chan->burst_size = gdma_dma_maxburst(config->dst_maxburst); -+ break; -+ case DMA_DEV_TO_MEM: -+ if (config->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) { -+ dev_err(dma_dev->ddev.dev, "only support 4 byte buswidth\n"); -+ return -EINVAL; -+ } -+ chan->slave_id = config->slave_id; -+ chan->fifo_addr = config->src_addr; -+ chan->burst_size = gdma_dma_maxburst(config->src_maxburst); -+ break; -+ default: -+ dev_err(dma_dev->ddev.dev, "direction type %d error\n", -+ config->direction); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int gdma_dma_terminate_all(struct dma_chan *c) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); -+ unsigned long flags, timeout; -+ LIST_HEAD(head); -+ int i = 0; -+ -+ spin_lock_irqsave(&chan->vchan.lock, flags); -+ chan->desc = NULL; -+ clear_bit(chan->id, &dma_dev->chan_issued); -+ vchan_get_all_descriptors(&chan->vchan, &head); -+ spin_unlock_irqrestore(&chan->vchan.lock, flags); -+ -+ vchan_dma_desc_free_list(&chan->vchan, &head); -+ -+ /* wait dma transfer complete */ -+ timeout = jiffies + msecs_to_jiffies(5000); -+ while (gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)) & -+ GDMA_REG_CTRL0_ENABLE) { -+ if (time_after_eq(jiffies, timeout)) { -+ dev_err(dma_dev->ddev.dev, "chan %d wait timeout\n", -+ chan->id); -+ /* restore to init value */ -+ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), 0); -+ break; -+ } -+ cpu_relax(); -+ i++; -+ } -+ -+ if (i) -+ dev_dbg(dma_dev->ddev.dev, "terminate chan %d loops %d\n", -+ chan->id, i); -+ -+ return 0; -+} -+ -+static void rt305x_dump_reg(struct gdma_dma_dev *dma_dev, int id) -+{ -+ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ -+ "ctr1 %08x, intr %08x, signal %08x\n", id, -+ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), -+ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_INT), -+ gdma_dma_read(dma_dev, GDMA_RT305X_STATUS_SIGNAL)); -+} -+ -+static int rt305x_gdma_start_transfer(struct gdma_dmaengine_chan *chan) -+{ -+ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); -+ dma_addr_t src_addr, dst_addr; -+ struct gdma_dma_sg *sg; -+ uint32_t ctrl0, ctrl1; -+ -+ /* verify chan is already stopped */ -+ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); -+ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { -+ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", -+ chan->id, ctrl0); -+ rt305x_dump_reg(dma_dev, chan->id); -+ return -EINVAL; -+ } -+ -+ sg = &chan->desc->sg[chan->next_sg]; -+ if (chan->desc->direction == DMA_MEM_TO_DEV) { -+ src_addr = sg->src_addr; -+ dst_addr = chan->fifo_addr; -+ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED | \ -+ (8 << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ -+ (chan->slave_id << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); -+ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { -+ src_addr = chan->fifo_addr; -+ dst_addr = sg->dst_addr; -+ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED | \ -+ (chan->slave_id << GDMA_RT305X_CTRL0_SRC_REQ_SHIFT) | \ -+ (8 << GDMA_RT305X_CTRL0_DST_REQ_SHIFT); -+ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { -+ /* -+ * TODO: memcpy function have bugs. sometime it will copy -+ * more 8 bytes data when using dmatest verify. -+ */ -+ src_addr = sg->src_addr; -+ dst_addr = sg->dst_addr; -+ ctrl0 = GDMA_REG_CTRL0_SW_MODE | \ -+ (8 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ -+ (8 << GDMA_REG_CTRL1_DST_REQ_SHIFT); -+ } else { -+ dev_err(dma_dev->ddev.dev, "direction type %d error\n", -+ chan->desc->direction); -+ return -EINVAL; -+ } -+ -+ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ -+ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ -+ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; -+ ctrl1 = chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; -+ -+ chan->next_sg++; -+ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); -+ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); -+ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); -+ -+ /* make sure next_sg is update */ -+ wmb(); -+ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); -+ -+ return 0; -+} -+ -+static void rt3883_dump_reg(struct gdma_dma_dev *dma_dev, int id) -+{ -+ dev_dbg(dma_dev->ddev.dev, "chan %d, src %08x, dst %08x, ctr0 %08x, " \ -+ "ctr1 %08x, unmask %08x, done %08x, " \ -+ "req %08x, ack %08x, fin %08x\n", id, -+ gdma_dma_read(dma_dev, GDMA_REG_SRC_ADDR(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_DST_ADDR(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_CTRL0(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_CTRL1(id)), -+ gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT), -+ gdma_dma_read(dma_dev, GDMA_REG_DONE_INT), -+ gdma_dma_read(dma_dev, GDMA_REG_REQSTS), -+ gdma_dma_read(dma_dev, GDMA_REG_ACKSTS), -+ gdma_dma_read(dma_dev, GDMA_REG_FINSTS)); -+} -+ -+static int rt3883_gdma_start_transfer(struct gdma_dmaengine_chan *chan) -+{ -+ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); -+ dma_addr_t src_addr, dst_addr; -+ struct gdma_dma_sg *sg; -+ uint32_t ctrl0, ctrl1; -+ -+ /* verify chan is already stopped */ -+ ctrl0 = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); -+ if (unlikely(ctrl0 & GDMA_REG_CTRL0_ENABLE)) { -+ dev_err(dma_dev->ddev.dev, "chan %d is start(%08x).\n", -+ chan->id, ctrl0); -+ rt3883_dump_reg(dma_dev, chan->id); -+ return -EINVAL; -+ } -+ -+ sg = &chan->desc->sg[chan->next_sg]; -+ if (chan->desc->direction == DMA_MEM_TO_DEV) { -+ src_addr = sg->src_addr; -+ dst_addr = chan->fifo_addr; -+ ctrl0 = GDMA_REG_CTRL0_DST_ADDR_FIXED; -+ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ -+ (chan->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT); -+ } else if (chan->desc->direction == DMA_DEV_TO_MEM) { -+ src_addr = chan->fifo_addr; -+ dst_addr = sg->dst_addr; -+ ctrl0 = GDMA_REG_CTRL0_SRC_ADDR_FIXED; -+ ctrl1 = (chan->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ -+ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ -+ GDMA_REG_CTRL1_COHERENT; -+ } else if (chan->desc->direction == DMA_MEM_TO_MEM) { -+ src_addr = sg->src_addr; -+ dst_addr = sg->dst_addr; -+ ctrl0 = GDMA_REG_CTRL0_SW_MODE; -+ ctrl1 = (32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT) | \ -+ (32 << GDMA_REG_CTRL1_DST_REQ_SHIFT) | \ -+ GDMA_REG_CTRL1_COHERENT; -+ } else { -+ dev_err(dma_dev->ddev.dev, "direction type %d error\n", -+ chan->desc->direction); -+ return -EINVAL; -+ } -+ -+ ctrl0 |= (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | \ -+ (chan->burst_size << GDMA_REG_CTRL0_BURST_SHIFT) | \ -+ GDMA_REG_CTRL0_DONE_INT | GDMA_REG_CTRL0_ENABLE; -+ ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; -+ -+ chan->next_sg++; -+ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); -+ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); -+ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); -+ -+ /* make sure next_sg is update */ -+ wmb(); -+ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); -+ -+ return 0; -+} -+ -+static inline int gdma_start_transfer(struct gdma_dma_dev *dma_dev, -+ struct gdma_dmaengine_chan *chan) -+{ -+ return dma_dev->data->start_transfer(chan); -+} -+ -+static int gdma_next_desc(struct gdma_dmaengine_chan *chan) -+{ -+ struct virt_dma_desc *vdesc; -+ -+ vdesc = vchan_next_desc(&chan->vchan); -+ if (!vdesc) { -+ chan->desc = NULL; -+ return 0; -+ } -+ chan->desc = to_gdma_dma_desc(vdesc); -+ chan->next_sg = 0; -+ -+ return 1; -+} -+ -+static void gdma_dma_chan_irq(struct gdma_dma_dev *dma_dev, -+ struct gdma_dmaengine_chan *chan) -+{ -+ struct gdma_dma_desc *desc; -+ unsigned long flags; -+ int chan_issued; -+ -+ chan_issued = 0; -+ spin_lock_irqsave(&chan->vchan.lock, flags); -+ desc = chan->desc; -+ if (desc) { -+ if (desc->cyclic) { -+ vchan_cyclic_callback(&desc->vdesc); -+ if (chan->next_sg == desc->num_sgs) -+ chan->next_sg = 0; -+ chan_issued = 1; -+ } else { -+ desc->residue -= desc->sg[chan->next_sg - 1].len; -+ if (chan->next_sg == desc->num_sgs) { -+ list_del(&desc->vdesc.node); -+ vchan_cookie_complete(&desc->vdesc); -+ chan_issued = gdma_next_desc(chan); -+ } else -+ chan_issued = 1; -+ } -+ } else -+ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to complete\n", -+ chan->id); -+ if (chan_issued) -+ set_bit(chan->id, &dma_dev->chan_issued); -+ spin_unlock_irqrestore(&chan->vchan.lock, flags); -+} -+ -+static irqreturn_t gdma_dma_irq(int irq, void *devid) -+{ -+ struct gdma_dma_dev *dma_dev = devid; -+ u32 done, done_reg; -+ unsigned int i; -+ -+ done_reg = dma_dev->data->done_int_reg; -+ done = gdma_dma_read(dma_dev, done_reg); -+ if (unlikely(!done)) -+ return IRQ_NONE; -+ -+ /* clean done bits */ -+ gdma_dma_write(dma_dev, done_reg, done); -+ -+ i = 0; -+ while (done) { -+ if (done & 0x1) { -+ gdma_dma_chan_irq(dma_dev, &dma_dev->chan[i]); -+ atomic_dec(&dma_dev->cnt); -+ } -+ done >>= 1; -+ i++; -+ } -+ -+ /* start only have work to do */ -+ if (dma_dev->chan_issued) -+ tasklet_schedule(&dma_dev->task); -+ -+ return IRQ_HANDLED; -+} -+ -+static void gdma_dma_issue_pending(struct dma_chan *c) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&chan->vchan.lock, flags); -+ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { -+ if (gdma_next_desc(chan)) { -+ set_bit(chan->id, &dma_dev->chan_issued); -+ tasklet_schedule(&dma_dev->task); -+ } else -+ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", -+ chan->id); -+ } -+ spin_unlock_irqrestore(&chan->vchan.lock, flags); -+} -+ -+static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( -+ struct dma_chan *c, struct scatterlist *sgl, -+ unsigned int sg_len, enum dma_transfer_direction direction, -+ unsigned long flags, void *context) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_desc *desc; -+ struct scatterlist *sg; -+ unsigned int i; -+ -+ desc = gdma_dma_alloc_desc(sg_len); -+ if (!desc) { -+ dev_err(c->device->dev, "alloc sg decs error\n"); -+ return NULL; -+ } -+ desc->residue = 0; -+ -+ for_each_sg(sgl, sg, sg_len, i) { -+ if (direction == DMA_MEM_TO_DEV) -+ desc->sg[i].src_addr = sg_dma_address(sg); -+ else if (direction == DMA_DEV_TO_MEM) -+ desc->sg[i].dst_addr = sg_dma_address(sg); -+ else { -+ dev_err(c->device->dev, "direction type %d error\n", -+ direction); -+ goto free_desc; -+ } -+ -+ if (unlikely(sg_dma_len(sg) > GDMA_REG_CTRL0_TX_MASK)) { -+ dev_err(c->device->dev, "sg len too large %d\n", -+ sg_dma_len(sg)); -+ goto free_desc; -+ } -+ desc->sg[i].len = sg_dma_len(sg); -+ desc->residue += sg_dma_len(sg); -+ } -+ -+ desc->num_sgs = sg_len; -+ desc->direction = direction; -+ desc->cyclic = false; -+ -+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -+ -+free_desc: -+ kfree(desc); -+ return NULL; -+} -+ -+static struct dma_async_tx_descriptor * gdma_dma_prep_dma_memcpy( -+ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, -+ size_t len, unsigned long flags) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_desc *desc; -+ unsigned int num_periods, i; -+ size_t xfer_count; -+ -+ if (len <= 0) -+ return NULL; -+ -+ chan->burst_size = gdma_dma_maxburst(len >> 2); -+ -+ xfer_count = GDMA_REG_CTRL0_TX_MASK; -+ num_periods = DIV_ROUND_UP(len, xfer_count); -+ -+ desc = gdma_dma_alloc_desc(num_periods); -+ if (!desc) { -+ dev_err(c->device->dev, "alloc memcpy decs error\n"); -+ return NULL; -+ } -+ desc->residue = len; -+ -+ for (i = 0; i < num_periods; i++) { -+ desc->sg[i].src_addr = src; -+ desc->sg[i].dst_addr = dest; -+ if (len > xfer_count) { -+ desc->sg[i].len = xfer_count; -+ } else { -+ desc->sg[i].len = len; -+ } -+ src += desc->sg[i].len; -+ dest += desc->sg[i].len; -+ len -= desc->sg[i].len; -+ } -+ -+ desc->num_sgs = num_periods; -+ desc->direction = DMA_MEM_TO_MEM; -+ desc->cyclic = false; -+ -+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -+} -+ -+static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( -+ struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, -+ size_t period_len, enum dma_transfer_direction direction, -+ unsigned long flags) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct gdma_dma_desc *desc; -+ unsigned int num_periods, i; -+ -+ if (buf_len % period_len) -+ return NULL; -+ -+ if (period_len > GDMA_REG_CTRL0_TX_MASK) { -+ dev_err(c->device->dev, "cyclic len too large %d\n", -+ period_len); -+ return NULL; -+ } -+ -+ num_periods = buf_len / period_len; -+ desc = gdma_dma_alloc_desc(num_periods); -+ if (!desc) { -+ dev_err(c->device->dev, "alloc cyclic decs error\n"); -+ return NULL; -+ } -+ desc->residue = buf_len; -+ -+ for (i = 0; i < num_periods; i++) { -+ if (direction == DMA_MEM_TO_DEV) -+ desc->sg[i].src_addr = buf_addr; -+ else if (direction == DMA_DEV_TO_MEM) -+ desc->sg[i].dst_addr = buf_addr; -+ else { -+ dev_err(c->device->dev, "direction type %d error\n", -+ direction); -+ goto free_desc; -+ } -+ desc->sg[i].len = period_len; -+ buf_addr += period_len; -+ } -+ -+ desc->num_sgs = num_periods; -+ desc->direction = direction; -+ desc->cyclic = true; -+ -+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -+ -+free_desc: -+ kfree(desc); -+ return NULL; -+} -+ -+static enum dma_status gdma_dma_tx_status(struct dma_chan *c, -+ dma_cookie_t cookie, struct dma_tx_state *state) -+{ -+ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); -+ struct virt_dma_desc *vdesc; -+ enum dma_status status; -+ unsigned long flags; -+ struct gdma_dma_desc *desc; -+ -+ status = dma_cookie_status(c, cookie, state); -+ if (status == DMA_COMPLETE || !state) -+ return status; -+ -+ spin_lock_irqsave(&chan->vchan.lock, flags); -+ desc = chan->desc; -+ if (desc && (cookie == desc->vdesc.tx.cookie)) { -+ /* -+ * We never update edesc->residue in the cyclic case, so we -+ * can tell the remaining room to the end of the circular -+ * buffer. -+ */ -+ if (desc->cyclic) -+ state->residue = desc->residue - -+ ((chan->next_sg - 1) * desc->sg[0].len); -+ else -+ state->residue = desc->residue; -+ } else if ((vdesc = vchan_find_desc(&chan->vchan, cookie))) -+ state->residue = to_gdma_dma_desc(vdesc)->residue; -+ spin_unlock_irqrestore(&chan->vchan.lock, flags); -+ -+ dev_dbg(c->device->dev, "tx residue %d bytes\n", state->residue); -+ -+ return status; -+} -+ -+static void gdma_dma_free_chan_resources(struct dma_chan *c) -+{ -+ vchan_free_chan_resources(to_virt_chan(c)); -+} -+ -+static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) -+{ -+ kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); -+} -+ -+static void gdma_dma_tasklet(unsigned long arg) -+{ -+ struct gdma_dma_dev *dma_dev = (struct gdma_dma_dev *)arg; -+ struct gdma_dmaengine_chan *chan; -+ static unsigned int last_chan; -+ unsigned int i, chan_mask; -+ -+ /* record last chan to round robin all chans */ -+ i = last_chan; -+ chan_mask = dma_dev->data->chancnt - 1; -+ do { -+ /* -+ * on mt7621. when verify with dmatest with all -+ * channel is enable. we need to limit only two -+ * channel is working at the same time. otherwise the -+ * data will have problem. -+ */ -+ if (atomic_read(&dma_dev->cnt) >= 2) { -+ last_chan = i; -+ break; -+ } -+ -+ if (test_and_clear_bit(i, &dma_dev->chan_issued)) { -+ chan = &dma_dev->chan[i]; -+ if (chan->desc) { -+ atomic_inc(&dma_dev->cnt); -+ gdma_start_transfer(dma_dev, chan); -+ } else -+ dev_dbg(dma_dev->ddev.dev, "chan %d no desc to issue\n", chan->id); -+ -+ if (!dma_dev->chan_issued) -+ break; -+ } -+ -+ i = (i + 1) & chan_mask; -+ } while (i != last_chan); -+} -+ -+static void rt305x_gdma_init(struct gdma_dma_dev *dma_dev) -+{ -+ uint32_t gct; -+ -+ /* all chans round robin */ -+ gdma_dma_write(dma_dev, GDMA_RT305X_GCT, GDMA_REG_GCT_ARBIT_RR); -+ -+ gct = gdma_dma_read(dma_dev, GDMA_RT305X_GCT); -+ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", -+ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, -+ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & -+ GDMA_REG_GCT_CHAN_MASK)); -+} -+ -+static void rt3883_gdma_init(struct gdma_dma_dev *dma_dev) -+{ -+ uint32_t gct; -+ -+ /* all chans round robin */ -+ gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); -+ -+ gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); -+ dev_info(dma_dev->ddev.dev, "revision: %d, channels: %d\n", -+ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, -+ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & -+ GDMA_REG_GCT_CHAN_MASK)); -+} -+ -+static struct gdma_data rt305x_gdma_data = { -+ .chancnt = 8, -+ .done_int_reg = GDMA_RT305X_STATUS_INT, -+ .init = rt305x_gdma_init, -+ .start_transfer = rt305x_gdma_start_transfer, -+}; -+ -+static struct gdma_data rt3883_gdma_data = { -+ .chancnt = 16, -+ .done_int_reg = GDMA_REG_DONE_INT, -+ .init = rt3883_gdma_init, -+ .start_transfer = rt3883_gdma_start_transfer, -+}; -+ -+static const struct of_device_id gdma_of_match_table[] = { -+ { .compatible = "ralink,rt305x-gdma", .data = &rt305x_gdma_data }, -+ { .compatible = "ralink,rt3883-gdma", .data = &rt3883_gdma_data }, -+ { }, -+}; -+ -+static int gdma_dma_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *match; -+ struct gdma_dmaengine_chan *chan; -+ struct gdma_dma_dev *dma_dev; -+ struct dma_device *dd; -+ unsigned int i; -+ struct resource *res; -+ int ret; -+ int irq; -+ void __iomem *base; -+ struct gdma_data *data; -+ -+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); -+ if (ret) -+ return ret; -+ -+ match = of_match_device(gdma_of_match_table, &pdev->dev); -+ if (!match) -+ return -EINVAL; -+ data = (struct gdma_data *) match->data; -+ -+ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev) + -+ (sizeof(struct gdma_dmaengine_chan) * data->chancnt), -+ GFP_KERNEL); -+ if (!dma_dev) { -+ dev_err(&pdev->dev, "alloc dma device failed\n"); -+ return -EINVAL; -+ } -+ dma_dev->data = data; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ dma_dev->base = base; -+ tasklet_init(&dma_dev->task, gdma_dma_tasklet, (unsigned long)dma_dev); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "failed to get irq\n"); -+ return -EINVAL; -+ } -+ ret = devm_request_irq(&pdev->dev, irq, gdma_dma_irq, -+ 0, dev_name(&pdev->dev), dma_dev); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to request irq\n"); -+ return ret; -+ } -+ -+ device_reset(&pdev->dev); -+ -+ dd = &dma_dev->ddev; -+ dma_cap_set(DMA_MEMCPY, dd->cap_mask); -+ dma_cap_set(DMA_SLAVE, dd->cap_mask); -+ dma_cap_set(DMA_CYCLIC, dd->cap_mask); -+ dd->device_free_chan_resources = gdma_dma_free_chan_resources; -+ dd->device_prep_dma_memcpy = gdma_dma_prep_dma_memcpy; -+ dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; -+ dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; -+ dd->device_config = gdma_dma_config; -+ dd->device_terminate_all = gdma_dma_terminate_all; -+ dd->device_tx_status = gdma_dma_tx_status; -+ dd->device_issue_pending = gdma_dma_issue_pending; -+ -+ dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -+ dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -+ dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); -+ dd->residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; -+ -+ dd->dev = &pdev->dev; -+ dd->dev->dma_parms = &dma_dev->dma_parms; -+ dma_set_max_seg_size(dd->dev, GDMA_REG_CTRL0_TX_MASK); -+ INIT_LIST_HEAD(&dd->channels); -+ -+ for (i = 0; i < data->chancnt; i++) { -+ chan = &dma_dev->chan[i]; -+ chan->id = i; -+ chan->vchan.desc_free = gdma_dma_desc_free; -+ vchan_init(&chan->vchan, dd); -+ } -+ -+ /* init hardware */ -+ data->init(dma_dev); -+ -+ ret = dma_async_device_register(dd); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register dma device\n"); -+ return ret; -+ } -+ -+ ret = of_dma_controller_register(pdev->dev.of_node, -+ of_dma_xlate_by_chan_id, dma_dev); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register of dma controller\n"); -+ goto err_unregister; -+ } -+ -+ platform_set_drvdata(pdev, dma_dev); -+ -+ return 0; -+ -+err_unregister: -+ dma_async_device_unregister(dd); -+ return ret; -+} -+ -+static int gdma_dma_remove(struct platform_device *pdev) -+{ -+ struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); -+ -+ tasklet_kill(&dma_dev->task); -+ of_dma_controller_free(pdev->dev.of_node); -+ dma_async_device_unregister(&dma_dev->ddev); -+ -+ return 0; -+} -+ -+static struct platform_driver gdma_dma_driver = { -+ .probe = gdma_dma_probe, -+ .remove = gdma_dma_remove, -+ .driver = { -+ .name = "gdma-rt2880", -+ .of_match_table = gdma_of_match_table, -+ }, -+}; -+module_platform_driver(gdma_dma_driver); -+ -+MODULE_AUTHOR("Lars-Peter Clausen "); -+MODULE_DESCRIPTION("Ralink/MTK DMA driver"); -+MODULE_LICENSE("GPL v2"); ---- a/include/linux/dmaengine.h -+++ b/include/linux/dmaengine.h -@@ -525,6 +525,7 @@ static inline void dma_set_unmap(struct - struct dmaengine_unmap_data * - dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags); - void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap); -+struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); - #else - static inline void dma_set_unmap(struct dma_async_tx_descriptor *tx, - struct dmaengine_unmap_data *unmap) ---- /dev/null -+++ b/drivers/dma/mtk-hsdma.c -@@ -0,0 +1,767 @@ -+/* -+ * Copyright (C) 2015, Michael Lee -+ * MTK HSDMA support -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "virt-dma.h" -+ -+#define HSDMA_BASE_OFFSET 0x800 -+ -+#define HSDMA_REG_TX_BASE 0x00 -+#define HSDMA_REG_TX_CNT 0x04 -+#define HSDMA_REG_TX_CTX 0x08 -+#define HSDMA_REG_TX_DTX 0x0c -+#define HSDMA_REG_RX_BASE 0x100 -+#define HSDMA_REG_RX_CNT 0x104 -+#define HSDMA_REG_RX_CRX 0x108 -+#define HSDMA_REG_RX_DRX 0x10c -+#define HSDMA_REG_INFO 0x200 -+#define HSDMA_REG_GLO_CFG 0x204 -+#define HSDMA_REG_RST_CFG 0x208 -+#define HSDMA_REG_DELAY_INT 0x20c -+#define HSDMA_REG_FREEQ_THRES 0x210 -+#define HSDMA_REG_INT_STATUS 0x220 -+#define HSDMA_REG_INT_MASK 0x228 -+#define HSDMA_REG_SCH_Q01 0x280 -+#define HSDMA_REG_SCH_Q23 0x284 -+ -+#define HSDMA_DESCS_MAX 0xfff -+#define HSDMA_DESCS_NUM 8 -+#define HSDMA_DESCS_MASK (HSDMA_DESCS_NUM - 1) -+#define HSDMA_NEXT_DESC(x) (((x) + 1) & HSDMA_DESCS_MASK) -+ -+/* HSDMA_REG_INFO */ -+#define HSDMA_INFO_INDEX_MASK 0xf -+#define HSDMA_INFO_INDEX_SHIFT 24 -+#define HSDMA_INFO_BASE_MASK 0xff -+#define HSDMA_INFO_BASE_SHIFT 16 -+#define HSDMA_INFO_RX_MASK 0xff -+#define HSDMA_INFO_RX_SHIFT 8 -+#define HSDMA_INFO_TX_MASK 0xff -+#define HSDMA_INFO_TX_SHIFT 0 -+ -+/* HSDMA_REG_GLO_CFG */ -+#define HSDMA_GLO_TX_2B_OFFSET BIT(31) -+#define HSDMA_GLO_CLK_GATE BIT(30) -+#define HSDMA_GLO_BYTE_SWAP BIT(29) -+#define HSDMA_GLO_MULTI_DMA BIT(10) -+#define HSDMA_GLO_TWO_BUF BIT(9) -+#define HSDMA_GLO_32B_DESC BIT(8) -+#define HSDMA_GLO_BIG_ENDIAN BIT(7) -+#define HSDMA_GLO_TX_DONE BIT(6) -+#define HSDMA_GLO_BT_MASK 0x3 -+#define HSDMA_GLO_BT_SHIFT 4 -+#define HSDMA_GLO_RX_BUSY BIT(3) -+#define HSDMA_GLO_RX_DMA BIT(2) -+#define HSDMA_GLO_TX_BUSY BIT(1) -+#define HSDMA_GLO_TX_DMA BIT(0) -+ -+#define HSDMA_BT_SIZE_16BYTES (0 << HSDMA_GLO_BT_SHIFT) -+#define HSDMA_BT_SIZE_32BYTES (1 << HSDMA_GLO_BT_SHIFT) -+#define HSDMA_BT_SIZE_64BYTES (2 << HSDMA_GLO_BT_SHIFT) -+#define HSDMA_BT_SIZE_128BYTES (3 << HSDMA_GLO_BT_SHIFT) -+ -+#define HSDMA_GLO_DEFAULT (HSDMA_GLO_MULTI_DMA | \ -+ HSDMA_GLO_RX_DMA | HSDMA_GLO_TX_DMA | HSDMA_BT_SIZE_32BYTES) -+ -+/* HSDMA_REG_RST_CFG */ -+#define HSDMA_RST_RX_SHIFT 16 -+#define HSDMA_RST_TX_SHIFT 0 -+ -+/* HSDMA_REG_DELAY_INT */ -+#define HSDMA_DELAY_INT_EN BIT(15) -+#define HSDMA_DELAY_PEND_OFFSET 8 -+#define HSDMA_DELAY_TIME_OFFSET 0 -+#define HSDMA_DELAY_TX_OFFSET 16 -+#define HSDMA_DELAY_RX_OFFSET 0 -+ -+#define HSDMA_DELAY_INIT(x) (HSDMA_DELAY_INT_EN | \ -+ ((x) << HSDMA_DELAY_PEND_OFFSET)) -+#define HSDMA_DELAY(x) ((HSDMA_DELAY_INIT(x) << \ -+ HSDMA_DELAY_TX_OFFSET) | HSDMA_DELAY_INIT(x)) -+ -+/* HSDMA_REG_INT_STATUS */ -+#define HSDMA_INT_DELAY_RX_COH BIT(31) -+#define HSDMA_INT_DELAY_RX_INT BIT(30) -+#define HSDMA_INT_DELAY_TX_COH BIT(29) -+#define HSDMA_INT_DELAY_TX_INT BIT(28) -+#define HSDMA_INT_RX_MASK 0x3 -+#define HSDMA_INT_RX_SHIFT 16 -+#define HSDMA_INT_RX_Q0 BIT(16) -+#define HSDMA_INT_TX_MASK 0xf -+#define HSDMA_INT_TX_SHIFT 0 -+#define HSDMA_INT_TX_Q0 BIT(0) -+ -+/* tx/rx dma desc flags */ -+#define HSDMA_PLEN_MASK 0x3fff -+#define HSDMA_DESC_DONE BIT(31) -+#define HSDMA_DESC_LS0 BIT(30) -+#define HSDMA_DESC_PLEN0(_x) (((_x) & HSDMA_PLEN_MASK) << 16) -+#define HSDMA_DESC_TAG BIT(15) -+#define HSDMA_DESC_LS1 BIT(14) -+#define HSDMA_DESC_PLEN1(_x) ((_x) & HSDMA_PLEN_MASK) -+ -+/* align 4 bytes */ -+#define HSDMA_ALIGN_SIZE 3 -+/* align size 128bytes */ -+#define HSDMA_MAX_PLEN 0x3f80 -+ -+struct hsdma_desc { -+ u32 addr0; -+ u32 flags; -+ u32 addr1; -+ u32 unused; -+}; -+ -+struct mtk_hsdma_sg { -+ dma_addr_t src_addr; -+ dma_addr_t dst_addr; -+ u32 len; -+}; -+ -+struct mtk_hsdma_desc { -+ struct virt_dma_desc vdesc; -+ unsigned int num_sgs; -+ struct mtk_hsdma_sg sg[1]; -+}; -+ -+struct mtk_hsdma_chan { -+ struct virt_dma_chan vchan; -+ unsigned int id; -+ dma_addr_t desc_addr; -+ int tx_idx; -+ int rx_idx; -+ struct hsdma_desc *tx_ring; -+ struct hsdma_desc *rx_ring; -+ struct mtk_hsdma_desc *desc; -+ unsigned int next_sg; -+}; -+ -+struct mtk_hsdam_engine { -+ struct dma_device ddev; -+ struct device_dma_parameters dma_parms; -+ void __iomem *base; -+ struct tasklet_struct task; -+ volatile unsigned long chan_issued; -+ -+ struct mtk_hsdma_chan chan[1]; -+}; -+ -+static inline struct mtk_hsdam_engine *mtk_hsdma_chan_get_dev( -+ struct mtk_hsdma_chan *chan) -+{ -+ return container_of(chan->vchan.chan.device, struct mtk_hsdam_engine, -+ ddev); -+} -+ -+static inline struct mtk_hsdma_chan *to_mtk_hsdma_chan(struct dma_chan *c) -+{ -+ return container_of(c, struct mtk_hsdma_chan, vchan.chan); -+} -+ -+static inline struct mtk_hsdma_desc *to_mtk_hsdma_desc( -+ struct virt_dma_desc *vdesc) -+{ -+ return container_of(vdesc, struct mtk_hsdma_desc, vdesc); -+} -+ -+static inline u32 mtk_hsdma_read(struct mtk_hsdam_engine *hsdma, u32 reg) -+{ -+ return readl(hsdma->base + reg); -+} -+ -+static inline void mtk_hsdma_write(struct mtk_hsdam_engine *hsdma, -+ unsigned reg, u32 val) -+{ -+ writel(val, hsdma->base + reg); -+} -+ -+static void mtk_hsdma_reset_chan(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ chan->tx_idx = 0; -+ chan->rx_idx = HSDMA_DESCS_NUM - 1; -+ -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); -+ -+ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, -+ 0x1 << (chan->id + HSDMA_RST_TX_SHIFT)); -+ mtk_hsdma_write(hsdma, HSDMA_REG_RST_CFG, -+ 0x1 << (chan->id + HSDMA_RST_RX_SHIFT)); -+} -+ -+static void hsdma_dump_reg(struct mtk_hsdam_engine *hsdma) -+{ -+ dev_dbg(hsdma->ddev.dev, "tbase %08x, tcnt %08x, " \ -+ "tctx %08x, tdtx: %08x, rbase %08x, " \ -+ "rcnt %08x, rctx %08x, rdtx %08x\n", -+ mtk_hsdma_read(hsdma, HSDMA_REG_TX_BASE), -+ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CNT), -+ mtk_hsdma_read(hsdma, HSDMA_REG_TX_CTX), -+ mtk_hsdma_read(hsdma, HSDMA_REG_TX_DTX), -+ mtk_hsdma_read(hsdma, HSDMA_REG_RX_BASE), -+ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CNT), -+ mtk_hsdma_read(hsdma, HSDMA_REG_RX_CRX), -+ mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX)); -+ -+ dev_dbg(hsdma->ddev.dev, "info %08x, glo %08x, delay %08x, " \ -+ "intr_stat %08x, intr_mask %08x\n", -+ mtk_hsdma_read(hsdma, HSDMA_REG_INFO), -+ mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG), -+ mtk_hsdma_read(hsdma, HSDMA_REG_DELAY_INT), -+ mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS), -+ mtk_hsdma_read(hsdma, HSDMA_REG_INT_MASK)); -+} -+ -+static void hsdma_dump_desc(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ struct hsdma_desc *tx_desc; -+ struct hsdma_desc *rx_desc; -+ int i; -+ -+ dev_dbg(hsdma->ddev.dev, "tx idx: %d, rx idx: %d\n", -+ chan->tx_idx, chan->rx_idx); -+ -+ for (i = 0; i < HSDMA_DESCS_NUM; i++) { -+ tx_desc = &chan->tx_ring[i]; -+ rx_desc = &chan->rx_ring[i]; -+ -+ dev_dbg(hsdma->ddev.dev, "%d tx addr0: %08x, flags %08x, " \ -+ "tx addr1: %08x, rx addr0 %08x, flags %08x\n", -+ i, tx_desc->addr0, tx_desc->flags, \ -+ tx_desc->addr1, rx_desc->addr0, rx_desc->flags); -+ } -+} -+ -+static void mtk_hsdma_reset(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ int i; -+ -+ /* disable dma */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); -+ -+ /* disable intr */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); -+ -+ /* init desc value */ -+ for (i = 0; i < HSDMA_DESCS_NUM; i++) { -+ chan->tx_ring[i].addr0 = 0; -+ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | -+ HSDMA_DESC_DONE; -+ } -+ for (i = 0; i < HSDMA_DESCS_NUM; i++) { -+ chan->rx_ring[i].addr0 = 0; -+ chan->rx_ring[i].flags = 0; -+ } -+ -+ /* reset */ -+ mtk_hsdma_reset_chan(hsdma, chan); -+ -+ /* enable intr */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); -+ -+ /* enable dma */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); -+} -+ -+static int mtk_hsdma_terminate_all(struct dma_chan *c) -+{ -+ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); -+ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); -+ unsigned long timeout; -+ LIST_HEAD(head); -+ -+ spin_lock_bh(&chan->vchan.lock); -+ chan->desc = NULL; -+ clear_bit(chan->id, &hsdma->chan_issued); -+ vchan_get_all_descriptors(&chan->vchan, &head); -+ spin_unlock_bh(&chan->vchan.lock); -+ -+ vchan_dma_desc_free_list(&chan->vchan, &head); -+ -+ /* wait dma transfer complete */ -+ timeout = jiffies + msecs_to_jiffies(2000); -+ while (mtk_hsdma_read(hsdma, HSDMA_REG_GLO_CFG) & -+ (HSDMA_GLO_RX_BUSY | HSDMA_GLO_TX_BUSY)) { -+ if (time_after_eq(jiffies, timeout)) { -+ hsdma_dump_desc(hsdma, chan); -+ mtk_hsdma_reset(hsdma, chan); -+ dev_err(hsdma->ddev.dev, "timeout, reset it\n"); -+ break; -+ } -+ cpu_relax(); -+ } -+ -+ return 0; -+} -+ -+static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ dma_addr_t src, dst; -+ size_t len, tlen; -+ struct hsdma_desc *tx_desc, *rx_desc; -+ struct mtk_hsdma_sg *sg; -+ unsigned int i; -+ int rx_idx; -+ -+ sg = &chan->desc->sg[0]; -+ len = sg->len; -+ chan->desc->num_sgs = DIV_ROUND_UP(len, HSDMA_MAX_PLEN); -+ -+ /* tx desc */ -+ src = sg->src_addr; -+ for (i = 0; i < chan->desc->num_sgs; i++) { -+ if (len > HSDMA_MAX_PLEN) -+ tlen = HSDMA_MAX_PLEN; -+ else -+ tlen = len; -+ -+ if (i & 0x1) { -+ tx_desc->addr1 = src; -+ tx_desc->flags |= HSDMA_DESC_PLEN1(tlen); -+ } else { -+ tx_desc = &chan->tx_ring[chan->tx_idx]; -+ tx_desc->addr0 = src; -+ tx_desc->flags = HSDMA_DESC_PLEN0(tlen); -+ -+ /* update index */ -+ chan->tx_idx = HSDMA_NEXT_DESC(chan->tx_idx); -+ } -+ -+ src += tlen; -+ len -= tlen; -+ } -+ if (i & 0x1) -+ tx_desc->flags |= HSDMA_DESC_LS0; -+ else -+ tx_desc->flags |= HSDMA_DESC_LS1; -+ -+ /* rx desc */ -+ rx_idx = HSDMA_NEXT_DESC(chan->rx_idx); -+ len = sg->len; -+ dst = sg->dst_addr; -+ for (i = 0; i < chan->desc->num_sgs; i++) { -+ rx_desc = &chan->rx_ring[rx_idx]; -+ if (len > HSDMA_MAX_PLEN) -+ tlen = HSDMA_MAX_PLEN; -+ else -+ tlen = len; -+ -+ rx_desc->addr0 = dst; -+ rx_desc->flags = HSDMA_DESC_PLEN0(tlen); -+ -+ dst += tlen; -+ len -= tlen; -+ -+ /* update index */ -+ rx_idx = HSDMA_NEXT_DESC(rx_idx); -+ } -+ -+ /* make sure desc and index all up to date */ -+ wmb(); -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CTX, chan->tx_idx); -+ -+ return 0; -+} -+ -+static int gdma_next_desc(struct mtk_hsdma_chan *chan) -+{ -+ struct virt_dma_desc *vdesc; -+ -+ vdesc = vchan_next_desc(&chan->vchan); -+ if (!vdesc) { -+ chan->desc = NULL; -+ return 0; -+ } -+ chan->desc = to_mtk_hsdma_desc(vdesc); -+ chan->next_sg = 0; -+ -+ return 1; -+} -+ -+static void mtk_hsdma_chan_done(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ struct mtk_hsdma_desc *desc; -+ int chan_issued; -+ -+ chan_issued = 0; -+ spin_lock_bh(&chan->vchan.lock); -+ desc = chan->desc; -+ if (likely(desc)) { -+ if (chan->next_sg == desc->num_sgs) { -+ list_del(&desc->vdesc.node); -+ vchan_cookie_complete(&desc->vdesc); -+ chan_issued = gdma_next_desc(chan); -+ } -+ } else -+ dev_dbg(hsdma->ddev.dev, "no desc to complete\n"); -+ -+ if (chan_issued) -+ set_bit(chan->id, &hsdma->chan_issued); -+ spin_unlock_bh(&chan->vchan.lock); -+} -+ -+static irqreturn_t mtk_hsdma_irq(int irq, void *devid) -+{ -+ struct mtk_hsdam_engine *hsdma = devid; -+ u32 status; -+ -+ status = mtk_hsdma_read(hsdma, HSDMA_REG_INT_STATUS); -+ if (unlikely(!status)) -+ return IRQ_NONE; -+ -+ if (likely(status & HSDMA_INT_RX_Q0)) -+ tasklet_schedule(&hsdma->task); -+ else -+ dev_dbg(hsdma->ddev.dev, "unhandle irq status %08x\n", -+ status); -+ /* clean intr bits */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_INT_STATUS, status); -+ -+ return IRQ_HANDLED; -+} -+ -+static void mtk_hsdma_issue_pending(struct dma_chan *c) -+{ -+ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); -+ struct mtk_hsdam_engine *hsdma = mtk_hsdma_chan_get_dev(chan); -+ -+ spin_lock_bh(&chan->vchan.lock); -+ if (vchan_issue_pending(&chan->vchan) && !chan->desc) { -+ if (gdma_next_desc(chan)) { -+ set_bit(chan->id, &hsdma->chan_issued); -+ tasklet_schedule(&hsdma->task); -+ } else -+ dev_dbg(hsdma->ddev.dev, "no desc to issue\n"); -+ } -+ spin_unlock_bh(&chan->vchan.lock); -+} -+ -+static struct dma_async_tx_descriptor * mtk_hsdma_prep_dma_memcpy( -+ struct dma_chan *c, dma_addr_t dest, dma_addr_t src, -+ size_t len, unsigned long flags) -+{ -+ struct mtk_hsdma_chan *chan = to_mtk_hsdma_chan(c); -+ struct mtk_hsdma_desc *desc; -+ -+ if (len <= 0) -+ return NULL; -+ -+ desc = kzalloc(sizeof(struct mtk_hsdma_desc), GFP_ATOMIC); -+ if (!desc) { -+ dev_err(c->device->dev, "alloc memcpy decs error\n"); -+ return NULL; -+ } -+ -+ desc->sg[0].src_addr = src; -+ desc->sg[0].dst_addr = dest; -+ desc->sg[0].len = len; -+ -+ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); -+} -+ -+static enum dma_status mtk_hsdma_tx_status(struct dma_chan *c, -+ dma_cookie_t cookie, struct dma_tx_state *state) -+{ -+ return dma_cookie_status(c, cookie, state); -+} -+ -+static void mtk_hsdma_free_chan_resources(struct dma_chan *c) -+{ -+ vchan_free_chan_resources(to_virt_chan(c)); -+} -+ -+static void mtk_hsdma_desc_free(struct virt_dma_desc *vdesc) -+{ -+ kfree(container_of(vdesc, struct mtk_hsdma_desc, vdesc)); -+} -+ -+static void mtk_hsdma_tx(struct mtk_hsdam_engine *hsdma) -+{ -+ struct mtk_hsdma_chan *chan; -+ -+ if (test_and_clear_bit(0, &hsdma->chan_issued)) { -+ chan = &hsdma->chan[0]; -+ if (chan->desc) { -+ mtk_hsdma_start_transfer(hsdma, chan); -+ } else -+ dev_dbg(hsdma->ddev.dev,"chan 0 no desc to issue\n"); -+ } -+} -+ -+static void mtk_hsdma_rx(struct mtk_hsdam_engine *hsdma) -+{ -+ struct mtk_hsdma_chan *chan; -+ int next_idx, drx_idx, cnt; -+ -+ chan = &hsdma->chan[0]; -+ next_idx = HSDMA_NEXT_DESC(chan->rx_idx); -+ drx_idx = mtk_hsdma_read(hsdma, HSDMA_REG_RX_DRX); -+ -+ cnt = (drx_idx - next_idx) & HSDMA_DESCS_MASK; -+ if (!cnt) -+ return; -+ -+ chan->next_sg += cnt; -+ chan->rx_idx = (chan->rx_idx + cnt) & HSDMA_DESCS_MASK; -+ -+ /* update rx crx */ -+ wmb(); -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CRX, chan->rx_idx); -+ -+ mtk_hsdma_chan_done(hsdma, chan); -+} -+ -+static void mtk_hsdma_tasklet(unsigned long arg) -+{ -+ struct mtk_hsdam_engine *hsdma = (struct mtk_hsdam_engine *)arg; -+ -+ mtk_hsdma_rx(hsdma); -+ mtk_hsdma_tx(hsdma); -+} -+ -+static int mtk_hsdam_alloc_desc(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ int i; -+ -+ chan->tx_ring = dma_alloc_coherent(hsdma->ddev.dev, -+ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), -+ &chan->desc_addr, GFP_ATOMIC | __GFP_ZERO); -+ if (!chan->tx_ring) -+ goto no_mem; -+ -+ chan->rx_ring = &chan->tx_ring[HSDMA_DESCS_NUM]; -+ -+ /* init tx ring value */ -+ for (i = 0; i < HSDMA_DESCS_NUM; i++) -+ chan->tx_ring[i].flags = HSDMA_DESC_LS0 | HSDMA_DESC_DONE; -+ -+ return 0; -+no_mem: -+ return -ENOMEM; -+} -+ -+static void mtk_hsdam_free_desc(struct mtk_hsdam_engine *hsdma, -+ struct mtk_hsdma_chan *chan) -+{ -+ if (chan->tx_ring) { -+ dma_free_coherent(hsdma->ddev.dev, -+ 2 * HSDMA_DESCS_NUM * sizeof(*chan->tx_ring), -+ chan->tx_ring, chan->desc_addr); -+ chan->tx_ring = NULL; -+ chan->rx_ring = NULL; -+ } -+} -+ -+static int mtk_hsdma_init(struct mtk_hsdam_engine *hsdma) -+{ -+ struct mtk_hsdma_chan *chan; -+ int ret; -+ u32 reg; -+ -+ /* init desc */ -+ chan = &hsdma->chan[0]; -+ ret = mtk_hsdam_alloc_desc(hsdma, chan); -+ if (ret) -+ return ret; -+ -+ /* tx */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, chan->desc_addr); -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, HSDMA_DESCS_NUM); -+ /* rx */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, chan->desc_addr + -+ (sizeof(struct hsdma_desc) * HSDMA_DESCS_NUM)); -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, HSDMA_DESCS_NUM); -+ /* reset */ -+ mtk_hsdma_reset_chan(hsdma, chan); -+ -+ /* enable rx intr */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, HSDMA_INT_RX_Q0); -+ -+ /* enable dma */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, HSDMA_GLO_DEFAULT); -+ -+ /* hardware info */ -+ reg = mtk_hsdma_read(hsdma, HSDMA_REG_INFO); -+ dev_info(hsdma->ddev.dev, "rx: %d, tx: %d\n", -+ (reg >> HSDMA_INFO_RX_SHIFT) & HSDMA_INFO_RX_MASK, -+ (reg >> HSDMA_INFO_TX_SHIFT) & HSDMA_INFO_TX_MASK); -+ -+ hsdma_dump_reg(hsdma); -+ -+ return ret; -+} -+ -+static void mtk_hsdma_uninit(struct mtk_hsdam_engine *hsdma) -+{ -+ struct mtk_hsdma_chan *chan; -+ -+ /* disable dma */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_GLO_CFG, 0); -+ -+ /* disable intr */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_INT_MASK, 0); -+ -+ /* free desc */ -+ chan = &hsdma->chan[0]; -+ mtk_hsdam_free_desc(hsdma, chan); -+ -+ /* tx */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_BASE, 0); -+ mtk_hsdma_write(hsdma, HSDMA_REG_TX_CNT, 0); -+ /* rx */ -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_BASE, 0); -+ mtk_hsdma_write(hsdma, HSDMA_REG_RX_CNT, 0); -+ /* reset */ -+ mtk_hsdma_reset_chan(hsdma, chan); -+} -+ -+static const struct of_device_id mtk_hsdma_of_match[] = { -+ { .compatible = "mediatek,mt7621-hsdma" }, -+ { }, -+}; -+ -+static int mtk_hsdma_probe(struct platform_device *pdev) -+{ -+ const struct of_device_id *match; -+ struct mtk_hsdma_chan *chan; -+ struct mtk_hsdam_engine *hsdma; -+ struct dma_device *dd; -+ struct resource *res; -+ int ret; -+ int irq; -+ void __iomem *base; -+ -+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); -+ if (ret) -+ return ret; -+ -+ match = of_match_device(mtk_hsdma_of_match, &pdev->dev); -+ if (!match) -+ return -EINVAL; -+ -+ hsdma = devm_kzalloc(&pdev->dev, sizeof(*hsdma), GFP_KERNEL); -+ if (!hsdma) { -+ dev_err(&pdev->dev, "alloc dma device failed\n"); -+ return -EINVAL; -+ } -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ base = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(base)) -+ return PTR_ERR(base); -+ hsdma->base = base + HSDMA_BASE_OFFSET; -+ tasklet_init(&hsdma->task, mtk_hsdma_tasklet, (unsigned long)hsdma); -+ -+ irq = platform_get_irq(pdev, 0); -+ if (irq < 0) { -+ dev_err(&pdev->dev, "failed to get irq\n"); -+ return -EINVAL; -+ } -+ ret = devm_request_irq(&pdev->dev, irq, mtk_hsdma_irq, -+ 0, dev_name(&pdev->dev), hsdma); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to request irq\n"); -+ return ret; -+ } -+ -+ device_reset(&pdev->dev); -+ -+ dd = &hsdma->ddev; -+ dma_cap_set(DMA_MEMCPY, dd->cap_mask); -+ dd->copy_align = HSDMA_ALIGN_SIZE; -+ dd->device_free_chan_resources = mtk_hsdma_free_chan_resources; -+ dd->device_prep_dma_memcpy = mtk_hsdma_prep_dma_memcpy; -+ dd->device_terminate_all = mtk_hsdma_terminate_all; -+ dd->device_tx_status = mtk_hsdma_tx_status; -+ dd->device_issue_pending = mtk_hsdma_issue_pending; -+ dd->dev = &pdev->dev; -+ dd->dev->dma_parms = &hsdma->dma_parms; -+ dma_set_max_seg_size(dd->dev, HSDMA_MAX_PLEN); -+ INIT_LIST_HEAD(&dd->channels); -+ -+ chan = &hsdma->chan[0]; -+ chan->id = 0; -+ chan->vchan.desc_free = mtk_hsdma_desc_free; -+ vchan_init(&chan->vchan, dd); -+ -+ /* init hardware */ -+ ret = mtk_hsdma_init(hsdma); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to alloc ring descs\n"); -+ return ret; -+ } -+ -+ ret = dma_async_device_register(dd); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register dma device\n"); -+ return ret; -+ } -+ -+ ret = of_dma_controller_register(pdev->dev.of_node, -+ of_dma_xlate_by_chan_id, hsdma); -+ if (ret) { -+ dev_err(&pdev->dev, "failed to register of dma controller\n"); -+ goto err_unregister; -+ } -+ -+ platform_set_drvdata(pdev, hsdma); -+ -+ return 0; -+ -+err_unregister: -+ dma_async_device_unregister(dd); -+ return ret; -+} -+ -+static int mtk_hsdma_remove(struct platform_device *pdev) -+{ -+ struct mtk_hsdam_engine *hsdma = platform_get_drvdata(pdev); -+ -+ mtk_hsdma_uninit(hsdma); -+ -+ of_dma_controller_free(pdev->dev.of_node); -+ dma_async_device_unregister(&hsdma->ddev); -+ -+ return 0; -+} -+ -+static struct platform_driver mtk_hsdma_driver = { -+ .probe = mtk_hsdma_probe, -+ .remove = mtk_hsdma_remove, -+ .driver = { -+ .name = "hsdma-mt7621", -+ .of_match_table = mtk_hsdma_of_match, -+ }, -+}; -+module_platform_driver(mtk_hsdma_driver); -+ -+MODULE_AUTHOR("Michael Lee "); -+MODULE_DESCRIPTION("MTK HSDMA driver"); -+MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch index 1834e88538..d0d4141a8d 100644 --- a/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch +++ b/target/linux/ramips/patches-5.4/0048-asoc-add-mt7620-support.patch @@ -20,15 +20,15 @@ Signed-off-by: John Crispin --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c -@@ -15,6 +15,7 @@ +@@ -13,6 +13,7 @@ #include #include - #include + #include +#include #include #include -@@ -26,6 +27,7 @@ +@@ -24,6 +25,7 @@ #include "common.h" __iomem void *rt_sysc_membase; @@ -38,7 +38,7 @@ Signed-off-by: John Crispin __iomem void *plat_of_remap_node(const char *node) --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig -@@ -59,6 +59,7 @@ source "sound/soc/mxs/Kconfig" +@@ -60,6 +60,7 @@ source "sound/soc/mxs/Kconfig" source "sound/soc/pxa/Kconfig" source "sound/soc/qcom/Kconfig" source "sound/soc/rockchip/Kconfig" @@ -48,7 +48,7 @@ Signed-off-by: John Crispin source "sound/soc/sirf/Kconfig" --- a/sound/soc/Makefile +++ b/sound/soc/Makefile -@@ -40,6 +40,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ +@@ -43,6 +43,7 @@ obj-$(CONFIG_SND_SOC) += kirkwood/ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += qcom/ obj-$(CONFIG_SND_SOC) += rockchip/ diff --git a/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch b/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch index 2ad1f6f9f8..4822226610 100644 --- a/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch +++ b/target/linux/ramips/patches-5.4/0051-serial-add-ugly-custom-baud-rate-hack.patch @@ -10,7 +10,7 @@ Signed-off-by: John Crispin --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c -@@ -428,6 +428,9 @@ uart_get_baud_rate(struct uart_port *por +@@ -416,6 +416,9 @@ uart_get_baud_rate(struct uart_port *por break; } diff --git a/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch b/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch index 6eb7f16b9d..d2c5724c06 100644 --- a/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch +++ b/target/linux/ramips/patches-5.4/0052-pwm-add-mediatek-support.patch @@ -13,7 +13,7 @@ Signed-off-by: John Crispin --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig -@@ -302,6 +302,15 @@ config PWM_MEDIATEK +@@ -316,6 +316,15 @@ config PWM_MEDIATEK To compile this driver as a module, choose M here: the module will be called pwm-mediatek. @@ -31,7 +31,7 @@ Signed-off-by: John Crispin depends on ARCH_MXS && OF --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p +@@ -29,6 +29,7 @@ obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-p obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o obj-$(CONFIG_PWM_MESON) += pwm-meson.o obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o diff --git a/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch deleted file mode 100644 index aa2fb60a2b..0000000000 --- a/target/linux/ramips/patches-5.4/0053-mtd-spi-nor-add-w25q256-3b-mode-switch.patch +++ /dev/null @@ -1,214 +0,0 @@ -mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash - -On some devices the flash chip needs to be in 3-byte addressing mode during -reboot, otherwise the boot loader will fail to start. -This mode however does not allow regular reads/writes onto the upper 16M -half. W25Q256 has separate read commands for reading from >16M, however -it does not have any separate write commands. -This patch changes the code to leave the chip in 3-byte mode most of the -time and only switch during erase/write cycles that go to >16M -addresses. - -Signed-off-by: Felix Fietkau ---- ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -89,6 +89,10 @@ struct flash_info { - #define NO_CHIP_ERASE BIT(12) /* Chip does not support chip erase */ - #define SPI_NOR_SKIP_SFDP BIT(13) /* Skip parsing of SFDP tables */ - #define USE_CLSR BIT(14) /* use CLSR command */ -+#define SPI_NOR_4B_READ_OP BIT(15) /* -+ * Like SPI_NOR_4B_OPCODES, but for read -+ * op code only. -+ */ - }; - - #define JEDEC_MFR(info) ((info)->id[0]) -@@ -240,6 +244,15 @@ static inline u8 spi_nor_convert_3to4_er - ARRAY_SIZE(spi_nor_3to4_erase)); - } - -+static void spi_nor_set_4byte_read(struct spi_nor *nor, -+ const struct flash_info *info) -+{ -+ nor->addr_width = 3; -+ nor->ext_addr = 0; -+ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); -+ nor->flags |= SNOR_F_4B_EXT_ADDR; -+} -+ - static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, - const struct flash_info *info) - { -@@ -467,6 +480,36 @@ static int spi_nor_erase_sector(struct s - return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width); - } - -+static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr) -+{ -+ bool ext_addr; -+ int ret; -+ u8 cmd; -+ -+ if (!(nor->flags & SNOR_F_4B_EXT_ADDR)) -+ return 0; -+ -+ ext_addr = !!(addr & 0xff000000); -+ if (nor->ext_addr == ext_addr) -+ return 0; -+ -+ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; -+ write_enable(nor); -+ ret = nor->write_reg(nor, cmd, NULL, 0); -+ if (ret) -+ return ret; -+ -+ cmd = 0; -+ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1); -+ if (ret) -+ return ret; -+ -+ nor->addr_width = 3 + ext_addr; -+ nor->ext_addr = ext_addr; -+ write_disable(nor); -+ return 0; -+} -+ - /* - * Erase an address range on the nor chip. The address range may extend - * one or more erase sectors. Return an error is there is a problem erasing. -@@ -492,6 +535,10 @@ static int spi_nor_erase(struct mtd_info - if (ret) - return ret; - -+ ret = spi_nor_check_ext_addr(nor, addr + len); -+ if (ret) -+ return ret; -+ - /* whole-chip erase? */ - if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { - unsigned long timeout; -@@ -542,6 +589,7 @@ static int spi_nor_erase(struct mtd_info - write_disable(nor); - - erase_err: -+ spi_nor_check_ext_addr(nor, 0); - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - - instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE; -@@ -834,7 +882,9 @@ static int spi_nor_lock(struct mtd_info - if (ret) - return ret; - -+ spi_nor_check_ext_addr(nor, ofs + len); - ret = nor->flash_lock(nor, ofs, len); -+ spi_nor_check_ext_addr(nor, 0); - - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); - return ret; -@@ -849,7 +899,9 @@ static int spi_nor_unlock(struct mtd_inf - if (ret) - return ret; - -+ spi_nor_check_ext_addr(nor, ofs + len); - ret = nor->flash_unlock(nor, ofs, len); -+ spi_nor_check_ext_addr(nor, 0); - - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); - return ret; -@@ -1182,7 +1234,7 @@ static const struct flash_info spi_nor_i - { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, - { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, - { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_READ_OP) }, - { "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024, - SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) }, - -@@ -1245,6 +1297,9 @@ static int spi_nor_read(struct mtd_info - if (ret) - return ret; - -+ if (nor->flags & SNOR_F_4B_EXT_ADDR) -+ nor->addr_width = 4; -+ - while (len) { - loff_t addr = from; - -@@ -1269,6 +1324,18 @@ static int spi_nor_read(struct mtd_info - ret = 0; - - read_err: -+ if (nor->flags & SNOR_F_4B_EXT_ADDR) { -+ u8 val = 0; -+ -+ if ((from + len) & 0xff000000) { -+ write_enable(nor); -+ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1); -+ write_disable(nor); -+ } -+ -+ nor->addr_width = 3; -+ } -+ - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); - return ret; - } -@@ -1370,6 +1437,10 @@ static int spi_nor_write(struct mtd_info - if (ret) - return ret; - -+ ret = spi_nor_check_ext_addr(nor, to + len); -+ if (ret < 0) -+ return ret; -+ - for (i = 0; i < len; ) { - ssize_t written; - loff_t addr = to + i; -@@ -1410,6 +1481,7 @@ static int spi_nor_write(struct mtd_info - } - - write_err: -+ spi_nor_check_ext_addr(nor, 0); - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); - return ret; - } -@@ -2826,8 +2898,10 @@ int spi_nor_scan(struct spi_nor *nor, co - } else if (mtd->size > 0x1000000) { - /* enable 4-byte addressing if the device exceeds 16MiB */ - nor->addr_width = 4; -- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || -- info->flags & SPI_NOR_4B_OPCODES) -+ if (info->flags & SPI_NOR_4B_READ_OP) -+ spi_nor_set_4byte_read(nor, info); -+ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || -+ info->flags & SPI_NOR_4B_OPCODES) - spi_nor_set_4byte_opcodes(nor, info); - else - set_4byte(nor, info, 1); ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -102,6 +102,7 @@ - /* Used for Macronix and Winbond flashes. */ - #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ - #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ -+#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ - - /* Used for Spansion flashes only. */ - #define SPINOR_OP_BRWR 0x17 /* Bank register write */ -@@ -229,6 +230,7 @@ enum spi_nor_option_flags { - SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), - SNOR_F_READY_XSR_RDY = BIT(4), - SNOR_F_USE_CLSR = BIT(5), -+ SNOR_F_4B_EXT_ADDR = BIT(6), - }; - - /** -@@ -280,6 +282,7 @@ struct spi_nor { - enum spi_nor_protocol reg_proto; - bool sst_write_second; - u32 flags; -+ u8 ext_addr; - u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; - - int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); diff --git a/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch b/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch deleted file mode 100644 index a686937989..0000000000 --- a/target/linux/ramips/patches-5.4/0054-mtd-spi-nor-w25q256-respect-default-mode.patch +++ /dev/null @@ -1,73 +0,0 @@ ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -142,20 +142,29 @@ static int read_fsr(struct spi_nor *nor) - * location. Return the configuration register value. - * Returns negative if error occurred. - */ --static int read_cr(struct spi_nor *nor) -+static int _read_cr(struct spi_nor *nor, u8 reg) - { - int ret; - u8 val; - -- ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); -+ ret = nor->read_reg(nor, reg, &val, 1); - if (ret < 0) { -- dev_err(nor->dev, "error %d reading CR\n", ret); -+ dev_err(nor->dev, "error %d reading %s\n", ret, -+ (reg==SPINOR_OP_RDCR)?"CR":"XCR"); - return ret; - } - - return val; - } - -+static inline int read_cr(struct spi_nor *nor) { -+ return _read_cr(nor, SPINOR_OP_RDCR); -+} -+ -+static inline int read_xcr(struct spi_nor *nor) { -+ return _read_cr(nor, SPINOR_OP_RDXCR); -+} -+ - /* - * Write status register 1 byte - * Returns negative if error occurred. -@@ -2898,9 +2907,16 @@ int spi_nor_scan(struct spi_nor *nor, co - } else if (mtd->size > 0x1000000) { - /* enable 4-byte addressing if the device exceeds 16MiB */ - nor->addr_width = 4; -- if (info->flags & SPI_NOR_4B_READ_OP) -- spi_nor_set_4byte_read(nor, info); -- else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || -+ if (info->flags & SPI_NOR_4B_READ_OP) { -+ if (JEDEC_MFR(info) == SNOR_MFR_WINBOND) { -+ ret = read_xcr(nor); -+ if (!(ret > 0 && (ret & XCR_DEF_4B_ADDR_MODE))) -+ spi_nor_set_4byte_read(nor, info); -+ else -+ set_4byte(nor, info, 1); -+ } else -+ spi_nor_set_4byte_read(nor, info); -+ } else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || - info->flags & SPI_NOR_4B_OPCODES) - spi_nor_set_4byte_opcodes(nor, info); - else ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -103,6 +103,7 @@ - #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ - #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ - #define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ -+#define SPINOR_OP_RDXCR 0x15 /* Read extended configuration register */ - - /* Used for Spansion flashes only. */ - #define SPINOR_OP_BRWR 0x17 /* Bank register write */ -@@ -135,6 +136,7 @@ - - /* Configuration Register bits. */ - #define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ -+#define XCR_DEF_4B_ADDR_MODE BIT(1) /* Winbond 4B mode default */ - - /* Status Register 2 bits. */ - #define SR2_QUAD_EN_BIT7 BIT(7) diff --git a/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch b/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch index 0e09e1d4e0..1ce8fac682 100644 --- a/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch +++ b/target/linux/ramips/patches-5.4/0069-awake-rt305x-dwc2-controller.patch @@ -1,12 +1,12 @@ --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c -@@ -406,6 +406,12 @@ static int dwc2_driver_probe(struct plat - if (retval) - return retval; +@@ -432,6 +432,12 @@ static int dwc2_driver_probe(struct plat + + hsotg->needs_byte_swap = dwc2_check_core_endianness(hsotg); + /* Enable USB port before any regs access */ -+ if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) { -+ dwc2_writel(0x00, hsotg->regs + PCGCTL); ++ if (dwc2_readl(hsotg, PCGCTL) & 0x0f) { ++ dwc2_writel(0x00, hsotg, PCGCTL); + /* TODO: mdelay(25) here? vendor driver don't use it */ + } + diff --git a/target/linux/ramips/patches-5.4/0070-weak_reordering.patch b/target/linux/ramips/patches-5.4/0070-weak_reordering.patch index 52e6641324..fe3fdec289 100644 --- a/target/linux/ramips/patches-5.4/0070-weak_reordering.patch +++ b/target/linux/ramips/patches-5.4/0070-weak_reordering.patch @@ -1,9 +1,9 @@ --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig -@@ -58,6 +58,7 @@ choice +@@ -57,6 +57,7 @@ choice select COMMON_CLK select CLKSRC_MIPS_GIC - select HW_HAS_PCI + select HAVE_PCI if PCI_MT7621 + select WEAK_REORDERING_BEYOND_LLSC endchoice diff --git a/target/linux/ramips/patches-5.4/0098-disable_cm.patch b/target/linux/ramips/patches-5.4/0098-disable_cm.patch index bc00619dff..9b280aef99 100644 --- a/target/linux/ramips/patches-5.4/0098-disable_cm.patch +++ b/target/linux/ramips/patches-5.4/0098-disable_cm.patch @@ -1,6 +1,6 @@ --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c -@@ -237,6 +237,7 @@ int mips_cm_probe(void) +@@ -233,6 +233,7 @@ int mips_cm_probe(void) /* disable CM regions */ write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR); @@ -8,7 +8,7 @@ write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK); write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR); write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK); -@@ -244,7 +245,7 @@ int mips_cm_probe(void) +@@ -240,7 +241,7 @@ int mips_cm_probe(void) write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK); write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR); write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK); diff --git a/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch b/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch deleted file mode 100644 index 997fb6a2b3..0000000000 --- a/target/linux/ramips/patches-5.4/0099-pci-mt7620.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/mips/pci/pci-mt7620.c -+++ b/arch/mips/pci/pci-mt7620.c -@@ -33,7 +33,6 @@ - #define RALINK_GPIOMODE 0x60 - - #define PPLL_CFG1 0x9c --#define PDRV_SW_SET BIT(23) - - #define PPLL_DRV 0xa0 - #define PDRV_SW_SET (1<<31) diff --git a/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch b/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch index cd1462fbcf..9142faaf43 100644 --- a/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch +++ b/target/linux/ramips/patches-5.4/0200-linkit_bootstrap.patch @@ -1,13 +1,13 @@ --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile -@@ -56,6 +56,7 @@ obj-$(CONFIG_CXL_BASE) += cxl/ - obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o - obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o +@@ -52,6 +52,7 @@ obj-$(CONFIG_ECHO) += echo/ + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o + obj-$(CONFIG_CXL_BASE) += cxl/ obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o +obj-$(CONFIG_SOC_MT7620) += linkit.o - - lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o - lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o + obj-$(CONFIG_OCXL) += ocxl/ + obj-y += cardreader/ + obj-$(CONFIG_PVPANIC) += pvpanic.o --- /dev/null +++ b/drivers/misc/linkit.c @@ -0,0 +1,84 @@ diff --git a/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch b/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch index 991e19b6df..1c8b61f8ef 100644 --- a/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch +++ b/target/linux/ramips/patches-5.4/100-mt7621-core-detect-hack.patch @@ -7,7 +7,7 @@ Signed-off-by: Felix Fietkau --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c -@@ -47,6 +47,11 @@ static unsigned core_vpe_count(unsigned +@@ -43,6 +43,11 @@ static unsigned core_vpe_count(unsigned return mips_cps_numvps(cluster, core); } @@ -19,7 +19,7 @@ Signed-off-by: Felix Fietkau static void __init cps_smp_setup(void) { unsigned int nclusters, ncores, nvpes, core_vpes; -@@ -64,6 +69,8 @@ static void __init cps_smp_setup(void) +@@ -60,6 +65,8 @@ static void __init cps_smp_setup(void) ncores = mips_cps_numcores(cl); for (c = 0; c < ncores; c++) { @@ -30,7 +30,7 @@ Signed-off-by: Felix Fietkau if (c > 0) --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c -@@ -15,6 +15,7 @@ +@@ -13,6 +13,7 @@ #include #include #include @@ -38,7 +38,7 @@ Signed-off-by: Felix Fietkau #include -@@ -162,6 +163,20 @@ void __init ralink_of_remap(void) +@@ -160,6 +161,20 @@ void __init ralink_of_remap(void) panic("Failed to remap core resources"); } diff --git a/target/linux/ramips/patches-5.4/101-mt7621-timer.patch b/target/linux/ramips/patches-5.4/101-mt7621-timer.patch index 10edafd412..8528b71c88 100644 --- a/target/linux/ramips/patches-5.4/101-mt7621-timer.patch +++ b/target/linux/ramips/patches-5.4/101-mt7621-timer.patch @@ -1,6 +1,6 @@ --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c -@@ -9,6 +9,7 @@ +@@ -7,6 +7,7 @@ #include #include @@ -8,7 +8,7 @@ #include #include -@@ -16,6 +17,7 @@ +@@ -14,6 +15,7 @@ #include #include #include @@ -16,7 +16,7 @@ #include -@@ -177,6 +179,58 @@ bool plat_cpu_core_present(int core) +@@ -175,6 +177,58 @@ bool plat_cpu_core_present(int core) return true; } @@ -77,9 +77,9 @@ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); --- a/arch/mips/ralink/Kconfig +++ b/arch/mips/ralink/Kconfig -@@ -59,6 +59,7 @@ choice +@@ -58,6 +58,7 @@ choice select CLKSRC_MIPS_GIC - select HW_HAS_PCI + select HAVE_PCI if PCI_MT7621 select WEAK_REORDERING_BEYOND_LLSC + select GENERIC_CLOCKEVENTS_BROADCAST endchoice diff --git a/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch b/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch index e647a2f4c8..0c997a3f28 100644 --- a/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch +++ b/target/linux/ramips/patches-5.4/102-mt7621-fix-cpu-clk-add-clkdev.patch @@ -1,6 +1,6 @@ --- a/arch/mips/include/asm/mach-ralink/mt7621.h +++ b/arch/mips/include/asm/mach-ralink/mt7621.h -@@ -19,6 +19,10 @@ +@@ -17,6 +17,10 @@ #define SYSC_REG_CHIP_REV 0x0c #define SYSC_REG_SYSTEM_CONFIG0 0x10 #define SYSC_REG_SYSTEM_CONFIG1 0x14 @@ -11,7 +11,7 @@ #define CHIP_REV_PKG_MASK 0x1 #define CHIP_REV_PKG_SHIFT 16 -@@ -26,6 +30,22 @@ +@@ -24,6 +28,22 @@ #define CHIP_REV_VER_SHIFT 8 #define CHIP_REV_ECO_MASK 0xf @@ -36,7 +36,7 @@ #define MT7621_DDR2_SIZE_MAX 256 --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c -@@ -10,6 +10,10 @@ +@@ -8,6 +8,10 @@ #include #include #include @@ -47,7 +47,7 @@ #include #include -@@ -18,16 +22,12 @@ +@@ -16,16 +20,12 @@ #include #include #include @@ -65,7 +65,7 @@ #define MT7621_GPIO_MODE_UART1 1 #define MT7621_GPIO_MODE_I2C 2 #define MT7621_GPIO_MODE_UART3_MASK 0x3 -@@ -113,49 +113,89 @@ static struct rt2880_pmx_group mt7621_pi +@@ -111,49 +111,89 @@ static struct rt2880_pmx_group mt7621_pi { 0 } }; @@ -184,7 +184,7 @@ rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc"); --- a/arch/mips/ralink/timer-gic.c +++ b/arch/mips/ralink/timer-gic.c -@@ -11,14 +11,14 @@ +@@ -9,14 +9,14 @@ #include #include diff --git a/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch b/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch index b19b57fd66..08b4b0de29 100644 --- a/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch +++ b/target/linux/ramips/patches-5.4/105-mt7621-memory-detect.patch @@ -28,7 +28,7 @@ Signed-off-by: Chuanhong Guo --- a/arch/mips/include/asm/mach-ralink/mt7621.h +++ b/arch/mips/include/asm/mach-ralink/mt7621.h -@@ -46,9 +46,10 @@ +@@ -44,9 +44,10 @@ #define CPU_PLL_FBDIV_MASK 0x7f #define CPU_PLL_FBDIV_SHIFT 4 @@ -44,7 +44,7 @@ Signed-off-by: Chuanhong Guo #define MT7621_CHIP_NAME1 0x20203132 --- a/arch/mips/ralink/mt7621.c +++ b/arch/mips/ralink/mt7621.c -@@ -15,6 +15,7 @@ +@@ -13,6 +13,7 @@ #include #include @@ -52,7 +52,7 @@ Signed-off-by: Chuanhong Guo #include #include #include -@@ -57,6 +58,8 @@ +@@ -55,6 +56,8 @@ #define MT7621_GPIO_MODE_SDHCI_SHIFT 18 #define MT7621_GPIO_MODE_SDHCI_GPIO 1 @@ -61,7 +61,7 @@ Signed-off-by: Chuanhong Guo static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) }; static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) }; static struct rt2880_pmx_func uart3_grp[] = { -@@ -141,6 +144,28 @@ static struct clk *__init mt7621_add_sys +@@ -139,6 +142,28 @@ static struct clk *__init mt7621_add_sys return clk; } @@ -90,7 +90,7 @@ Signed-off-by: Chuanhong Guo void __init ralink_clk_init(void) { u32 syscfg, xtal_sel, clkcfg, clk_sel, curclk, ffiv, ffrac; -@@ -319,10 +344,7 @@ void prom_soc_init(struct ralink_soc_inf +@@ -317,10 +342,7 @@ void prom_soc_init(struct ralink_soc_inf (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, (rev & CHIP_REV_ECO_MASK)); @@ -104,7 +104,7 @@ Signed-off-by: Chuanhong Guo --- a/arch/mips/ralink/common.h +++ b/arch/mips/ralink/common.h -@@ -19,6 +19,7 @@ struct ralink_soc_info { +@@ -17,6 +17,7 @@ struct ralink_soc_info { unsigned long mem_size; unsigned long mem_size_min; unsigned long mem_size_max; @@ -114,7 +114,7 @@ Signed-off-by: Chuanhong Guo --- a/arch/mips/ralink/of.c +++ b/arch/mips/ralink/of.c -@@ -89,6 +89,8 @@ void __init plat_mem_setup(void) +@@ -87,6 +87,8 @@ void __init plat_mem_setup(void) of_scan_flat_dt(early_init_dt_find_memory, NULL); if (memory_dtb) of_scan_flat_dt(early_init_dt_scan_memory, NULL); diff --git a/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch b/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch index 4c40e65ab9..dfeac7eb99 100644 --- a/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch +++ b/target/linux/ramips/patches-5.4/110-mt7621-perfctr-fix.patch @@ -1,6 +1,6 @@ --- a/arch/mips/ralink/irq-gic.c +++ b/arch/mips/ralink/irq-gic.c -@@ -15,6 +15,12 @@ +@@ -13,6 +13,12 @@ int get_c0_perfcount_int(void) { diff --git a/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch b/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch index 0cb1fede30..8b4335eb03 100644 --- a/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch +++ b/target/linux/ramips/patches-5.4/300-mt7620-export-chip-version-and-pkg.patch @@ -1,6 +1,6 @@ --- a/arch/mips/include/asm/mach-ralink/mt7620.h +++ b/arch/mips/include/asm/mach-ralink/mt7620.h -@@ -137,4 +137,16 @@ static inline int mt7620_get_eco(void) +@@ -135,4 +135,16 @@ static inline int mt7620_get_eco(void) return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK; } diff --git a/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch b/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch index 0a3a65d70a..3e229bcc1b 100644 --- a/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch +++ b/target/linux/ramips/patches-5.4/302-spi-nor-add-gd25q512.patch @@ -1,8 +1,8 @@ --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1066,6 +1066,11 @@ static const struct flash_info spi_nor_i - SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | - SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) +@@ -2238,6 +2238,11 @@ static const struct flash_info spi_nor_i + SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + .fixups = &gd25q256_fixups, }, + { + "gd25q512", INFO(0xc84020, 0, 64 * 1024, 1024, diff --git a/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch b/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch deleted file mode 100644 index 8b59a106e1..0000000000 --- a/target/linux/ramips/patches-5.4/304-spi-nor-enable-4B-opcodes-for-mx25l25635f.patch +++ /dev/null @@ -1,72 +0,0 @@ -This hack can be dropped after the next stable release from -v5.x-tree. - -The problem was fixed upstream by - -commit 2bffa65da43e ("mtd: spi-nor: Add a post BFPT fixup for MX25L25635E") - -For reference see: - - ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -1103,6 +1103,7 @@ static const struct flash_info spi_nor_i - { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, - { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, - { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, - { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) }, - { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, - { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, -@@ -1275,11 +1276,12 @@ static const struct flash_info spi_nor_i - { }, - }; - --static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -+static const struct flash_info *spi_nor_read_id(struct spi_nor *nor, -+ const char *name) - { - int tmp; - u8 id[SPI_NOR_MAX_ID_LEN]; -- const struct flash_info *info; -+ const struct flash_info *info, *first_match = NULL; - - tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); - if (tmp < 0) { -@@ -1290,10 +1292,16 @@ static const struct flash_info *spi_nor_ - for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { - info = &spi_nor_ids[tmp]; - if (info->id_len) { -- if (!memcmp(info->id, id, info->id_len)) -- return &spi_nor_ids[tmp]; -+ if (!memcmp(info->id, id, info->id_len)) { -+ if (!name || !strcmp(name, info->name)) -+ return info; -+ if (!first_match) -+ first_match = info; -+ } - } - } -+ if (first_match) -+ return first_match; - dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n", - id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); -@@ -2773,7 +2781,7 @@ int spi_nor_scan(struct spi_nor *nor, co - info = spi_nor_match_id(name); - /* Try to auto-detect if chip name wasn't specified or not found */ - if (!info) -- info = spi_nor_read_id(nor); -+ info = spi_nor_read_id(nor, NULL); - if (IS_ERR_OR_NULL(info)) - return -ENOENT; - -@@ -2784,7 +2792,7 @@ int spi_nor_scan(struct spi_nor *nor, co - if (name && info->id_len) { - const struct flash_info *jinfo; - -- jinfo = spi_nor_read_id(nor); -+ jinfo = spi_nor_read_id(nor, name); - if (IS_ERR(jinfo)) { - return PTR_ERR(jinfo); - } else if (jinfo != info) { diff --git a/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch b/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch index 3310a6bdba..7c00d4c9ae 100644 --- a/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch +++ b/target/linux/ramips/patches-5.4/999-fix-pci-init-mt7620.patch @@ -1,14 +1,14 @@ --- a/arch/mips/pci/pci-mt7620.c +++ b/arch/mips/pci/pci-mt7620.c -@@ -35,6 +35,7 @@ +@@ -32,6 +32,7 @@ #define PPLL_CFG1 0x9c #define PPLL_DRV 0xa0 -+#define PPLL_LD (1<<23) - #define PDRV_SW_SET (1<<31) - #define LC_CKDRVPD (1<<19) - #define LC_CKDRVOHZ (1<<18) -@@ -242,8 +243,8 @@ static int mt7620_pci_hw_init(struct pla ++#define PPLL_LD BIT(23) + #define PDRV_SW_SET BIT(31) + #define LC_CKDRVPD BIT(19) + #define LC_CKDRVOHZ BIT(18) +@@ -239,8 +240,8 @@ static int mt7620_pci_hw_init(struct pla rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); mdelay(100); From 99d210d6a09935f741e474873d89cb104baecec2 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:11:06 +0800 Subject: [PATCH 05/35] ramips: mt7621: refresh kernel config Signed-off-by: DENG Qingfang --- target/linux/ramips/mt7621/config-5.4 | 120 +++++++++++++++----------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/target/linux/ramips/mt7621/config-5.4 b/target/linux/ramips/mt7621/config-5.4 index 4112cad780..20fb53c69c 100644 --- a/target/linux/ramips/mt7621/config-5.4 +++ b/target/linux/ramips/mt7621/config-5.4 @@ -1,31 +1,28 @@ -CONFIG_ARCH_BINFMT_ELF_STATE=y +CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN=y +CONFIG_ARCH_HAS_DMA_PREP_COHERENT=y +CONFIG_ARCH_HAS_DMA_WRITE_COMBINE=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set CONFIG_ARCH_HAS_RESET_CONTROLLER=y -# CONFIG_ARCH_HAS_SG_CHAIN is not set -# CONFIG_ARCH_HAS_STRICT_KERNEL_RWX is not set -# CONFIG_ARCH_HAS_STRICT_MODULE_RWX is not set +CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE=y CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_ARCH_HAS_UNCACHED_SEGMENT=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 -# CONFIG_ARCH_OPTIONAL_KERNEL_RWX is not set -# CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT is not set CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_USE_BUILTIN_BSWAP=y +CONFIG_ARCH_USE_MEMREMAP_PROT=y CONFIG_ARCH_USE_QUEUED_RWLOCKS=y CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_BLK_MQ_PCI=y CONFIG_BOARD_SCACHE=y CONFIG_BOUNCE=y CONFIG_CEVT_R4K=y -# CONFIG_CEVT_SYSTICK_QUIRK is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_MIPS_GIC=y CONFIG_CLONE_BACKWARDS=y @@ -34,7 +31,9 @@ CONFIG_CMDLINE_BOOL=y # CONFIG_CMDLINE_OVERRIDE is not set CONFIG_COMMON_CLK=y # CONFIG_COMMON_CLK_BOSTON is not set +CONFIG_COMPAT_32BIT_TIME=y CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_LOAD_STORE_LR=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_RIXI=y CONFIG_CPU_HAS_SYNC=y @@ -47,7 +46,6 @@ CONFIG_CPU_MIPSR2_IRQ_EI=y CONFIG_CPU_MIPSR2_IRQ_VI=y CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y CONFIG_CPU_R4K_CACHE_TLB=y -CONFIG_CPU_R4K_FPU=y CONFIG_CPU_RMAP=y CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y CONFIG_CPU_SUPPORTS_HIGHMEM=y @@ -58,55 +56,69 @@ CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HASH_INFO=y CONFIG_CRYPTO_LZO=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y CONFIG_CRYPTO_NULL2=y CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y CONFIG_DEBUG_PINCTRL=y CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NONCOHERENT_CACHE_SYNC=y +# CONFIG_DMA_RALINK is not set +# CONFIG_DTB_GNUBEE1 is not set +# CONFIG_DTB_GNUBEE2 is not set CONFIG_DTB_RT_NONE=y CONFIG_DTC=y CONFIG_EARLY_PRINTK=y +CONFIG_EFI_EARLYCON=y CONFIG_FIXED_PHY=y +CONFIG_FONT_8x16=y +CONFIG_FONT_AUTOSELECT=y +CONFIG_FONT_SUPPORT=y +CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_CPU_AUTOPROBE=y -CONFIG_GENERIC_IO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_IRQ_CHIP=y CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y CONFIG_GENERIC_IRQ_IPI=y CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_GENERIC=y CONFIG_GPIO_MT7621=y # CONFIG_GPIO_RALINK is not set CONFIG_GPIO_SYSFS=y CONFIG_GPIO_WATCHDOG=y # CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set -# CONFIG_GRO_CELLS is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y -# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set -# CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_HAVE_ARCH_COMPILER_H=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_HAVE_ARCH_KGDB=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_HAVE_ARCH_TRACEHOOK=y -# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set -CONFIG_HAVE_CBPF_JIT=y -CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_ASM_MODVERSIONS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_HAVE_CONTEXT_TRACKING=y @@ -114,28 +126,31 @@ CONFIG_HAVE_COPY_THREAD_TLS=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_HAVE_DEBUG_STACKOVERFLOW=y -CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FAST_GUP=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_GENERIC_VDSO=y CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_KVM=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y CONFIG_HAVE_MEMBLOCK_NODE_MAP=y CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_HAVE_NET_DSA=y CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PCI=y CONFIG_HAVE_PERF_EVENTS=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HIGHMEM=y -CONFIG_HW_HAS_PCI=y +CONFIG_HZ=250 +CONFIG_HZ_250=y CONFIG_HZ_PERIODIC=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y @@ -147,16 +162,19 @@ CONFIG_IRQ_DOMAIN_HIERARCHY=y CONFIG_IRQ_FORCED_THREADING=y CONFIG_IRQ_MIPS_CPU=y CONFIG_IRQ_WORK=y +CONFIG_LED_TRIGGER_PHY=y CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y +CONFIG_MEMFD_CREATE=y +CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y CONFIG_MIPS=y CONFIG_MIPS_ASID_BITS=8 CONFIG_MIPS_ASID_SHIFT=0 -CONFIG_MIPS_CBPF_JIT=y CONFIG_MIPS_CLOCK_VSYSCALL=y CONFIG_MIPS_CM=y # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set @@ -165,29 +183,27 @@ CONFIG_MIPS_CM=y CONFIG_MIPS_CMDLINE_FROM_DTB=y CONFIG_MIPS_CPC=y CONFIG_MIPS_CPS=y -# CONFIG_MIPS_CPS_NS16550 is not set +# CONFIG_MIPS_CPS_NS16550_BOOL is not set CONFIG_MIPS_CPU_SCACHE=y # CONFIG_MIPS_ELF_APPENDED_DTB is not set CONFIG_MIPS_GIC=y -# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 -# CONFIG_MIPS_MACHINE is not set CONFIG_MIPS_MT=y CONFIG_MIPS_MT_FPAFF=y CONFIG_MIPS_MT_SMP=y # CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_NR_CPU_NR_MAP=4 CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y CONFIG_MIPS_RAW_APPENDED_DTB=y CONFIG_MIPS_SPRAM=y -# CONFIG_MIPS_VPE_LOADER is not set CONFIG_MODULES_USE_ELF_REL=y CONFIG_MT7621_WDT=y # CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_M25P80=y -CONFIG_MTD_NAND=y -CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NOR=y CONFIG_MTD_SPLIT_MINOR_FW=y CONFIG_MTD_SPLIT_SEAMA_FW=y @@ -200,38 +216,38 @@ CONFIG_MTD_UBI_BLOCK=y # CONFIG_MTD_UBI_FASTMAP is not set # CONFIG_MTD_UBI_GLUEBI is not set CONFIG_MTD_UBI_WL_THRESHOLD=4096 -CONFIG_MTK_MTD_NAND=y +# CONFIG_MTK_HSDMA is not set CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_MEDIATEK_GSW_MT7621=y -CONFIG_NET_MEDIATEK_MDIO=y -CONFIG_NET_MEDIATEK_MDIO_MT7620=y -CONFIG_NET_MEDIATEK_MT7621=y -CONFIG_NET_MEDIATEK_OFFLOAD=y CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_SWITCHDEV=y CONFIG_NET_VENDOR_MEDIATEK=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y -# CONFIG_NO_IOPORT_MAP is not set CONFIG_NR_CPUS=4 CONFIG_OF=y CONFIG_OF_ADDRESS=y -CONFIG_OF_ADDRESS_PCI=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y CONFIG_OF_MDIO=y CONFIG_OF_NET=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y CONFIG_PADATA=y CONFIG_PCI=y CONFIG_PCI_DISABLE_COMMON_QUIRKS=y CONFIG_PCI_DOMAINS=y -CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_DRIVERS_GENERIC=y +CONFIG_PCI_MT7621=y +CONFIG_PCI_MT7621_PHY=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y +CONFIG_PHYLINK=y # CONFIG_PHY_RALINK_USB is not set CONFIG_PINCTRL=y CONFIG_PINCTRL_RT2880=y @@ -247,8 +263,7 @@ CONFIG_RATIONAL=y CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_STALL_COMMON=y CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_RESET_CONTROLLER=y @@ -256,16 +271,16 @@ CONFIG_RFS_ACCEL=y CONFIG_RPS=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_BQ32K=y +# CONFIG_RTC_DRV_JZ4740 is not set CONFIG_RTC_DRV_PCF8563=y CONFIG_RTC_I2C_AND_SPI=y CONFIG_RTC_MC146818_LIB=y -# CONFIG_SCHED_INFO is not set CONFIG_SCHED_SMT=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SERIAL_8250_FSL is not set CONFIG_SERIAL_8250_NR_UARTS=3 CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_MCTRL_GPIO=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y CONFIG_SMP=y CONFIG_SMP_UP=y # CONFIG_SOC_MT7620 is not set @@ -275,11 +290,10 @@ CONFIG_SOC_MT7621=y # CONFIG_SOC_RT3883 is not set CONFIG_SPI=y CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y CONFIG_SPI_MT7621=y # CONFIG_SPI_RT2880 is not set CONFIG_SRCU=y -CONFIG_SWCONFIG=y -CONFIG_SWCONFIG_LEDS=y CONFIG_SWPHY=y CONFIG_SYNC_R4K=y CONFIG_SYSCTL_EXCEPTION_TRACE=y @@ -296,6 +310,7 @@ CONFIG_SYS_SUPPORTS_MIPS_CPS=y CONFIG_SYS_SUPPORTS_MULTITHREADING=y CONFIG_SYS_SUPPORTS_SCHED_SMT=y CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_TARGET_ISA_REV=2 CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TIMER_OF=y CONFIG_TIMER_PROBE=y @@ -305,6 +320,7 @@ CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_ADVANCED_COMPR=y CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_ZSTD is not set CONFIG_USB_SUPPORT=y CONFIG_USE_OF=y CONFIG_WATCHDOG_CORE=y From 783fc8e55354cc2f6a5891c2c5647a6179ddd86f Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:14:44 +0800 Subject: [PATCH 06/35] ramips: mt7621: replace gpio/eth nodes in mt7621.dtsi There's different gpio and ethernet drivers upstream for mt7621. Update these two nodes to match upstream dt bindings. Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621.dtsi | 138 +++++++++++++++++++--------- 1 file changed, 95 insertions(+), 43 deletions(-) diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index 849f1f0a09..28ee0902cc 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -1,5 +1,6 @@ #include #include +#include / { #address-cells = <1>; @@ -67,36 +68,15 @@ reg = <0x100 0x100>; }; - gpio@600 { - #address-cells = <1>; - #size-cells = <0>; - - compatible = "mtk,mt7621-gpio"; + gpio: gpio@600 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "mediatek,mt7621-gpio"; + gpio-controller; + interrupt-controller; reg = <0x600 0x100>; - interrupt-parent = <&gic>; interrupts = ; - - gpio0: bank@0 { - reg = <0>; - compatible = "mtk,mt7621-gpio-bank"; - gpio-controller; - #gpio-cells = <2>; - }; - - gpio1: bank@1 { - reg = <1>; - compatible = "mtk,mt7621-gpio-bank"; - gpio-controller; - #gpio-cells = <2>; - }; - - gpio2: bank@2 { - reg = <2>; - compatible = "mtk,mt7621-gpio-bank"; - gpio-controller; - #gpio-cells = <2>; - }; }; i2c: i2c@900 { @@ -443,12 +423,22 @@ 0x1e003800 0x800>; }; + ethsys: syscon@1e000000 { + compatible = "mediatek,mt7621-ethsys", + "syscon"; + reg = <0x1e000000 0x1000>; + #clock-cells = <1>; + }; + ethernet: ethernet@1e100000 { compatible = "mediatek,mt7621-eth"; reg = <0x1e100000 0x10000>; + clocks = <&sysclock>; + clock-names = "ethif"; + #address-cells = <1>; - #size-cells = <1>; + #size-cells = <0>; resets = <&rstctrl 6 &rstctrl 23>; reset-names = "fe", "eth"; @@ -456,26 +446,88 @@ interrupt-parent = <&gic>; interrupts = ; - mediatek,switch = <&gsw>; + mediatek,ethsys = <ðsys>; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "rgmii"; - phy1f: ethernet-phy@1f { - reg = <0x1f>; - phy-mode = "rgmii"; + fixed-link { + speed = <1000>; + full-duplex; + pause; }; }; - hnat: hnat@0 { - compatible = "mediatek,mt7623-hnat"; - reg = <0 0x10000>; - mtketh-ppd = "eth0"; - mtketh-lan = "eth0"; - mtketh-wan = "eth0"; - resets = <&rstctrl 0>; - reset-names = "mtketh"; + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + status = "disabled"; + phy-mode = "rgmii-rxid"; + }; + + mdio: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + switch0: switch@1f { + compatible = "mediatek,mt7621"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x1f>; + mediatek,mcm; + resets = <&rstctrl 2>; + reset-names = "mcm"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + + port@0 { + status = "disabled"; + reg = <0>; + label = "lan0"; + }; + + port@1 { + status = "disabled"; + reg = <1>; + label = "lan1"; + }; + + port@2 { + status = "disabled"; + reg = <2>; + label = "lan2"; + }; + + port@3 { + status = "disabled"; + reg = <3>; + label = "lan3"; + }; + + port@4 { + status = "disabled"; + reg = <4>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "rgmii"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; }; }; From 60f691dae4654a38430cf87abaff497429a28271 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 4 Mar 2020 05:22:24 +0800 Subject: [PATCH 07/35] ramips: mt7621: convert GPIO dts refs The upstream driver does not use &gpio0..2 banks notation anymore, so convert them to &gpio Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621_adslr_g7.dts | 4 +- .../ramips/dts/mt7621_afoundry_ew1200.dts | 6 +-- .../dts/mt7621_alfa-network_quad-e4g.dts | 38 +++++++++---------- .../ramips/dts/mt7621_asiarf_ap7621.dtsi | 6 +-- .../linux/ramips/dts/mt7621_asus_rt-ac57u.dts | 10 ++--- .../ramips/dts/mt7621_asus_rt-acx5p.dtsi | 10 ++--- .../ramips/dts/mt7621_buffalo_wsr-1166dhp.dts | 30 +++++++-------- .../ramips/dts/mt7621_buffalo_wsr-600dhp.dts | 30 +++++++-------- .../ramips/dts/mt7621_d-team_newifi-d2.dts | 20 +++++----- .../linux/ramips/dts/mt7621_d-team_pbr-m1.dts | 20 +++++----- .../ramips/dts/mt7621_dlink_dir-860l-b1.dts | 12 +++--- .../linux/ramips/dts/mt7621_edimax_ra21s.dts | 8 ++-- .../linux/ramips/dts/mt7621_edimax_rg21s.dts | 8 ++-- .../linux/ramips/dts/mt7621_edimax_rx21s.dtsi | 4 +- .../dts/mt7621_elecom_wrc-1167ghbk2-s.dts | 16 ++++---- .../ramips/dts/mt7621_elecom_wrc-gst.dtsi | 20 +++++----- .../ramips/dts/mt7621_firefly_firewrt.dts | 6 +-- .../ramips/dts/mt7621_gehua_ghl-r-001.dts | 6 +-- .../linux/ramips/dts/mt7621_gnubee_gb-pc1.dts | 10 ++--- .../linux/ramips/dts/mt7621_gnubee_gb-pc2.dts | 14 +++---- .../linux/ramips/dts/mt7621_hiwifi_hc5962.dts | 6 +-- .../ramips/dts/mt7621_iodata_wn-ax1167gr.dts | 12 +++--- .../ramips/dts/mt7621_iodata_wn-gx300gr.dts | 12 +++--- .../ramips/dts/mt7621_iodata_wn-xx-xr.dtsi | 10 ++--- .../ramips/dts/mt7621_iodata_wnpr2600g.dts | 14 +++---- .../linux/ramips/dts/mt7621_iptime_a6ns-m.dts | 12 +++--- .../linux/ramips/dts/mt7621_iptime_a8004t.dts | 10 ++--- .../ramips/dts/mt7621_jcg_jhr-ac876m.dts | 10 ++--- .../ramips/dts/mt7621_lenovo_newifi-d1.dts | 12 +++--- .../ramips/dts/mt7621_linksys_re6500.dts | 8 ++-- .../ramips/dts/mt7621_mikrotik_rb750gr3.dts | 12 +++--- .../ramips/dts/mt7621_mikrotik_rbm11g.dts | 16 ++++---- .../ramips/dts/mt7621_mikrotik_rbm33g.dts | 12 +++--- .../linux/ramips/dts/mt7621_mqmaker_witi.dts | 2 +- target/linux/ramips/dts/mt7621_mtc_wr1201.dts | 10 ++--- .../ramips/dts/mt7621_netgear_ex6150.dts | 24 ++++++------ .../ramips/dts/mt7621_netgear_r6700-v2.dts | 4 +- .../linux/ramips/dts/mt7621_netgear_r6800.dts | 4 +- .../dts/mt7621_netgear_sercomm_ayx.dtsi | 18 ++++----- .../dts/mt7621_netgear_sercomm_bzv.dtsi | 6 +-- .../dts/mt7621_netgear_sercomm_chj.dtsi | 14 +++---- .../linux/ramips/dts/mt7621_netis_wf2881.dts | 6 +-- .../linux/ramips/dts/mt7621_phicomm_k2p.dts | 8 ++-- .../linux/ramips/dts/mt7621_planex_vr500.dts | 4 +- .../dts/mt7621_samknows_whitebox-v8.dts | 8 ++-- .../dts/mt7621_storylink_sap-g3200u3.dts | 6 +-- .../dts/mt7621_telco-electronics_x1.dts | 22 +++++------ .../ramips/dts/mt7621_thunder_timecloud.dts | 8 ++-- .../ramips/dts/mt7621_totolink_a7000r.dts | 4 +- .../ramips/dts/mt7621_tplink_re350-v1.dts | 22 +++++------ .../ramips/dts/mt7621_tplink_re650-v1.dts | 22 +++++------ .../dts/mt7621_ubiquiti_edgerouterx-sfp.dts | 4 +- .../dts/mt7621_ubiquiti_edgerouterx.dtsi | 2 +- .../ramips/dts/mt7621_ubnt_unifi-nanohd.dts | 6 +-- .../ramips/dts/mt7621_unielec_u7621-06.dtsi | 12 +++--- .../linux/ramips/dts/mt7621_wevo_11acnas.dts | 2 +- .../ramips/dts/mt7621_wevo_w2914ns-v2.dts | 2 +- .../ramips/dts/mt7621_wevo_w2914ns-v2.dtsi | 4 +- .../ramips/dts/mt7621_xiaomi_mir3g-v2.dts | 6 +-- .../linux/ramips/dts/mt7621_xiaomi_mir3g.dts | 16 ++++---- .../linux/ramips/dts/mt7621_xiaomi_mir3p.dts | 18 ++++----- .../linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts | 6 +-- .../dts/mt7621_xzwifi_creativebox-v1.dts | 18 ++++----- .../ramips/dts/mt7621_youhua_wr1200js.dts | 12 +++--- .../linux/ramips/dts/mt7621_youku_yk-l2.dts | 10 ++--- .../ramips/dts/mt7621_zbtlink_zbt-we1326.dts | 2 +- .../ramips/dts/mt7621_zbtlink_zbt-we3526.dts | 2 +- .../ramips/dts/mt7621_zbtlink_zbt-wg2626.dts | 4 +- .../ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi | 4 +- .../linux/ramips/dts/mt7621_zio_freezio.dts | 2 +- 70 files changed, 374 insertions(+), 374 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_adslr_g7.dts b/target/linux/ramips/dts/mt7621_adslr_g7.dts index 26e66f9a31..870b3834dd 100644 --- a/target/linux/ramips/dts/mt7621_adslr_g7.dts +++ b/target/linux/ramips/dts/mt7621_adslr_g7.dts @@ -27,7 +27,7 @@ led_sys: sys { label = "g7:blue:sys"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; }; }; @@ -36,7 +36,7 @@ reset { label = "reset"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; diff --git a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts index 8dab036b17..5c274a9664 100644 --- a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts +++ b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts @@ -31,7 +31,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -41,12 +41,12 @@ led_run: run { label = "ew1200:green:run"; - gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 5 GPIO_ACTIVE_HIGH>; }; usb { label = "ew1200:green:usb"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; diff --git a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts index 1066536ea6..95dc5c8d5b 100644 --- a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts +++ b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts @@ -29,61 +29,61 @@ m2-enable { gpio-export,name = "m2-enable"; gpio-export,output = <1>; - gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 32 GPIO_ACTIVE_HIGH>; }; minipcie0-enable { gpio-export,name = "minipcie0-enable"; gpio-export,output = <1>; - gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 29 GPIO_ACTIVE_HIGH>; }; minipcie0-reset { gpio-export,name = "minipcie0-reset"; gpio-export,output = <0>; - gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 23 GPIO_ACTIVE_HIGH>; }; minipcie1-enable { gpio-export,name = "minipcie1-enable"; gpio-export,output = <1>; - gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 30 GPIO_ACTIVE_HIGH>; }; minipcie1-reset { gpio-export,name = "minipcie1-reset"; gpio-export,output = <0>; - gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 24 GPIO_ACTIVE_HIGH>; }; minipcie2-enable { gpio-export,name = "minipcie2-enable"; gpio-export,output = <1>; - gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 31 GPIO_ACTIVE_HIGH>; }; minipcie2-reset { gpio-export,name = "minipcie2-reset"; gpio-export,output = <0>; - gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; }; pcie-perst-disable { gpio-export,name = "pcie-perst-enable"; gpio-export,output = <0>; - gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; }; sim-select { gpio-export,name = "sim-select"; gpio-export,output = <1>; - gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; }; watchdog-enable { gpio-export,name = "watchdog-enable"; gpio-export,output = <1>; - gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; }; }; @@ -92,19 +92,19 @@ reset { label = "reset"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; user1 { label = "user1"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,code = ; }; user2 { label = "user2"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -114,34 +114,34 @@ led_system: system { label = "quad-e4g:red:system"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; default-state = "keep"; }; m2 { label = "quad-e4g:orange:m2"; - gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; }; minipcie0 { label = "quad-e4g:orange:minipcie0"; - gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; minipcie1 { label = "quad-e4g:orange:minipcie1"; - gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; }; minipcie2 { label = "quad-e4g:orange:minipcie2"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; }; watchdog { compatible = "linux,wdt-gpio"; - gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; hw_algo = "toggle"; hw_margin_ms = <25000>; always-running; diff --git a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi index d4e5cfbf04..5c8084d8f0 100644 --- a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi +++ b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi @@ -15,7 +15,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -25,12 +25,12 @@ wlan1 { label = "ap7621-001:orange:wlan1"; - gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; }; wlan0 { label = "ap7621-001:orange:wlan0"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts index 0a315398ef..7c3524d450 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts @@ -26,12 +26,12 @@ led_power: power { label = "rt-ac57u:blue:power"; - gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 48 GPIO_ACTIVE_LOW>; }; usb { label = "rt-ac57u:blue:usb"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; trigger-sources = <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -42,14 +42,14 @@ wps { label = "wps"; - gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; linux,code = ; debounce-interval = <60>; }; reset { label = "reset"; - gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; linux,code = ; debounce-interval = <60>; }; @@ -58,7 +58,7 @@ led-regulator { compatible = "regulator-fixed"; regulator-name = "LED-Power"; - gpio = <&gpio1 14 GPIO_ACTIVE_LOW>; + gpio = <&gpio 46 GPIO_ACTIVE_LOW>; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi index 2de6d4c761..a34aed2df0 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi +++ b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi @@ -28,13 +28,13 @@ reset { label = "reset"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -44,17 +44,17 @@ led_power: power { label = "rt-ac85p:blue:power"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; }; wlan2g { label = "rt-ac85p:blue:wlan2g"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0radio"; }; wlan5g { label = "rt-ac85p:blue:wlan5g"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1radio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts index b67e430e5f..4ea2464219 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts @@ -25,42 +25,42 @@ internet_g { label = "wsr-1166:green:internet"; - gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; }; router_g { label = "wsr-1166:green:router"; - gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 42 GPIO_ACTIVE_LOW>; }; router_o { label = "wsr-1166:orange:router"; - gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 43 GPIO_ACTIVE_LOW>; }; internet_o { label = "wsr-1166:orange:internet"; - gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; }; wifi_o { label = "wsr-1166:orange:wifi"; - gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 45 GPIO_ACTIVE_LOW>; }; led_power: power { label = "wsr-1166:green:power"; - gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 46 GPIO_ACTIVE_LOW>; }; diag { label = "wsr-1166:orange:diag"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; }; wifi_g { label = "wsr-1166:green:wifi"; - gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 48 GPIO_ACTIVE_LOW>; }; }; @@ -69,39 +69,39 @@ power { label = "power"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; aoss { label = "aoss"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; linux,code = ; }; auto { label = "mode"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; ap { label = "ap"; - gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; router { label = "router"; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; @@ -109,7 +109,7 @@ gpio_poweroff { compatible = "gpio-poweroff"; - gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 0 GPIO_ACTIVE_LOW>; }; }; diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts index dadc26c12b..f0a79aed0b 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts @@ -25,42 +25,42 @@ led_power: power { label = "wsr-600:green:power"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; }; wifi_o { label = "wsr-600:orange:wifi"; - gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; }; diag { label = "wsr-600:orange:diag"; - gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 42 GPIO_ACTIVE_LOW>; }; wifi_g { label = "wsr-600:green:wifi"; - gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; }; router_o { label = "wsr-600:orange:router"; - gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 45 GPIO_ACTIVE_LOW>; }; router_g { label = "wsr-600:green:router"; - gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 46 GPIO_ACTIVE_LOW>; }; internet_o { label = "wsr-600:orange:internet"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; }; internet_g { label = "wsr-600:green:internet"; - gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 48 GPIO_ACTIVE_LOW>; }; }; @@ -69,39 +69,39 @@ power { label = "power"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; linux,code = ; }; aoss { label = "aoss"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; auto { label = "mode"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; ap { label = "ap"; - gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 6 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; router { label = "router"; - gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; linux,code = ; linux,input-type = ; }; @@ -109,7 +109,7 @@ gpio_poweroff { compatible = "gpio-poweroff"; - gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 43 GPIO_ACTIVE_LOW>; }; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts index f1b4d3d8ab..d0d1088b7b 100644 --- a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts +++ b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts @@ -26,37 +26,37 @@ power-amber { label = "newifi-d2:amber:power"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_power_blue: power-blue { label = "newifi-d2:blue:power"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; internet-amber { label = "newifi-d2:amber:internet"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; }; internet-blue { label = "newifi-d2:blue:internet"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; wlan2g { label = "newifi-d2:blue:wlan2g"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; wlan5g { label = "newifi-d2:blue:wlan5g"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; usb { label = "newifi-d2:blue:usb"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -67,13 +67,13 @@ reset { label = "reset"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -85,7 +85,7 @@ power_usb3 { gpio-export,name = "power_usb3"; gpio-export,output = <1>; - gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts index 59dd80fc62..e4662272a2 100644 --- a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts +++ b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts @@ -37,28 +37,28 @@ power { label = "pbr-m1:blue:power"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; default-state = "on"; }; led_sys: sys { label = "pbr-m1:blue:sys"; - gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; internet { label = "pbr-m1:blue:internet"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; }; wlan2g { label = "pbr-m1:blue:wlan2g"; - gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; }; wlan5g { label = "pbr-m1:blue:wlan5g"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; }; @@ -67,7 +67,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -79,25 +79,25 @@ power_usb2 { gpio-export,name = "power_usb2"; gpio-export,output = <1>; - gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; }; power_usb3 { gpio-export,name = "power_usb3"; gpio-export,output = <1>; - gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; }; power_sata { gpio-export,name = "power_sata"; gpio-export,output = <1>; - gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; }; }; beeper: beeper { compatible = "gpio-beeper"; - gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts index 65924bb2e6..f49bc0e114 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts @@ -26,22 +26,22 @@ power { label = "dir-860l-b1:orange:power"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led_power_green: power2 { label = "dir-860l-b1:green:power"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; net { label = "dir-860l-b1:orange:net"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; net2 { label = "dir-860l-b1:green:net"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; }; @@ -50,13 +50,13 @@ reset { label = "reset"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_edimax_ra21s.dts b/target/linux/ramips/dts/mt7621_edimax_ra21s.dts index ad0eee0d18..7f41bb14e9 100644 --- a/target/linux/ramips/dts/mt7621_edimax_ra21s.dts +++ b/target/linux/ramips/dts/mt7621_edimax_ra21s.dts @@ -19,22 +19,22 @@ led_power: led_1 { label = "ra21s:red:led1"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; }; led_2 { label = "ra21s:red:led2"; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; }; led_3 { label = "ra21s:red:led3"; - gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; }; led_4 { label = "ra21s:red:led4"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_edimax_rg21s.dts b/target/linux/ramips/dts/mt7621_edimax_rg21s.dts index 4325e98132..f00d0cf859 100644 --- a/target/linux/ramips/dts/mt7621_edimax_rg21s.dts +++ b/target/linux/ramips/dts/mt7621_edimax_rg21s.dts @@ -19,22 +19,22 @@ led_power: led_1 { label = "rg21s:red:led1"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; }; led_2 { label = "rg21s:red:led2"; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; }; led_3 { label = "rg21s:red:led3"; - gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; }; led_4 { label = "rg21s:red:led4"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi index 31498a5340..151f3934eb 100644 --- a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi +++ b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi @@ -20,13 +20,13 @@ reset { label = "reset"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts index c43f0ad198..2e7e9255f2 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts @@ -25,33 +25,33 @@ wlan2g { label = "wrc-1167ghbk2-s:white:wlan2g"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0radio"; }; wlan5g { label = "wrc-1167ghbk2-s:white:wlan5g"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; }; led_power_green: power_green { label = "wrc-1167ghbk2-s:green:power"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; }; power_blue { label = "wrc-1167ghbk2-s:blue:power"; - gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; }; wps { label = "wrc-1167ghbk2-s:red:wps"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; power_red { label = "wrc-1167ghbk2-s:red:power"; - gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; }; }; @@ -60,13 +60,13 @@ reset { label = "reset"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi index 0a4afd964f..b4acc3718e 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi @@ -22,22 +22,22 @@ led_power_green: power_green { label = "wrc-gst:green:power"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; }; power_blue { label = "wrc-gst:blue:power"; - gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; }; wps { label = "wrc-gst:red:wps"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; power_red { label = "wrc-gst:red:power"; - gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; }; }; @@ -46,40 +46,40 @@ reset { label = "reset"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; client { label = "client"; - gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; ap { label = "ap"; - gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 42 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; extender { label = "extender"; - gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 43 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; router { label = "router"; - gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 44 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; diff --git a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts index 1df3116d22..4f234db49c 100644 --- a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts +++ b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts @@ -25,7 +25,7 @@ led_power: power { label = "firewrt:green:power"; - gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; }; @@ -34,13 +34,13 @@ wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; power { label = "power"; - gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts index fea83e5e15..5ce4d61b57 100644 --- a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts +++ b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts @@ -19,12 +19,12 @@ internet { label = "ghl-r-001:blue:internet"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; usb { label = "ghl-r-001:blue:usb"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -35,7 +35,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts index 25ad9dc131..236737fb93 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts @@ -25,7 +25,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; linux,code = ; }; }; @@ -35,22 +35,22 @@ system { label = "gb-pc1:green:system"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_status: status { label = "gb-pc1:green:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; lan1 { label = "gb-pc1:green:lan1"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; lan2 { label = "gb-pc1:green:lan2"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts index 9920a1f0ba..a0fd6decd7 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts @@ -25,7 +25,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; linux,code = ; }; }; @@ -35,32 +35,32 @@ system { label = "gb-pc2:green:system"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_status: status { label = "gb-pc2:green:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; lan1 { label = "gb-pc2:green:lan1"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; lan2 { label = "gb-pc2:green:lan2"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; lan3-yellow { label = "gb-pc2:yellow:lan3"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; lan3-green { label = "gb-pc2:green:lan3"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts index f8d7268b92..baef38fe53 100644 --- a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts +++ b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts @@ -25,12 +25,12 @@ led_status: status { label = "hc5962:white:status"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_system: system { label = "hc5962:red:system"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; panic-indicator; }; }; @@ -40,7 +40,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts index d3bdc4acd8..213e706ccc 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts @@ -25,12 +25,12 @@ led_power: power { label = "wn-ax1167gr:green:power"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; }; wps { label = "wn-ax1167gr:green:wps"; - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; }; }; @@ -39,26 +39,26 @@ reset { label = "reset"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; auto { label = "auto"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; custom { label = "custom"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts index fa8c4aa653..66edebacf1 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts @@ -25,12 +25,12 @@ led_power: power { label = "wn-gx300gr:green:power"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; }; wps { label = "wn-gx300gr:green:wps"; - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; }; }; @@ -39,26 +39,26 @@ reset { label = "reset"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; auto { label = "auto"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; custom { label = "custom"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi index 8b3329113f..b582f32eea 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi +++ b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi @@ -22,12 +22,12 @@ wps { label = "iodata:green:wps"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; led_power: power { label = "iodata:green:power"; - gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 9 GPIO_ACTIVE_HIGH>; }; }; @@ -36,20 +36,20 @@ reset { label = "reset"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; linux,code = ; }; repeater { label = "repeater"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts index 7fa06b1844..b49bfd785a 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts @@ -26,24 +26,24 @@ led_power: power { label = "wnpr2600g:green:power"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; default-state = "on"; }; notification { label = "wnpr2600g:green:notification"; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; }; wlan2g { label = "wnpr2600g:green:wlan2g"; - gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 14 GPIO_ACTIVE_HIGH>; linux,default-trigger = "phy0radio"; }; wlan5g { label = "wnpr2600g:green:wlan5g"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; linux,default-trigger = "phy1radio"; }; }; @@ -53,20 +53,20 @@ auto { label = "auto"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; linux,code = ; linux,input-type = ; }; reset { label = "reset"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts index 92e2d9908c..ce0e60bef3 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts @@ -27,26 +27,26 @@ usb { label = "a6ns-m:blue:usb"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>; linux,default-trigger = "usbport"; }; wlan5g { label = "a6ns-m:blue:wlan5g"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0radio"; }; wlan2g { label = "a6ns-m:blue:wlan2g"; - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1radio"; }; led_cpu: cpu { label = "a6ns-m:blue:cpu"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; }; @@ -55,13 +55,13 @@ wps { label = "wps"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts index 81643e6f6a..e8a0888be6 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts @@ -26,18 +26,18 @@ led_cpu: cpu { label = "a8004t:orange:cpu"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; wlan2g { label = "a8004t:orange:wlan2g"; - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0radio"; }; wlan5g { label = "a8004t:orange:wlan5g"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1radio"; }; }; @@ -47,13 +47,13 @@ reset { label = "reset"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts index e3266ebbcb..efb42536bc 100644 --- a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts +++ b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts @@ -26,21 +26,21 @@ usb3 { label = "jhr-ac876m:blue:usb3"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>; linux,default-trigger = "usbport"; }; usb2 { label = "jhr-ac876m:blue:usb2"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; trigger-sources = <&ehci_port2>; linux,default-trigger = "usbport"; }; led_wps: wps { label = "jhr-ac876m:blue:wps"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; }; @@ -49,13 +49,13 @@ reset { label = "reset"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts index 0ff5f2e76d..3ede66344d 100644 --- a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts +++ b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts @@ -26,17 +26,17 @@ status-red { label = "newifi-d1:red:status"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; status-green { label = "newifi-d1:green:status"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led_blue: status-blue { label = "newifi-d1:blue:status"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; default-state = "on"; }; }; @@ -46,7 +46,7 @@ reset { label = "reset"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -58,13 +58,13 @@ usb2power { gpio-export,name = "usb2power"; gpio-export,output = <1>; - gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 9 GPIO_ACTIVE_HIGH>; }; usb3power { gpio-export,name = "usb3power"; gpio-export,output = <1>; - gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_re6500.dts b/target/linux/ramips/dts/mt7621_linksys_re6500.dts index 9c12f0ff80..e2c6b6e980 100644 --- a/target/linux/ramips/dts/mt7621_linksys_re6500.dts +++ b/target/linux/ramips/dts/mt7621_linksys_re6500.dts @@ -25,12 +25,12 @@ wifi { label = "re6500:orange:wifi"; - gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; }; led_power: power { label = "re6500:white:power"; - gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 9 GPIO_ACTIVE_HIGH>; }; }; @@ -39,13 +39,13 @@ wps { label = "wps"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts index da2b571dd4..ebb6585c91 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts @@ -26,13 +26,13 @@ pwr { label = "rb750gr3:blue:pwr"; - gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; default-state = "on"; }; led_usr: usr { label = "rb750gr3:green:usr"; - gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; }; }; @@ -41,20 +41,20 @@ mode { label = "mode"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; beeper { compatible = "gpio-beeper"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 15 GPIO_ACTIVE_HIGH>; }; gpio_export { @@ -64,7 +64,7 @@ usb_power { gpio-export,name = "usb_power"; gpio-export,output = <1>; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts index 60b6395c17..022e8faaab 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts @@ -25,32 +25,32 @@ led_usr: usr { label = "rbm11g:green:usr"; - gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; }; rssi0 { label = "rbm11g:green:rssi0"; - gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; rssi1 { label = "rbm11g:green:rssi1"; - gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; rssi2 { label = "rbm11g:green:rssi2"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; rssi3 { label = "rbm11g:green:rssi3"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; rssi4 { label = "rbm11g:green:rssi4"; - gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; }; @@ -59,7 +59,7 @@ res { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -70,7 +70,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 9 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; regulator-always-on; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts index 2500ae29da..90093c501c 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts @@ -25,7 +25,7 @@ led_usr: usr { label = "rbm33g:green:usr"; - gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; }; }; @@ -34,7 +34,7 @@ res { label = "res"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -45,7 +45,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio0 9 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 9 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; regulator-always-on; @@ -57,7 +57,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 10 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; regulator-always-on; @@ -69,7 +69,7 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 11 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-boot-on; regulator-always-on; @@ -81,7 +81,7 @@ regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 12 GPIO_ACTIVE_HIGH>; enable-active-high; regulator-always-on; }; diff --git a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts index d0ea445283..e801db22d6 100644 --- a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts +++ b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts @@ -30,7 +30,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts index 40180068e4..534f1a7f8f 100644 --- a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts +++ b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts @@ -26,24 +26,24 @@ led_power: power { label = "wr1201:green:power"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; usb { label = "wr1201:green:usb"; - gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; eth_link { label = "wr1201:green:eth_link"; - gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; wps { label = "wr1201:green:wps"; - gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; }; @@ -52,7 +52,7 @@ reset { label = "reset"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts index 0d6dac0ca2..7b9d4afa34 100644 --- a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts +++ b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts @@ -26,49 +26,49 @@ power_amber: power_amber { label = "ex6150:amber:power"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; power_green: power_green { label = "ex6150:green:power"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; wps { label = "ex6150:green:wps"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; rightarrow { label = "ex6150:blue:rightarrow"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; leftarrow { label = "ex6150:blue:leftarrow"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; }; router_green { label = "ex6150:green:router"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1tpt"; }; router_red { label = "ex6150:red:router"; - gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + gpios = <&gpio 30 GPIO_ACTIVE_LOW>; }; client_green { label = "ex6150:green:client"; - gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; client_red { label = "ex6150:red:client"; - gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; }; @@ -77,19 +77,19 @@ wps { label = "wps"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 46 GPIO_ACTIVE_LOW>; linux,code = ; }; toggle { label = "AP/Extender toggle"; - gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 48 GPIO_ACTIVE_LOW>; linux,code = ; /* Active when switch is set to "Access Point" */ }; diff --git a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts index 6a8cd6e4e4..a8a3f73cf2 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts @@ -103,12 +103,12 @@ }; wps { - gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; label = "r6700-v2:white:wps"; }; wlan { - gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + gpios = <&gpio 5 GPIO_ACTIVE_LOW>; label = "r6700-v2:white:wlan"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_r6800.dts b/target/linux/ramips/dts/mt7621_netgear_r6800.dts index fed7bbba38..90503340e2 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6800.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6800.dts @@ -105,12 +105,12 @@ }; wps { - gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; label = "r6800:white:wps"; }; wlan { - gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + gpios = <&gpio 5 GPIO_ACTIVE_LOW>; label = "r6800:white:wlan"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi index 116c412b06..af8774b4da 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi @@ -25,19 +25,19 @@ wps { label = "wps"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; wifi { label = "wifi"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -46,26 +46,26 @@ compatible = "gpio-leds"; led_power: power { - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; led_usb: usb { - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; led_internet: internet { - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led_wifi: wifi { - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; led_wps: wps { - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; }; }; @@ -74,7 +74,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 10 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi index 6538b6926e..12621d8b71 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi @@ -17,19 +17,19 @@ wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; rfkill { label = "rfkill"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi index 52af14723e..9d10acda7d 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi @@ -24,21 +24,21 @@ compatible = "gpio-leds"; led_power: power { - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; led_usb: usb { - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; led_internet: internet { - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; led_wifi: wifi { - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; }; @@ -48,13 +48,13 @@ wps { label = "wps"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -64,7 +64,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 10 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ramips/dts/mt7621_netis_wf2881.dts b/target/linux/ramips/dts/mt7621_netis_wf2881.dts index 63a4975dcf..d874c61886 100644 --- a/target/linux/ramips/dts/mt7621_netis_wf2881.dts +++ b/target/linux/ramips/dts/mt7621_netis_wf2881.dts @@ -26,14 +26,14 @@ usb { label = "wf2881:green:usb"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; led_wps: wps { label = "wf2881:green:wps"; - gpios = <&gpio0 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 0 GPIO_ACTIVE_LOW>; }; }; @@ -42,7 +42,7 @@ reset { label = "reset"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts index 9e9e2c0df4..3c43cbda51 100644 --- a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts +++ b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts @@ -25,17 +25,17 @@ stat_r { label = "k2p:red:status"; - gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 13 GPIO_ACTIVE_HIGH>; }; stat_y { label = "k2p:yellow:status"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; led_blue: stat_b { label = "k2p:blue:status"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; }; @@ -44,7 +44,7 @@ reset { label = "reset"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_planex_vr500.dts b/target/linux/ramips/dts/mt7621_planex_vr500.dts index 87c638429f..b34f651437 100644 --- a/target/linux/ramips/dts/mt7621_planex_vr500.dts +++ b/target/linux/ramips/dts/mt7621_planex_vr500.dts @@ -25,7 +25,7 @@ led_power: power { label = "vr500:green:power"; - gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 45 GPIO_ACTIVE_LOW>; }; }; @@ -34,7 +34,7 @@ reset { label = "reset"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts index 4b5fc7edfd..8d73847b50 100644 --- a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts +++ b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts @@ -24,12 +24,12 @@ led_wps: wps { label = "sk-wb8:green:wps"; - gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 46 GPIO_ACTIVE_LOW>; }; usb { label = "sk-wb8:green:usb"; - gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 47 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -40,13 +40,13 @@ wps { label = "wps"; - gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; + gpios = <&gpio 43 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + gpios = <&gpio 41 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts index 002804bbf1..d02b808603 100644 --- a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts +++ b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts @@ -18,7 +18,7 @@ usb { label = "sap-g3200u3:green:usb"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -29,13 +29,13 @@ reset { label = "reset"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; linux,code = ; }; rfkill { label = "rfkill"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts index 50df90b695..050c39b0cc 100644 --- a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts +++ b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts @@ -27,7 +27,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -37,47 +37,47 @@ system_led: system { label = "x1:green:system"; - gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + gpios = <&gpio 26 GPIO_ACTIVE_LOW>; }; modem_offline { label = "x1:red:modem-offline"; - gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 23 GPIO_ACTIVE_HIGH>; }; modem_4g { label = "x1:blue:modem-4g"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; modem_3g { label = "x1:green:modem-3g"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; }; modem_rssi_lowest { label = "x1:green:modem-rssi-lowest"; - gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; }; modem_rssi_low { label = "x1:green:modem-rssi-low"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; modem_rssi_medium { label = "x1:green:modem-rssi-medium"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; }; modem_rssi_high { label = "x1:green:modem-rssi-high"; - gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + gpios = <&gpio 30 GPIO_ACTIVE_LOW>; }; modem_rssi_highest { label = "x1:green:modem-rssi-highest"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; }; }; }; @@ -122,7 +122,7 @@ }; }; -&gpio0 { +&gpio { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts index e1f6835a81..11c3a9ba1c 100644 --- a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts +++ b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts @@ -25,12 +25,12 @@ statw { label = "timecloud:white:status"; - gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH>; }; led_statuso: stato { label = "timecloud:orange:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 8 GPIO_ACTIVE_HIGH>; }; }; @@ -39,13 +39,13 @@ reset { label = "reset"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; linux,code = ; }; BTN_0 { label = "BTN_0"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts index dd4336367a..c5aaedf2c6 100644 --- a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts +++ b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts @@ -26,7 +26,7 @@ led_sys: sys { label = "a7000r:blue:sys"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; }; }; @@ -35,7 +35,7 @@ reset { label = "reset"; - gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + gpios = <&gpio 4 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts index 76134925b1..0f2bf9d1e4 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts @@ -25,37 +25,37 @@ led_power: power { label = "re350-v1:blue:power"; - gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; wifi2g { label = "re350-v1:blue:wifi2G"; - gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; wifi5g { label = "re350-v1:blue:wifi5G"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; wps_r { label = "re350-v1:red:wps"; - gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; }; wps_b { label = "re350-v1:blue:wps"; - gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 26 GPIO_ACTIVE_HIGH>; }; eth { label = "re350-v1:green:eth_act"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; eth2 { label = "re350-v1:green:eth_link"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; }; }; @@ -64,25 +64,25 @@ led { label = "led"; - gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + gpios = <&gpio 30 GPIO_ACTIVE_LOW>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; linux,code = ; }; power { label = "power"; - gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 32 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts index 8122e11a31..b81c787efc 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts @@ -27,37 +27,37 @@ led_power: power { label = "re650-v1:blue:power"; - gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + gpios = <&gpio 22 GPIO_ACTIVE_LOW>; }; wifi2g { label = "re650-v1:blue:wifi2G"; - gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + gpios = <&gpio 23 GPIO_ACTIVE_LOW>; }; wifi5g { label = "re650-v1:blue:wifi5G"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; wps_red { label = "re650-v1:red:wps"; - gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 26 GPIO_ACTIVE_HIGH>; }; wps_blue { label = "re650-v1:blue:wps"; - gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; }; eth_act { label = "re650-v1:green:eth_act"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; }; eth_link { label = "re650-v1:green:eth_link"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; }; }; @@ -66,28 +66,28 @@ wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; power { label = "power"; - gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + gpios = <&gpio 25 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; led { label = "led"; - gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + gpios = <&gpio 30 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; reset { label = "reset"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; debounce-interval = <60>; linux,code = ; }; diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts index 4715cecb61..c6a64c0528 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts @@ -8,8 +8,8 @@ i2c-gpio { compatible = "i2c-gpio"; - gpios = <&gpio0 3 GPIO_ACTIVE_HIGH /* sda */ - &gpio0 4 GPIO_ACTIVE_HIGH /* scl */ + gpios = <&gpio 3 GPIO_ACTIVE_HIGH /* sda */ + &gpio 4 GPIO_ACTIVE_HIGH /* scl */ >; #address-cells = <1>; #size-cells = <0>; diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi index 540ef10e2a..df64a3456f 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi @@ -17,7 +17,7 @@ reset { label = "reset"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts index 903cbc6125..7c1ca609a7 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts @@ -28,12 +28,12 @@ led_blue: dome_blue { label = "nanohd:blue:dome"; - gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 3 GPIO_ACTIVE_HIGH>; }; led_white: dome_white { label = "nanohd:white:dome"; - gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 4 GPIO_ACTIVE_HIGH>; }; }; @@ -42,7 +42,7 @@ reset { label = "reset"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi index 209656232b..a9c85ed288 100644 --- a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi +++ b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi @@ -58,7 +58,7 @@ modem_reset { gpio-export,name = "modem_reset"; gpio-export,output = <1>; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; }; @@ -67,7 +67,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -77,22 +77,22 @@ led_status: status { label = "u7621-06:green:status"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; led4 { label = "u7621-06:green:led4"; - gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 11 GPIO_ACTIVE_HIGH>; }; led5 { label = "u7621-06:green:led5"; - gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 12 GPIO_ACTIVE_HIGH>; }; }; }; -&gpio0 { +&gpio { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_wevo_11acnas.dts b/target/linux/ramips/dts/mt7621_wevo_11acnas.dts index 0320a45060..9c04b5b117 100644 --- a/target/linux/ramips/dts/mt7621_wevo_11acnas.dts +++ b/target/linux/ramips/dts/mt7621_wevo_11acnas.dts @@ -11,7 +11,7 @@ usb { label = "11acnas:green:usb"; - gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; diff --git a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dts b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dts index bb9fa59484..65000c1ed4 100644 --- a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dts +++ b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dts @@ -11,7 +11,7 @@ usb { label = "w2914nsv2:green:usb"; - gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; diff --git a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi index 2cffb9520c..bba8932749 100644 --- a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi +++ b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi @@ -13,13 +13,13 @@ reset { label = "reset"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts index 6e06ed07e8..530717305a 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts @@ -26,12 +26,12 @@ led_status_blue: status_blue { label = "mir3gv2:blue:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; led_status_yellow: status_yellow { label = "mir3gv2:yellow:status"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; }; @@ -40,7 +40,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts index a09cbb6ee4..1730bc62ee 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts @@ -25,32 +25,32 @@ led_status_red: status_red { label = "mir3g:red:status"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_status_blue: status_blue { label = "mir3g:blue:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; led_status_yellow: status_yellow { label = "mir3g:yellow:status"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; wan_amber { label = "mir3g:amber:wan"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; lan1_amber { label = "mir3g:amber:lan1"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; lan2_amber { label = "mir3g:amber:lan2"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; }; @@ -59,7 +59,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -69,7 +69,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 12 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts index 0a566afffd..469674b9c6 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts @@ -26,37 +26,37 @@ led_status_red: status_red { label = "mir3p:red:status"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_status_blue: status_blue { label = "mir3p:blue:status"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; led_status_yellow: status_yellow { label = "mir3p:yellow:status"; - gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; wan_amber { label = "mir3p:amber:wan"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; lan3_amber { label = "mir3p:amber:lan3"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; }; lan2_amber { label = "mir3p:amber:lan2"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; }; lan1_amber { label = "mir3p:amber:lan1"; - gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; }; }; @@ -65,7 +65,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -75,7 +75,7 @@ regulator-name = "usb_vbus"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; - gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>; + gpio = <&gpio 12 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts index b544760967..d60aabccc1 100644 --- a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts +++ b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts @@ -26,12 +26,12 @@ work { label = "xy-c5:green:work"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; }; led_sys: sys { label = "xy-c5:green:sys"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; }; }; @@ -40,7 +40,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts index 0792b7fb90..ae1b20cdcb 100644 --- a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts +++ b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts @@ -26,29 +26,29 @@ power { label = "creativebox-v1:blue:power"; - gpios = <&gpio0 31 GPIO_ACTIVE_LOW>; + gpios = <&gpio 31 GPIO_ACTIVE_LOW>; default-state = "on"; }; led_sys: sys { label = "creativebox-v1:blue:sys"; - gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + gpios = <&gpio 32 GPIO_ACTIVE_LOW>; }; internet { label = "creativebox-v1:blue:internet"; - gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; + gpios = <&gpio 29 GPIO_ACTIVE_LOW>; }; wlan2g { label = "creativebox-v1:blue:wlan2g"; - gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + gpios = <&gpio 33 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy0tpt"; }; wlan5g { label = "creativebox-v1:blue:wlan5g"; - gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + gpios = <&gpio 28 GPIO_ACTIVE_LOW>; linux,default-trigger = "phy1tpt"; }; }; @@ -58,7 +58,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -70,19 +70,19 @@ power_usb2 { gpio-export,name = "power_usb2"; gpio-export,output = <1>; - gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; }; power_usb3 { gpio-export,name = "power_usb3"; gpio-export,output = <1>; - gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 25 GPIO_ACTIVE_HIGH>; }; power_sata { gpio-export,name = "power_sata"; gpio-export,output = <1>; - gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; + gpios = <&gpio 27 GPIO_ACTIVE_HIGH>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts index 1a759bf7c3..a0643307dc 100644 --- a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts +++ b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts @@ -23,17 +23,17 @@ internet { label = "wr1200js:blue:internet"; - gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; }; led_wps: wps { label = "wr1200js:blue:wps"; - gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; }; usb { label = "wr1200js:blue:usb"; - gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -44,19 +44,19 @@ reset { label = "reset"; - gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + gpios = <&gpio 3 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = ; }; wifi { label = "wifi"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts index 1673baabc1..5193a06278 100644 --- a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts +++ b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts @@ -26,18 +26,18 @@ led_power: power { label = "yk-l2:blue:power"; - gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; default-state = "on"; }; led_wps: wps { label = "yk-l2:blue:wps"; - gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; }; usb { label = "yk-l2:blue:usb"; - gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>, <&ehci_port2>; linux,default-trigger = "usbport"; }; @@ -48,13 +48,13 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; wps { label = "wps"; - gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts index 7bfb39212e..38b939b850 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts @@ -22,7 +22,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts index 15a4472cd8..224ea6377d 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts @@ -24,7 +24,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts index f3f06dd69b..5c22a5c7c0 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts @@ -31,7 +31,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -41,7 +41,7 @@ led_status: status { label = "zbt-wg2626:green:status"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi index 48de87269a..6a9e5e07d2 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi @@ -29,7 +29,7 @@ reset { label = "reset"; - gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + gpios = <&gpio 18 GPIO_ACTIVE_LOW>; linux,code = ; }; }; @@ -39,7 +39,7 @@ led_status: status { label = "zbt-wg3526:green:status"; - gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + gpios = <&gpio 24 GPIO_ACTIVE_LOW>; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_zio_freezio.dts b/target/linux/ramips/dts/mt7621_zio_freezio.dts index dce1c4bd4d..cf194f1ff5 100644 --- a/target/linux/ramips/dts/mt7621_zio_freezio.dts +++ b/target/linux/ramips/dts/mt7621_zio_freezio.dts @@ -12,7 +12,7 @@ usb { label = "freezio:green:usb"; - gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + gpios = <&gpio 27 GPIO_ACTIVE_LOW>; trigger-sources = <&xhci_ehci_port1>; linux,default-trigger = "usbport"; }; From 66984646c2d6f2e868657d3a83fa5038d5b94487 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Fri, 13 Mar 2020 21:27:03 +0800 Subject: [PATCH 08/35] ramips: mt7621: update pinctrl nodes Upstream GPIO driver uses "groups" "function" properties Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621.dtsi | 48 +++++++++---------- target/linux/ramips/dts/mt7621_adslr_g7.dts | 4 +- .../ramips/dts/mt7621_afoundry_ew1200.dts | 4 +- .../dts/mt7621_alfa-network_quad-e4g.dts | 4 +- .../ramips/dts/mt7621_asiarf_ap7621.dtsi | 4 +- .../linux/ramips/dts/mt7621_asus_rt-ac57u.dts | 4 +- .../ramips/dts/mt7621_asus_rt-acx5p.dtsi | 4 +- .../ramips/dts/mt7621_buffalo_wsr-1166dhp.dts | 4 +- .../ramips/dts/mt7621_buffalo_wsr-600dhp.dts | 4 +- .../ramips/dts/mt7621_d-team_newifi-d2.dts | 4 +- .../linux/ramips/dts/mt7621_d-team_pbr-m1.dts | 4 +- .../ramips/dts/mt7621_dlink_dir-860l-b1.dts | 4 +- .../linux/ramips/dts/mt7621_edimax_rx21s.dtsi | 4 +- .../dts/mt7621_elecom_wrc-1167ghbk2-s.dts | 4 +- .../ramips/dts/mt7621_elecom_wrc-gst.dtsi | 4 +- .../ramips/dts/mt7621_firefly_firewrt.dts | 4 +- .../ramips/dts/mt7621_gehua_ghl-r-001.dts | 4 +- .../linux/ramips/dts/mt7621_gnubee_gb-pc1.dts | 4 +- .../linux/ramips/dts/mt7621_gnubee_gb-pc2.dts | 4 +- .../linux/ramips/dts/mt7621_hiwifi_hc5962.dts | 4 +- .../ramips/dts/mt7621_iodata_wn-ax1167gr.dts | 4 +- .../ramips/dts/mt7621_iodata_wn-gx300gr.dts | 4 +- .../ramips/dts/mt7621_iodata_wn-xx-xr.dtsi | 4 +- .../ramips/dts/mt7621_iodata_wnpr2600g.dts | 4 +- .../linux/ramips/dts/mt7621_iptime_a6ns-m.dts | 4 +- .../linux/ramips/dts/mt7621_iptime_a8004t.dts | 4 +- .../ramips/dts/mt7621_jcg_jhr-ac876m.dts | 4 +- .../ramips/dts/mt7621_lenovo_newifi-d1.dts | 4 +- .../ramips/dts/mt7621_linksys_re6500.dts | 4 +- .../dts/mt7621_mediatek_ap-mt7621a-v60.dts | 8 ++-- .../dts/mt7621_mediatek_mt7621-eval-board.dts | 4 +- .../ramips/dts/mt7621_mikrotik_rb750gr3.dts | 4 +- .../ramips/dts/mt7621_mikrotik_rbm11g.dts | 4 +- .../ramips/dts/mt7621_mikrotik_rbm33g.dts | 4 +- .../linux/ramips/dts/mt7621_mqmaker_witi.dts | 4 +- target/linux/ramips/dts/mt7621_mtc_wr1201.dts | 4 +- .../ramips/dts/mt7621_netgear_ex6150.dts | 4 +- .../ramips/dts/mt7621_netgear_r6700-v2.dts | 4 +- .../linux/ramips/dts/mt7621_netgear_r6800.dts | 4 +- .../dts/mt7621_netgear_sercomm_ayx.dtsi | 4 +- .../dts/mt7621_netgear_sercomm_chj.dtsi | 4 +- .../linux/ramips/dts/mt7621_netis_wf2881.dts | 4 +- .../linux/ramips/dts/mt7621_phicomm_k2p.dts | 4 +- .../linux/ramips/dts/mt7621_planex_vr500.dts | 4 +- .../dts/mt7621_samknows_whitebox-v8.dts | 4 +- .../dts/mt7621_storylink_sap-g3200u3.dts | 4 +- .../dts/mt7621_telco-electronics_x1.dts | 4 +- .../ramips/dts/mt7621_thunder_timecloud.dts | 4 +- .../ramips/dts/mt7621_totolink_a7000r.dts | 4 +- .../ramips/dts/mt7621_tplink_re350-v1.dts | 4 +- .../ramips/dts/mt7621_tplink_re650-v1.dts | 4 +- .../dts/mt7621_ubiquiti_edgerouterx.dtsi | 4 +- .../ramips/dts/mt7621_ubnt_unifi-nanohd.dts | 4 +- .../ramips/dts/mt7621_unielec_u7621-06.dtsi | 4 +- .../ramips/dts/mt7621_wevo_w2914ns-v2.dtsi | 4 +- .../ramips/dts/mt7621_xiaomi_mir3g-v2.dts | 4 +- .../linux/ramips/dts/mt7621_xiaomi_mir3g.dts | 4 +- .../linux/ramips/dts/mt7621_xiaomi_mir3p.dts | 4 +- .../linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts | 4 +- .../dts/mt7621_xzwifi_creativebox-v1.dts | 4 +- .../ramips/dts/mt7621_youhua_wr1200js.dts | 4 +- .../linux/ramips/dts/mt7621_youku_yk-l2.dts | 4 +- .../ramips/dts/mt7621_zbtlink_zbt-we1326.dts | 4 +- .../ramips/dts/mt7621_zbtlink_zbt-we3526.dts | 4 +- .../ramips/dts/mt7621_zbtlink_zbt-wg2626.dts | 4 +- .../ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi | 4 +- 66 files changed, 156 insertions(+), 156 deletions(-) diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index 28ee0902cc..2db238f57f 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -258,83 +258,83 @@ i2c_pins: i2c_pins { i2c_pins { - ralink,group = "i2c"; - ralink,function = "i2c"; + groups = "i2c"; + function = "i2c"; }; }; spi_pins: spi_pins { spi_pins { - ralink,group = "spi"; - ralink,function = "spi"; + groups = "spi"; + function = "spi"; }; }; uart1_pins: uart1 { uart1 { - ralink,group = "uart1"; - ralink,function = "uart1"; + groups = "uart1"; + function = "uart1"; }; }; uart2_pins: uart2 { uart2 { - ralink,group = "uart2"; - ralink,function = "uart2"; + groups = "uart2"; + function = "uart2"; }; }; uart3_pins: uart3 { uart3 { - ralink,group = "uart3"; - ralink,function = "uart3"; + groups = "uart3"; + function = "uart3"; }; }; rgmii1_pins: rgmii1 { rgmii1 { - ralink,group = "rgmii1"; - ralink,function = "rgmii1"; + groups = "rgmii1"; + function = "rgmii1"; }; }; rgmii2_pins: rgmii2 { rgmii2 { - ralink,group = "rgmii2"; - ralink,function = "rgmii2"; + groups = "rgmii2"; + function = "rgmii2"; }; }; mdio_pins: mdio { mdio { - ralink,group = "mdio"; - ralink,function = "mdio"; + groups = "mdio"; + function = "mdio"; }; }; pcie_pins: pcie { pcie { - ralink,group = "pcie"; - ralink,function = "pcie rst"; + groups = "pcie"; + function = "pcie rst"; }; }; nand_pins: nand { spi-nand { - ralink,group = "spi"; - ralink,function = "nand1"; + groups = "spi"; + function = "nand1"; }; sdhci-nand { - ralink,group = "sdhci"; - ralink,function = "nand2"; + groups = "sdhci"; + function = "nand2"; }; }; sdhci_pins: sdhci { sdhci { - ralink,group = "sdhci"; - ralink,function = "sdhci"; + groups = "sdhci"; + function = "sdhci"; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_adslr_g7.dts b/target/linux/ramips/dts/mt7621_adslr_g7.dts index 870b3834dd..91a6ab26ab 100644 --- a/target/linux/ramips/dts/mt7621_adslr_g7.dts +++ b/target/linux/ramips/dts/mt7621_adslr_g7.dts @@ -111,7 +111,7 @@ &state_default { gpio { - ralink,group = "i2c", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts index 5c274a9664..877b8d7d9d 100644 --- a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts +++ b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts @@ -123,7 +123,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "mdio"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "mdio"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts index 95dc5c8d5b..266e765d7b 100644 --- a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts +++ b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts @@ -167,8 +167,8 @@ &state_default { gpio { - ralink,group = "jtag", "rgmii2", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "rgmii2", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi index 5c8084d8f0..a965cb4e63 100644 --- a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi +++ b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi @@ -110,7 +110,7 @@ &state_default { gpio { - ralink,group = "wdt", "jtag"; - ralink,function = "gpio"; + groups = "wdt", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts index 7c3524d450..ac1d88a6ce 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts @@ -140,7 +140,7 @@ &state_default { gpio { - ralink,group = "sdhci"; - ralink,function = "gpio"; + groups = "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi index a34aed2df0..c1ef3ce98c 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi +++ b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi @@ -149,7 +149,7 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "i2c"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "i2c"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts index 4ea2464219..8e0a1d8912 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts @@ -160,8 +160,8 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts index f0a79aed0b..ca060e7c0a 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts @@ -155,8 +155,8 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts index d0d1088b7b..85b8c5c2e0 100644 --- a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts +++ b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts @@ -155,7 +155,7 @@ &state_default { gpio { - ralink,group = "i2c", "jtag", "uart2", "uart3"; - ralink,function = "gpio"; + groups = "i2c", "jtag", "uart2", "uart3"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts index e4662272a2..73e6e32f42 100644 --- a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts +++ b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts @@ -170,7 +170,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "mdio"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "mdio"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts index f49bc0e114..f83c9a4afb 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts @@ -136,7 +136,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi index 151f3934eb..3cef0026b4 100644 --- a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi +++ b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi @@ -105,8 +105,8 @@ &state_default { gpio { - ralink,group = "uart3", "uart2", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "uart2", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts index 2e7e9255f2..c61ef885f2 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts @@ -130,8 +130,8 @@ &state_default { gpio { - ralink,group = "i2c", "uart3", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "uart3", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi index b4acc3718e..e120ee3ca4 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi @@ -156,8 +156,8 @@ &state_default { gpio { - ralink,group = "uart3", "jtag", "wdt", "sdhci"; - ralink,function = "gpio"; + groups = "uart3", "jtag", "wdt", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts index 4f234db49c..57318f3694 100644 --- a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts +++ b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts @@ -116,7 +116,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts index 5ce4d61b57..6e3eda5290 100644 --- a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts +++ b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts @@ -116,7 +116,7 @@ &state_default { gpio { - ralink,group = "jtag", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts index 236737fb93..8544e21528 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts @@ -110,7 +110,7 @@ &state_default { gpio { - ralink,group = "jtag", "rgmii2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "rgmii2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts index a0fd6decd7..0dae7b5ce7 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts @@ -120,7 +120,7 @@ &state_default { gpio { - ralink,group = "jtag", "rgmii2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "rgmii2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts index baef38fe53..d5fa290bcf 100644 --- a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts +++ b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts @@ -144,7 +144,7 @@ &state_default { gpio { - ralink,group = "uart3", "jtag"; - ralink,function = "gpio"; + groups = "uart3", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts index 213e706ccc..57c4638f16 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts @@ -135,8 +135,8 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "jtag"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts index 66edebacf1..ca08f1dabb 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts @@ -135,8 +135,8 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "jtag"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi index b582f32eea..c771eb20af 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi +++ b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi @@ -130,8 +130,8 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts index b49bfd785a..a208757c28 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts @@ -131,8 +131,8 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts index ce0e60bef3..7ff01b133a 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts @@ -110,8 +110,8 @@ &state_default { gpio { - ralink,group = "i2c", "uart3", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "uart3", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts index e8a0888be6..179a9cda4c 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts @@ -128,7 +128,7 @@ &state_default { gpio { - ralink,group = "wdt", "jtag", "i2c"; - ralink,function = "gpio"; + groups = "wdt", "jtag", "i2c"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts index efb42536bc..bdb9860291 100644 --- a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts +++ b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts @@ -138,7 +138,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart3", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "uart3", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts index 3ede66344d..7f7dc9c3ea 100644 --- a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts +++ b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts @@ -139,7 +139,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "uart2", "uart3", "i2c"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "uart2", "uart3", "i2c"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_re6500.dts b/target/linux/ramips/dts/mt7621_linksys_re6500.dts index e2c6b6e980..a97e64dbec 100644 --- a/target/linux/ramips/dts/mt7621_linksys_re6500.dts +++ b/target/linux/ramips/dts/mt7621_linksys_re6500.dts @@ -93,8 +93,8 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts b/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts index 09063e677f..4a225d81c4 100644 --- a/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts +++ b/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts @@ -38,16 +38,16 @@ &state_default { gpio { - ralink,group = "uart2", "rgmii2"; - ralink,function = "gpio"; + groups = "uart2", "rgmii2"; + function = "gpio"; }; }; &pinctrl { i2s_pins: i2s { i2s { - ralink,group = "uart3"; - ralink,function = "i2s"; + groups = "uart3"; + function = "i2s"; }; }; }; diff --git a/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts b/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts index 5a330a7428..93588b5d53 100644 --- a/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts +++ b/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts @@ -47,7 +47,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts index ebb6585c91..ebb35b9204 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts @@ -137,8 +137,8 @@ &state_default { gpio { /* via gpio7 (uart3 group) the PoE status can be read */ - ralink,group = "uart2", "uart3", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts index 022e8faaab..85ea796f97 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts @@ -145,8 +145,8 @@ &state_default { gpio { - ralink,group = "uart2", "wdt", "rgmii2"; - ralink,function = "gpio"; + groups = "uart2", "wdt", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts index 90093c501c..d65d1de05c 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts @@ -169,8 +169,8 @@ &state_default { gpio { - ralink,group = "uart2", "wdt"; - ralink,function = "gpio"; + groups = "uart2", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts index e801db22d6..f59cc57be3 100644 --- a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts +++ b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts @@ -107,7 +107,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "mdio"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "mdio"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts index 534f1a7f8f..6e1c6eabaa 100644 --- a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts +++ b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts @@ -144,7 +144,7 @@ &state_default { gpio { - ralink,group = "rgmii2"; - ralink,function = "gpio"; + groups = "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts index 7b9d4afa34..701f8274a4 100644 --- a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts +++ b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts @@ -234,7 +234,7 @@ &state_default { gpio { - ralink,group = "sdhci", "rgmii2", "jtag"; - ralink,function = "gpio"; + groups = "sdhci", "rgmii2", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts index a8a3f73cf2..07b696c42d 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts @@ -116,7 +116,7 @@ &state_default { gpio { - ralink,group = "uart3", "uart2", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "uart2", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_r6800.dts b/target/linux/ramips/dts/mt7621_netgear_r6800.dts index 90503340e2..a64c976a44 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6800.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6800.dts @@ -118,7 +118,7 @@ &state_default { gpio { - ralink,group = "uart3", "uart2", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "uart2", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi index af8774b4da..ba0853d3ca 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi @@ -111,7 +111,7 @@ &state_default { gpio { - ralink,group = "uart3", "uart2", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "uart2", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi index 9d10acda7d..c7dcfae870 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi @@ -101,8 +101,8 @@ &state_default { gpio { - ralink,group = "uart3", "uart2", "jtag", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "uart2", "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_netis_wf2881.dts b/target/linux/ramips/dts/mt7621_netis_wf2881.dts index d874c61886..11aa68d8f1 100644 --- a/target/linux/ramips/dts/mt7621_netis_wf2881.dts +++ b/target/linux/ramips/dts/mt7621_netis_wf2881.dts @@ -133,7 +133,7 @@ &state_default { gpio { - ralink,group = "uart3", "uart2"; - ralink,function = "gpio"; + groups = "uart3", "uart2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts index 3c43cbda51..104d10fdb3 100644 --- a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts +++ b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts @@ -113,7 +113,7 @@ &state_default { gpio { - ralink,group = "i2c", "jtag"; - ralink,function = "gpio"; + groups = "i2c", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_planex_vr500.dts b/target/linux/ramips/dts/mt7621_planex_vr500.dts index b34f651437..30257ffb5a 100644 --- a/target/linux/ramips/dts/mt7621_planex_vr500.dts +++ b/target/linux/ramips/dts/mt7621_planex_vr500.dts @@ -86,7 +86,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts index 8d73847b50..cf982d1a86 100644 --- a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts +++ b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts @@ -116,7 +116,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts index d02b808603..7a5b2a840c 100644 --- a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts +++ b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts @@ -113,7 +113,7 @@ &state_default { gpio { - ralink,group = "uart3", "jtag"; - ralink,function = "gpio"; + groups = "uart3", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts index 050c39b0cc..fa85cf1017 100644 --- a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts +++ b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts @@ -133,8 +133,8 @@ &state_default { gpio { - ralink,group = "jtag", "uart2", "wdt", "rgmii2"; - ralink,function = "gpio"; + groups = "jtag", "uart2", "wdt", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts index 11c3a9ba1c..195750a27d 100644 --- a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts +++ b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts @@ -101,7 +101,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "jtag"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts index c5aaedf2c6..db6edde74d 100644 --- a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts +++ b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts @@ -110,7 +110,7 @@ &state_default { gpio { - ralink,group = "i2c", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts index 0f2bf9d1e4..13faedd0ea 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts @@ -157,7 +157,7 @@ &state_default { gpio { - ralink,group = "rgmii2", "wdt"; - ralink,function = "gpio"; + groups = "rgmii2", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts index b81c787efc..265739bbda 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts @@ -170,7 +170,7 @@ &state_default { gpio { - ralink,group = "rgmii2", "wdt"; - ralink,function = "gpio"; + groups = "rgmii2", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi index df64a3456f..1efc930d49 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi @@ -71,8 +71,8 @@ &state_default { gpio { - ralink,group = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag"; - ralink,function = "gpio"; + groups = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts index 7c1ca609a7..9b3a5be444 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts @@ -135,7 +135,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2"; - ralink,function = "gpio"; + groups = "i2c", "uart2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi index a9c85ed288..c4116e8541 100644 --- a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi +++ b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi @@ -111,7 +111,7 @@ &state_default { gpio { - ralink,group = "jtag", "uart2", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "uart2", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi index bba8932749..d519961424 100644 --- a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi +++ b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi @@ -103,7 +103,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts index 530717305a..a8125d355e 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts @@ -139,7 +139,7 @@ &state_default { gpio { - ralink,group = "jtag", "uart2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "uart2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts index 1730bc62ee..a4ffb150b3 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts @@ -193,7 +193,7 @@ &state_default { gpio { - ralink,group = "jtag", "uart2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "uart2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts index 469674b9c6..45d7411bd0 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts @@ -178,7 +178,7 @@ &state_default { gpio { - ralink,group = "jtag", "uart2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "uart2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts index d60aabccc1..618c0ab565 100644 --- a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts +++ b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts @@ -96,7 +96,7 @@ &state_default { gpio { - ralink,group = "uart3", "wdt"; - ralink,function = "gpio"; + groups = "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts index ae1b20cdcb..ad8f7fdc91 100644 --- a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts +++ b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts @@ -158,7 +158,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts index a0643307dc..aa749ec6b8 100644 --- a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts +++ b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts @@ -132,7 +132,7 @@ &state_default { gpio { - ralink,group = "i2c", "uart2", "uart3", "wdt"; - ralink,function = "gpio"; + groups = "i2c", "uart2", "uart3", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts index 5193a06278..49fa312f58 100644 --- a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts +++ b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts @@ -143,7 +143,7 @@ &state_default { gpio { - ralink,group = "jtag", "wdt"; - ralink,function = "gpio"; + groups = "jtag", "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts index 38b939b850..6d765a2a61 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts @@ -30,8 +30,8 @@ &state_default { gpio { - ralink,group = "wdt"; - ralink,function = "gpio"; + groups = "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts index 224ea6377d..8088d5e8b4 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts @@ -105,7 +105,7 @@ &state_default { gpio { - ralink,group = "wdt"; - ralink,function = "gpio"; + groups = "wdt"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts index 5c22a5c7c0..fba959c8df 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts @@ -116,7 +116,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "mdio"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "mdio"; + function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi index 6a9e5e07d2..6977997633 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi @@ -118,7 +118,7 @@ &state_default { gpio { - ralink,group = "wdt", "rgmii2", "jtag", "mdio"; - ralink,function = "gpio"; + groups = "wdt", "rgmii2", "jtag", "mdio"; + function = "gpio"; }; }; From d21d6ea4547412632e01de505b7a2c8a83817a02 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 11 Mar 2020 21:05:41 +0800 Subject: [PATCH 09/35] ramips: mt7621: backport PCIe driver fixes from staging-test Backport mt7621-pci/mt7621-pci-phy fixes from staging-test Signed-off-by: DENG Qingfang --- ...ci-simplify-mt7621_pcie_init_virtual.patch | 133 +++++++++ ...1-pci-enable-clock-bit-for-each-port.patch | 74 +++++ ...621-pci-use-gpios-for-properly-reset.patch | 222 ++++++++++++++ ...-pci-change-value-for-PERST_DELAY_MS.patch | 45 +++ ...ci-release-gpios-after-pci-initializ.patch | 76 +++++ ...ci-delete-no-more-needed-mt7621_rese.patch | 46 +++ ...ci-phy-add-mt7621_phy_rmw-to-simplif.patch | 234 +++++++++++++++ ...ci-fix-io-space-and-properly-set-res.patch | 131 +++++++++ ...ci-fix-register-to-set-up-virtual-br.patch | 28 ++ ...1-pci-don-t-return-if-get-gpio-fails.patch | 34 +++ ...ci-phy-avoid-to-create-to-different-.patch | 272 ++++++++++++++++++ ...ci-use-only-two-phys-from-device-tre.patch | 42 +++ ...ci-change-variable-to-print-for-slot.patch | 26 ++ ...ci-be-sure-gpio-descriptor-is-null-o.patch | 33 +++ ...ci-avoid-to-poweroff-the-phy-for-slo.patch | 79 +++++ ...ci-delete-release-gpios-related-code.patch | 91 ++++++ ...7621-pci-use-builtin_platform_driver.patch | 29 ++ ...-pci-phy-use-builtin_platform_driver.patch | 32 +++ ...21-pci-phy-re-do-xtal_mode-detection.patch | 68 +++++ ...ci-avoid-to-set-iomem_resource-addre.patch | 35 +++ 20 files changed, 1730 insertions(+) create mode 100644 target/linux/ramips/patches-5.4/0100-staging-mt7621-pci-simplify-mt7621_pcie_init_virtual.patch create mode 100644 target/linux/ramips/patches-5.4/0101-staging-mt7621-pci-enable-clock-bit-for-each-port.patch create mode 100644 target/linux/ramips/patches-5.4/0102-staging-mt7621-pci-use-gpios-for-properly-reset.patch create mode 100644 target/linux/ramips/patches-5.4/0103-staging-mt7621-pci-change-value-for-PERST_DELAY_MS.patch create mode 100644 target/linux/ramips/patches-5.4/0104-staging-mt7621-pci-release-gpios-after-pci-initializ.patch create mode 100644 target/linux/ramips/patches-5.4/0105-staging-mt7621-pci-delete-no-more-needed-mt7621_rese.patch create mode 100644 target/linux/ramips/patches-5.4/0106-staging-mt7621-pci-phy-add-mt7621_phy_rmw-to-simplif.patch create mode 100644 target/linux/ramips/patches-5.4/0107-staging-mt7621-pci-fix-io-space-and-properly-set-res.patch create mode 100644 target/linux/ramips/patches-5.4/0108-staging-mt7621-pci-fix-register-to-set-up-virtual-br.patch create mode 100644 target/linux/ramips/patches-5.4/0109-staging-mt7621-pci-don-t-return-if-get-gpio-fails.patch create mode 100644 target/linux/ramips/patches-5.4/0110-staging-mt7621-pci-phy-avoid-to-create-to-different-.patch create mode 100644 target/linux/ramips/patches-5.4/0111-staging-mt7621-pci-use-only-two-phys-from-device-tre.patch create mode 100644 target/linux/ramips/patches-5.4/0112-staging-mt7621-pci-change-variable-to-print-for-slot.patch create mode 100644 target/linux/ramips/patches-5.4/0113-staging-mt7621-pci-be-sure-gpio-descriptor-is-null-o.patch create mode 100644 target/linux/ramips/patches-5.4/0114-staging-mt7621-pci-avoid-to-poweroff-the-phy-for-slo.patch create mode 100644 target/linux/ramips/patches-5.4/0115-staging-mt7621-pci-delete-release-gpios-related-code.patch create mode 100644 target/linux/ramips/patches-5.4/0116-staging-mt7621-pci-use-builtin_platform_driver.patch create mode 100644 target/linux/ramips/patches-5.4/0117-staging-mt7621-pci-phy-use-builtin_platform_driver.patch create mode 100644 target/linux/ramips/patches-5.4/0118-staging-mt7621-pci-phy-re-do-xtal_mode-detection.patch create mode 100644 target/linux/ramips/patches-5.4/0119-staging-mt7621-pci-avoid-to-set-iomem_resource-addre.patch diff --git a/target/linux/ramips/patches-5.4/0100-staging-mt7621-pci-simplify-mt7621_pcie_init_virtual.patch b/target/linux/ramips/patches-5.4/0100-staging-mt7621-pci-simplify-mt7621_pcie_init_virtual.patch new file mode 100644 index 0000000000..b9bcd63488 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0100-staging-mt7621-pci-simplify-mt7621_pcie_init_virtual.patch @@ -0,0 +1,133 @@ +From b327cd58c3fec1c6382128e929eab9bc0d68e912 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sun, 8 Mar 2020 10:19:27 +0100 +Subject: [PATCH] staging: mt7621-pci: simplify + 'mt7621_pcie_init_virtual_bridges' function + +Function 'mt7621_pcie_init_virtual_bridges' is a bit mess and can be +refactorized properly in a cleaner way. Introduce new 'pcie_rmw' inline +function helper to do clear and set the correct bits this function needs +to work. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200308091928.17177-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 85 +++++++++++++-------------------- + 1 file changed, 33 insertions(+), 52 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -57,13 +57,13 @@ + #define RALINK_PCI_IOBASE 0x002C + + /* PCICFG virtual bridges */ +-#define MT7621_BR0_MASK GENMASK(19, 16) +-#define MT7621_BR1_MASK GENMASK(23, 20) +-#define MT7621_BR2_MASK GENMASK(27, 24) +-#define MT7621_BR_ALL_MASK GENMASK(27, 16) +-#define MT7621_BR0_SHIFT 16 +-#define MT7621_BR1_SHIFT 20 +-#define MT7621_BR2_SHIFT 24 ++#define PCIE_P2P_MAX 3 ++#define PCIE_P2P_BR_DEVNUM_SHIFT(p) (16 + (p) * 4) ++#define PCIE_P2P_BR_DEVNUM0_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(0) ++#define PCIE_P2P_BR_DEVNUM1_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(1) ++#define PCIE_P2P_BR_DEVNUM2_SHIFT PCIE_P2P_BR_DEVNUM_SHIFT(2) ++#define PCIE_P2P_BR_DEVNUM_MASK 0xf ++#define PCIE_P2P_BR_DEVNUM_MASK_FULL (0xfff << PCIE_P2P_BR_DEVNUM0_SHIFT) + + /* PCIe RC control registers */ + #define MT7621_PCIE_OFFSET 0x2000 +@@ -154,6 +154,15 @@ static inline void pcie_write(struct mt7 + writel(val, pcie->base + reg); + } + ++static inline void pcie_rmw(struct mt7621_pcie *pcie, u32 reg, u32 clr, u32 set) ++{ ++ u32 val = readl(pcie->base + reg); ++ ++ val &= ~clr; ++ val |= set; ++ writel(val, pcie->base + reg); ++} ++ + static inline u32 pcie_port_read(struct mt7621_pcie_port *port, u32 reg) + { + return readl(port->base + reg); +@@ -554,7 +563,9 @@ static void mt7621_pcie_enable_ports(str + static int mt7621_pcie_init_virtual_bridges(struct mt7621_pcie *pcie) + { + u32 pcie_link_status = 0; +- u32 val = 0; ++ u32 n; ++ int i; ++ u32 p2p_br_devnum[PCIE_P2P_MAX]; + struct mt7621_pcie_port *port; + + list_for_each_entry(port, &pcie->ports, list) { +@@ -567,50 +578,20 @@ static int mt7621_pcie_init_virtual_brid + if (pcie_link_status == 0) + return -1; + +- /* +- * pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num +- * 3'b000 x x x +- * 3'b001 x x 0 +- * 3'b010 x 0 x +- * 3'b011 x 1 0 +- * 3'b100 0 x x +- * 3'b101 1 x 0 +- * 3'b110 1 0 x +- * 3'b111 2 1 0 +- */ +- switch (pcie_link_status) { +- case 2: +- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR); +- val &= ~(MT7621_BR0_MASK | MT7621_BR1_MASK); +- val |= 0x1 << MT7621_BR0_SHIFT; +- val |= 0x0 << MT7621_BR1_SHIFT; +- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR); +- break; +- case 4: +- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR); +- val &= ~MT7621_BR_ALL_MASK; +- val |= 0x1 << MT7621_BR0_SHIFT; +- val |= 0x2 << MT7621_BR1_SHIFT; +- val |= 0x0 << MT7621_BR2_SHIFT; +- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR); +- break; +- case 5: +- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR); +- val &= ~MT7621_BR_ALL_MASK; +- val |= 0x0 << MT7621_BR0_SHIFT; +- val |= 0x2 << MT7621_BR1_SHIFT; +- val |= 0x1 << MT7621_BR2_SHIFT; +- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR); +- break; +- case 6: +- val = pcie_read(pcie, RALINK_PCI_PCICFG_ADDR); +- val &= ~MT7621_BR_ALL_MASK; +- val |= 0x2 << MT7621_BR0_SHIFT; +- val |= 0x0 << MT7621_BR1_SHIFT; +- val |= 0x1 << MT7621_BR2_SHIFT; +- pcie_write(pcie, val, RALINK_PCI_PCICFG_ADDR); +- break; +- } ++ n = 0; ++ for (i = 0; i < PCIE_P2P_MAX; i++) ++ if (pcie_link_status & BIT(i)) ++ p2p_br_devnum[i] = n++; ++ ++ for (i = 0; i < PCIE_P2P_MAX; i++) ++ if ((pcie_link_status & BIT(i)) == 0) ++ p2p_br_devnum[i] = n++; ++ ++ pcie_rmw(pcie, RALINK_PCI_CONFIG_ADDR, ++ PCIE_P2P_BR_DEVNUM_MASK_FULL, ++ (p2p_br_devnum[0] << PCIE_P2P_BR_DEVNUM0_SHIFT) | ++ (p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) | ++ (p2p_br_devnum[2] << PCIE_P2P_BR_DEVNUM2_SHIFT)); + + return 0; + } diff --git a/target/linux/ramips/patches-5.4/0101-staging-mt7621-pci-enable-clock-bit-for-each-port.patch b/target/linux/ramips/patches-5.4/0101-staging-mt7621-pci-enable-clock-bit-for-each-port.patch new file mode 100644 index 0000000000..3939280a16 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0101-staging-mt7621-pci-enable-clock-bit-for-each-port.patch @@ -0,0 +1,74 @@ +From 550fabd71d7fcdfe099bbf41e00e28719737161e Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Tue, 10 Mar 2020 12:34:59 +0100 +Subject: [PATCH] staging: mt7621-pci: enable clock bit for each port + +The clock related code concerns me from the very beginning because +there are some set ups got from legacy driver that are not documented +anywhere. According to the programming guide 0x7c is 'CPE_ROSC_SEL1' +register and 0x80 is 'CPU_CPE_CN'. I do think this set up is not needed +at all and the proper thing to do is just enable the clock bit for each +pcie port. Hence remove useless code and do the right thing which is +setting up the clock bit for each port enabled. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200310113459.30539-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -45,8 +45,6 @@ + + /* rt_sysc_membase relative registers */ + #define RALINK_CLKCFG1 0x30 +-#define RALINK_PCIE_CLK_GEN 0x7c +-#define RALINK_PCIE_CLK_GEN1 0x80 + + /* Host-PCI bridge registers */ + #define RALINK_PCI_PCICFG_ADDR 0x0000 +@@ -85,10 +83,6 @@ + #define PCIE_PORT_CLK_EN(x) BIT(24 + (x)) + #define PCIE_PORT_LINKUP BIT(0) + +-#define PCIE_CLK_GEN_EN BIT(31) +-#define PCIE_CLK_GEN_DIS 0 +-#define PCIE_CLK_GEN1_DIS GENMASK(30, 24) +-#define PCIE_CLK_GEN1_EN (BIT(27) | BIT(25)) + #define MEMORY_BASE 0x0 + #define PERST_MODE_MASK GENMASK(11, 10) + #define PERST_MODE_GPIO BIT(10) +@@ -233,6 +227,11 @@ static inline bool mt7621_pcie_port_is_l + return (pcie_port_read(port, RALINK_PCI_STATUS) & PCIE_PORT_LINKUP) != 0; + } + ++static inline void mt7621_pcie_port_clk_enable(struct mt7621_pcie_port *port) ++{ ++ rt_sysc_m32(0, PCIE_PORT_CLK_EN(port->slot), RALINK_CLKCFG1); ++} ++ + static inline void mt7621_pcie_port_clk_disable(struct mt7621_pcie_port *port) + { + rt_sysc_m32(PCIE_PORT_CLK_EN(port->slot), 0, RALINK_CLKCFG1); +@@ -501,11 +500,6 @@ static void mt7621_pcie_init_ports(struc + } + } + +- rt_sysc_m32(0x30, 2 << 4, SYSC_REG_SYSTEM_CONFIG1); +- rt_sysc_m32(PCIE_CLK_GEN_EN, PCIE_CLK_GEN_DIS, RALINK_PCIE_CLK_GEN); +- rt_sysc_m32(PCIE_CLK_GEN1_DIS, PCIE_CLK_GEN1_EN, RALINK_PCIE_CLK_GEN1); +- rt_sysc_m32(PCIE_CLK_GEN_DIS, PCIE_CLK_GEN_EN, RALINK_PCIE_CLK_GEN); +- msleep(50); + reset_control_deassert(pcie->rst); + } + +@@ -542,6 +536,7 @@ static void mt7621_pcie_enable_ports(str + + list_for_each_entry(port, &pcie->ports, list) { + if (port->enabled) { ++ mt7621_pcie_port_clk_enable(port); + mt7621_pcie_enable_port(port); + dev_info(dev, "PCIE%d enabled\n", num_slots_enabled); + num_slots_enabled++; diff --git a/target/linux/ramips/patches-5.4/0102-staging-mt7621-pci-use-gpios-for-properly-reset.patch b/target/linux/ramips/patches-5.4/0102-staging-mt7621-pci-use-gpios-for-properly-reset.patch new file mode 100644 index 0000000000..1b7828f1e6 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0102-staging-mt7621-pci-use-gpios-for-properly-reset.patch @@ -0,0 +1,222 @@ +From 227a8bf421ff8b085444e51e471ef06a87228cfd Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 13 Mar 2020 21:09:08 +0100 +Subject: [PATCH] staging: mt7621-pci: use gpios for properly reset + +Original driver code was using three gpio's for reset +asserts and deasserts the pcis. Instead of using that +a general reset control with a perst gpio was introduced +and it seems it is partially working but sometimes there +are some unexpected hangs on boot. This commit make use of +the three original gpios using 'reset-gpios' property of +the device tree and removes the reset line and perst gpio. +According to the mediatek aplication note v0.1 there are +three gpios used for pcie ports reset control: gpio#19, +gpio#8 and gpio#7 for slots 0, 1 and 2 respectively. +This schema can be used separately for mt7621A but in some +boards due to pin share issue, if the PCM and I2S function +are enable at the same time, there are no enough GPIO to +control per-port PCIe reset. In those cases gpio#19 is enought +for reset the three ports together. Because of this we just +try to get the three gpios but if some of them fail we are not +failing in boot process, just prints a kernel notice and take +after into account if the descriptor is or not valid in order +to use it. All of them are set as GPIO output low configuration. +The gpio descriptor's API takes device tree property into account +and invert value if the pin is configured as active low. +So we also have to properly request pins from device tree +and set values correct in assert and deassert functions. +After this changes the order to make all assert and +deassert in the 'probe' process makes more sense: +* Parse device tree. +* make assert of the RC's and EP's before doing anything else. +* make deassert of the RC's before initializing the phy. +* Init the phy. +* make deassert of the EP's before initialize pci ports. +* Normal PCI initialization. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200313200913.24321-2-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 84 ++++++++++++++++++++------------- + 1 file changed, 51 insertions(+), 33 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -95,6 +95,7 @@ + * @pcie: pointer to PCIe host info + * @phy: pointer to PHY control block + * @pcie_rst: pointer to port reset control ++ * @gpio_rst: gpio reset + * @slot: port slot + * @enabled: indicates if port is enabled + */ +@@ -104,6 +105,7 @@ struct mt7621_pcie_port { + struct mt7621_pcie *pcie; + struct phy *phy; + struct reset_control *pcie_rst; ++ struct gpio_desc *gpio_rst; + u32 slot; + bool enabled; + }; +@@ -117,8 +119,6 @@ struct mt7621_pcie_port { + * @offset: IO / Memory offset + * @dev: Pointer to PCIe device + * @ports: pointer to PCIe port information +- * @perst: gpio reset +- * @rst: pointer to pcie reset + * @resets_inverted: depends on chip revision + * reset lines are inverted. + */ +@@ -133,8 +133,6 @@ struct mt7621_pcie { + resource_size_t io; + } offset; + struct list_head ports; +- struct gpio_desc *perst; +- struct reset_control *rst; + bool resets_inverted; + }; + +@@ -210,16 +208,16 @@ static void write_config(struct mt7621_p + pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); + } + +-static inline void mt7621_perst_gpio_pcie_assert(struct mt7621_pcie *pcie) ++static inline void mt7621_rst_gpio_pcie_assert(struct mt7621_pcie_port *port) + { +- gpiod_set_value(pcie->perst, 0); +- mdelay(PERST_DELAY_US); ++ if (port->gpio_rst) ++ gpiod_set_value(port->gpio_rst, 1); + } + +-static inline void mt7621_perst_gpio_pcie_deassert(struct mt7621_pcie *pcie) ++static inline void mt7621_rst_gpio_pcie_deassert(struct mt7621_pcie_port *port) + { +- gpiod_set_value(pcie->perst, 1); +- mdelay(PERST_DELAY_US); ++ if (port->gpio_rst) ++ gpiod_set_value(port->gpio_rst, 0); + } + + static inline bool mt7621_pcie_port_is_linkup(struct mt7621_pcie_port *port) +@@ -367,6 +365,13 @@ static int mt7621_pcie_parse_port(struct + if (IS_ERR(port->phy)) + return PTR_ERR(port->phy); + ++ port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, ++ GPIOD_OUT_LOW); ++ if (IS_ERR(port->gpio_rst)) { ++ dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot); ++ return PTR_ERR(port->gpio_rst); ++ } ++ + port->slot = slot; + port->pcie = pcie; + +@@ -383,12 +388,6 @@ static int mt7621_pcie_parse_dt(struct m + struct resource regs; + int err; + +- pcie->perst = devm_gpiod_get(dev, "perst", GPIOD_OUT_HIGH); +- if (IS_ERR(pcie->perst)) { +- dev_err(dev, "failed to get gpio perst\n"); +- return PTR_ERR(pcie->perst); +- } +- + err = of_address_to_resource(node, 0, ®s); + if (err) { + dev_err(dev, "missing \"reg\" property\n"); +@@ -399,12 +398,6 @@ static int mt7621_pcie_parse_dt(struct m + if (IS_ERR(pcie->base)) + return PTR_ERR(pcie->base); + +- pcie->rst = devm_reset_control_get_exclusive(dev, "pcie"); +- if (PTR_ERR(pcie->rst) == -EPROBE_DEFER) { +- dev_err(dev, "failed to get pcie reset control\n"); +- return PTR_ERR(pcie->rst); +- } +- + for_each_available_child_of_node(node, child) { + int slot; + +@@ -458,16 +451,49 @@ static int mt7621_pcie_init_port(struct + return 0; + } + ++static void mt7621_pcie_reset_assert(struct mt7621_pcie *pcie) ++{ ++ struct mt7621_pcie_port *port; ++ ++ list_for_each_entry(port, &pcie->ports, list) { ++ /* PCIe RC reset assert */ ++ mt7621_control_assert(port); ++ ++ /* PCIe EP reset assert */ ++ mt7621_rst_gpio_pcie_assert(port); ++ } ++ ++ mdelay(PERST_DELAY_US); ++} ++ ++static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) ++{ ++ struct mt7621_pcie_port *port; ++ ++ list_for_each_entry(port, &pcie->ports, list) ++ mt7621_control_deassert(port); ++} ++ ++static void mt7621_pcie_reset_ep_deassert(struct mt7621_pcie *pcie) ++{ ++ struct mt7621_pcie_port *port; ++ ++ list_for_each_entry(port, &pcie->ports, list) ++ mt7621_rst_gpio_pcie_deassert(port); ++ ++ mdelay(PERST_DELAY_US); ++} ++ + static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) + { + struct device *dev = pcie->dev; + struct mt7621_pcie_port *port, *tmp; +- u32 val = 0; + int err; + + rt_sysc_m32(PERST_MODE_MASK, PERST_MODE_GPIO, MT7621_GPIO_MODE); + +- mt7621_perst_gpio_pcie_assert(pcie); ++ mt7621_pcie_reset_assert(pcie); ++ mt7621_pcie_reset_rc_deassert(pcie); + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + u32 slot = port->slot; +@@ -476,16 +502,10 @@ static void mt7621_pcie_init_ports(struc + if (err) { + dev_err(dev, "Initiating port %d failed\n", slot); + list_del(&port->list); +- } else { +- val = read_config(pcie, slot, PCIE_FTS_NUM); +- dev_info(dev, "Port %d N_FTS = %x\n", slot, +- (unsigned int)val); + } + } + +- reset_control_assert(pcie->rst); +- +- mt7621_perst_gpio_pcie_deassert(pcie); ++ mt7621_pcie_reset_ep_deassert(pcie); + + list_for_each_entry(port, &pcie->ports, list) { + u32 slot = port->slot; +@@ -499,8 +519,6 @@ static void mt7621_pcie_init_ports(struc + port->enabled = false; + } + } +- +- reset_control_deassert(pcie->rst); + } + + static void mt7621_pcie_enable_port(struct mt7621_pcie_port *port) diff --git a/target/linux/ramips/patches-5.4/0103-staging-mt7621-pci-change-value-for-PERST_DELAY_MS.patch b/target/linux/ramips/patches-5.4/0103-staging-mt7621-pci-change-value-for-PERST_DELAY_MS.patch new file mode 100644 index 0000000000..3d86355b29 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0103-staging-mt7621-pci-change-value-for-PERST_DELAY_MS.patch @@ -0,0 +1,45 @@ +From e462e7d3211479df42357a620fa788a2257556b7 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 13 Mar 2020 21:09:09 +0100 +Subject: [PATCH] staging: mt7621-pci: change value for 'PERST_DELAY_MS' + +Value of 'PERST_DELAY_MS' is too high and it is ok just +to set up to 100 ms. Update also define name from +'PERST_DELAY_US' into 'PERST_DELAY_MS' + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200313200913.24321-3-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -86,7 +86,7 @@ + #define MEMORY_BASE 0x0 + #define PERST_MODE_MASK GENMASK(11, 10) + #define PERST_MODE_GPIO BIT(10) +-#define PERST_DELAY_US 1000 ++#define PERST_DELAY_MS 100 + + /** + * struct mt7621_pcie_port - PCIe port information +@@ -463,7 +463,7 @@ static void mt7621_pcie_reset_assert(str + mt7621_rst_gpio_pcie_assert(port); + } + +- mdelay(PERST_DELAY_US); ++ mdelay(PERST_DELAY_MS); + } + + static void mt7621_pcie_reset_rc_deassert(struct mt7621_pcie *pcie) +@@ -481,7 +481,7 @@ static void mt7621_pcie_reset_ep_deasser + list_for_each_entry(port, &pcie->ports, list) + mt7621_rst_gpio_pcie_deassert(port); + +- mdelay(PERST_DELAY_US); ++ mdelay(PERST_DELAY_MS); + } + + static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) diff --git a/target/linux/ramips/patches-5.4/0104-staging-mt7621-pci-release-gpios-after-pci-initializ.patch b/target/linux/ramips/patches-5.4/0104-staging-mt7621-pci-release-gpios-after-pci-initializ.patch new file mode 100644 index 0000000000..f24bf833c9 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0104-staging-mt7621-pci-release-gpios-after-pci-initializ.patch @@ -0,0 +1,76 @@ +From 4d6a758f2cd2122a7d895f913854c13da62ba6df Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 13 Mar 2020 21:09:12 +0100 +Subject: [PATCH] staging: mt7621-pci: release gpios after pci initialization + +R3G's LEDs fail to initialize because one of them uses GPIO8 +Hence, release the GPIO resources after PCIe initialization +and properly release also in driver error path. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200313200913.24321-6-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -484,6 +484,15 @@ static void mt7621_pcie_reset_ep_deasser + mdelay(PERST_DELAY_MS); + } + ++static void mt7621_pcie_release_gpios(struct mt7621_pcie *pcie) ++{ ++ struct mt7621_pcie_port *port; ++ ++ list_for_each_entry(port, &pcie->ports, list) ++ if (port->gpio_rst) ++ gpiod_put(port->gpio_rst); ++} ++ + static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) + { + struct device *dev = pcie->dev; +@@ -683,7 +692,8 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pcie_init_virtual_bridges(pcie); + if (err) { + dev_err(dev, "Nothing is connected in virtual bridges. Exiting..."); +- return 0; ++ err = 0; ++ goto out_release_gpios; + } + + mt7621_pcie_enable_ports(pcie); +@@ -691,7 +701,7 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pci_parse_request_of_pci_ranges(pcie); + if (err) { + dev_err(dev, "Error requesting pci resources from ranges"); +- return err; ++ goto out_release_gpios; + } + + setup_cm_memory_region(pcie); +@@ -699,16 +709,19 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pcie_request_resources(pcie, &res); + if (err) { + dev_err(dev, "Error requesting resources\n"); +- return err; ++ goto out_release_gpios; + } + + err = mt7621_pcie_register_host(bridge, &res); + if (err) { + dev_err(dev, "Error registering host\n"); +- return err; ++ goto out_release_gpios; + } + +- return 0; ++out_release_gpios: ++ mt7621_pcie_release_gpios(pcie); ++ ++ return err; + } + + static const struct of_device_id mt7621_pci_ids[] = { diff --git a/target/linux/ramips/patches-5.4/0105-staging-mt7621-pci-delete-no-more-needed-mt7621_rese.patch b/target/linux/ramips/patches-5.4/0105-staging-mt7621-pci-delete-no-more-needed-mt7621_rese.patch new file mode 100644 index 0000000000..fc509e945b --- /dev/null +++ b/target/linux/ramips/patches-5.4/0105-staging-mt7621-pci-delete-no-more-needed-mt7621_rese.patch @@ -0,0 +1,46 @@ +From 4be54c3a495f08c05a8e485566e5b88cd3537f16 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 13 Mar 2020 21:09:13 +0100 +Subject: [PATCH] staging: mt7621-pci: delete no more needed + 'mt7621_reset_port' + +After review all the resets at the beggining the function +'mt7621_reset_port' is not needed anymore. Hence delete it +and its uses. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200313200913.24321-7-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 13 ------------- + 1 file changed, 13 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -255,13 +255,6 @@ static inline void mt7621_control_deasse + reset_control_assert(port->pcie_rst); + } + +-static void mt7621_reset_port(struct mt7621_pcie_port *port) +-{ +- mt7621_control_assert(port); +- msleep(100); +- mt7621_control_deassert(port); +-} +- + static void setup_cm_memory_region(struct mt7621_pcie *pcie) + { + struct resource *mem_resource = &pcie->mem; +@@ -427,12 +420,6 @@ static int mt7621_pcie_init_port(struct + u32 slot = port->slot; + int err; + +- /* +- * Any MT7621 Ralink pcie controller that doesn't have 0x0101 at +- * the end of the chip_id has inverted PCI resets. +- */ +- mt7621_reset_port(port); +- + err = phy_init(port->phy); + if (err) { + dev_err(dev, "failed to initialize port%d phy\n", slot); diff --git a/target/linux/ramips/patches-5.4/0106-staging-mt7621-pci-phy-add-mt7621_phy_rmw-to-simplif.patch b/target/linux/ramips/patches-5.4/0106-staging-mt7621-pci-phy-add-mt7621_phy_rmw-to-simplif.patch new file mode 100644 index 0000000000..234af32308 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0106-staging-mt7621-pci-phy-add-mt7621_phy_rmw-to-simplif.patch @@ -0,0 +1,234 @@ +From bf0c6782e5b9a6deee4e223655325dc004fae8dd Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sun, 15 Mar 2020 17:01:54 +0100 +Subject: [PATCH] staging: mt7621-pci-phy: add 'mt7621_phy_rmw' to simplify + code + +In order to simplify driver code and decrease a bit LOC add new +function 'mt7621_phy_rmw' where clear and set bits are passed as +arguments. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200315160154.10292-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 158 +++++++++++------------- + 1 file changed, 71 insertions(+), 87 deletions(-) + +--- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c ++++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c +@@ -120,17 +120,25 @@ static inline void phy_write(struct mt76 + regmap_write(phy->regmap, reg, val); + } + ++static inline void mt7621_phy_rmw(struct mt7621_pci_phy *phy, ++ u32 reg, u32 clr, u32 set) ++{ ++ u32 val = phy_read(phy, reg); ++ ++ val &= ~clr; ++ val |= set; ++ phy_write(phy, val, reg); ++} ++ + static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy, + struct mt7621_pci_phy_instance *instance) + { + u32 offset = (instance->index != 1) ? + RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH; +- u32 reg; + +- reg = phy_read(phy, offset); +- reg &= ~(RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); +- reg |= (RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); +- phy_write(phy, reg, offset); ++ mt7621_phy_rmw(phy, offset, ++ RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC, ++ RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); + } + + static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy, +@@ -139,97 +147,77 @@ static void mt7621_set_phy_for_ssc(struc + struct device *dev = phy->dev; + u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); + u32 offset; +- u32 val; + + reg = (reg >> 6) & 0x7; + /* Set PCIe Port PHY to disable SSC */ + /* Debug Xtal Type */ +- val = phy_read(phy, RG_PE1_FRC_H_XTAL_REG); +- val &= ~(RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE); +- val |= RG_PE1_FRC_H_XTAL_TYPE; +- val |= RG_PE1_H_XTAL_TYPE_VAL(0x00); +- phy_write(phy, val, RG_PE1_FRC_H_XTAL_REG); ++ mt7621_phy_rmw(phy, RG_PE1_FRC_H_XTAL_REG, ++ RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE, ++ RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE_VAL(0x00)); + + /* disable port */ + offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; +- val = phy_read(phy, offset); +- val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); +- val |= RG_PE1_FRC_PHY_EN; +- phy_write(phy, val, offset); +- +- /* Set Pre-divider ratio (for host mode) */ +- val = phy_read(phy, RG_PE1_H_PLL_REG); +- val &= ~(RG_PE1_H_PLL_PREDIV); ++ mt7621_phy_rmw(phy, offset, ++ RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); + + if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ +- val |= RG_PE1_H_PLL_PREDIV_VAL(0x01); +- phy_write(phy, val, RG_PE1_H_PLL_REG); ++ /* Set Pre-divider ratio (for host mode) */ ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, ++ RG_PE1_H_PLL_PREDIV, ++ RG_PE1_H_PLL_PREDIV_VAL(0x01)); + dev_info(dev, "Xtal is 40MHz\n"); +- } else { /* 25MHz | 20MHz Xtal */ +- val |= RG_PE1_H_PLL_PREDIV_VAL(0x00); +- phy_write(phy, val, RG_PE1_H_PLL_REG); +- if (reg >= 6) { +- dev_info(dev, "Xtal is 25MHz\n"); +- +- /* Select feedback clock */ +- val = phy_read(phy, RG_PE1_H_PLL_FBKSEL_REG); +- val &= ~(RG_PE1_H_PLL_FBKSEL); +- val |= RG_PE1_H_PLL_FBKSEL_VAL(0x01); +- phy_write(phy, val, RG_PE1_H_PLL_FBKSEL_REG); +- +- /* DDS NCPO PCW (for host mode) */ +- val = phy_read(phy, RG_PE1_H_LCDDS_SSC_PRD_REG); +- val &= ~(RG_PE1_H_LCDDS_SSC_PRD); +- val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000); +- phy_write(phy, val, RG_PE1_H_LCDDS_SSC_PRD_REG); +- +- /* DDS SSC dither period control */ +- val = phy_read(phy, RG_PE1_H_LCDDS_SSC_PRD_REG); +- val &= ~(RG_PE1_H_LCDDS_SSC_PRD); +- val |= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d); +- phy_write(phy, val, RG_PE1_H_LCDDS_SSC_PRD_REG); +- +- /* DDS SSC dither amplitude control */ +- val = phy_read(phy, RG_PE1_H_LCDDS_SSC_DELTA_REG); +- val &= ~(RG_PE1_H_LCDDS_SSC_DELTA | +- RG_PE1_H_LCDDS_SSC_DELTA1); +- val |= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a); +- val |= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a); +- phy_write(phy, val, RG_PE1_H_LCDDS_SSC_DELTA_REG); +- } else { +- dev_info(dev, "Xtal is 20MHz\n"); +- } ++ } else if (reg >= 6) { /* 25MHz Xal */ ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, ++ RG_PE1_H_PLL_PREDIV, ++ RG_PE1_H_PLL_PREDIV_VAL(0x00)); ++ /* Select feedback clock */ ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_FBKSEL_REG, ++ RG_PE1_H_PLL_FBKSEL, ++ RG_PE1_H_PLL_FBKSEL_VAL(0x01)); ++ /* DDS NCPO PCW (for host mode) */ ++ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG, ++ RG_PE1_H_LCDDS_SSC_PRD, ++ RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000)); ++ /* DDS SSC dither period control */ ++ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_PRD_REG, ++ RG_PE1_H_LCDDS_SSC_PRD, ++ RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d)); ++ /* DDS SSC dither amplitude control */ ++ mt7621_phy_rmw(phy, RG_PE1_H_LCDDS_SSC_DELTA_REG, ++ RG_PE1_H_LCDDS_SSC_DELTA | ++ RG_PE1_H_LCDDS_SSC_DELTA1, ++ RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a) | ++ RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a)); ++ dev_info(dev, "Xtal is 25MHz\n"); ++ } else { /* 20MHz Xtal */ ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, ++ RG_PE1_H_PLL_PREDIV, ++ RG_PE1_H_PLL_PREDIV_VAL(0x00)); ++ ++ dev_info(dev, "Xtal is 20MHz\n"); + } + + /* DDS clock inversion */ +- val = phy_read(phy, RG_PE1_LCDDS_CLK_PH_INV_REG); +- val &= ~(RG_PE1_LCDDS_CLK_PH_INV); +- val |= RG_PE1_LCDDS_CLK_PH_INV; +- phy_write(phy, val, RG_PE1_LCDDS_CLK_PH_INV_REG); ++ mt7621_phy_rmw(phy, RG_PE1_LCDDS_CLK_PH_INV_REG, ++ RG_PE1_LCDDS_CLK_PH_INV, RG_PE1_LCDDS_CLK_PH_INV); + + /* Set PLL bits */ +- val = phy_read(phy, RG_PE1_H_PLL_REG); +- val &= ~(RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR | +- RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN); +- val |= RG_PE1_H_PLL_BC_VAL(0x02); +- val |= RG_PE1_H_PLL_BP_VAL(0x06); +- val |= RG_PE1_H_PLL_IR_VAL(0x02); +- val |= RG_PE1_H_PLL_IC_VAL(0x01); +- val |= RG_PE1_PLL_DIVEN_VAL(0x02); +- phy_write(phy, val, RG_PE1_H_PLL_REG); +- +- val = phy_read(phy, RG_PE1_H_PLL_BR_REG); +- val &= ~(RG_PE1_H_PLL_BR); +- val |= RG_PE1_H_PLL_BR_VAL(0x00); +- phy_write(phy, val, RG_PE1_H_PLL_BR_REG); ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, ++ RG_PE1_H_PLL_BC | RG_PE1_H_PLL_BP | RG_PE1_H_PLL_IR | ++ RG_PE1_H_PLL_IC | RG_PE1_PLL_DIVEN, ++ RG_PE1_H_PLL_BC_VAL(0x02) | RG_PE1_H_PLL_BP_VAL(0x06) | ++ RG_PE1_H_PLL_IR_VAL(0x02) | RG_PE1_H_PLL_IC_VAL(0x01) | ++ RG_PE1_PLL_DIVEN_VAL(0x02)); ++ ++ mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, ++ RG_PE1_H_PLL_BR, RG_PE1_H_PLL_BR_VAL(0x00)); + + if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ + /* set force mode enable of da_pe1_mstckdiv */ +- val = phy_read(phy, RG_PE1_MSTCKDIV_REG); +- val &= ~(RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV); +- val |= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV); +- phy_write(phy, val, RG_PE1_MSTCKDIV_REG); ++ mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG, ++ RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV, ++ RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV); + } + } + +@@ -252,13 +240,11 @@ static int mt7621_pci_phy_power_on(struc + struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); + u32 offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; +- u32 val; + + /* Enable PHY and disable force mode */ +- val = phy_read(mphy, offset); +- val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); +- val |= (RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); +- phy_write(mphy, val, offset); ++ mt7621_phy_rmw(mphy, offset, ++ RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, ++ RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); + + return 0; + } +@@ -269,13 +255,11 @@ static int mt7621_pci_phy_power_off(stru + struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); + u32 offset = (instance->index != 1) ? + RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; +- u32 val; + + /* Disable PHY */ +- val = phy_read(mphy, offset); +- val &= ~(RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); +- val |= RG_PE1_FRC_PHY_EN; +- phy_write(mphy, val, offset); ++ mt7621_phy_rmw(mphy, offset, ++ RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, ++ RG_PE1_FRC_PHY_EN); + + return 0; + } diff --git a/target/linux/ramips/patches-5.4/0107-staging-mt7621-pci-fix-io-space-and-properly-set-res.patch b/target/linux/ramips/patches-5.4/0107-staging-mt7621-pci-fix-io-space-and-properly-set-res.patch new file mode 100644 index 0000000000..393fd4d5dd --- /dev/null +++ b/target/linux/ramips/patches-5.4/0107-staging-mt7621-pci-fix-io-space-and-properly-set-res.patch @@ -0,0 +1,131 @@ +From 3faf4e1c537de86058fc22a851cd979489b9185e Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Wed, 18 Mar 2020 10:44:45 +0100 +Subject: [PATCH] staging: mt7621-pci: fix io space and properly set resource + limits + +Function 'mt7621_pci_parse_request_of_pci_ranges' is using +'of_pci_range_to_resource' to get both mem and io resources. +Internally this function calls to 'pci_address_to_pio' which +returns -1 if io space address is an address > IO_SPACE_LIMIT +which is 0xFFFF for mips. This mt7621 soc has io space in physical +address 0x1e160000. In order to fix this, overwrite invalid io +0xffffffff with properly values from the device tree and set +mapped address of this resource as io port base memory address +calling 'set_io_port_base' function. There is also need to properly +setup resource limits and io and memory windows with properly +parsed values instead of set them as 'no limit' which it is wrong. +For any reason I don't really know legacy driver sets up mem window +as 0xFFFFFFFF and any other value seems to does not work as expected, +so set up also here with same values. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200318094445.19669-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 43 +++++++++++++++++++-------------- + 1 file changed, 25 insertions(+), 18 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -118,6 +118,7 @@ struct mt7621_pcie_port { + * @busn: bus range + * @offset: IO / Memory offset + * @dev: Pointer to PCIe device ++ * @io_map_base: virtual memory base address for io + * @ports: pointer to PCIe port information + * @resets_inverted: depends on chip revision + * reset lines are inverted. +@@ -132,6 +133,7 @@ struct mt7621_pcie { + resource_size_t mem; + resource_size_t io; + } offset; ++ unsigned long io_map_base; + struct list_head ports; + bool resets_inverted; + }; +@@ -291,22 +293,21 @@ static int mt7621_pci_parse_request_of_p + } + + for_each_of_pci_range(&parser, &range) { +- struct resource *res = NULL; +- + switch (range.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: +- ioremap(range.cpu_addr, range.size); +- res = &pcie->io; ++ pcie->io_map_base = ++ (unsigned long)ioremap(range.cpu_addr, ++ range.size); ++ of_pci_range_to_resource(&range, node, &pcie->io); ++ pcie->io.start = range.cpu_addr; ++ pcie->io.end = range.cpu_addr + range.size - 1; + pcie->offset.io = 0x00000000UL; + break; + case IORESOURCE_MEM: +- res = &pcie->mem; ++ of_pci_range_to_resource(&range, node, &pcie->mem); + pcie->offset.mem = 0x00000000UL; + break; + } +- +- if (res) +- of_pci_range_to_resource(&range, node, res); + } + + err = of_pci_parse_bus_range(node, &pcie->busn); +@@ -318,6 +319,8 @@ static int mt7621_pci_parse_request_of_p + pcie->busn.flags = IORESOURCE_BUS; + } + ++ set_io_port_base(pcie->io_map_base); ++ + return 0; + } + +@@ -548,6 +551,10 @@ static void mt7621_pcie_enable_ports(str + u32 slot; + u32 val; + ++ /* Setup MEMWIN and IOWIN */ ++ pcie_write(pcie, 0xffffffff, RALINK_PCI_MEMBASE); ++ pcie_write(pcie, pcie->io.start, RALINK_PCI_IOBASE); ++ + list_for_each_entry(port, &pcie->ports, list) { + if (port->enabled) { + mt7621_pcie_port_clk_enable(port); +@@ -668,11 +675,17 @@ static int mt7621_pci_probe(struct platf + return err; + } + ++ err = mt7621_pci_parse_request_of_pci_ranges(pcie); ++ if (err) { ++ dev_err(dev, "Error requesting pci resources from ranges"); ++ goto out_release_gpios; ++ } ++ + /* set resources limits */ +- iomem_resource.start = 0; +- iomem_resource.end = ~0UL; /* no limit */ +- ioport_resource.start = 0; +- ioport_resource.end = ~0UL; /* no limit */ ++ iomem_resource.start = pcie->mem.start; ++ iomem_resource.end = pcie->mem.end; ++ ioport_resource.start = pcie->io.start; ++ ioport_resource.end = pcie->io.end; + + mt7621_pcie_init_ports(pcie); + +@@ -685,12 +698,6 @@ static int mt7621_pci_probe(struct platf + + mt7621_pcie_enable_ports(pcie); + +- err = mt7621_pci_parse_request_of_pci_ranges(pcie); +- if (err) { +- dev_err(dev, "Error requesting pci resources from ranges"); +- goto out_release_gpios; +- } +- + setup_cm_memory_region(pcie); + + err = mt7621_pcie_request_resources(pcie, &res); diff --git a/target/linux/ramips/patches-5.4/0108-staging-mt7621-pci-fix-register-to-set-up-virtual-br.patch b/target/linux/ramips/patches-5.4/0108-staging-mt7621-pci-fix-register-to-set-up-virtual-br.patch new file mode 100644 index 0000000000..5b4c461b2f --- /dev/null +++ b/target/linux/ramips/patches-5.4/0108-staging-mt7621-pci-fix-register-to-set-up-virtual-br.patch @@ -0,0 +1,28 @@ +From 0a3085ae142d8f5cf905b104bc66db3721a2fa33 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Thu, 19 Mar 2020 10:57:33 +0100 +Subject: [PATCH] staging: mt7621-pci: fix register to set up virtual bridges + +Instead of being using PCI Configuration and Status Register to +set up virtual bridges we are using CONFIG_ADDR Register which is +wrong. Hence, set the correct value. + +Fixes: 9a5e71a68d20 ("staging: mt7621-pci: simplify 'mt7621_pcie_init_virtual_bridges' function") +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200319095733.1557-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -603,7 +603,7 @@ static int mt7621_pcie_init_virtual_brid + if ((pcie_link_status & BIT(i)) == 0) + p2p_br_devnum[i] = n++; + +- pcie_rmw(pcie, RALINK_PCI_CONFIG_ADDR, ++ pcie_rmw(pcie, RALINK_PCI_PCICFG_ADDR, + PCIE_P2P_BR_DEVNUM_MASK_FULL, + (p2p_br_devnum[0] << PCIE_P2P_BR_DEVNUM0_SHIFT) | + (p2p_br_devnum[1] << PCIE_P2P_BR_DEVNUM1_SHIFT) | diff --git a/target/linux/ramips/patches-5.4/0109-staging-mt7621-pci-don-t-return-if-get-gpio-fails.patch b/target/linux/ramips/patches-5.4/0109-staging-mt7621-pci-don-t-return-if-get-gpio-fails.patch new file mode 100644 index 0000000000..55abb8999f --- /dev/null +++ b/target/linux/ramips/patches-5.4/0109-staging-mt7621-pci-don-t-return-if-get-gpio-fails.patch @@ -0,0 +1,34 @@ +From 23a788c23ed10e0d79092fcb693dcf0e357e1f7e Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Thu, 19 Mar 2020 17:14:16 +0100 +Subject: [PATCH] staging: mt7621-pci: don't return if get gpio fails + +In some platforms gpio's are not used for reset but +for other purposes. Because of that when we try to +get them are valid gpio's but are already assigned +to do other function. To avoid those kind of problems +in those platforms just notice the fail in the kernel +but continue doing normal boot. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200319161416.19033-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -363,10 +363,8 @@ static int mt7621_pcie_parse_port(struct + + port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, + GPIOD_OUT_LOW); +- if (IS_ERR(port->gpio_rst)) { +- dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot); +- return PTR_ERR(port->gpio_rst); +- } ++ if (IS_ERR(port->gpio_rst)) ++ dev_notice(dev, "Failed to get GPIO for PCIe%d\n", slot); + + port->slot = slot; + port->pcie = pcie; diff --git a/target/linux/ramips/patches-5.4/0110-staging-mt7621-pci-phy-avoid-to-create-to-different-.patch b/target/linux/ramips/patches-5.4/0110-staging-mt7621-pci-phy-avoid-to-create-to-different-.patch new file mode 100644 index 0000000000..6d84bfdd5b --- /dev/null +++ b/target/linux/ramips/patches-5.4/0110-staging-mt7621-pci-phy-avoid-to-create-to-different-.patch @@ -0,0 +1,272 @@ +From 91eb47531421f0e8c9bc4594b4a7caa0e59dc83e Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 20 Mar 2020 12:01:19 +0100 +Subject: [PATCH] staging: mt7621-pci-phy: avoid to create to different phys + for a dual port one + +This soc has two phy's for the pcie one of them using just a different +register for settig it up but sharing all the rest of the config. Until +now we was presenting this schema as three different phy's in the device +tree using the 'phy-cells' node property to discriminate an index and +setting up a complete phy for the dual port index. This sometimes worked +properly but reconfiguring the same registers twice presents sometimes +some unstable pcie links and the ports was not properly being detected. +The problems only appears on hard resets and soft resets was properly +working. Instead of having this schema just set two phy's in the device +ree and use the 'phy-cells' property to say if the port has or not a dual +port. Doing this configuration and set up becomes easier, LOC is decreased +and the behaviour also gets deterministic with properly and stable pcie +links in both hard and soft resets. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200320110123.9907-2-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 144 ++++++++++-------------- + 1 file changed, 59 insertions(+), 85 deletions(-) + +--- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c ++++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c +@@ -78,31 +78,21 @@ + #define MAX_PHYS 2 + + /** +- * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device +- * @phy: pointer to the kernel PHY device +- * @port_base: base register +- * @index: internal ID to identify the Mt7621 PCIe PHY +- */ +-struct mt7621_pci_phy_instance { +- struct phy *phy; +- void __iomem *port_base; +- u32 index; +-}; +- +-/** + * struct mt7621_pci_phy - Mt7621 Pcie PHY core + * @dev: pointer to device + * @regmap: kernel regmap pointer +- * @phys: pointer to Mt7621 PHY device +- * @nphys: number of PHY devices for this core ++ * @phy: pointer to the kernel PHY device ++ * @port_base: base register ++ * @has_dual_port: if the phy has dual ports. + * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst' + * needs to be executed. Depends on chip revision. + */ + struct mt7621_pci_phy { + struct device *dev; + struct regmap *regmap; +- struct mt7621_pci_phy_instance **phys; +- int nphys; ++ struct phy *phy; ++ void __iomem *port_base; ++ bool has_dual_port; + bool bypass_pipe_rst; + }; + +@@ -130,23 +120,23 @@ static inline void mt7621_phy_rmw(struct + phy_write(phy, val, reg); + } + +-static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy, +- struct mt7621_pci_phy_instance *instance) ++static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy *phy) + { +- u32 offset = (instance->index != 1) ? +- RG_PE1_PIPE_REG : RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH; ++ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_RST); ++ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG, 0, RG_PE1_PIPE_CMD_FRC); + +- mt7621_phy_rmw(phy, offset, +- RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC, +- RG_PE1_PIPE_RST | RG_PE1_PIPE_CMD_FRC); ++ if (phy->has_dual_port) { ++ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH, ++ 0, RG_PE1_PIPE_RST); ++ mt7621_phy_rmw(phy, RG_PE1_PIPE_REG + RG_P0_TO_P1_WIDTH, ++ 0, RG_PE1_PIPE_CMD_FRC); ++ } + } + +-static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy, +- struct mt7621_pci_phy_instance *instance) ++static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) + { + struct device *dev = phy->dev; + u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); +- u32 offset; + + reg = (reg >> 6) & 0x7; + /* Set PCIe Port PHY to disable SSC */ +@@ -156,10 +146,13 @@ static void mt7621_set_phy_for_ssc(struc + RG_PE1_FRC_H_XTAL_TYPE | RG_PE1_H_XTAL_TYPE_VAL(0x00)); + + /* disable port */ +- offset = (instance->index != 1) ? +- RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; +- mt7621_phy_rmw(phy, offset, +- RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); ++ mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG, ++ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); ++ ++ if (phy->has_dual_port) { ++ mt7621_phy_rmw(phy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH, ++ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); ++ } + + if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ + /* Set Pre-divider ratio (for host mode) */ +@@ -223,43 +216,44 @@ static void mt7621_set_phy_for_ssc(struc + + static int mt7621_pci_phy_init(struct phy *phy) + { +- struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); +- struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); ++ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy); + + if (mphy->bypass_pipe_rst) +- mt7621_bypass_pipe_rst(mphy, instance); ++ mt7621_bypass_pipe_rst(mphy); + +- mt7621_set_phy_for_ssc(mphy, instance); ++ mt7621_set_phy_for_ssc(mphy); + + return 0; + } + + static int mt7621_pci_phy_power_on(struct phy *phy) + { +- struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); +- struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); +- u32 offset = (instance->index != 1) ? +- RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; ++ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy); + + /* Enable PHY and disable force mode */ +- mt7621_phy_rmw(mphy, offset, +- RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, +- RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN); ++ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG, ++ RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN); ++ ++ if (mphy->has_dual_port) { ++ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH, ++ RG_PE1_FRC_PHY_EN, RG_PE1_PHY_EN); ++ } + + return 0; + } + + static int mt7621_pci_phy_power_off(struct phy *phy) + { +- struct mt7621_pci_phy_instance *instance = phy_get_drvdata(phy); +- struct mt7621_pci_phy *mphy = dev_get_drvdata(phy->dev.parent); +- u32 offset = (instance->index != 1) ? +- RG_PE1_FRC_PHY_REG : RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH; ++ struct mt7621_pci_phy *mphy = phy_get_drvdata(phy); + + /* Disable PHY */ +- mt7621_phy_rmw(mphy, offset, +- RG_PE1_FRC_PHY_EN | RG_PE1_PHY_EN, +- RG_PE1_FRC_PHY_EN); ++ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG, ++ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); ++ ++ if (mphy->has_dual_port) { ++ mt7621_phy_rmw(mphy, RG_PE1_FRC_PHY_REG + RG_P0_TO_P1_WIDTH, ++ RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); ++ } + + return 0; + } +@@ -282,13 +276,15 @@ static struct phy *mt7621_pcie_phy_of_xl + { + struct mt7621_pci_phy *mt7621_phy = dev_get_drvdata(dev); + +- if (args->args_count == 0) +- return mt7621_phy->phys[0]->phy; +- + if (WARN_ON(args->args[0] >= MAX_PHYS)) + return ERR_PTR(-ENODEV); + +- return mt7621_phy->phys[args->args[0]]->phy; ++ mt7621_phy->has_dual_port = args->args[0]; ++ ++ dev_info(dev, "PHY for 0x%08x (dual port = %d)\n", ++ (unsigned int)mt7621_phy->port_base, mt7621_phy->has_dual_port); ++ ++ return mt7621_phy->phy; + } + + static const struct soc_device_attribute mt7621_pci_quirks_match[] = { +@@ -309,19 +305,11 @@ static int mt7621_pci_phy_probe(struct p + struct phy_provider *provider; + struct mt7621_pci_phy *phy; + struct resource *res; +- int port; +- void __iomem *port_base; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + +- phy->nphys = MAX_PHYS; +- phy->phys = devm_kcalloc(dev, phy->nphys, +- sizeof(*phy->phys), GFP_KERNEL); +- if (!phy->phys) +- return -ENOMEM; +- + attr = soc_device_match(mt7621_pci_quirks_match); + if (attr) + phy->bypass_pipe_rst = true; +@@ -335,39 +323,25 @@ static int mt7621_pci_phy_probe(struct p + return -ENXIO; + } + +- port_base = devm_ioremap_resource(dev, res); +- if (IS_ERR(port_base)) { ++ phy->port_base = devm_ioremap_resource(dev, res); ++ if (IS_ERR(phy->port_base)) { + dev_err(dev, "failed to remap phy regs\n"); +- return PTR_ERR(port_base); ++ return PTR_ERR(phy->port_base); + } + +- phy->regmap = devm_regmap_init_mmio(phy->dev, port_base, ++ phy->regmap = devm_regmap_init_mmio(phy->dev, phy->port_base, + &mt7621_pci_phy_regmap_config); + if (IS_ERR(phy->regmap)) + return PTR_ERR(phy->regmap); + +- for (port = 0; port < MAX_PHYS; port++) { +- struct mt7621_pci_phy_instance *instance; +- struct phy *pphy; +- +- instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); +- if (!instance) +- return -ENOMEM; +- +- phy->phys[port] = instance; +- +- pphy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops); +- if (IS_ERR(phy)) { +- dev_err(dev, "failed to create phy\n"); +- return PTR_ERR(phy); +- } +- +- instance->port_base = port_base; +- instance->phy = pphy; +- instance->index = port; +- phy_set_drvdata(pphy, instance); ++ phy->phy = devm_phy_create(dev, dev->of_node, &mt7621_pci_phy_ops); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create phy\n"); ++ return PTR_ERR(phy); + } + ++ phy_set_drvdata(phy->phy, phy); ++ + provider = devm_of_phy_provider_register(dev, mt7621_pcie_phy_of_xlate); + + return PTR_ERR_OR_ZERO(provider); diff --git a/target/linux/ramips/patches-5.4/0111-staging-mt7621-pci-use-only-two-phys-from-device-tre.patch b/target/linux/ramips/patches-5.4/0111-staging-mt7621-pci-use-only-two-phys-from-device-tre.patch new file mode 100644 index 0000000000..61aa80eb76 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0111-staging-mt7621-pci-use-only-two-phys-from-device-tre.patch @@ -0,0 +1,42 @@ +From c752b54bda4d772426c5eeb56978d2e41bd525b4 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 20 Mar 2020 12:01:21 +0100 +Subject: [PATCH] staging: mt7621-pci: use only two phys from device tree + +In order to align work with the mt7621-pci-phy part of +the driver and device tree which is now using only two +real phys one of them dual ported properly parse the +device tree and don't call phy initialization for the +slot 1 because is being taking into account when the +phy for the slot 0 is instantiated. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200320110123.9907-4-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -358,7 +358,7 @@ static int mt7621_pcie_parse_port(struct + + snprintf(name, sizeof(name), "pcie-phy%d", slot); + port->phy = devm_phy_get(dev, name); +- if (IS_ERR(port->phy)) ++ if (IS_ERR(port->phy) && slot != 1) + return PTR_ERR(port->phy); + + port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, +@@ -495,6 +495,11 @@ static void mt7621_pcie_init_ports(struc + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + u32 slot = port->slot; + ++ if (slot == 1) { ++ port->enabled = true; ++ continue; ++ } ++ + err = mt7621_pcie_init_port(port); + if (err) { + dev_err(dev, "Initiating port %d failed\n", slot); diff --git a/target/linux/ramips/patches-5.4/0112-staging-mt7621-pci-change-variable-to-print-for-slot.patch b/target/linux/ramips/patches-5.4/0112-staging-mt7621-pci-change-variable-to-print-for-slot.patch new file mode 100644 index 0000000000..383c896a3e --- /dev/null +++ b/target/linux/ramips/patches-5.4/0112-staging-mt7621-pci-change-variable-to-print-for-slot.patch @@ -0,0 +1,26 @@ +From b59343b7de448c30e5b098484a7c7c5cb300df2f Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 20 Mar 2020 12:01:22 +0100 +Subject: [PATCH] staging: mt7621-pci: change variable to print for slot + +We are using the counter to print the slot which has been +enabled. Use the correct associated slot for the port instead. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200320110123.9907-5-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -562,7 +562,7 @@ static void mt7621_pcie_enable_ports(str + if (port->enabled) { + mt7621_pcie_port_clk_enable(port); + mt7621_pcie_enable_port(port); +- dev_info(dev, "PCIE%d enabled\n", num_slots_enabled); ++ dev_info(dev, "PCIE%d enabled\n", port->slot); + num_slots_enabled++; + } + } diff --git a/target/linux/ramips/patches-5.4/0113-staging-mt7621-pci-be-sure-gpio-descriptor-is-null-o.patch b/target/linux/ramips/patches-5.4/0113-staging-mt7621-pci-be-sure-gpio-descriptor-is-null-o.patch new file mode 100644 index 0000000000..bf6fdf1d49 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0113-staging-mt7621-pci-be-sure-gpio-descriptor-is-null-o.patch @@ -0,0 +1,33 @@ +From 87068309300c707d659ce79232eae827604804a4 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 20 Mar 2020 12:01:23 +0100 +Subject: [PATCH] staging: mt7621-pci: be sure gpio descriptor is null on fails + +Function 'devm_gpiod_get_index_optional' returns NULL if the +descriptor is invalid and the error associated for the error +pointer is ENOENT. Sometimes if the pin is just assigned the +error associated for the pointer might not be ENOENT but other. +In order to avoid weirds behaviours if this happen set descriptor +to NULL in the driver port structure. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200320110123.9907-6-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -363,8 +363,10 @@ static int mt7621_pcie_parse_port(struct + + port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, + GPIOD_OUT_LOW); +- if (IS_ERR(port->gpio_rst)) ++ if (IS_ERR(port->gpio_rst)) { + dev_notice(dev, "Failed to get GPIO for PCIe%d\n", slot); ++ port->gpio_rst = NULL; ++ } + + port->slot = slot; + port->pcie = pcie; diff --git a/target/linux/ramips/patches-5.4/0114-staging-mt7621-pci-avoid-to-poweroff-the-phy-for-slo.patch b/target/linux/ramips/patches-5.4/0114-staging-mt7621-pci-avoid-to-poweroff-the-phy-for-slo.patch new file mode 100644 index 0000000000..d733e58537 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0114-staging-mt7621-pci-avoid-to-poweroff-the-phy-for-slo.patch @@ -0,0 +1,79 @@ +From d81fe3c13aa6f4ab1ec318212d2007175e6d05aa Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Fri, 20 Mar 2020 16:38:37 +0100 +Subject: [PATCH] staging: mt7621-pci: avoid to poweroff the phy for slot one + +Phy for slot 0 and 1 is shared and handled properly in slot 0. +If there is only one port in use,(slot 0) we shall not call the +'phy_power_off' function with an invalid slot because kernel +will crash with an unaligned access fault like the following: + +mt7621-pci 1e140000.pcie: Error applying setting, reverse things back +mt7621-pci-phy 1e149000.pcie-phy: PHY for 0xbe149000 (dual port = 1) +mt7621-pci-phy 1e14a000.pcie-phy: PHY for 0xbe14a000 (dual port = 0) +mt7621-pci-phy 1e149000.pcie-phy: Xtal is 40MHz +mt7621-pci-phy 1e14a000.pcie-phy: Xtal is 40MHz +mt7621-pci 1e140000.pcie: pcie1 no card, disable it (RST & CLK) +Unhandled kernel unaligned access[#1]: +CPU: 3 PID: 111 Comm: kworker/3:2 Not tainted 5.6.0-rc3-00347-g825c6f470c62-dirty #9 +Workqueue: events deferred_probe_work_func +$ 0 : 00000000 00000001 5f60d043 8fe1ba80 +$ 4 : 0000010d 01eb9000 00000000 00000000 +$ 8 : 294b4c00 80940000 00000008 000000ce +$12 : 2e303030 00000000 00000000 65696370 +$16 : ffffffed 0000010d 8e373cd0 8214c1e0 +$20 : 00000000 82144c80 82144680 8214c250 +$24 : 00000018 803ef8f4 +$28 : 8e372000 8e373c60 8214c080 803940e8 +Hi : 00000125 +Lo : 122f2000 +epc : 807b3328 mutex_lock+0x8/0x44 +ra : 803940e8 phy_power_off+0x28/0xb0 +Status: 1100fc03 KERNEL EXL IE +Cause : 00800010 (ExcCode 04) +BadVA : 0000010d +PrId : 0001992f (MIPS 1004Kc) +Modules linked in: +Process kworker/3:2 (pid: 111, threadinfo=(ptrval), task=(ptrval), tls=00000000) +Stack : 8e373cd0 803fe4f4 8e372000 8e373c90 8214c080 804fde1c 8e373c98 808d62f4 + 8e373c78 00000000 8214c254 804fe648 1e160000 804f27b8 00000001 808d62f4 + 00000000 00000001 8214c228 808d62f4 80930000 809a0000 8fd47e10 808d63d4 + 808d62d4 8fd47e10 808d0000 808d0000 8e373cd0 8e373cd0 809e2a74 809db510 + 809db510 00000006 00000001 00000000 00000000 00000000 01000000 1e1440ff + ... +Call Trace: +[<807b3328>] mutex_lock+0x8/0x44 +[<803940e8>] phy_power_off+0x28/0xb0 +[<804fe648>] mt7621_pci_probe+0xc20/0xd18 +[<80402ab8>] platform_drv_probe+0x40/0x94 +[<80400a74>] really_probe+0x104/0x364 +[<803feb74>] bus_for_each_drv+0x84/0xdc +[<80400924>] __device_attach+0xdc/0x120 +[<803ffb5c>] bus_probe_device+0xa0/0xbc +[<80400124>] deferred_probe_work_func+0x7c/0xbc +[<800420e8>] process_one_work+0x230/0x450 +[<80042638>] worker_thread+0x330/0x5fc +[<80048eb0>] kthread+0x12c/0x134 +[<80007438>] ret_from_kernel_thread+0x14/0x1c +Code: 24050002 27bdfff8 8f830000 14a00005 00000000 00600825 e0810000 1020fffa + +Fixes: bf516f413f4e ("staging: mt7621-pci: use only two phys from device tree") +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200320153837.20415-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -517,7 +517,8 @@ static void mt7621_pcie_init_ports(struc + if (!mt7621_pcie_port_is_linkup(port)) { + dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", + slot); +- phy_power_off(port->phy); ++ if (slot != 1) ++ phy_power_off(port->phy); + mt7621_control_assert(port); + mt7621_pcie_port_clk_disable(port); + port->enabled = false; diff --git a/target/linux/ramips/patches-5.4/0115-staging-mt7621-pci-delete-release-gpios-related-code.patch b/target/linux/ramips/patches-5.4/0115-staging-mt7621-pci-delete-release-gpios-related-code.patch new file mode 100644 index 0000000000..5bfd205691 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0115-staging-mt7621-pci-delete-release-gpios-related-code.patch @@ -0,0 +1,91 @@ +From 9d789a7728c37e8730b6a9cca60cf155f18537ea Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sat, 21 Mar 2020 08:26:50 +0100 +Subject: [PATCH] staging: mt7621-pci: delete release gpios related code + +Making gpio8 and gpio9 vendor specific and putting them +into the specific dts file makes not needed to release +gpios anymore because we are not occupying those pins +in the first place if it is not necessary. When the +device tree is parsed we can also check and return for +the error because we rely in the fact that the related +device for the board is correct. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200321072650.7784-3-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 27 +++++++-------------------- + 1 file changed, 7 insertions(+), 20 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -364,8 +364,8 @@ static int mt7621_pcie_parse_port(struct + port->gpio_rst = devm_gpiod_get_index_optional(dev, "reset", slot, + GPIOD_OUT_LOW); + if (IS_ERR(port->gpio_rst)) { +- dev_notice(dev, "Failed to get GPIO for PCIe%d\n", slot); +- port->gpio_rst = NULL; ++ dev_err(dev, "Failed to get GPIO for PCIe%d\n", slot); ++ return PTR_ERR(port->gpio_rst); + } + + port->slot = slot; +@@ -474,15 +474,6 @@ static void mt7621_pcie_reset_ep_deasser + mdelay(PERST_DELAY_MS); + } + +-static void mt7621_pcie_release_gpios(struct mt7621_pcie *pcie) +-{ +- struct mt7621_pcie_port *port; +- +- list_for_each_entry(port, &pcie->ports, list) +- if (port->gpio_rst) +- gpiod_put(port->gpio_rst); +-} +- + static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie) + { + struct device *dev = pcie->dev; +@@ -684,7 +675,7 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pci_parse_request_of_pci_ranges(pcie); + if (err) { + dev_err(dev, "Error requesting pci resources from ranges"); +- goto out_release_gpios; ++ return err; + } + + /* set resources limits */ +@@ -698,8 +689,7 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pcie_init_virtual_bridges(pcie); + if (err) { + dev_err(dev, "Nothing is connected in virtual bridges. Exiting..."); +- err = 0; +- goto out_release_gpios; ++ return 0; + } + + mt7621_pcie_enable_ports(pcie); +@@ -709,19 +699,16 @@ static int mt7621_pci_probe(struct platf + err = mt7621_pcie_request_resources(pcie, &res); + if (err) { + dev_err(dev, "Error requesting resources\n"); +- goto out_release_gpios; ++ return err; + } + + err = mt7621_pcie_register_host(bridge, &res); + if (err) { + dev_err(dev, "Error registering host\n"); +- goto out_release_gpios; ++ return err; + } + +-out_release_gpios: +- mt7621_pcie_release_gpios(pcie); +- +- return err; ++ return 0; + } + + static const struct of_device_id mt7621_pci_ids[] = { diff --git a/target/linux/ramips/patches-5.4/0116-staging-mt7621-pci-use-builtin_platform_driver.patch b/target/linux/ramips/patches-5.4/0116-staging-mt7621-pci-use-builtin_platform_driver.patch new file mode 100644 index 0000000000..b333bb326b --- /dev/null +++ b/target/linux/ramips/patches-5.4/0116-staging-mt7621-pci-use-builtin_platform_driver.patch @@ -0,0 +1,29 @@ +From 60a15339ceab9fc2a6cdc85fd54b66b2c947ab4e Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sat, 21 Mar 2020 14:36:21 +0100 +Subject: [PATCH] staging: mt7621-pci: use builtin_platform_driver() + +Macro builtin_platform_driver can be used for builtin drivers +that don't do anything in driver init. So, use the macro +builtin_platform_driver and remove some boilerplate code. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200321133624.31388-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -725,9 +725,4 @@ static struct platform_driver mt7621_pci + }, + }; + +-static int __init mt7621_pci_init(void) +-{ +- return platform_driver_register(&mt7621_pci_driver); +-} +- +-module_init(mt7621_pci_init); ++builtin_platform_driver(mt7621_pci_driver); diff --git a/target/linux/ramips/patches-5.4/0117-staging-mt7621-pci-phy-use-builtin_platform_driver.patch b/target/linux/ramips/patches-5.4/0117-staging-mt7621-pci-phy-use-builtin_platform_driver.patch new file mode 100644 index 0000000000..e55def40f5 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0117-staging-mt7621-pci-phy-use-builtin_platform_driver.patch @@ -0,0 +1,32 @@ +From ffe3dee4081055b4f58bc50dd3f5c97de42cf126 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sat, 21 Mar 2020 14:36:23 +0100 +Subject: [PATCH] staging: mt7621-pci-phy: use builtin_platform_driver() + +Macro builtin_platform_driver can be used for builtin drivers +that don't do anything in driver init. So, use the macro +builtin_platform_driver and remove some boilerplate code. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200321133624.31388-3-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c ++++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c +@@ -361,12 +361,7 @@ static struct platform_driver mt7621_pci + }, + }; + +-static int __init mt7621_pci_phy_drv_init(void) +-{ +- return platform_driver_register(&mt7621_pci_phy_driver); +-} +- +-module_init(mt7621_pci_phy_drv_init); ++builtin_platform_driver(mt7621_pci_phy_driver); + + MODULE_AUTHOR("Sergio Paracuellos "); + MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver"); diff --git a/target/linux/ramips/patches-5.4/0118-staging-mt7621-pci-phy-re-do-xtal_mode-detection.patch b/target/linux/ramips/patches-5.4/0118-staging-mt7621-pci-phy-re-do-xtal_mode-detection.patch new file mode 100644 index 0000000000..9eb8345144 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0118-staging-mt7621-pci-phy-re-do-xtal_mode-detection.patch @@ -0,0 +1,68 @@ +From ff83e3023cb8fc3b5dfc12e0c91bf1eb9dc4c4c6 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sat, 21 Mar 2020 14:36:24 +0100 +Subject: [PATCH] staging: mt7621-pci-phy: re-do 'xtal_mode' detection + +Detection of the Xtal mode is using magic numbers that +can be avoided using properly some definitions and a more +accurate variable name from 'reg' into 'xtal_mode'. This +increase readability. + +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200321133624.31388-4-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c ++++ b/drivers/staging/mt7621-pci-phy/pci-mt7621-phy.c +@@ -75,6 +75,9 @@ + + #define RG_PE1_FRC_MSTCKDIV BIT(5) + ++#define XTAL_MODE_SEL_SHIFT 6 ++#define XTAL_MODE_SEL_MASK 0x7 ++ + #define MAX_PHYS 2 + + /** +@@ -136,9 +139,11 @@ static void mt7621_bypass_pipe_rst(struc + static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy *phy) + { + struct device *dev = phy->dev; +- u32 reg = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0); ++ u32 xtal_mode; ++ ++ xtal_mode = (rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0) ++ >> XTAL_MODE_SEL_SHIFT) & XTAL_MODE_SEL_MASK; + +- reg = (reg >> 6) & 0x7; + /* Set PCIe Port PHY to disable SSC */ + /* Debug Xtal Type */ + mt7621_phy_rmw(phy, RG_PE1_FRC_H_XTAL_REG, +@@ -154,13 +159,13 @@ static void mt7621_set_phy_for_ssc(struc + RG_PE1_PHY_EN, RG_PE1_FRC_PHY_EN); + } + +- if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ ++ if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */ + /* Set Pre-divider ratio (for host mode) */ + mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, + RG_PE1_H_PLL_PREDIV, + RG_PE1_H_PLL_PREDIV_VAL(0x01)); + dev_info(dev, "Xtal is 40MHz\n"); +- } else if (reg >= 6) { /* 25MHz Xal */ ++ } else if (xtal_mode >= 6) { /* 25MHz Xal */ + mt7621_phy_rmw(phy, RG_PE1_H_PLL_REG, + RG_PE1_H_PLL_PREDIV, + RG_PE1_H_PLL_PREDIV_VAL(0x00)); +@@ -206,7 +211,7 @@ static void mt7621_set_phy_for_ssc(struc + mt7621_phy_rmw(phy, RG_PE1_H_PLL_BR_REG, + RG_PE1_H_PLL_BR, RG_PE1_H_PLL_BR_VAL(0x00)); + +- if (reg <= 5 && reg >= 3) { /* 40MHz Xtal */ ++ if (xtal_mode <= 5 && xtal_mode >= 3) { /* 40MHz Xtal */ + /* set force mode enable of da_pe1_mstckdiv */ + mt7621_phy_rmw(phy, RG_PE1_MSTCKDIV_REG, + RG_PE1_MSTCKDIV | RG_PE1_FRC_MSTCKDIV, diff --git a/target/linux/ramips/patches-5.4/0119-staging-mt7621-pci-avoid-to-set-iomem_resource-addre.patch b/target/linux/ramips/patches-5.4/0119-staging-mt7621-pci-avoid-to-set-iomem_resource-addre.patch new file mode 100644 index 0000000000..9af46f4196 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0119-staging-mt7621-pci-avoid-to-set-iomem_resource-addre.patch @@ -0,0 +1,35 @@ +From 4f0f36b67564311a4ce4441510ef94848febbab2 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Sun, 22 Mar 2020 08:21:28 +0100 +Subject: [PATCH] staging: mt7621-pci: avoid to set 'iomem_resource' addresses + +Setting up kernel resource 'iomem_resource' for PCI with +addresses parsed from device tree gots into a conflict within +the usb xhci driver: + +xhci-mtk 1e1c0000.xhci: can't request region for resource [mem 0x1e1c0000-0x1e1c0fff] +xhci-mtk: probe of 1e1c0000.xhci failed with error -16 + +Don't assign it and maintain the default addresses for this +resource seems to fix the problem. Checking legacy driver it +is being only setting the 'ioport_resource'. + +Fixes: 09dd629eeabb ("staging: mt7621-pci: fix io space and properly set resource limits") +Signed-off-by: Sergio Paracuellos +Link: https://lore.kernel.org/r/20200322072128.4454-1-sergio.paracuellos@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -679,8 +679,6 @@ static int mt7621_pci_probe(struct platf + } + + /* set resources limits */ +- iomem_resource.start = pcie->mem.start; +- iomem_resource.end = pcie->mem.end; + ioport_resource.start = pcie->io.start; + ioport_resource.end = pcie->io.end; + From 9ebb85c372e525b08debe286d976a6376ca0dbbe Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 1 Apr 2020 23:14:33 +0800 Subject: [PATCH 10/35] ramips: mt7621: update PCIe node in dtsi Update PCIe node in dtsi to match the new driver Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621.dtsi | 43 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index 2db238f57f..cc387519e4 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -315,7 +315,7 @@ pcie_pins: pcie { pcie { groups = "pcie"; - function = "pcie rst"; + function = "gpio"; }; }; @@ -540,9 +540,10 @@ pcie: pcie@1e140000 { compatible = "mediatek,mt7621-pci"; - reg = <0x1e140000 0x100 - 0x1e142000 0x100>; - + reg = <0x1e140000 0x100 /* host-pci bridge registers */ + 0x1e142000 0x100 /* pcie port 0 RC control registers */ + 0x1e143000 0x100 /* pcie port 1 RC control registers */ + 0x1e144000 0x100>; /* pcie port 2 RC control registers */ #address-cells = <3>; #size-cells = <2>; @@ -557,10 +558,11 @@ 0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */ >; - interrupt-parent = <&gic>; - interrupts = ; + #interrupt-cells = <1>; + interrupt-map-mask = <0xF0000 0 0 1>; + interrupt-map = <0x10000 0 0 1 &gic GIC_SHARED 4 IRQ_TYPE_LEVEL_HIGH>, + <0x20000 0 0 1 &gic GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>, + <0x30000 0 0 1 &gic GIC_SHARED 25 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; @@ -568,32 +570,45 @@ reset-names = "pcie0", "pcie1", "pcie2"; clocks = <&clkctrl 24 &clkctrl 25 &clkctrl 26>; clock-names = "pcie0", "pcie1", "pcie2"; + phys = <&pcie0_phy 1>, <&pcie2_phy 0>; + phy-names = "pcie-phy0", "pcie-phy2"; + + reset-gpios = <&gpio 19 GPIO_ACTIVE_LOW>; pcie0: pcie@0,0 { reg = <0x0000 0 0 0 0>; - #address-cells = <3>; #size-cells = <2>; - ranges; + bus-range = <0x00 0xff>; }; pcie1: pcie@1,0 { reg = <0x0800 0 0 0 0>; - #address-cells = <3>; #size-cells = <2>; - ranges; + bus-range = <0x00 0xff>; }; pcie2: pcie@2,0 { reg = <0x1000 0 0 0 0>; - #address-cells = <3>; #size-cells = <2>; - ranges; + bus-range = <0x00 0xff>; }; }; + + pcie0_phy: pcie-phy@1e149000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1e149000 0x0700>; + #phy-cells = <1>; + }; + + pcie2_phy: pcie-phy@1e14a000 { + compatible = "mediatek,mt7621-pci-phy"; + reg = <0x1e14a000 0x0700>; + #phy-cells = <1>; + }; }; From 7bd19dbe99b18c5dfd85a004595df6061e8df8f6 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Tue, 17 Mar 2020 20:54:34 +0800 Subject: [PATCH 11/35] ramips: mt7621: backport GPIO driver fix Backport 2 patches from linux-next to fix mt7621 GPIO driver Signed-off-by: DENG Qingfang --- ...mio-introduce-BGPIOF_NO_SET_ON_INPUT.patch | 85 +++++++++++++++++++ ...7621-add-BGPIOF_NO_SET_ON_INPUT-flag.patch | 33 +++++++ 2 files changed, 118 insertions(+) create mode 100644 target/linux/ramips/patches-5.4/111-gpio-mmio-introduce-BGPIOF_NO_SET_ON_INPUT.patch create mode 100644 target/linux/ramips/patches-5.4/112-gpio-mt7621-add-BGPIOF_NO_SET_ON_INPUT-flag.patch diff --git a/target/linux/ramips/patches-5.4/111-gpio-mmio-introduce-BGPIOF_NO_SET_ON_INPUT.patch b/target/linux/ramips/patches-5.4/111-gpio-mmio-introduce-BGPIOF_NO_SET_ON_INPUT.patch new file mode 100644 index 0000000000..fdb89d0902 --- /dev/null +++ b/target/linux/ramips/patches-5.4/111-gpio-mmio-introduce-BGPIOF_NO_SET_ON_INPUT.patch @@ -0,0 +1,85 @@ +From 5d7b644aad721ecca20bd8976b38fb243fdc84f9 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Sun, 15 Mar 2020 20:13:37 +0800 +Subject: [PATCH] gpio: mmio: introduce BGPIOF_NO_SET_ON_INPUT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Some gpio controllers ignores pin value writing when that pin is +configured as input mode. As a result, bgpio_dir_out should set +pin to output before configuring pin values or gpio pin values +can't be set up properly. +Introduce two variants of bgpio_dir_out: bgpio_dir_out_val_first +and bgpio_dir_out_dir_first, and assign direction_output according +to a new flag: BGPIOF_NO_SET_ON_INPUT. + +Signed-off-by: Chuanhong Guo +Tested-by: René van Dorst +Reviewed-by: Sergio Paracuellos +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mmio.c | 23 +++++++++++++++++++---- + include/linux/gpio/driver.h | 1 + + 2 files changed, 20 insertions(+), 4 deletions(-) + +--- a/drivers/gpio/gpio-mmio.c ++++ b/drivers/gpio/gpio-mmio.c +@@ -381,12 +381,10 @@ static int bgpio_get_dir(struct gpio_chi + return 1; + } + +-static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) ++static void bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) + { + unsigned long flags; + +- gc->set(gc, gpio, val); +- + spin_lock_irqsave(&gc->bgpio_lock, flags); + + gc->bgpio_dir |= bgpio_line2mask(gc, gpio); +@@ -397,7 +395,21 @@ static int bgpio_dir_out(struct gpio_chi + gc->write_reg(gc->reg_dir_out, gc->bgpio_dir); + + spin_unlock_irqrestore(&gc->bgpio_lock, flags); ++} + ++static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio, ++ int val) ++{ ++ bgpio_dir_out(gc, gpio, val); ++ gc->set(gc, gpio, val); ++ return 0; ++} ++ ++static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio, ++ int val) ++{ ++ gc->set(gc, gpio, val); ++ bgpio_dir_out(gc, gpio, val); + return 0; + } + +@@ -530,7 +542,10 @@ static int bgpio_setup_direction(struct + if (dirout || dirin) { + gc->reg_dir_out = dirout; + gc->reg_dir_in = dirin; +- gc->direction_output = bgpio_dir_out; ++ if (flags & BGPIOF_NO_SET_ON_INPUT) ++ gc->direction_output = bgpio_dir_out_dir_first; ++ else ++ gc->direction_output = bgpio_dir_out_val_first; + gc->direction_input = bgpio_dir_in; + gc->get_direction = bgpio_get_dir; + } else { +--- a/include/linux/gpio/driver.h ++++ b/include/linux/gpio/driver.h +@@ -567,6 +567,7 @@ int bgpio_init(struct gpio_chip *gc, str + #define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3) + #define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ + #define BGPIOF_NO_OUTPUT BIT(5) /* only input */ ++#define BGPIOF_NO_SET_ON_INPUT BIT(6) + + int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq); diff --git a/target/linux/ramips/patches-5.4/112-gpio-mt7621-add-BGPIOF_NO_SET_ON_INPUT-flag.patch b/target/linux/ramips/patches-5.4/112-gpio-mt7621-add-BGPIOF_NO_SET_ON_INPUT-flag.patch new file mode 100644 index 0000000000..862f9adb47 --- /dev/null +++ b/target/linux/ramips/patches-5.4/112-gpio-mt7621-add-BGPIOF_NO_SET_ON_INPUT-flag.patch @@ -0,0 +1,33 @@ +From ad65f02fd73e9a700f1693a4513ae923ca07beb0 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Sun, 15 Mar 2020 20:13:38 +0800 +Subject: [PATCH] gpio: mt7621: add BGPIOF_NO_SET_ON_INPUT flag +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +DSET/DCLR registers only works on output pins. Add corresponding +BGPIOF_NO_SET_ON_INPUT flag to bgpio_init call to fix direction_out +behavior. + +Signed-off-by: Chuanhong Guo +Tested-by: René van Dorst +Reviewed-by: Sergio Paracuellos +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-mt7621.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpio/gpio-mt7621.c ++++ b/drivers/gpio/gpio-mt7621.c +@@ -227,8 +227,8 @@ mediatek_gpio_bank_probe(struct device * + ctrl = mtk->base + GPIO_REG_DCLR + (rg->bank * GPIO_BANK_STRIDE); + diro = mtk->base + GPIO_REG_CTRL + (rg->bank * GPIO_BANK_STRIDE); + +- ret = bgpio_init(&rg->chip, dev, 4, +- dat, set, ctrl, diro, NULL, 0); ++ ret = bgpio_init(&rg->chip, dev, 4, dat, set, ctrl, diro, NULL, ++ BGPIOF_NO_SET_ON_INPUT); + if (ret) { + dev_err(dev, "bgpio_init() failed\n"); + return ret; From 30644bc579e771e4b6dcc165ca966124e0259e1e Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 18 Mar 2020 23:38:58 +0800 Subject: [PATCH 12/35] ramips: mt7621: update dts/defconfig for DSA update dts and network/LED configuration for DSA driver. sysupgrade from images prior to this commit with config preserved will cause broken ethernet setup. Signed-off-by: DENG Qingfang Acked-by: Jo-Philipp Wich [split commit] Signed-off-by: Chuanhong Guo --- target/linux/ramips/dts/mt7621_adslr_g7.dts | 35 ++- .../ramips/dts/mt7621_afoundry_ew1200.dts | 39 ++- .../dts/mt7621_alfa-network_quad-e4g.dts | 34 ++- .../ramips/dts/mt7621_asiarf_ap7621-001.dts | 16 ++ .../ramips/dts/mt7621_asiarf_ap7621-nv1.dts | 21 ++ .../ramips/dts/mt7621_asiarf_ap7621.dtsi | 3 +- .../linux/ramips/dts/mt7621_asus_rt-ac57u.dts | 32 ++- .../ramips/dts/mt7621_asus_rt-acx5p.dtsi | 35 ++- .../ramips/dts/mt7621_buffalo_wsr-1166dhp.dts | 29 ++ .../ramips/dts/mt7621_buffalo_wsr-600dhp.dts | 31 ++- .../ramips/dts/mt7621_d-team_newifi-d2.dts | 34 ++- .../linux/ramips/dts/mt7621_d-team_pbr-m1.dts | 32 ++- .../ramips/dts/mt7621_dlink_dir-860l-b1.dts | 35 ++- .../linux/ramips/dts/mt7621_edimax_rx21s.dtsi | 34 ++- .../dts/mt7621_elecom_wrc-1167ghbk2-s.dts | 32 ++- .../ramips/dts/mt7621_elecom_wrc-gst.dtsi | 32 ++- .../ramips/dts/mt7621_firefly_firewrt.dts | 33 ++- .../ramips/dts/mt7621_gehua_ghl-r-001.dts | 28 +- .../linux/ramips/dts/mt7621_gnubee_gb-pc1.dts | 16 +- .../linux/ramips/dts/mt7621_gnubee_gb-pc2.dts | 16 +- .../linux/ramips/dts/mt7621_hiwifi_hc5962.dts | 24 ++ .../ramips/dts/mt7621_iodata_wn-ax1167gr.dts | 33 ++- .../ramips/dts/mt7621_iodata_wn-gx300gr.dts | 33 ++- .../ramips/dts/mt7621_iodata_wn-xx-xr.dtsi | 33 ++- .../ramips/dts/mt7621_iodata_wnpr2600g.dts | 32 ++- .../linux/ramips/dts/mt7621_iptime_a6ns-m.dts | 34 ++- .../linux/ramips/dts/mt7621_iptime_a8004t.dts | 32 ++- .../ramips/dts/mt7621_jcg_jhr-ac876m.dts | 32 ++- .../ramips/dts/mt7621_lenovo_newifi-d1.dts | 24 +- .../ramips/dts/mt7621_linksys_re6500.dts | 26 +- .../dts/mt7621_mediatek_ap-mt7621a-v60.dts | 33 ++- .../dts/mt7621_mediatek_mt7621-eval-board.dts | 29 ++ .../ramips/dts/mt7621_mikrotik_rb750gr3.dts | 33 ++- .../ramips/dts/mt7621_mikrotik_rbm11g.dts | 12 +- .../ramips/dts/mt7621_mikrotik_rbm33g.dts | 23 +- .../linux/ramips/dts/mt7621_mqmaker_witi.dts | 33 ++- target/linux/ramips/dts/mt7621_mtc_wr1201.dts | 35 ++- .../ramips/dts/mt7621_netgear_ex6150.dts | 13 +- .../ramips/dts/mt7621_netgear_r6700-v2.dts | 1 - .../linux/ramips/dts/mt7621_netgear_r6800.dts | 1 - .../dts/mt7621_netgear_sercomm_ayx.dtsi | 35 ++- .../dts/mt7621_netgear_sercomm_bzv.dtsi | 37 ++- .../dts/mt7621_netgear_sercomm_chj.dtsi | 35 ++- .../linux/ramips/dts/mt7621_netis_wf2881.dts | 34 ++- .../linux/ramips/dts/mt7621_phicomm_k2p.dts | 32 ++- .../linux/ramips/dts/mt7621_planex_vr500.dts | 32 ++- .../dts/mt7621_samknows_whitebox-v8.dts | 32 ++- .../dts/mt7621_storylink_sap-g3200u3.dts | 33 ++- .../dts/mt7621_telco-electronics_x1.dts | 34 ++- .../ramips/dts/mt7621_thunder_timecloud.dts | 11 +- .../ramips/dts/mt7621_totolink_a7000r.dts | 33 ++- .../ramips/dts/mt7621_tplink_re350-v1.dts | 11 +- .../ramips/dts/mt7621_tplink_re650-v1.dts | 14 +- .../dts/mt7621_ubiquiti_edgerouterx.dtsi | 35 ++- .../ramips/dts/mt7621_ubnt_unifi-nanohd.dts | 14 +- .../ramips/dts/mt7621_unielec_u7621-06.dtsi | 34 ++- .../ramips/dts/mt7621_wevo_w2914ns-v2.dtsi | 35 ++- .../ramips/dts/mt7621_xiaomi_mir3g-v2.dts | 23 +- .../linux/ramips/dts/mt7621_xiaomi_mir3g.dts | 29 +- .../linux/ramips/dts/mt7621_xiaomi_mir3p.dts | 35 ++- .../linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts | 35 ++- .../dts/mt7621_xzwifi_creativebox-v1.dts | 33 ++- .../ramips/dts/mt7621_youhua_wr1200js.dts | 32 ++- .../linux/ramips/dts/mt7621_youku_yk-l2.dts | 32 ++- .../ramips/dts/mt7621_zbtlink_zbt-we1326.dts | 32 ++- .../ramips/dts/mt7621_zbtlink_zbt-we3526.dts | 32 ++- .../ramips/dts/mt7621_zbtlink_zbt-wg2626.dts | 33 ++- .../ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi | 33 ++- .../mt7621/base-files/etc/board.d/01_leds | 43 ++- .../mt7621/base-files/etc/board.d/02_network | 253 ++++-------------- 70 files changed, 1895 insertions(+), 324 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_adslr_g7.dts b/target/linux/ramips/dts/mt7621_adslr_g7.dts index 91a6ab26ab..2448248c31 100644 --- a/target/linux/ramips/dts/mt7621_adslr_g7.dts +++ b/target/linux/ramips/dts/mt7621_adslr_g7.dts @@ -15,7 +15,7 @@ led-failsafe = &led_sys; led-running = &led_sys; led-upgrade = &led_sys; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -105,10 +105,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe00c>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe00c>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts index 877b8d7d9d..c0166c730a 100644 --- a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts +++ b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts @@ -20,12 +20,6 @@ bootargs = "console=ttyS0,57600"; }; - palmbus: palmbus@1E000000 { - i2c@900 { - status = "okay"; - }; - }; - keys { compatible = "gpio-keys"; @@ -117,10 +111,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "mdio"; diff --git a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts index 266e765d7b..6ac9e337fc 100644 --- a/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts +++ b/target/linux/ramips/dts/mt7621_alfa-network_quad-e4g.dts @@ -11,7 +11,7 @@ model = "ALFA Network Quad-E4G"; aliases { - label-mac-device = ðernet; + label-mac-device = &gmac0; led-boot = &led_system; led-failsafe = &led_system; led-running = &led_system; @@ -148,10 +148,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &i2c { status = "okay"; diff --git a/target/linux/ramips/dts/mt7621_asiarf_ap7621-001.dts b/target/linux/ramips/dts/mt7621_asiarf_ap7621-001.dts index 9926a9bd5a..6e21420733 100644 --- a/target/linux/ramips/dts/mt7621_asiarf_ap7621-001.dts +++ b/target/linux/ramips/dts/mt7621_asiarf_ap7621-001.dts @@ -7,3 +7,19 @@ compatible = "asiarf,ap7621-001", "mediatek,mt7621-soc"; model = "AsiaRF AP7621-001"; }; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/mt7621_asiarf_ap7621-nv1.dts b/target/linux/ramips/dts/mt7621_asiarf_ap7621-nv1.dts index ec322d0e08..977f43e114 100644 --- a/target/linux/ramips/dts/mt7621_asiarf_ap7621-nv1.dts +++ b/target/linux/ramips/dts/mt7621_asiarf_ap7621-nv1.dts @@ -7,3 +7,24 @@ compatible = "asiarf,ap7621-nv1", "mediatek,mt7621-soc"; model = "AsiaRF AP7621-NV1"; }; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + + port@2 { + status = "okay"; + label = "lan1"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + }; +}; diff --git a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi index a965cb4e63..bd6642fe51 100644 --- a/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi +++ b/target/linux/ramips/dts/mt7621_asiarf_ap7621.dtsi @@ -103,9 +103,8 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "llllw"; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts index ac1d88a6ce..0b37dc8395 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts +++ b/target/linux/ramips/dts/mt7621_asus_rt-ac57u.dts @@ -134,10 +134,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &state_default { gpio { groups = "sdhci"; diff --git a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi index c1ef3ce98c..37056c7934 100644 --- a/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi +++ b/target/linux/ramips/dts/mt7621_asus_rt-acx5p.dtsi @@ -135,16 +135,37 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "wllll"; - port@5 { - status = "disabled"; - }; }; -&i2c { - status = "disabled"; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts index 8e0a1d8912..af83d0f1b3 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-1166dhp.dts @@ -158,6 +158,35 @@ }; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; diff --git a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts index ca060e7c0a..1d0c8b3dcc 100644 --- a/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts +++ b/target/linux/ramips/dts/mt7621_buffalo_wsr-600dhp.dts @@ -178,10 +178,39 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + }; + }; +}; + &xhci { status = "disabled"; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts index 85b8c5c2e0..c5548a673e 100644 --- a/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts +++ b/target/linux/ramips/dts/mt7621_d-team_newifi-d2.dts @@ -14,7 +14,7 @@ led-failsafe = &led_power_blue; led-running = &led_power_blue; led-upgrade = &led_power_blue; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -149,10 +149,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "jtag", "uart2", "uart3"; diff --git a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts index 73e6e32f42..528f86f943 100644 --- a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts +++ b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts @@ -164,10 +164,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "mdio"; diff --git a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts index f83c9a4afb..28005b3f35 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts @@ -14,7 +14,7 @@ led-failsafe = &led_power_green; led-running = &led_power_green; led-upgrade = &led_power_green; - label-mac-device = &wifi1; + label-mac-device = &gmac0; }; chosen { @@ -114,6 +114,39 @@ }; }; +&gmac0 { + mtd-mac-address = <&radio 0x4>; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi index 3cef0026b4..b52ead09d3 100644 --- a/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi +++ b/target/linux/ramips/dts/mt7621_edimax_rx21s.dtsi @@ -8,7 +8,7 @@ / { aliases { - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -94,12 +94,36 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; +}; - mediatek,portmap = "wllll"; - port@5 { - status = "disabled"; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; }; }; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts index c61ef885f2..5a8ee2884c 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-1167ghbk2-s.dts @@ -72,10 +72,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &spi0 { status = "okay"; diff --git a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi index e120ee3ca4..85bbcd0b6a 100644 --- a/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi +++ b/target/linux/ramips/dts/mt7621_elecom_wrc-gst.dtsi @@ -86,10 +86,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &spi0 { status = "okay"; diff --git a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts index 57318f3694..10b33993ac 100644 --- a/target/linux/ramips/dts/mt7621_firefly_firewrt.dts +++ b/target/linux/ramips/dts/mt7621_firefly_firewrt.dts @@ -110,10 +110,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2"; diff --git a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts index 6e3eda5290..b501034b7f 100644 --- a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts +++ b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts @@ -110,10 +110,36 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "jtag", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts index 8544e21528..1cf121a7c3 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc1.dts @@ -104,10 +104,24 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "lan2"; + }; + }; +}; + &state_default { gpio { groups = "jtag", "rgmii2", "uart3", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts index 0dae7b5ce7..f279ccaae0 100644 --- a/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts +++ b/target/linux/ramips/dts/mt7621_gnubee_gb-pc2.dts @@ -114,10 +114,24 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "lan2"; + }; + }; +}; + &state_default { gpio { groups = "jtag", "rgmii2", "uart3", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts index d5fa290bcf..9d60d509ab 100644 --- a/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts +++ b/target/linux/ramips/dts/mt7621_hiwifi_hc5962.dts @@ -142,6 +142,30 @@ }; }; +&switch0 { + ports { + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "wan"; + }; + }; +}; + &state_default { gpio { groups = "uart3", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts index 57c4638f16..1fabad5da6 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-ax1167gr.dts @@ -129,10 +129,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&iNIC_rf 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <1>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &state_default { gpio { groups = "uart2", "uart3", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts index ca08f1dabb..c345896bd2 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wn-gx300gr.dts @@ -129,10 +129,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <1>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &state_default { gpio { groups = "uart2", "uart3", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi index c771eb20af..acef4d22a0 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi +++ b/target/linux/ramips/dts/mt7621_iodata_wn-xx-xr.dtsi @@ -11,6 +11,7 @@ led-failsafe = &led_power; led-running = &led_power; led-upgrade = &led_power; + label-mac-device = &wan; }; chosen { @@ -120,10 +121,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + wan: port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts index a208757c28..94b0c18d45 100644 --- a/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts +++ b/target/linux/ramips/dts/mt7621_iodata_wnpr2600g.dts @@ -124,9 +124,37 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; - mediatek,portmap = "wllll"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts index 7ff01b133a..be8b101b78 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a6ns-m.dts @@ -15,7 +15,7 @@ led-failsafe = &led_cpu; led-running = &led_cpu; led-upgrade = &led_cpu; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -115,10 +115,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&uboot 0x1fc20>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&uboot 0x1fc40>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts index 179a9cda4c..b948236c15 100644 --- a/target/linux/ramips/dts/mt7621_iptime_a8004t.dts +++ b/target/linux/ramips/dts/mt7621_iptime_a8004t.dts @@ -100,10 +100,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&uboot 0x1fc20>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&uboot 0x1fc40>; + }; + + port@1 { + status = "okay"; + label = "lan4"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan2"; + }; + + port@4 { + status = "okay"; + label = "lan1"; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts index bdb9860291..126896c906 100644 --- a/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts +++ b/target/linux/ramips/dts/mt7621_jcg_jhr-ac876m.dts @@ -15,6 +15,7 @@ led-failsafe = &led_wps; led-running = &led_wps; led-upgrade = &led_wps; + label-mac-device = &wan; }; chosen { @@ -132,10 +133,39 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + wan: port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart3", "jtag", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts index 7f7dc9c3ea..984c886ff3 100644 --- a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts +++ b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts @@ -14,7 +14,7 @@ led-failsafe = &led_blue; led-running = &led_blue; led-upgrade = &led_blue; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -133,10 +133,30 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "uart2", "uart3", "i2c"; diff --git a/target/linux/ramips/dts/mt7621_linksys_re6500.dts b/target/linux/ramips/dts/mt7621_linksys_re6500.dts index a97e64dbec..c325b33f12 100644 --- a/target/linux/ramips/dts/mt7621_linksys_re6500.dts +++ b/target/linux/ramips/dts/mt7621_linksys_re6500.dts @@ -118,10 +118,34 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x2e>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &xhci { status = "disabled"; }; diff --git a/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts b/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts index 4a225d81c4..731eb4d8e2 100644 --- a/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts +++ b/target/linux/ramips/dts/mt7621_mediatek_ap-mt7621a-v60.dts @@ -118,10 +118,41 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x5>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x5>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts b/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts index 93588b5d53..8321caae6e 100644 --- a/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts +++ b/target/linux/ramips/dts/mt7621_mediatek_mt7621-eval-board.dts @@ -45,6 +45,35 @@ status = "okay"; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts index ebb35b9204..a065ce804d 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts @@ -129,11 +129,42 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&hard_config 0x0010>; mtd-mac-address-increment = <1>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&hard_config 0x0010>; + mtd-mac-address-increment = <2>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &state_default { gpio { /* via gpio7 (uart3 group) the PoE status can be read */ diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts index 85ea796f97..bcfce33a16 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm11g.dts @@ -138,11 +138,21 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&hard_config 0x0010>; mtd-mac-address-increment = <1>; }; +&switch0 { + ports { + /* FIXME: Is LAN port at switch port 0? */ + port@0 { + status = "okay"; + label = "lan"; + }; + }; +}; + &state_default { gpio { groups = "uart2", "wdt", "rgmii2"; diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts index d65d1de05c..f7889bd68a 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rbm33g.dts @@ -162,11 +162,32 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&hard_config 0x0010>; mtd-mac-address-increment = <1>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&hard_config 0x0010>; + mtd-mac-address-increment = <2>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + }; +}; + &state_default { gpio { groups = "uart2", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts index f59cc57be3..6870ed94a0 100644 --- a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts +++ b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts @@ -101,10 +101,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "mdio"; diff --git a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts index 6e1c6eabaa..eca7b3b0bb 100644 --- a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts +++ b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts @@ -14,7 +14,7 @@ led-failsafe = &led_power; led-running = &led_power; led-upgrade = &led_power; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -104,10 +104,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &sdhci { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts index 701f8274a4..1b0b9e29e9 100644 --- a/target/linux/ramips/dts/mt7621_netgear_ex6150.dts +++ b/target/linux/ramips/dts/mt7621_netgear_ex6150.dts @@ -228,8 +228,17 @@ }; }; -ðernet { - mtd-mac-address = <&factory 0x00000004>; +&gmac0 { + mtd-mac-address = <&factory 0x4>; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan"; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts index 07b696c42d..b206cf7d95 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6700-v2.dts @@ -12,7 +12,6 @@ led-failsafe = &led_power_orange; led-running = &led_power_white; led-upgrade = &led_power_orange; - label-mac-device = ðernet; }; leds { diff --git a/target/linux/ramips/dts/mt7621_netgear_r6800.dts b/target/linux/ramips/dts/mt7621_netgear_r6800.dts index a64c976a44..cce701ea32 100644 --- a/target/linux/ramips/dts/mt7621_netgear_r6800.dts +++ b/target/linux/ramips/dts/mt7621_netgear_r6800.dts @@ -12,7 +12,6 @@ led-failsafe = &led_power_orange; led-running = &led_power_white; led-upgrade = &led_power_orange; - label-mac-device = ðernet; }; leds { diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi index ba0853d3ca..0b9e7c6626 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_ayx.dtsi @@ -13,7 +13,7 @@ led-failsafe = &led_power; led-running = &led_power; led-upgrade = &led_power; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -105,10 +105,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "uart3", "uart2", "jtag", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi index 12621d8b71..d2e5502e48 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_bzv.dtsi @@ -8,6 +8,10 @@ / { compatible = "mediatek,mt7621-soc"; + aliases { + label-mac-device = &gmac0; + }; + chosen { bootargs = "console=ttyS0,57600"; }; @@ -57,10 +61,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <2>; + }; + }; +}; + &i2c { status = "okay"; diff --git a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi index c7dcfae870..b781edf6be 100644 --- a/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi +++ b/target/linux/ramips/dts/mt7621_netgear_sercomm_chj.dtsi @@ -13,7 +13,7 @@ led-failsafe = &led_power; led-running = &led_power; led-upgrade = &led_power; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -95,10 +95,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <2>; + }; + }; +}; + &state_default { gpio { groups = "uart3", "uart2", "jtag", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_netis_wf2881.dts b/target/linux/ramips/dts/mt7621_netis_wf2881.dts index 11aa68d8f1..e937134ae9 100644 --- a/target/linux/ramips/dts/mt7621_netis_wf2881.dts +++ b/target/linux/ramips/dts/mt7621_netis_wf2881.dts @@ -14,7 +14,7 @@ led-failsafe = &led_wps; led-running = &led_wps; led-upgrade = &led_wps; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -127,10 +127,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "uart3", "uart2"; diff --git a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts index 104d10fdb3..761b690d1e 100644 --- a/target/linux/ramips/dts/mt7621_phicomm_k2p.dts +++ b/target/linux/ramips/dts/mt7621_phicomm_k2p.dts @@ -107,10 +107,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_planex_vr500.dts b/target/linux/ramips/dts/mt7621_planex_vr500.dts index 30257ffb5a..7114ba9834 100644 --- a/target/linux/ramips/dts/mt7621_planex_vr500.dts +++ b/target/linux/ramips/dts/mt7621_planex_vr500.dts @@ -80,10 +80,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; diff --git a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts index cf982d1a86..4bd7611359 100644 --- a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts +++ b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts @@ -110,10 +110,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; diff --git a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts index 7a5b2a840c..84bd049d8a 100644 --- a/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts +++ b/target/linux/ramips/dts/mt7621_storylink_sap-g3200u3.dts @@ -107,10 +107,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe006>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "uart3", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts index fa85cf1017..7c94db8dcb 100644 --- a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts +++ b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts @@ -126,9 +126,39 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe006>; - mediatek,portmap = "llllw"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + mtd-mac-address-increment = <1>; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts index 195750a27d..60eea877b1 100644 --- a/target/linux/ramips/dts/mt7621_thunder_timecloud.dts +++ b/target/linux/ramips/dts/mt7621_thunder_timecloud.dts @@ -95,10 +95,19 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@4 { + status = "okay"; + label = "lan"; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "jtag"; diff --git a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts index db6edde74d..fd24d40fe1 100644 --- a/target/linux/ramips/dts/mt7621_totolink_a7000r.dts +++ b/target/linux/ramips/dts/mt7621_totolink_a7000r.dts @@ -104,10 +104,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "i2c", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts index 13faedd0ea..d04d87dd37 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re350-v1.dts @@ -151,10 +151,19 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&config 0x10008>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan"; + }; + }; +}; + &state_default { gpio { groups = "rgmii2", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts index 265739bbda..a26ad98cc2 100644 --- a/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts +++ b/target/linux/ramips/dts/mt7621_tplink_re650-v1.dts @@ -15,7 +15,7 @@ led-failsafe = &led_power; led-running = &led_power; led-upgrade = &led_power; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -164,10 +164,20 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&config 0x10008>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan"; + }; + }; +}; + + &state_default { gpio { groups = "rgmii2", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi index 1efc930d49..6fed4a0b7b 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi @@ -5,7 +5,7 @@ / { aliases { - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -23,10 +23,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x22>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x22>; + mtd-mac-address-increment = <1>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &nand { status = "okay"; diff --git a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts index 9b3a5be444..6292762ea7 100644 --- a/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts +++ b/target/linux/ramips/dts/mt7621_ubnt_unifi-nanohd.dts @@ -15,8 +15,7 @@ led-failsafe = &led_white; led-running = &led_blue; led-upgrade = &led_blue; - - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -129,10 +128,19 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&eeprom 0x0>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan"; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2"; diff --git a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi index c4116e8541..ca0e2d7dcd 100644 --- a/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi +++ b/target/linux/ramips/dts/mt7621_unielec_u7621-06.dtsi @@ -104,9 +104,39 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "llllw"; +}; + +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi index d519961424..9592363260 100644 --- a/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi +++ b/target/linux/ramips/dts/mt7621_wevo_w2914ns-v2.dtsi @@ -4,6 +4,10 @@ #include / { + aliases { + label-mac-device = &wan; + }; + chosen { bootargs = "console=ttyS0,57600"; }; @@ -97,10 +101,39 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan4"; + }; + + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + wan: port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x2e>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2"; diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts index a8125d355e..41e11216d2 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g-v2.dts @@ -15,6 +15,7 @@ led-failsafe = &led_status_yellow; led-running = &led_status_blue; led-upgrade = &led_status_yellow; + label-mac-device = &wan; }; chosen { @@ -132,9 +133,27 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "llllw"; +}; + +&switch0 { + ports { + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + wan: port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts index a4ffb150b3..60786e421e 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3g.dts @@ -14,6 +14,7 @@ led-failsafe = &led_status_red; led-running = &led_status_blue; led-upgrade = &led_status_yellow; + label-mac-device = &gmac0; }; chosen { @@ -41,16 +42,19 @@ wan_amber { label = "mir3g:amber:wan"; gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:01:1Gbps"; }; lan1_amber { label = "mir3g:amber:lan1"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:03:1Gbps"; }; lan2_amber { label = "mir3g:amber:lan2"; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:02:1Gbps"; }; }; @@ -186,9 +190,28 @@ }; }; -ðernet { - mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "lwlll"; +&gmac0 { + mtd-mac-address = <&factory 0xe006>; +}; + +&switch0 { + ports { + port@1 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts index 45d7411bd0..8a85c8b48d 100644 --- a/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts +++ b/target/linux/ramips/dts/mt7621_xiaomi_mir3p.dts @@ -15,6 +15,7 @@ led-failsafe = &led_status_red; led-running = &led_status_blue; led-upgrade = &led_status_yellow; + label-mac-device = &gmac0; }; chosen { @@ -42,21 +43,25 @@ wan_amber { label = "mir3p:amber:wan"; gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:04:1Gbps"; }; lan3_amber { label = "mir3p:amber:lan3"; gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:01:1Gbps"; }; lan2_amber { label = "mir3p:amber:lan2"; gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:02:1Gbps"; }; lan1_amber { label = "mir3p:amber:lan1"; gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + linux,default-trigger = "dsa-0.0:03:1Gbps"; }; }; @@ -171,9 +176,33 @@ }; }; -ðernet { - mtd-mac-address = <&factory 0xe000>; - mediatek,portmap = "llllw"; +&gmac0 { + mtd-mac-address = <&factory 0xe006>; +}; + +&switch0 { + ports { + port@1 { + status = "okay"; + label = "lan3"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan1"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + }; + }; }; &state_default { diff --git a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts index 618c0ab565..d99cc7d257 100644 --- a/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts +++ b/target/linux/ramips/dts/mt7621_xiaoyu_xy-c5.dts @@ -14,7 +14,7 @@ led-failsafe = &led_sys; led-running = &led_sys; led-upgrade = &led_sys; - label-mac-device = ðernet; + label-mac-device = &gmac0; }; chosen { @@ -90,10 +90,41 @@ status = "okay"; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0x4>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x4>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "uart3", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts index ad8f7fdc91..36ef348ec5 100644 --- a/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts +++ b/target/linux/ramips/dts/mt7621_xzwifi_creativebox-v1.dts @@ -152,10 +152,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2"; diff --git a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts index aa749ec6b8..c70350fd41 100644 --- a/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts +++ b/target/linux/ramips/dts/mt7621_youhua_wr1200js.dts @@ -126,10 +126,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + &state_default { gpio { groups = "i2c", "uart2", "uart3", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts index 49fa312f58..e43ee8451a 100644 --- a/target/linux/ramips/dts/mt7621_youku_yk-l2.dts +++ b/target/linux/ramips/dts/mt7621_youku_yk-l2.dts @@ -137,10 +137,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "jtag", "wdt"; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts index 6d765a2a61..f91f0d77d4 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we1326.dts @@ -75,10 +75,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &pcie { status = "okay"; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts index 8088d5e8b4..1f43f2a2dc 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-we3526.dts @@ -99,10 +99,40 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe006>; + }; + }; +}; + &state_default { gpio { groups = "wdt"; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts index fba959c8df..6461302154 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts @@ -110,10 +110,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "mdio"; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi index 6977997633..9728119adf 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi @@ -112,10 +112,41 @@ }; }; -ðernet { +&gmac0 { mtd-mac-address = <&factory 0xe000>; }; +&switch0 { + ports { + port@0 { + status = "okay"; + label = "lan1"; + }; + + port@1 { + status = "okay"; + label = "lan2"; + }; + + port@2 { + status = "okay"; + label = "lan3"; + }; + + port@3 { + status = "okay"; + label = "lan4"; + }; + + port@4 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0xe000>; + mtd-mac-address-increment = <1>; + }; + }; +}; + &state_default { gpio { groups = "wdt", "rgmii2", "jtag", "mdio"; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index 7695cb9918..66739a7536 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -18,21 +18,21 @@ led_wlan="$(get_dt_led wlan)" case $board in d-team,newifi-d2) - ucidef_set_led_switch "internet" "internet" "$boardname:amber:internet" "switch0" "0x10" + ucidef_set_led_netdev "internet" "internet" "$boardname:amber:internet" "wan" ucidef_set_led_netdev "wlan2g" "WiFi 2.4GHz" "$boardname:blue:wlan2g" "wlan0" ucidef_set_led_netdev "wlan5g" "WiFi 5GHz" "$boardname:blue:wlan5g" "wlan1" ;; d-team,pbr-m1|\ gehua,ghl-r-001) - ucidef_set_led_netdev "internet" "internet" "$boardname:blue:internet" "eth0.2" + ucidef_set_led_netdev "internet" "internet" "$boardname:blue:internet" "wan" ;; dlink,dir-860l-b1) - ucidef_set_led_netdev "wan" "wan" "$boardname:green:net" "eth0.2" + ucidef_set_led_netdev "wan" "wan" "$boardname:green:net" "wan" ;; gnubee,gb-pc1|\ gnubee,gb-pc2) - ucidef_set_led_switch "lan1" "lan1" "$boardname:green:lan1" "switch0" "0x01" - ucidef_set_led_switch "lan2" "lan2" "$boardname:green:lan2" "switch0" "0x10" + ucidef_set_led_netdev "lan1" "lan1" "$boardname:green:lan1" "lan1" + ucidef_set_led_netdev "lan2" "lan2" "$boardname:green:lan2" "lan2" ;; mikrotik,rbm11g) ucidef_set_rssimon "wlan0" "200000" "1" @@ -43,46 +43,35 @@ mikrotik,rbm11g) ucidef_set_led_rssi "rssiveryhigh" "RSSIVERYHIGH" "$boardname:green:rssi4" "wlan0" "80" "100" ;; mtc,wr1201) - ucidef_set_led_switch "eth_link" "LAN link" "$boardname:green:eth_link" "switch0" "0x0f" + ucidef_set_led_netdev "eth_link" "LAN link" "$boardname:green:eth_link" "br-lan" ;; netgear,r6220|\ netgear,r6260|\ netgear,r6350|\ netgear,r6850|\ netgear,wndr3700-v5) - ucidef_set_led_switch "wan" "wan" "$boardname:green:wan" "switch0" "0x10" + ucidef_set_led_netdev "wan" "wan" "$boardname:green:wan" "wan" ;; netgear,r6700-v2|\ netgear,r6800) - ucidef_set_led_switch "wan" "WAN" "$boardname:white:wan" "switch0" "0x10" - ucidef_set_led_switch "lan1" "LAN1" "$boardname:white:lan1" "switch0" "0x08" - ucidef_set_led_switch "lan2" "LAN2" "$boardname:white:lan2" "switch0" "0x04" - ucidef_set_led_switch "lan3" "LAN3" "$boardname:white:lan3" "switch0" "0x02" - ucidef_set_led_switch "lan4" "LAN4" "$boardname:white:lan4" "switch0" "0x01" + ucidef_set_led_netdev "wan" "WAN" "$boardname:white:wan" "wan" + ucidef_set_led_netdev "lan1" "LAN1" "$boardname:white:lan1" "lan1" + ucidef_set_led_netdev "lan2" "LAN2" "$boardname:white:lan2" "lan2" + ucidef_set_led_netdev "lan3" "LAN3" "$boardname:white:lan3" "lan3" + ucidef_set_led_netdev "lan4" "LAN4" "$boardname:white:lan4" "lan4" ;; tplink,re350-v1|\ tplink,re650-v1) ucidef_set_led_netdev "wifi2g" "Wifi 2.4G" "$boardname:blue:wifi2G" "wlan0" ucidef_set_led_netdev "wifi5g" "Wifi 5G" "$boardname:blue:wifi5G" "wlan1" - ucidef_set_led_netdev "eth_act" "LAN act" "$boardname:green:eth_act" "eth0" "tx rx" - ucidef_set_led_switch "eth_link" "LAN link" "$boardname:green:eth_link" "switch0" "0x01" - ;; -xiaomi,mir3g) - ucidef_set_led_switch "wan-amber" "WAN (amber)" "$boardname:amber:wan" "switch0" "0x02" "0x08" - ucidef_set_led_switch "lan1-amber" "LAN1 (amber)" "$boardname:amber:lan1" "switch0" "0x08" "0x08" - ucidef_set_led_switch "lan2-amber" "LAN2 (amber)" "$boardname:amber:lan2" "switch0" "0x04" "0x08" - ;; -xiaomi,mir3p) - ucidef_set_led_switch "wan-amber" "WAN (amber)" "$boardname:amber:wan" "switch0" "0x10" "0x08" - ucidef_set_led_switch "lan1-amber" "LAN1 (amber)" "$boardname:amber:lan1" "switch0" "0x02" "0x08" - ucidef_set_led_switch "lan2-amber" "LAN2 (amber)" "$boardname:amber:lan2" "switch0" "0x04" "0x08" - ucidef_set_led_switch "lan3-amber" "LAN3 (amber)" "$boardname:amber:lan3" "switch0" "0x08" "0x08" + ucidef_set_led_netdev "eth_act" "LAN act" "$boardname:green:eth_act" "lan" "tx rx" + ucidef_set_led_netdev "eth_link" "LAN link" "$boardname:green:eth_link" "lan" "link" ;; xzwifi,creativebox-v1) - ucidef_set_led_switch "internet" "internet" "$boardname:blue:internet" "switch0" "0x10" + ucidef_set_led_netdev "internet" "internet" "$boardname:blue:internet" "wan" ;; youhua,wr1200js) - ucidef_set_led_switch "internet" "INTERNET" "$boardname:green:wan" "switch0" "0x01" + ucidef_set_led_netdev "internet" "INTERNET" "$boardname:green:wan" "wan" ;; esac diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index a68ffe6126..f27ffcccbf 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -11,33 +11,34 @@ ramips_setup_interfaces() case $board in adslr,g7|\ afoundry,ew1200|\ + alfa-network,quad-e4g|\ + asus,rt-ac57u|\ + asus,rt-ac65p|\ + asus,rt-ac85p|\ + buffalo,wsr-1166dhp|\ + buffalo,wsr-600dhp|\ + dlink,dir-860l-b1|\ + d-team,newifi-d2|\ d-team,pbr-m1|\ + edimax,ra21s|\ + edimax,rg21s|\ + elecom,wrc-1167ghbk2-s|\ + elecom,wrc-1900gst|\ + elecom,wrc-2533gst|\ firefly,firewrt|\ + iodata,wn-ax1167gr|\ + iodata,wn-ax1167gr2|\ + iodata,wn-dx1167r|\ + iodata,wn-gx300gr|\ + iodata,wnpr2600g|\ + iptime,a6ns-m|\ + iptime,a8004t|\ jcg,jhr-ac876m|\ mediatek,ap-mt7621a-v60|\ mediatek,mt7621-eval-board|\ + mikrotik,rb750gr3|\ mqmaker,witi|\ mtc,wr1201|\ - phicomm,k2p|\ - planex,vr500|\ - samknows,whitebox-v8|\ - storylink,sap-g3200u3|\ - telco-electronics,x1|\ - totolink,a7000r|\ - unielec,u7621-06-16m|\ - unielec,u7621-06-64m|\ - xiaoyu,xy-c5|\ - xzwifi,creativebox-v1|\ - youku,yk-l2|\ - zbtlink,zbt-we1326|\ - zbtlink,zbt-we3526|\ - zbtlink,zbt-wg2626|\ - zbtlink,zbt-wg3526-16m|\ - zbtlink,zbt-wg3526-32m) - ucidef_add_switch "switch0" \ - "0:lan" "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" - ;; - alfa-network,quad-e4g|\ netgear,r6220|\ netgear,r6260|\ netgear,r6350|\ @@ -46,105 +47,59 @@ ramips_setup_interfaces() netgear,r6850|\ netgear,wndr3700-v5|\ netis,wf2881|\ - wevo,11acnas|\ - wevo,w2914ns-v2|\ - zio,freezio) - ucidef_add_switch "switch0" \ - "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "4:wan" "6@eth0" - ;; - asiarf,ap7621-001) - ucidef_add_switch "switch0" "0:lan" "4:wan" "6@eth0" - ;; - asiarf,ap7621-nv1) - ucidef_add_switch "switch0" "0:wan" "2:lan" "3:lan" "6@eth0" - ;; - asus,rt-ac65p|\ - asus,rt-ac57u|\ - asus,rt-ac85p|\ - iptime,a6ns-m|\ - mikrotik,rb750gr3|\ + phicomm,k2p|\ + planex,vr500|\ + samknows,whitebox-v8|\ + storylink,sap-g3200u3|\ + telco-electronics,x1|\ + totolink,a7000r|\ ubiquiti,edgerouterx|\ ubiquiti,edgerouterx-sfp|\ - youhua,wr1200js) - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "3:lan" "4:lan" "0:wan" "6@eth0" + unielec,u7621-06-16m|\ + unielec,u7621-06-64m|\ + wevo,11acnas|\ + wevo,w2914ns-v2|\ + xiaoyu,xy-c5|\ + xzwifi,creativebox-v1|\ + youhua,wr1200js|\ + youku,yk-l2|\ + zbtlink,zbt-we1326|\ + zbtlink,zbt-we3526|\ + zbtlink,zbt-wg2626|\ + zbtlink,zbt-wg3526-16m|\ + zbtlink,zbt-wg3526-32m|\ + zio,freezio) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; - dlink,dir-860l-b1|\ - elecom,wrc-1167ghbk2-s|\ - elecom,wrc-1900gst|\ - elecom,wrc-2533gst|\ - iodata,wn-ax1167gr|\ - iodata,wn-ax1167gr2|\ - iodata,wn-dx1167r|\ - iodata,wn-gx300gr|\ - iodata,wnpr2600g|\ - iptime,a8004t) - ucidef_add_switch "switch0" \ - "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "0:wan" "6@eth0" + asiarf,ap7621-001) + ucidef_set_interfaces_lan_wan "lan" "wan" ;; - buffalo,wsr-1166dhp|\ - buffalo,wsr-600dhp) - ucidef_add_switch "switch0" \ - "0:lan:1" "1:lan:2" "2:lan:3" "3:lan:4" "4:wan:5" "6@eth0" + asiarf,ap7621-nv1|\ + lenovo,newifi-d1|\ + mikrotik,rbm33g|\ + xiaomi,mir3g|\ + xiaomi,mir3g-v2) + ucidef_set_interfaces_lan_wan "lan1 lan2" "wan" ;; - d-team,newifi-d2) - ucidef_add_switch "switch0" \ - "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "4:wan:5" "6@eth0" - ;; - edimax,ra21s|\ - edimax,rg21s) - ucidef_add_switch "switch0" \ - "1:lan:4" "2:lan:3" "3:lan:2" "4:lan:1" "0:wan" "6@eth0" - ;; - gehua,ghl-r-001) - ucidef_add_switch "switch0" \ - "0:lan" "1:lan" "2:lan" "4:wan" "6@eth0" + gehua,ghl-r-001|\ + hiwifi,hc5962|\ + xiaomi,mir3p) + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3" "wan" ;; gnubee,gb-pc1|\ gnubee,gb-pc2) - ucidef_add_switch "switch0" \ - "0:lan" "4:lan" "6@eth0" - ;; - hiwifi,hc5962) - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "3:lan" "4:wan" "6@eth0" - ;; - lenovo,newifi-d1) - ucidef_add_switch "switch0" \ - "1:lan:2" "2:lan:1" "4:wan" "6@eth0" + ucidef_set_interface_lan "lan1 lan2" ;; linksys,re6500) - ucidef_add_switch "switch0" \ - "0:lan:1" "1:lan:2" "2:lan:3" "3:lan:4" "6@eth0" + ucidef_set_interface_lan "lan1 lan2 lan3 lan4" ;; mikrotik,rbm11g|\ - thunder,timecloud) - ucidef_add_switch "switch0" - ucidef_add_switch_attr "switch0" "enable" "false" - ucidef_set_interface_lan "eth0" - ;; - mikrotik,rbm33g) - ucidef_add_switch "switch0" \ - "1:lan" "2:lan" "0:wan" "6@eth0" - ;; netgear,ex6150|\ + thunder,timecloud|\ tplink,re350-v1|\ tplink,re650-v1|\ ubnt,unifi-nanohd) - ucidef_add_switch "switch0" \ - "0:lan" "6@eth0" - ;; - xiaomi,mir3g) - ucidef_add_switch "switch0" \ - "2:lan:2" "3:lan:1" "1:wan" "6t@eth0" - ;; - xiaomi,mir3g-v2) - ucidef_add_switch "switch0" \ - "2:lan:2" "3:lan:1" "4:wan" "6@eth0" - ;; - xiaomi,mir3p) - ucidef_add_switch "switch0" \ - "1:lan:3" "2:lan:2" "3:lan:1" "4:wan" "6@eth0" + ucidef_set_interface_lan "lan" ;; *) ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" @@ -160,39 +115,6 @@ ramips_setup_macs() local label_mac="" case $board in - adslr,g7) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0xe00c)" 1) - ;; - afoundry,ew1200|\ - asiarf,ap7621-001|\ - asiarf,ap7621-nv1|\ - firefly,firewrt|\ - gehua,ghl-r-001|\ - mqmaker,witi|\ - totolink,a7000r|\ - unielec,u7621-06-16m|\ - unielec,u7621-06-64m|\ - xzwifi,creativebox-v1|\ - zbtlink,zbt-wg2626) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0xe000)" 1) - ;; - alfa-network,quad-e4g|\ - asus,rt-ac57u|\ - d-team,newifi-d2|\ - d-team,pbr-m1|\ - elecom,wrc-1167ghbk2-s|\ - elecom,wrc-1900gst|\ - elecom,wrc-2533gst|\ - lenovo,newifi-d1|\ - netis,wf2881|\ - phicomm,k2p|\ - planex,vr500|\ - samknows,whitebox-v8|\ - youhua,wr1200js|\ - youku,yk-l2|\ - zbtlink,zbt-we3526) - wan_mac=$(mtd_get_mac_binary factory 0xe006) - ;; asus,rt-ac65p|\ asus,rt-ac85p) wan_mac=$(mtd_get_mac_ascii u-boot-env et1macaddr) @@ -206,7 +128,6 @@ ramips_setup_macs() dlink,dir-860l-b1) lan_mac=$(mtd_get_mac_ascii factory lanmac) wan_mac=$(mtd_get_mac_ascii factory wanmac) - label_mac=$(mtd_get_mac_binary radio 0x4) ;; edimax,ra21s|\ edimax,rg21s) @@ -219,73 +140,17 @@ ramips_setup_macs() [ -n "$lan_mac" ] || lan_mac=$(cat /sys/class/net/eth0/address) wan_mac=$(macaddr_add "$lan_mac" 1) ;; - iodata,wn-ax1167gr|\ - iodata,wn-gx300gr|\ - mtc,wr1201|\ - netgear,r6220|\ - netgear,wndr3700-v5|\ - xiaoyu,xy-c5) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x4)" 1) - ;; - iodata,wn-ax1167gr2|\ - iodata,wn-dx1167r|\ - xiaomi,mir3g-v2) - wan_mac=$(mtd_get_mac_binary factory 0xe006) - label_mac=$wan_mac - ;; iodata,wnpr2600g) wan_mac=$(mtd_get_mac_ascii u-boot-env wanaddr) label_mac=$wan_mac ;; - iptime,a6ns-m|\ - iptime,a8004t) - wan_mac=$(mtd_get_mac_binary u-boot 0x1fc40) - ;; - jcg,jhr-ac876m) - label_mac=$(mtd_get_mac_binary factory 0x4) - wan_mac=$label_mac - ;; - mediatek,ap-mt7621a-v60) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x5)" 1) - ;; mikrotik,rb750gr3|\ mikrotik,rbm33g) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary hard_config 0x10)" 2) label_mac=$(mtd_get_mac_binary hard_config 0x10) ;; - netgear,r6260|\ - netgear,r6350|\ - netgear,r6700-v2|\ - netgear,r6800|\ - netgear,r6850) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x4)" 2) - ;; - storylink,sap-g3200u3|\ - telco-electronics,x1) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0xe006)" 1) - ;; - ubiquiti,edgerouterx|\ - ubiquiti,edgerouterx-sfp) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x22)" 1) - ;; - wevo,11acnas|\ - wevo,w2914ns-v2|\ - zio,freezio) - wan_mac=$(mtd_get_mac_binary factory 0x2e) - label_mac=$wan_mac - ;; - xiaomi,mir3g|\ - xiaomi,mir3p) - lan_mac=$(mtd_get_mac_binary factory 0xe006) - label_mac=$lan_mac - ;; - zbtlink,zbt-we1326) - wan_mac=$(mtd_get_mac_binary factory 0xe006) - label_mac=$(mtd_get_mac_binary factory 0x4) - ;; + zbtlink,zbt-we1326|\ zbtlink,zbt-wg3526-16m|\ zbtlink,zbt-wg3526-32m) - wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0xe000)" 1) label_mac=$(mtd_get_mac_binary factory 0x4) ;; esac From d2b9461a558f4a005ecaab3e681886297b51270b Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sat, 4 Apr 2020 14:52:12 +0800 Subject: [PATCH 13/35] ramips: mt7621 remove unused pinctrl groups in dts Signed-off-by: DENG Qingfang [split commit, remove leftover uart3->gpio setup] Signed-off-by: Chuanhong Guo --- target/linux/ramips/dts/mt7621_adslr_g7.dts | 2 +- target/linux/ramips/dts/mt7621_afoundry_ew1200.dts | 2 +- target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts | 2 +- target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts | 2 +- target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts | 2 +- target/linux/ramips/dts/mt7621_linksys_re6500.dts | 2 +- target/linux/ramips/dts/mt7621_mqmaker_witi.dts | 2 +- target/linux/ramips/dts/mt7621_planex_vr500.dts | 2 +- target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts | 2 +- target/linux/ramips/dts/mt7621_telco-electronics_x1.dts | 2 +- target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts | 2 +- target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_adslr_g7.dts b/target/linux/ramips/dts/mt7621_adslr_g7.dts index 2448248c31..aa3f423f9b 100644 --- a/target/linux/ramips/dts/mt7621_adslr_g7.dts +++ b/target/linux/ramips/dts/mt7621_adslr_g7.dts @@ -142,7 +142,7 @@ &state_default { gpio { - groups = "i2c", "wdt"; + groups = "i2c", "uart3", "wdt"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts index c0166c730a..97f13b0bb0 100644 --- a/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts +++ b/target/linux/ramips/dts/mt7621_afoundry_ew1200.dts @@ -148,7 +148,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "mdio"; + groups = "i2c", "uart3", "wdt"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts index 528f86f943..64170281ed 100644 --- a/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts +++ b/target/linux/ramips/dts/mt7621_d-team_pbr-m1.dts @@ -200,7 +200,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "mdio"; + groups = "wdt", "rgmii2", "jtag"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts index 28005b3f35..7a3afa00dd 100644 --- a/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts +++ b/target/linux/ramips/dts/mt7621_dlink_dir-860l-b1.dts @@ -169,7 +169,7 @@ &state_default { gpio { - groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + groups = "uart3", "jtag", "wdt"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts index 984c886ff3..f17bc4d145 100644 --- a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts +++ b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts @@ -159,7 +159,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "uart2", "uart3", "i2c"; + groups = "jtag", "uart2"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_linksys_re6500.dts b/target/linux/ramips/dts/mt7621_linksys_re6500.dts index c325b33f12..61d99009d4 100644 --- a/target/linux/ramips/dts/mt7621_linksys_re6500.dts +++ b/target/linux/ramips/dts/mt7621_linksys_re6500.dts @@ -93,7 +93,7 @@ &state_default { gpio { - groups = "i2c", "uart2", "uart3", "rgmii2"; + groups = "i2c", "uart2"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts index 6870ed94a0..87421486a9 100644 --- a/target/linux/ramips/dts/mt7621_mqmaker_witi.dts +++ b/target/linux/ramips/dts/mt7621_mqmaker_witi.dts @@ -138,7 +138,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "mdio"; + groups = "wdt"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_planex_vr500.dts b/target/linux/ramips/dts/mt7621_planex_vr500.dts index 7114ba9834..096faba8bc 100644 --- a/target/linux/ramips/dts/mt7621_planex_vr500.dts +++ b/target/linux/ramips/dts/mt7621_planex_vr500.dts @@ -116,7 +116,7 @@ &state_default { gpio { - groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + groups = "sdhci"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts index 4bd7611359..a2614869f4 100644 --- a/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts +++ b/target/linux/ramips/dts/mt7621_samknows_whitebox-v8.dts @@ -146,7 +146,7 @@ &state_default { gpio { - groups = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + groups = "sdhci"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts index 7c94db8dcb..f76dc110ac 100644 --- a/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts +++ b/target/linux/ramips/dts/mt7621_telco-electronics_x1.dts @@ -163,7 +163,7 @@ &state_default { gpio { - groups = "jtag", "uart2", "wdt", "rgmii2"; + groups = "wdt", "rgmii2"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts index 6461302154..5e8e250432 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg2626.dts @@ -147,7 +147,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "mdio"; + groups = "wdt", "rgmii2"; function = "gpio"; }; }; diff --git a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi index 9728119adf..8c9d31325a 100644 --- a/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi +++ b/target/linux/ramips/dts/mt7621_zbtlink_zbt-wg3526.dtsi @@ -149,7 +149,7 @@ &state_default { gpio { - groups = "wdt", "rgmii2", "jtag", "mdio"; + groups = "wdt", "rgmii2"; function = "gpio"; }; }; From c9f4f765c8e10aba3450fc3866c27c74f4bd645f Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Thu, 19 Mar 2020 01:10:50 +0800 Subject: [PATCH 14/35] ramips: mt7621: change default ramips_setup_interfaces configuration Most of MT7621 boards have LAN1~4 and WAN, so make this as the default Acked-by: Adrian Schmutzler Signed-off-by: DENG Qingfang --- .../mt7621/base-files/etc/board.d/02_network | 64 +------------------ 1 file changed, 1 insertion(+), 63 deletions(-) diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index f27ffcccbf..6205fab301 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -9,68 +9,6 @@ ramips_setup_interfaces() local board="$1" case $board in - adslr,g7|\ - afoundry,ew1200|\ - alfa-network,quad-e4g|\ - asus,rt-ac57u|\ - asus,rt-ac65p|\ - asus,rt-ac85p|\ - buffalo,wsr-1166dhp|\ - buffalo,wsr-600dhp|\ - dlink,dir-860l-b1|\ - d-team,newifi-d2|\ - d-team,pbr-m1|\ - edimax,ra21s|\ - edimax,rg21s|\ - elecom,wrc-1167ghbk2-s|\ - elecom,wrc-1900gst|\ - elecom,wrc-2533gst|\ - firefly,firewrt|\ - iodata,wn-ax1167gr|\ - iodata,wn-ax1167gr2|\ - iodata,wn-dx1167r|\ - iodata,wn-gx300gr|\ - iodata,wnpr2600g|\ - iptime,a6ns-m|\ - iptime,a8004t|\ - jcg,jhr-ac876m|\ - mediatek,ap-mt7621a-v60|\ - mediatek,mt7621-eval-board|\ - mikrotik,rb750gr3|\ - mqmaker,witi|\ - mtc,wr1201|\ - netgear,r6220|\ - netgear,r6260|\ - netgear,r6350|\ - netgear,r6700-v2|\ - netgear,r6800|\ - netgear,r6850|\ - netgear,wndr3700-v5|\ - netis,wf2881|\ - phicomm,k2p|\ - planex,vr500|\ - samknows,whitebox-v8|\ - storylink,sap-g3200u3|\ - telco-electronics,x1|\ - totolink,a7000r|\ - ubiquiti,edgerouterx|\ - ubiquiti,edgerouterx-sfp|\ - unielec,u7621-06-16m|\ - unielec,u7621-06-64m|\ - wevo,11acnas|\ - wevo,w2914ns-v2|\ - xiaoyu,xy-c5|\ - xzwifi,creativebox-v1|\ - youhua,wr1200js|\ - youku,yk-l2|\ - zbtlink,zbt-we1326|\ - zbtlink,zbt-we3526|\ - zbtlink,zbt-wg2626|\ - zbtlink,zbt-wg3526-16m|\ - zbtlink,zbt-wg3526-32m|\ - zio,freezio) - ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" - ;; asiarf,ap7621-001) ucidef_set_interfaces_lan_wan "lan" "wan" ;; @@ -102,7 +40,7 @@ ramips_setup_interfaces() ucidef_set_interface_lan "lan" ;; *) - ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; esac } From 1dce5c8a2835a05fbf532115a2baf0d1a8ca76c9 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sun, 1 Mar 2020 17:17:49 +0800 Subject: [PATCH 15/35] ramips: mt7621: switch kernel version to 5.4 After all dts and config changes, 4.14 no longer works on mt7621. Switch it to 5.4 directly. Signed-off-by: DENG Qingfang --- target/linux/ramips/mt7621/target.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/linux/ramips/mt7621/target.mk b/target/linux/ramips/mt7621/target.mk index c2eba1d0da..2684ea5b64 100644 --- a/target/linux/ramips/mt7621/target.mk +++ b/target/linux/ramips/mt7621/target.mk @@ -7,6 +7,8 @@ BOARDNAME:=MT7621 based boards FEATURES+=nand ramdisk rtc usb minor CPU_TYPE:=24kc +KERNEL_PATCHVER:=5.4 + define Target/Description Build firmware images for Ralink MT7621 based boards. endef From 3211c983fd7a51208f22866193df64a009b64fdb Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 11 Mar 2020 01:33:40 +0800 Subject: [PATCH 16/35] ramips: mt7621: net-label support Add support for renaming ethernet interfaces in DTS Signed-off-by: DENG Qingfang --- ...ethernet-mediatek-support-net-labels.patch | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 target/linux/ramips/patches-5.4/401-net-ethernet-mediatek-support-net-labels.patch diff --git a/target/linux/ramips/patches-5.4/401-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.4/401-net-ethernet-mediatek-support-net-labels.patch new file mode 100644 index 0000000000..e3035b95f3 --- /dev/null +++ b/target/linux/ramips/patches-5.4/401-net-ethernet-mediatek-support-net-labels.patch @@ -0,0 +1,34 @@ +From bd0f89de5476ca25e73fae829ba3e1dafae1d90d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= +Date: Fri, 21 Jun 2019 10:04:05 +0200 +Subject: [PATCH] net: ethernet: mediatek: support net-labels + +With this patch, device name can be set within dts file in the same way as dsa +port can. +Add: label = "wan"; to GMAC node. + +Signed-off-by: René van Dorst +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2757,6 +2757,7 @@ static const struct net_device_ops mtk_n + + static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + { ++ const char *name = of_get_property(np, "label", NULL); + const __be32 *_id = of_get_property(np, "reg", NULL); + struct phylink *phylink; + int phy_mode, id, err; +@@ -2847,6 +2848,9 @@ static int mtk_add_mac(struct mtk_eth *e + eth->netdev[id]->irq = eth->irq[0]; + eth->netdev[id]->dev.of_node = np; + ++ if (name) ++ strlcpy(eth->netdev[id]->name, name, IFNAMSIZ); ++ + return 0; + + free_netdev: From 5acd1ed0be0d78847cd7d9d5599526f59babaf4d Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Thu, 19 Mar 2020 19:33:27 +0800 Subject: [PATCH 17/35] ramips: mt7621: fix Ubiquiti ER-X ports names and MAC addresses The name of each user port should be eth0..4, instead of lan1..4 and there is no WAN port. Rename them to match the official firmware. To avoid conflict with the master port (gmac0), rename it to "dsa". The official firmware assigns MAC address in this way: eth0 = label mac eth1 = label mac + 1 ... eth4 = label mac + 4 Since we have switched to DSA, it's possible to use different MAC for each port. Acked-by: Adrian Schmutzler Signed-off-by: DENG Qingfang --- .../dts/mt7621_ubiquiti_edgerouterx.dtsi | 21 ++++++++++++------- .../mt7621/base-files/etc/board.d/02_network | 4 ++++ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi index 6fed4a0b7b..b10953f45e 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi @@ -25,35 +25,42 @@ &gmac0 { mtd-mac-address = <&factory 0x22>; + label = "dsa"; }; &switch0 { ports { port@0 { status = "okay"; - label = "wan"; - mtd-mac-address = <&factory 0x22>; - mtd-mac-address-increment = <1>; + label = "eth0"; }; port@1 { status = "okay"; - label = "lan1"; + label = "eth1"; + mtd-mac-address = <&factory 0x22>; + mtd-mac-address-increment = <1>; }; port@2 { status = "okay"; - label = "lan2"; + label = "eth2"; + mtd-mac-address = <&factory 0x22>; + mtd-mac-address-increment = <2>; }; port@3 { status = "okay"; - label = "lan3"; + label = "eth3"; + mtd-mac-address = <&factory 0x22>; + mtd-mac-address-increment = <3>; }; port@4 { status = "okay"; - label = "lan4"; + label = "eth4"; + mtd-mac-address = <&factory 0x22>; + mtd-mac-address-increment = <4>; }; }; }; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index 6205fab301..e2a8a9392d 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -39,6 +39,10 @@ ramips_setup_interfaces() ubnt,unifi-nanohd) ucidef_set_interface_lan "lan" ;; + ubiquiti,edgerouterx|\ + ubiquiti,edgerouterx-sfp) + ucidef_set_interface_lan "eth0 eth1 eth2 eth3 eth4" + ;; *) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" "wan" ;; From 53b66248f4ad4767f19ff243d8f839d9dea15b00 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Thu, 19 Mar 2020 19:43:39 +0800 Subject: [PATCH 18/35] ramips: use SoC I2C instead of bitbanged for Ubiquiti ER-X-SFP The original idea of bitbanged I2C is to use i2c-gpio-custom Since i2c-gpio-custom is no longer available on 5.4, use SoC I2C instead Signed-off-by: DENG Qingfang --- .../dts/mt7621_ubiquiti_edgerouterx-sfp.dts | 17 ++++++----------- .../ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi | 2 +- target/linux/ramips/image/mt7621.mk | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts index c6a64c0528..b4deb490ed 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx-sfp.dts @@ -5,18 +5,13 @@ / { model = "UBNT-ERX-SFP"; compatible = "ubiquiti,edgerouterx-sfp", "mediatek,mt7621-soc"; +}; - i2c-gpio { - compatible = "i2c-gpio"; - gpios = <&gpio 3 GPIO_ACTIVE_HIGH /* sda */ - &gpio 4 GPIO_ACTIVE_HIGH /* scl */ - >; - #address-cells = <1>; - #size-cells = <0>; +&i2c { + status = "okay"; - pca9555@25 { - compatible = "pca9555"; - reg = <0x25>; - }; + pca9555@25 { + compatible = "nxp,pca9555"; + reg = <0x25>; }; }; diff --git a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi index b10953f45e..4503f67a64 100644 --- a/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi +++ b/target/linux/ramips/dts/mt7621_ubiquiti_edgerouterx.dtsi @@ -109,7 +109,7 @@ &state_default { gpio { - groups = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag"; + groups = "uart2", "uart3", "pcie", "rgmii2", "jtag"; function = "gpio"; }; }; diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index b2590c5759..cd5be15837 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -785,7 +785,7 @@ define Device/ubiquiti_edgerouterx-sfp $(Device/ubiquiti_edgerouterx) DEVICE_VENDOR := Ubiquiti DEVICE_MODEL := EdgeRouter X-SFP - DEVICE_PACKAGES += kmod-i2c-algo-pca kmod-gpio-pca953x kmod-i2c-gpio-custom + DEVICE_PACKAGES += kmod-i2c-algo-pca kmod-gpio-pca953x SUPPORTED_DEVICES += ubnt-erx-sfp endef TARGET_DEVICES += ubiquiti_edgerouterx-sfp From c24d6111f4c86c115d879b362e00554cc6f1b211 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Fri, 20 Mar 2020 00:26:08 +0800 Subject: [PATCH 19/35] ramips: fix MikroTik 750Gr3 LAN ports names They are labeled as LAN2..LAN5 instead of LAN1..LAN4 Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts | 8 ++++---- .../linux/ramips/mt7621/base-files/etc/board.d/02_network | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts index a065ce804d..e268b233d4 100644 --- a/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts +++ b/target/linux/ramips/dts/mt7621_mikrotik_rb750gr3.dts @@ -145,22 +145,22 @@ port@1 { status = "okay"; - label = "lan1"; + label = "lan2"; }; port@2 { status = "okay"; - label = "lan2"; + label = "lan3"; }; port@3 { status = "okay"; - label = "lan3"; + label = "lan4"; }; port@4 { status = "okay"; - label = "lan4"; + label = "lan5"; }; }; }; diff --git a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network index e2a8a9392d..d73305981f 100755 --- a/target/linux/ramips/mt7621/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt7621/base-files/etc/board.d/02_network @@ -39,6 +39,9 @@ ramips_setup_interfaces() ubnt,unifi-nanohd) ucidef_set_interface_lan "lan" ;; + mikrotik,rb750gr3) + ucidef_set_interfaces_lan_wan "lan2 lan3 lan4 lan5" "wan" + ;; ubiquiti,edgerouterx|\ ubiquiti,edgerouterx-sfp) ucidef_set_interface_lan "eth0 eth1 eth2 eth3 eth4" From 657096091353f3f11e2636b2ba0e5782450076a1 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Tue, 24 Mar 2020 20:09:10 +0800 Subject: [PATCH 20/35] ramips: mt7621: introduce 'soc_device' initialization mt7621 SoC has its own 'ralink_soc_info' structure with some information about the soc itself. Pcie controller and pcie phy drivers for this soc which are still in staging git tree make uses of 'soc_device_attribute' looking for revision 'E2' in order to know if reset lines are or not inverted. This way of doing things seems to be necessary in order to make things clean and properly. Hence, introduce this 'soc_device' to be able to properly use those attributes in drivers. Also set 'data' pointer points to the struct 'ralink_soc_info' to be able to export also current soc information using this mechanism. Signed-off-by: DENG Qingfang --- ...21-introduce-soc_device-initializati.patch | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 target/linux/ramips/patches-5.4/301-MIPS-ralink-mt7621-introduce-soc_device-initializati.patch diff --git a/target/linux/ramips/patches-5.4/301-MIPS-ralink-mt7621-introduce-soc_device-initializati.patch b/target/linux/ramips/patches-5.4/301-MIPS-ralink-mt7621-introduce-soc_device-initializati.patch new file mode 100644 index 0000000000..dc3dd0d1ec --- /dev/null +++ b/target/linux/ramips/patches-5.4/301-MIPS-ralink-mt7621-introduce-soc_device-initializati.patch @@ -0,0 +1,89 @@ +From f798b7588bd7397bbab958281ca6c88d08714941 Mon Sep 17 00:00:00 2001 +From: Sergio Paracuellos +Date: Thu, 12 Mar 2020 12:29:15 +0100 +Subject: [PATCH] MIPS: ralink: mt7621: introduce 'soc_device' initialization + +mt7621 SoC has its own 'ralink_soc_info' structure with some +information about the soc itself. Pcie controller and pcie phy +drivers for this soc which are still in staging git tree make uses +of 'soc_device_attribute' looking for revision 'E2' in order to +know if reset lines are or not inverted. This way of doing things +seems to be necessary in order to make things clean and properly. +Hence, introduce this 'soc_device' to be able to properly use those +attributes in drivers. Also set 'data' pointer points to the struct +'ralink_soc_info' to be able to export also current soc information +using this mechanism. + +Cc: Paul Burton +Cc: ralf@linux-mips.org +Cc: jhogan@kernel.org +Cc: john@phrozen.org +Cc: NeilBrown +Cc: Greg Kroah-Hartman +Cc: linux-mips@vger.kernel.org + +Signed-off-by: Sergio Paracuellos +Signed-off-by: Thomas Bogendoerfer +--- + arch/mips/ralink/mt7621.c | 32 +++++++++++++++++++++++++++++++- + 1 file changed, 31 insertions(+), 1 deletion(-) + +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -7,6 +7,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -294,6 +296,33 @@ static int udelay_recal(void) + } + device_initcall(udelay_recal); + ++static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) ++{ ++ struct soc_device *soc_dev; ++ struct soc_device_attribute *soc_dev_attr; ++ ++ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); ++ if (!soc_dev_attr) ++ return; ++ ++ soc_dev_attr->soc_id = "mt7621"; ++ soc_dev_attr->family = "Ralink"; ++ ++ if (((rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK) == 1 && ++ (rev & CHIP_REV_ECO_MASK) == 1) ++ soc_dev_attr->revision = "E2"; ++ else ++ soc_dev_attr->revision = "E1"; ++ ++ soc_dev_attr->data = soc_info; ++ ++ soc_dev = soc_device_register(soc_dev_attr); ++ if (IS_ERR(soc_dev)) { ++ kfree(soc_dev_attr); ++ return; ++ } ++} ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); +@@ -345,11 +374,12 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->mem_detect = mt7621_memory_detect; + rt2880_pinmux_data = mt7621_pinmux_data; + +- + if (!register_cps_smp_ops()) + return; + if (!register_cmp_smp_ops()) + return; + if (!register_vsmp_smp_ops()) + return; ++ ++ soc_dev_init(soc_info, rev); + } From dcf7fdbdbfa0a1a3c6b666d5c2d38de4b0e64e67 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Thu, 26 Mar 2020 22:00:48 +0800 Subject: [PATCH 21/35] ramips: move swconfig to subtargets except for MT7621 As MT7621 does not use swconfig anymore, move the package swconfig to other subtargets. Signed-off-by: DENG Qingfang --- target/linux/ramips/Makefile | 3 +-- target/linux/ramips/mt7620/target.mk | 2 +- target/linux/ramips/mt76x8/target.mk | 2 +- target/linux/ramips/rt288x/target.mk | 2 +- target/linux/ramips/rt305x/target.mk | 2 +- target/linux/ramips/rt3883/target.mk | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index f57d9a817d..82576cf155 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -19,7 +19,6 @@ define Target/Description endef include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES += \ - kmod-leds-gpio kmod-gpio-button-hotplug swconfig +DEFAULT_PACKAGES += kmod-leds-gpio kmod-gpio-button-hotplug $(eval $(call BuildTarget)) diff --git a/target/linux/ramips/mt7620/target.mk b/target/linux/ramips/mt7620/target.mk index f3d450edf4..56ceaee37f 100644 --- a/target/linux/ramips/mt7620/target.mk +++ b/target/linux/ramips/mt7620/target.mk @@ -7,7 +7,7 @@ BOARDNAME:=MT7620 based boards FEATURES+=usb ramdisk CPU_TYPE:=24kc -DEFAULT_PACKAGES += kmod-rt2800-soc wpad-basic +DEFAULT_PACKAGES += kmod-rt2800-soc wpad-basic swconfig define Target/Description Build firmware images for Ralink MT7620 based boards. diff --git a/target/linux/ramips/mt76x8/target.mk b/target/linux/ramips/mt76x8/target.mk index f8b21eac02..e13a12cf58 100644 --- a/target/linux/ramips/mt76x8/target.mk +++ b/target/linux/ramips/mt76x8/target.mk @@ -7,7 +7,7 @@ BOARDNAME:=MT76x8 based boards FEATURES+=usb ramdisk CPU_TYPE:=24kc -DEFAULT_PACKAGES += kmod-mt7603 wpad-basic +DEFAULT_PACKAGES += kmod-mt7603 wpad-basic swconfig define Target/Description Build firmware images for Ralink MT76x8 based boards. diff --git a/target/linux/ramips/rt288x/target.mk b/target/linux/ramips/rt288x/target.mk index 11b5a0b520..57b0ee2251 100644 --- a/target/linux/ramips/rt288x/target.mk +++ b/target/linux/ramips/rt288x/target.mk @@ -7,7 +7,7 @@ BOARDNAME:=RT288x based boards FEATURES+=small_flash CPU_TYPE:=24kc -DEFAULT_PACKAGES += kmod-rt2800-soc wpad-mini +DEFAULT_PACKAGES += kmod-rt2800-soc wpad-mini swconfig define Target/Description Build firmware images for Ralink RT288x based boards. diff --git a/target/linux/ramips/rt305x/target.mk b/target/linux/ramips/rt305x/target.mk index e36fa637b1..51edace592 100644 --- a/target/linux/ramips/rt305x/target.mk +++ b/target/linux/ramips/rt305x/target.mk @@ -7,7 +7,7 @@ BOARDNAME:=RT3x5x/RT5350 based boards FEATURES+=usb ramdisk small_flash CPU_TYPE:=24kc -DEFAULT_PACKAGES += kmod-rt2800-soc wpad-mini +DEFAULT_PACKAGES += kmod-rt2800-soc wpad-mini swconfig define Target/Description Build firmware images for Ralink RT3x5x/RT5350 based boards. diff --git a/target/linux/ramips/rt3883/target.mk b/target/linux/ramips/rt3883/target.mk index 2cc19858e4..4a032f5437 100644 --- a/target/linux/ramips/rt3883/target.mk +++ b/target/linux/ramips/rt3883/target.mk @@ -7,7 +7,7 @@ BOARDNAME:=RT3662/RT3883 based boards FEATURES+=usb pci small_flash CPU_TYPE:=74kc -DEFAULT_PACKAGES += kmod-rt2800-pci kmod-rt2800-soc wpad-mini +DEFAULT_PACKAGES += kmod-rt2800-pci kmod-rt2800-soc wpad-mini swconfig define Target/Description Build firmware images for Ralink RT3662/RT3883 based boards. From 437aaae6ca6fb30a5647b9478f7830b13c1b2dff Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 1 Apr 2020 16:42:08 +0800 Subject: [PATCH 22/35] Revert "ramips: mt7621: disable images for gehua_ghl-r-001" This reverts commit 28080d54d217fb4ab112e079f69462fee695dbf8. Support for MX25L25635F flash is fixed upstream Signed-off-by: DENG Qingfang --- target/linux/ramips/image/mt7621.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index cd5be15837..a4484b408f 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -308,7 +308,6 @@ define Device/gehua_ghl-r-001 DEVICE_MODEL := GHL-R-001 DEVICE_PACKAGES := kmod-mt7603 kmod-mt76x2 kmod-usb3 \ kmod-usb-ledtrig-usbport wpad-basic - DEFAULT := n endef TARGET_DEVICES += gehua_ghl-r-001 From 92daa06f22c5268277be92b55a28de5e26c19636 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Thu, 26 Mar 2020 23:14:05 +0800 Subject: [PATCH 23/35] ramips: mt7621: drop obsolete mx25l25635f dts hack 5.4 kernel has fixed this issue, so the hack is no longer needed. Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts | 2 +- target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts index b501034b7f..602fd846cb 100644 --- a/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts +++ b/target/linux/ramips/dts/mt7621_gehua_ghl-r-001.dts @@ -49,7 +49,7 @@ status = "okay"; flash@0 { - compatible = "mx25l25635f", "jedec,spi-nor"; + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; m25p,fast-read; diff --git a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts index f17bc4d145..711ddbf398 100644 --- a/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts +++ b/target/linux/ramips/dts/mt7621_lenovo_newifi-d1.dts @@ -77,7 +77,7 @@ status = "okay"; m25p80@0 { - compatible = "mx25l25635f", "jedec,spi-nor"; + compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <25000000>; m25p,fast-read; From 10f27c6f00ecfe75fa5a0a5817f3d66f15f847ea Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Wed, 1 Apr 2020 11:19:12 +0800 Subject: [PATCH 24/35] ramips: mt7621: add new NAND driver Add new NAND driver for MT7621 Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621.dtsi | 14 +- target/linux/ramips/mt7621/config-5.4 | 1 + ...driver-support-for-MT7621-nand-flash.patch | 1398 +++++++++++++++++ ...documentation-for-mt7621-nand-driver.patch | 85 + 4 files changed, 1496 insertions(+), 2 deletions(-) create mode 100644 target/linux/ramips/patches-5.4/0300-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch create mode 100644 target/linux/ramips/patches-5.4/0301-dt-bindings-add-documentation-for-mt7621-nand-driver.patch diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi index cc387519e4..63befa1fdc 100644 --- a/target/linux/ramips/dts/mt7621.dtsi +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -414,13 +414,23 @@ }; }; + nficlock: nficlock { + #clock-cells = <0>; + compatible = "fixed-clock"; + + clock-frequency = <125000000>; + }; + nand: nand@1e003000 { status = "disabled"; - compatible = "mtk,mt7621-nand"; - bank-width = <2>; + compatible = "mediatek,mt7621-nfc"; reg = <0x1e003000 0x800 0x1e003800 0x800>; + reg-names = "nfi", "ecc"; + + clocks = <&nficlock>; + clock-names = "nfi_clk"; }; ethsys: syscon@1e000000 { diff --git a/target/linux/ramips/mt7621/config-5.4 b/target/linux/ramips/mt7621/config-5.4 index 20fb53c69c..9fb90b8625 100644 --- a/target/linux/ramips/mt7621/config-5.4 +++ b/target/linux/ramips/mt7621/config-5.4 @@ -202,6 +202,7 @@ CONFIG_MT7621_WDT=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_NAND_CORE=y CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MT7621=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_RAW_NAND=y CONFIG_MTD_SPI_NOR=y diff --git a/target/linux/ramips/patches-5.4/0300-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch b/target/linux/ramips/patches-5.4/0300-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch new file mode 100644 index 0000000000..f65092afb1 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0300-mtd-rawnand-add-driver-support-for-MT7621-nand-flash.patch @@ -0,0 +1,1398 @@ +From e84e2430ee0e483842b4ff013ae8a6e7e2fa2734 Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 1 Apr 2020 02:07:58 +0800 +Subject: [PATCH 1/2] mtd: rawnand: add driver support for MT7621 nand + flash controller + +This patch adds NAND flash controller driver for MediaTek MT7621 SoC. + +The NAND flash controller is similar with controllers described in +mtk_nand.c, except that the controller from MT7621 doesn't support DMA +transmission, and some registers' offset and fields are different. + +Signed-off-by: Weijie Gao +--- + drivers/mtd/nand/raw/Kconfig | 8 + + drivers/mtd/nand/raw/Makefile | 1 + + drivers/mtd/nand/raw/mt7621_nand.c | 1348 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 1357 insertions(+) + create mode 100644 drivers/mtd/nand/raw/mt7621_nand.c + +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -391,6 +391,14 @@ config MTD_NAND_QCOM + Enables support for NAND flash chips on SoCs containing the EBI2 NAND + controller. This controller is found on IPQ806x SoC. + ++config MTD_NAND_MT7621 ++ tristate "MT7621 NAND controller" ++ depends on SOC_MT7621 || COMPILE_TEST ++ depends on HAS_IOMEM ++ help ++ Enables support for NAND controller on MT7621 SoC. ++ This driver uses PIO mode for data transmission instead of DMA mode. ++ + config MTD_NAND_MTK + tristate "MTK NAND controller" + depends on ARCH_MEDIATEK || COMPILE_TEST +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI) += sunxi_n + obj-$(CONFIG_MTD_NAND_HISI504) += hisi504_nand.o + obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand/ + obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o ++obj-$(CONFIG_MTD_NAND_MT7621) += mt7621_nand.o + obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o + obj-$(CONFIG_MTD_NAND_MXIC) += mxic_nand.o + obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o +--- /dev/null ++++ b/drivers/mtd/nand/raw/mt7621_nand.c +@@ -0,0 +1,1348 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * MediaTek MT7621 NAND Flash Controller driver ++ * ++ * Copyright (C) 2020 MediaTek Inc. All Rights Reserved. ++ * ++ * Author: Weijie Gao ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* NFI core registers */ ++#define NFI_CNFG 0x000 ++#define CNFG_OP_MODE_S 12 ++#define CNFG_OP_MODE_M GENMASK(14, 12) ++#define CNFG_OP_CUSTOM 6 ++#define CNFG_AUTO_FMT_EN BIT(9) ++#define CNFG_HW_ECC_EN BIT(8) ++#define CNFG_BYTE_RW BIT(6) ++#define CNFG_READ_MODE BIT(1) ++ ++#define NFI_PAGEFMT 0x004 ++#define PAGEFMT_FDM_ECC_S 12 ++#define PAGEFMT_FDM_ECC_M GENMASK(15, 12) ++#define PAGEFMT_FDM_S 8 ++#define PAGEFMT_FDM_M GENMASK(11, 8) ++#define PAGEFMT_SPARE_S 4 ++#define PAGEFMT_SPARE_M GENMASK(5, 4) ++#define PAGEFMT_PAGE_S 0 ++#define PAGEFMT_PAGE_M GENMASK(1, 0) ++ ++#define NFI_CON 0x008 ++#define CON_NFI_SEC_S 12 ++#define CON_NFI_SEC_M GENMASK(15, 12) ++#define CON_NFI_BWR BIT(9) ++#define CON_NFI_BRD BIT(8) ++#define CON_NFI_RST BIT(1) ++#define CON_FIFO_FLUSH BIT(0) ++ ++#define NFI_ACCCON 0x00c ++#define ACCCON_POECS_S 28 ++#define ACCCON_POECS_MAX 0x0f ++#define ACCCON_POECS_DEF 3 ++#define ACCCON_PRECS_S 22 ++#define ACCCON_PRECS_MAX 0x3f ++#define ACCCON_PRECS_DEF 3 ++#define ACCCON_C2R_S 16 ++#define ACCCON_C2R_MAX 0x3f ++#define ACCCON_C2R_DEF 7 ++#define ACCCON_W2R_S 12 ++#define ACCCON_W2R_MAX 0x0f ++#define ACCCON_W2R_DEF 7 ++#define ACCCON_WH_S 8 ++#define ACCCON_WH_MAX 0x0f ++#define ACCCON_WH_DEF 15 ++#define ACCCON_WST_S 4 ++#define ACCCON_WST_MAX 0x0f ++#define ACCCON_WST_DEF 15 ++#define ACCCON_WST_MIN 3 ++#define ACCCON_RLT_S 0 ++#define ACCCON_RLT_MAX 0x0f ++#define ACCCON_RLT_DEF 15 ++#define ACCCON_RLT_MIN 3 ++ ++#define NFI_CMD 0x020 ++ ++#define NFI_ADDRNOB 0x030 ++#define ADDR_ROW_NOB_S 4 ++#define ADDR_ROW_NOB_M GENMASK(6, 4) ++#define ADDR_COL_NOB_S 0 ++#define ADDR_COL_NOB_M GENMASK(2, 0) ++ ++#define NFI_COLADDR 0x034 ++#define NFI_ROWADDR 0x038 ++ ++#define NFI_STRDATA 0x040 ++#define STR_DATA BIT(0) ++ ++#define NFI_CNRNB 0x044 ++#define CB2R_TIME_S 4 ++#define CB2R_TIME_M GENMASK(7, 4) ++#define STR_CNRNB BIT(0) ++ ++#define NFI_DATAW 0x050 ++#define NFI_DATAR 0x054 ++ ++#define NFI_PIO_DIRDY 0x058 ++#define PIO_DIRDY BIT(0) ++ ++#define NFI_STA 0x060 ++#define STA_NFI_FSM_S 16 ++#define STA_NFI_FSM_M GENMASK(19, 16) ++#define STA_FSM_CUSTOM_DATA 14 ++#define STA_BUSY BIT(8) ++#define STA_ADDR BIT(1) ++#define STA_CMD BIT(0) ++ ++#define NFI_ADDRCNTR 0x070 ++#define SEC_CNTR_S 12 ++#define SEC_CNTR_M GENMASK(15, 12) ++#define SEC_ADDR_S 0 ++#define SEC_ADDR_M GENMASK(9, 0) ++ ++#define NFI_CSEL 0x090 ++#define CSEL_S 0 ++#define CSEL_M GENMASK(1, 0) ++ ++#define NFI_FDM0L 0x0a0 ++#define NFI_FDML(n) (0x0a0 + ((n) << 3)) ++ ++#define NFI_FDM0M 0x0a4 ++#define NFI_FDMM(n) (0x0a4 + ((n) << 3)) ++ ++#define NFI_MASTER_STA 0x210 ++#define MAS_ADDR GENMASK(11, 9) ++#define MAS_RD GENMASK(8, 6) ++#define MAS_WR GENMASK(5, 3) ++#define MAS_RDDLY GENMASK(2, 0) ++ ++/* ECC engine registers */ ++#define ECC_ENCCON 0x000 ++#define ENC_EN BIT(0) ++ ++#define ECC_ENCCNFG 0x004 ++#define ENC_CNFG_MSG_S 16 ++#define ENC_CNFG_MSG_M GENMASK(28, 16) ++#define ENC_MODE_S 4 ++#define ENC_MODE_M GENMASK(5, 4) ++#define ENC_MODE_NFI 1 ++#define ENC_TNUM_S 0 ++#define ENC_TNUM_M GENMASK(2, 0) ++ ++#define ECC_ENCIDLE 0x00c ++#define ENC_IDLE BIT(0) ++ ++#define ECC_DECCON 0x100 ++#define DEC_EN BIT(0) ++ ++#define ECC_DECCNFG 0x104 ++#define DEC_EMPTY_EN BIT(31) ++#define DEC_CS_S 16 ++#define DEC_CS_M GENMASK(28, 16) ++#define DEC_CON_S 12 ++#define DEC_CON_M GENMASK(13, 12) ++#define DEC_CON_EL 2 ++#define DEC_MODE_S 4 ++#define DEC_MODE_M GENMASK(5, 4) ++#define DEC_MODE_NFI 1 ++#define DEC_TNUM_S 0 ++#define DEC_TNUM_M GENMASK(2, 0) ++ ++#define ECC_DECIDLE 0x10c ++#define DEC_IDLE BIT(1) ++ ++#define ECC_DECENUM 0x114 ++#define ERRNUM_S 2 ++#define ERRNUM_M GENMASK(3, 0) ++ ++#define ECC_DECDONE 0x118 ++#define DEC_DONE7 BIT(7) ++#define DEC_DONE6 BIT(6) ++#define DEC_DONE5 BIT(5) ++#define DEC_DONE4 BIT(4) ++#define DEC_DONE3 BIT(3) ++#define DEC_DONE2 BIT(2) ++#define DEC_DONE1 BIT(1) ++#define DEC_DONE0 BIT(0) ++ ++#define ECC_DECEL(n) (0x11c + (n) * 4) ++#define DEC_EL_ODD_S 16 ++#define DEC_EL_EVEN_S 0 ++#define DEC_EL_M 0x1fff ++#define DEC_EL_BYTE_POS_S 3 ++#define DEC_EL_BIT_POS_M GENMASK(3, 0) ++ ++#define ECC_FDMADDR 0x13c ++ ++/* ENCIDLE and DECIDLE */ ++#define ECC_IDLE BIT(0) ++ ++#define ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt) \ ++ ((tpoecs) << ACCCON_POECS_S | (tprecs) << ACCCON_PRECS_S | \ ++ (tc2r) << ACCCON_C2R_S | (tw2r) << ACCCON_W2R_S | \ ++ (twh) << ACCCON_WH_S | (twst) << ACCCON_WST_S | (trlt)) ++ ++#define MASTER_STA_MASK (MAS_ADDR | MAS_RD | MAS_WR | \ ++ MAS_RDDLY) ++#define NFI_RESET_TIMEOUT 1000000 ++#define NFI_CORE_TIMEOUT 500000 ++#define ECC_ENGINE_TIMEOUT 500000 ++ ++#define ECC_SECTOR_SIZE 512 ++#define ECC_PARITY_BITS 13 ++ ++#define NFI_FDM_SIZE 8 ++ ++#define MT7621_NFC_NAME "mt7621-nand" ++ ++struct mt7621_nfc { ++ struct nand_controller controller; ++ struct nand_chip nand; ++ struct clk *nfi_clk; ++ struct device *dev; ++ ++ void __iomem *nfi_regs; ++ void __iomem *ecc_regs; ++ ++ u32 spare_per_sector; ++}; ++ ++static const u16 mt7621_nfi_page_size[] = { SZ_512, SZ_2K, SZ_4K }; ++static const u8 mt7621_nfi_spare_size[] = { 16, 26, 27, 28 }; ++static const u8 mt7621_ecc_strength[] = { 4, 6, 8, 10, 12 }; ++ ++static inline u32 nfi_read32(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readl(nfc->nfi_regs + reg); ++} ++ ++static inline void nfi_write32(struct mt7621_nfc *nfc, u32 reg, u32 val) ++{ ++ writel(val, nfc->nfi_regs + reg); ++} ++ ++static inline u16 nfi_read16(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readw(nfc->nfi_regs + reg); ++} ++ ++static inline void nfi_write16(struct mt7621_nfc *nfc, u32 reg, u16 val) ++{ ++ writew(val, nfc->nfi_regs + reg); ++} ++ ++static inline void ecc_write16(struct mt7621_nfc *nfc, u32 reg, u16 val) ++{ ++ writew(val, nfc->ecc_regs + reg); ++} ++ ++static inline u32 ecc_read32(struct mt7621_nfc *nfc, u32 reg) ++{ ++ return readl(nfc->ecc_regs + reg); ++} ++ ++static inline void ecc_write32(struct mt7621_nfc *nfc, u32 reg, u32 val) ++{ ++ return writel(val, nfc->ecc_regs + reg); ++} ++ ++static inline u8 *oob_fdm_ptr(struct nand_chip *nand, int sect) ++{ ++ return nand->oob_poi + sect * NFI_FDM_SIZE; ++} ++ ++static inline u8 *oob_ecc_ptr(struct mt7621_nfc *nfc, int sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ ++ return nand->oob_poi + nand->ecc.steps * NFI_FDM_SIZE + ++ sect * (nfc->spare_per_sector - NFI_FDM_SIZE); ++} ++ ++static inline u8 *page_data_ptr(struct nand_chip *nand, const u8 *buf, ++ int sect) ++{ ++ return (u8 *)buf + sect * nand->ecc.size; ++} ++ ++static int mt7621_ecc_wait_idle(struct mt7621_nfc *nfc, u32 reg) ++{ ++ struct device *dev = nfc->dev; ++ u32 val; ++ int ret; ++ ++ ret = readw_poll_timeout_atomic(nfc->ecc_regs + reg, val, ++ val & ECC_IDLE, 10, ++ ECC_ENGINE_TIMEOUT); ++ if (ret) { ++ dev_warn(dev, "ECC engine timed out entering idle mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_ecc_decoder_wait_done(struct mt7621_nfc *nfc, u32 sect) ++{ ++ struct device *dev = nfc->dev; ++ u32 val; ++ int ret; ++ ++ ret = readw_poll_timeout_atomic(nfc->ecc_regs + ECC_DECDONE, val, ++ val & (1 << sect), 10, ++ ECC_ENGINE_TIMEOUT); ++ ++ if (ret) { ++ dev_warn(dev, "ECC decoder for sector %d timed out\n", ++ sect); ++ return -ETIMEDOUT; ++ } ++ ++ return 0; ++} ++ ++static void mt7621_ecc_encoder_op(struct mt7621_nfc *nfc, bool enable) ++{ ++ mt7621_ecc_wait_idle(nfc, ECC_ENCIDLE); ++ ecc_write16(nfc, ECC_ENCCON, enable ? ENC_EN : 0); ++} ++ ++static void mt7621_ecc_decoder_op(struct mt7621_nfc *nfc, bool enable) ++{ ++ mt7621_ecc_wait_idle(nfc, ECC_DECIDLE); ++ ecc_write16(nfc, ECC_DECCON, enable ? DEC_EN : 0); ++} ++ ++static int mt7621_ecc_correct_check(struct mt7621_nfc *nfc, u8 *sector_buf, ++ u8 *fdm_buf, u32 sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 decnum, num_error_bits, fdm_end_bits; ++ u32 error_locations, error_bit_loc; ++ u32 error_byte_pos, error_bit_pos; ++ int bitflips = 0; ++ u32 i; ++ ++ decnum = ecc_read32(nfc, ECC_DECENUM); ++ num_error_bits = (decnum >> (sect << ERRNUM_S)) & ERRNUM_M; ++ fdm_end_bits = (nand->ecc.size + NFI_FDM_SIZE) << 3; ++ ++ if (!num_error_bits) ++ return 0; ++ ++ if (num_error_bits == ERRNUM_M) ++ return -1; ++ ++ for (i = 0; i < num_error_bits; i++) { ++ error_locations = ecc_read32(nfc, ECC_DECEL(i / 2)); ++ error_bit_loc = (error_locations >> ((i % 2) * DEC_EL_ODD_S)) & ++ DEC_EL_M; ++ error_byte_pos = error_bit_loc >> DEC_EL_BYTE_POS_S; ++ error_bit_pos = error_bit_loc & DEC_EL_BIT_POS_M; ++ ++ if (error_bit_loc < (nand->ecc.size << 3)) { ++ if (sector_buf) { ++ sector_buf[error_byte_pos] ^= ++ (1 << error_bit_pos); ++ } ++ } else if (error_bit_loc < fdm_end_bits) { ++ if (fdm_buf) { ++ fdm_buf[error_byte_pos - nand->ecc.size] ^= ++ (1 << error_bit_pos); ++ } ++ } ++ ++ bitflips++; ++ } ++ ++ return bitflips; ++} ++ ++static int mt7621_nfc_wait_write_completion(struct mt7621_nfc *nfc, ++ struct nand_chip *nand) ++{ ++ struct device *dev = nfc->dev; ++ u16 val; ++ int ret; ++ ++ ret = readw_poll_timeout_atomic(nfc->nfi_regs + NFI_ADDRCNTR, val, ++ ((val & SEC_CNTR_M) >> SEC_CNTR_S) >= nand->ecc.steps, 10, ++ NFI_CORE_TIMEOUT); ++ ++ if (ret) { ++ dev_warn(dev, "NFI core write operation timed out\n"); ++ return -ETIMEDOUT; ++ } ++ ++ return ret; ++} ++ ++static void mt7621_nfc_hw_reset(struct mt7621_nfc *nfc) ++{ ++ u32 val; ++ int ret; ++ ++ /* reset all registers and force the NFI master to terminate */ ++ nfi_write16(nfc, NFI_CON, CON_FIFO_FLUSH | CON_NFI_RST); ++ ++ /* wait for the master to finish the last transaction */ ++ ret = readw_poll_timeout(nfc->nfi_regs + NFI_MASTER_STA, val, ++ !(val & MASTER_STA_MASK), 50, ++ NFI_RESET_TIMEOUT); ++ if (ret) { ++ dev_warn(nfc->dev, "Failed to reset NFI master in %dms\n", ++ NFI_RESET_TIMEOUT); ++ } ++ ++ /* ensure any status register affected by the NFI master is reset */ ++ nfi_write16(nfc, NFI_CON, CON_FIFO_FLUSH | CON_NFI_RST); ++ nfi_write16(nfc, NFI_STRDATA, 0); ++} ++ ++static inline void mt7621_nfc_hw_init(struct mt7621_nfc *nfc) ++{ ++ u32 acccon; ++ ++ /* ++ * CNRNB: nand ready/busy register ++ * ------------------------------- ++ * 7:4: timeout register for polling the NAND busy/ready signal ++ * 0 : poll the status of the busy/ready signal after [7:4]*16 cycles. ++ */ ++ nfi_write16(nfc, NFI_CNRNB, CB2R_TIME_M | STR_CNRNB); ++ ++ mt7621_nfc_hw_reset(nfc); ++ ++ /* Apply default access timing */ ++ acccon = ACCTIMING(ACCCON_POECS_DEF, ACCCON_PRECS_DEF, ACCCON_C2R_DEF, ++ ACCCON_W2R_DEF, ACCCON_WH_DEF, ACCCON_WST_DEF, ++ ACCCON_RLT_DEF); ++ ++ nfi_write32(nfc, NFI_ACCCON, acccon); ++} ++ ++static int mt7621_nfc_send_command(struct mt7621_nfc *nfc, u8 command) ++{ ++ struct device *dev = nfc->dev; ++ u32 val; ++ int ret; ++ ++ nfi_write32(nfc, NFI_CMD, command); ++ ++ ret = readl_poll_timeout_atomic(nfc->nfi_regs + NFI_STA, val, ++ !(val & STA_CMD), 10, ++ NFI_CORE_TIMEOUT); ++ if (ret) { ++ dev_warn(dev, "NFI core timed out entering command mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_nfc_send_address_byte(struct mt7621_nfc *nfc, int addr) ++{ ++ struct device *dev = nfc->dev; ++ u32 val; ++ int ret; ++ ++ nfi_write32(nfc, NFI_COLADDR, addr); ++ nfi_write32(nfc, NFI_ROWADDR, 0); ++ nfi_write16(nfc, NFI_ADDRNOB, 1); ++ ++ ret = readl_poll_timeout_atomic(nfc->nfi_regs + NFI_STA, val, ++ !(val & STA_ADDR), 10, ++ NFI_CORE_TIMEOUT); ++ if (ret) { ++ dev_warn(dev, "NFI core timed out entering address mode\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_nfc_send_address(struct mt7621_nfc *nfc, const u8 *addr, ++ unsigned int naddrs) ++{ ++ int ret; ++ ++ while (naddrs) { ++ ret = mt7621_nfc_send_address_byte(nfc, *addr); ++ if (ret) ++ return ret; ++ ++ addr++; ++ naddrs--; ++ } ++ ++ return 0; ++} ++ ++static void mt7621_nfc_wait_pio_ready(struct mt7621_nfc *nfc) ++{ ++ struct device *dev = nfc->dev; ++ int ret; ++ u16 val; ++ ++ ret = readw_poll_timeout_atomic(nfc->nfi_regs + NFI_PIO_DIRDY, val, ++ val & PIO_DIRDY, 10, ++ NFI_CORE_TIMEOUT); ++ if (ret < 0) ++ dev_err(dev, "NFI core PIO mode not ready\n"); ++} ++ ++static u32 mt7621_nfc_pio_read(struct mt7621_nfc *nfc, bool br) ++{ ++ u32 reg; ++ ++ /* after each byte read, the NFI_STA reg is reset by the hardware */ ++ reg = (nfi_read32(nfc, NFI_STA) & STA_NFI_FSM_M) >> STA_NFI_FSM_S; ++ if (reg != STA_FSM_CUSTOM_DATA) { ++ reg = nfi_read16(nfc, NFI_CNFG); ++ reg |= CNFG_READ_MODE | CNFG_BYTE_RW; ++ if (!br) ++ reg &= ~CNFG_BYTE_RW; ++ nfi_write16(nfc, NFI_CNFG, reg); ++ ++ /* ++ * set to max sector to allow the HW to continue reading over ++ * unaligned accesses ++ */ ++ nfi_write16(nfc, NFI_CON, CON_NFI_SEC_M | CON_NFI_BRD); ++ ++ /* trigger to fetch data */ ++ nfi_write16(nfc, NFI_STRDATA, STR_DATA); ++ } ++ ++ mt7621_nfc_wait_pio_ready(nfc); ++ ++ return nfi_read32(nfc, NFI_DATAR); ++} ++ ++static void mt7621_nfc_read_data(struct mt7621_nfc *nfc, u8 *buf, u32 len) ++{ ++ while (((uintptr_t)buf & 3) && len) { ++ *buf = mt7621_nfc_pio_read(nfc, true); ++ buf++; ++ len--; ++ } ++ ++ while (len >= 4) { ++ *(u32 *)buf = mt7621_nfc_pio_read(nfc, false); ++ buf += 4; ++ len -= 4; ++ } ++ ++ while (len) { ++ *buf = mt7621_nfc_pio_read(nfc, true); ++ buf++; ++ len--; ++ } ++} ++ ++static void mt7621_nfc_read_data_discard(struct mt7621_nfc *nfc, u32 len) ++{ ++ while (len >= 4) { ++ mt7621_nfc_pio_read(nfc, false); ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_read(nfc, true); ++ len--; ++ } ++} ++ ++static void mt7621_nfc_pio_write(struct mt7621_nfc *nfc, u32 val, bool bw) ++{ ++ u32 reg; ++ ++ reg = (nfi_read32(nfc, NFI_STA) & STA_NFI_FSM_M) >> STA_NFI_FSM_S; ++ if (reg != STA_FSM_CUSTOM_DATA) { ++ reg = nfi_read16(nfc, NFI_CNFG); ++ reg &= ~(CNFG_READ_MODE | CNFG_BYTE_RW); ++ if (bw) ++ reg |= CNFG_BYTE_RW; ++ nfi_write16(nfc, NFI_CNFG, reg); ++ ++ nfi_write16(nfc, NFI_CON, CON_NFI_SEC_M | CON_NFI_BWR); ++ nfi_write16(nfc, NFI_STRDATA, STR_DATA); ++ } ++ ++ mt7621_nfc_wait_pio_ready(nfc); ++ nfi_write32(nfc, NFI_DATAW, val); ++} ++ ++static void mt7621_nfc_write_data(struct mt7621_nfc *nfc, const u8 *buf, ++ u32 len) ++{ ++ while (((uintptr_t)buf & 3) && len) { ++ mt7621_nfc_pio_write(nfc, *buf, true); ++ buf++; ++ len--; ++ } ++ ++ while (len >= 4) { ++ mt7621_nfc_pio_write(nfc, *(const u32 *)buf, false); ++ buf += 4; ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_write(nfc, *buf, true); ++ buf++; ++ len--; ++ } ++} ++ ++static void mt7621_nfc_write_data_empty(struct mt7621_nfc *nfc, u32 len) ++{ ++ while (len >= 4) { ++ mt7621_nfc_pio_write(nfc, 0xffffffff, false); ++ len -= 4; ++ } ++ ++ while (len) { ++ mt7621_nfc_pio_write(nfc, 0xff, true); ++ len--; ++ } ++} ++ ++static int mt7621_nfc_dev_ready(struct mt7621_nfc *nfc, ++ unsigned int timeout_ms) ++{ ++ u32 val; ++ ++ return readl_poll_timeout_atomic(nfc->nfi_regs + NFI_STA, val, ++ !(val & STA_BUSY), 10, ++ timeout_ms * 1000); ++} ++ ++static int mt7621_nfc_exec_instr(struct nand_chip *nand, ++ const struct nand_op_instr *instr) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ ++ switch (instr->type) { ++ case NAND_OP_CMD_INSTR: ++ mt7621_nfc_hw_reset(nfc); ++ nfi_write16(nfc, NFI_CNFG, CNFG_OP_CUSTOM << CNFG_OP_MODE_S); ++ return mt7621_nfc_send_command(nfc, instr->ctx.cmd.opcode); ++ case NAND_OP_ADDR_INSTR: ++ return mt7621_nfc_send_address(nfc, instr->ctx.addr.addrs, ++ instr->ctx.addr.naddrs); ++ case NAND_OP_DATA_IN_INSTR: ++ mt7621_nfc_read_data(nfc, instr->ctx.data.buf.in, ++ instr->ctx.data.len); ++ return 0; ++ case NAND_OP_DATA_OUT_INSTR: ++ mt7621_nfc_write_data(nfc, instr->ctx.data.buf.out, ++ instr->ctx.data.len); ++ return 0; ++ case NAND_OP_WAITRDY_INSTR: ++ return mt7621_nfc_dev_ready(nfc, ++ instr->ctx.waitrdy.timeout_ms); ++ default: ++ WARN_ONCE(1, "unsupported NAND instruction type: %d\n", ++ instr->type); ++ ++ return -EINVAL; ++ } ++} ++ ++static int mt7621_nfc_exec_op(struct nand_chip *nand, ++ const struct nand_operation *op, bool check_only) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int i, ret; ++ ++ if (check_only) ++ return 0; ++ ++ /* Only CS0 available */ ++ nfi_write16(nfc, NFI_CSEL, 0); ++ ++ for (i = 0; i < op->ninstrs; i++) { ++ ret = mt7621_nfc_exec_instr(nand, &op->instrs[i]); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_nfc_setup_data_interface(struct nand_chip *nand, int csline, ++ const struct nand_data_interface *conf) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ const struct nand_sdr_timings *timings; ++ u32 acccon, temp, rate, tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt; ++ ++ if (!nfc->nfi_clk) ++ return -ENOTSUPP; ++ ++ timings = nand_get_sdr_timings(conf); ++ if (IS_ERR(timings)) ++ return -ENOTSUPP; ++ ++ rate = clk_get_rate(nfc->nfi_clk); ++ ++ /* turn clock rate into KHZ */ ++ rate /= 1000; ++ ++ tpoecs = max(timings->tALH_min, timings->tCLH_min) / 1000; ++ tpoecs = DIV_ROUND_UP(tpoecs * rate, 1000000); ++ tpoecs = min_t(u32, tpoecs, ACCCON_POECS_MAX); ++ ++ tprecs = max(timings->tCLS_min, timings->tALS_min) / 1000; ++ tprecs = DIV_ROUND_UP(tprecs * rate, 1000000); ++ tprecs = min_t(u32, tprecs, ACCCON_PRECS_MAX); ++ ++ /* sdr interface has no tCR which means CE# low to RE# low */ ++ tc2r = 0; ++ ++ tw2r = timings->tWHR_min / 1000; ++ tw2r = DIV_ROUND_UP(tw2r * rate, 1000000); ++ tw2r = DIV_ROUND_UP(tw2r - 1, 2); ++ tw2r = min_t(u32, tw2r, ACCCON_W2R_MAX); ++ ++ twh = max(timings->tREH_min, timings->tWH_min) / 1000; ++ twh = DIV_ROUND_UP(twh * rate, 1000000) - 1; ++ twh = min_t(u32, twh, ACCCON_WH_MAX); ++ ++ /* Calculate real WE#/RE# hold time in nanosecond */ ++ temp = (twh + 1) * 1000000 / rate; ++ /* nanosecond to picosecond */ ++ temp *= 1000; ++ ++ /* ++ * WE# low level time should be expaned to meet WE# pulse time ++ * and WE# cycle time at the same time. ++ */ ++ if (temp < timings->tWC_min) ++ twst = timings->tWC_min - temp; ++ else ++ twst = 0; ++ twst = max(timings->tWP_min, twst) / 1000; ++ twst = DIV_ROUND_UP(twst * rate, 1000000) - 1; ++ twst = min_t(u32, twst, ACCCON_WST_MAX); ++ ++ /* ++ * RE# low level time should be expaned to meet RE# pulse time ++ * and RE# cycle time at the same time. ++ */ ++ if (temp < timings->tRC_min) ++ trlt = timings->tRC_min - temp; ++ else ++ trlt = 0; ++ trlt = max(trlt, timings->tRP_min) / 1000; ++ trlt = DIV_ROUND_UP(trlt * rate, 1000000) - 1; ++ trlt = min_t(u32, trlt, ACCCON_RLT_MAX); ++ ++ if (csline == NAND_DATA_IFACE_CHECK_ONLY) { ++ if (twst < ACCCON_WST_MIN || trlt < ACCCON_RLT_MIN) ++ return -ENOTSUPP; ++ } ++ ++ acccon = ACCTIMING(tpoecs, tprecs, tc2r, tw2r, twh, twst, trlt); ++ ++ dev_info(nfc->dev, "Using programmed access timing: %08x\n", acccon); ++ ++ nfi_write32(nfc, NFI_ACCCON, acccon); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_calc_ecc_strength(struct mt7621_nfc *nfc, ++ u32 avail_ecc_bytes) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 strength; ++ int i; ++ ++ strength = avail_ecc_bytes * 8 / ECC_PARITY_BITS; ++ ++ /* Find the closest supported ecc strength */ ++ for (i = ARRAY_SIZE(mt7621_ecc_strength) - 1; i >= 0; i--) { ++ if (mt7621_ecc_strength[i] <= strength) ++ break; ++ } ++ ++ if (unlikely(i < 0)) { ++ dev_err(nfc->dev, "OOB size (%u) is not supported\n", ++ mtd->oobsize); ++ return -EINVAL; ++ } ++ ++ nand->ecc.strength = mt7621_ecc_strength[i]; ++ nand->ecc.bytes = ++ DIV_ROUND_UP(nand->ecc.strength * ECC_PARITY_BITS, 8); ++ ++ dev_info(nfc->dev, "ECC strength adjusted to %u bits\n", ++ nand->ecc.strength); ++ ++ return i; ++} ++ ++static int mt7621_nfc_set_spare_per_sector(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 size; ++ int i; ++ ++ size = nand->ecc.bytes + NFI_FDM_SIZE; ++ ++ /* Find the closest supported spare size */ ++ for (i = 0; i < ARRAY_SIZE(mt7621_nfi_spare_size); i++) { ++ if (mt7621_nfi_spare_size[i] >= size) ++ break; ++ } ++ ++ if (unlikely(i >= ARRAY_SIZE(mt7621_nfi_spare_size))) { ++ dev_err(nfc->dev, "OOB size (%u) is not supported\n", ++ mtd->oobsize); ++ return -EINVAL; ++ } ++ ++ nfc->spare_per_sector = mt7621_nfi_spare_size[i]; ++ ++ return i; ++} ++ ++static int mt7621_nfc_ecc_init(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ u32 spare_per_sector, encode_block_size, decode_block_size; ++ u32 ecc_enccfg, ecc_deccfg; ++ int ecc_cap; ++ ++ /* Only hardware ECC mode is supported */ ++ if (nand->ecc.mode != NAND_ECC_HW_SYNDROME) { ++ dev_err(nfc->dev, "Only hardware ECC mode is supported\n"); ++ return -EINVAL; ++ } ++ ++ nand->ecc.size = ECC_SECTOR_SIZE; ++ nand->ecc.steps = mtd->writesize / nand->ecc.size; ++ ++ spare_per_sector = mtd->oobsize / nand->ecc.steps; ++ ++ ecc_cap = mt7621_nfc_calc_ecc_strength(nfc, ++ spare_per_sector - NFI_FDM_SIZE); ++ if (ecc_cap < 0) ++ return ecc_cap; ++ ++ /* Sector + FDM */ ++ encode_block_size = (nand->ecc.size + NFI_FDM_SIZE) * 8; ++ ecc_enccfg = ecc_cap | (ENC_MODE_NFI << ENC_MODE_S) | ++ (encode_block_size << ENC_CNFG_MSG_S); ++ ++ /* Sector + FDM + ECC parity bits */ ++ decode_block_size = ((nand->ecc.size + NFI_FDM_SIZE) * 8) + ++ nand->ecc.strength * ECC_PARITY_BITS; ++ ecc_deccfg = ecc_cap | (DEC_MODE_NFI << DEC_MODE_S) | ++ (decode_block_size << DEC_CS_S) | ++ (DEC_CON_EL << DEC_CON_S) | DEC_EMPTY_EN; ++ ++ mt7621_ecc_encoder_op(nfc, false); ++ ecc_write32(nfc, ECC_ENCCNFG, ecc_enccfg); ++ ++ mt7621_ecc_decoder_op(nfc, false); ++ ecc_write32(nfc, ECC_DECCNFG, ecc_deccfg); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_set_page_format(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ int i, spare_size; ++ u32 pagefmt; ++ ++ spare_size = mt7621_nfc_set_spare_per_sector(nfc); ++ if (spare_size < 0) ++ return spare_size; ++ ++ for (i = 0; i < ARRAY_SIZE(mt7621_nfi_page_size); i++) { ++ if (mt7621_nfi_page_size[i] == mtd->writesize) ++ break; ++ } ++ ++ if (unlikely(i >= ARRAY_SIZE(mt7621_nfi_page_size))) { ++ dev_err(nfc->dev, "Page size (%u) is not supported\n", ++ mtd->writesize); ++ return -EINVAL; ++ } ++ ++ pagefmt = i | (spare_size << PAGEFMT_SPARE_S) | ++ (NFI_FDM_SIZE << PAGEFMT_FDM_S) | ++ (NFI_FDM_SIZE << PAGEFMT_FDM_ECC_S); ++ ++ nfi_write16(nfc, NFI_PAGEFMT, pagefmt); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_attach_chip(struct nand_chip *nand) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int ret; ++ ++ if (nand->options & NAND_BUSWIDTH_16) { ++ dev_err(nfc->dev, "16-bit buswidth is not supported"); ++ return -EINVAL; ++ } ++ ++ ret = mt7621_nfc_ecc_init(nfc); ++ if (ret) ++ return ret; ++ ++ return mt7621_nfc_set_page_format(nfc); ++} ++ ++static const struct nand_controller_ops mt7621_nfc_controller_ops = { ++ .attach_chip = mt7621_nfc_attach_chip, ++ .exec_op = mt7621_nfc_exec_op, ++ .setup_data_interface = mt7621_nfc_setup_data_interface, ++}; ++ ++static int mt7621_nfc_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *nand = mtd_to_nand(mtd); ++ ++ if (section >= nand->ecc.steps) ++ return -ERANGE; ++ ++ oob_region->length = NFI_FDM_SIZE - 1; ++ oob_region->offset = section * NFI_FDM_SIZE + 1; ++ ++ return 0; ++} ++ ++static int mt7621_nfc_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *oob_region) ++{ ++ struct nand_chip *nand = mtd_to_nand(mtd); ++ ++ if (section) ++ return -ERANGE; ++ ++ oob_region->offset = NFI_FDM_SIZE * nand->ecc.steps; ++ oob_region->length = mtd->oobsize - oob_region->offset; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops mt7621_nfc_ooblayout_ops = { ++ .free = mt7621_nfc_ooblayout_free, ++ .ecc = mt7621_nfc_ooblayout_ecc, ++}; ++ ++static void mt7621_nfc_write_fdm(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 vall, valm; ++ u8 *oobptr; ++ int i, j; ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ vall = 0; ++ valm = 0; ++ oobptr = oob_fdm_ptr(nand, i); ++ ++ for (j = 0; j < 4; j++) ++ vall |= (u32)oobptr[j] << (j * 8); ++ ++ for (j = 0; j < 4; j++) ++ valm |= (u32)oobptr[j + 4] << ((j - 4) * 8); ++ ++ nfi_write32(nfc, NFI_FDML(i), vall); ++ nfi_write32(nfc, NFI_FDMM(i), valm); ++ } ++} ++ ++static void mt7621_nfc_read_sector_fdm(struct mt7621_nfc *nfc, u32 sect) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ u32 vall, valm; ++ u8 *oobptr; ++ int i; ++ ++ vall = nfi_read32(nfc, NFI_FDML(sect)); ++ valm = nfi_read32(nfc, NFI_FDMM(sect)); ++ oobptr = oob_fdm_ptr(nand, sect); ++ ++ for (i = 0; i < 4; i++) ++ oobptr[i] = (vall >> (i * 8)) & 0xff; ++ ++ for (i = 0; i < 4; i++) ++ oobptr[i + 4] = (valm >> (i * 8)) & 0xff; ++} ++ ++static int mt7621_nfc_read_page_hwecc(struct nand_chip *nand, uint8_t *buf, ++ int oob_required, int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ int bitflips = 0; ++ int rc, i; ++ ++ nand_read_page_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, (CNFG_OP_CUSTOM << CNFG_OP_MODE_S) | ++ CNFG_READ_MODE | CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); ++ ++ mt7621_ecc_decoder_op(nfc, true); ++ ++ nfi_write16(nfc, NFI_CON, ++ CON_NFI_BRD | (nand->ecc.steps << CON_NFI_SEC_S)); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ if (buf) ++ mt7621_nfc_read_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_read_data_discard(nfc, nand->ecc.size); ++ ++ rc = mt7621_ecc_decoder_wait_done(nfc, i); ++ ++ mt7621_nfc_read_sector_fdm(nfc, i); ++ ++ if (rc < 0) { ++ bitflips = -EIO; ++ continue; ++ } ++ ++ rc = mt7621_ecc_correct_check(nfc, ++ buf ? page_data_ptr(nand, buf, i) : NULL, ++ oob_fdm_ptr(nand, i), i); ++ ++ if (rc < 0) { ++ dev_warn(nfc->dev, ++ "Uncorrectable ECC error at page %d.%d\n", ++ page, i); ++ bitflips = -EBADMSG; ++ mtd->ecc_stats.failed++; ++ } else if (bitflips >= 0) { ++ bitflips += rc; ++ mtd->ecc_stats.corrected += rc; ++ } ++ } ++ ++ mt7621_ecc_decoder_op(nfc, false); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return bitflips; ++} ++ ++static int mt7621_nfc_read_page_raw(struct nand_chip *nand, uint8_t *buf, ++ int oob_required, int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int i; ++ ++ nand_read_page_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, (CNFG_OP_CUSTOM << CNFG_OP_MODE_S) | ++ CNFG_READ_MODE); ++ ++ nfi_write16(nfc, NFI_CON, ++ CON_NFI_BRD | (nand->ecc.steps << CON_NFI_SEC_S)); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ /* Read data */ ++ if (buf) ++ mt7621_nfc_read_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_read_data_discard(nfc, nand->ecc.size); ++ ++ /* Read FDM */ ++ mt7621_nfc_read_data(nfc, oob_fdm_ptr(nand, i), NFI_FDM_SIZE); ++ ++ /* Read ECC parity data */ ++ mt7621_nfc_read_data(nfc, oob_ecc_ptr(nfc, i), ++ nfc->spare_per_sector - NFI_FDM_SIZE); ++ } ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return 0; ++} ++ ++static int mt7621_nfc_read_oob_hwecc(struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_read_page_hwecc(nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_read_oob_raw(struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_read_page_raw(nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_check_empty_page(struct nand_chip *nand, const u8 *buf) ++{ ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ uint32_t i, j; ++ u8 *oobptr; ++ ++ for (i = 0; i < mtd->writesize; i++) ++ if (buf[i] != 0xff) ++ return 0; ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ oobptr = oob_fdm_ptr(nand, i); ++ for (j = 0; j < NFI_FDM_SIZE; j++) ++ if (oobptr[j] != 0xff) ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int mt7621_nfc_write_page_hwecc(struct nand_chip *nand, ++ const uint8_t *buf, int oob_required, ++ int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ struct mtd_info *mtd = nand_to_mtd(nand); ++ ++ if (mt7621_nfc_check_empty_page(nand, buf)) { ++ /* ++ * MT7621 ECC engine always generates parity code for input ++ * pages, even for empty pages. Doing so will write back ECC ++ * parity code to the oob region, which means such pages will ++ * no longer be empty pages. ++ * ++ * To avoid this, stop write operation if current page is an ++ * empty page. ++ */ ++ return 0; ++ } ++ ++ nand_prog_page_begin_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, (CNFG_OP_CUSTOM << CNFG_OP_MODE_S) | ++ CNFG_AUTO_FMT_EN | CNFG_HW_ECC_EN); ++ ++ mt7621_ecc_encoder_op(nfc, true); ++ ++ mt7621_nfc_write_fdm(nfc); ++ ++ nfi_write16(nfc, NFI_CON, ++ CON_NFI_BWR | (nand->ecc.steps << CON_NFI_SEC_S)); ++ ++ if (buf) ++ mt7621_nfc_write_data(nfc, buf, mtd->writesize); ++ else ++ mt7621_nfc_write_data_empty(nfc, mtd->writesize); ++ ++ mt7621_nfc_wait_write_completion(nfc, nand); ++ ++ mt7621_ecc_encoder_op(nfc, false); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return nand_prog_page_end_op(nand); ++} ++ ++static int mt7621_nfc_write_page_raw(struct nand_chip *nand, ++ const uint8_t *buf, int oob_required, ++ int page) ++{ ++ struct mt7621_nfc *nfc = nand_get_controller_data(nand); ++ int i; ++ ++ nand_prog_page_begin_op(nand, page, 0, NULL, 0); ++ ++ nfi_write16(nfc, NFI_CNFG, (CNFG_OP_CUSTOM << CNFG_OP_MODE_S)); ++ ++ nfi_write16(nfc, NFI_CON, ++ CON_NFI_BWR | (nand->ecc.steps << CON_NFI_SEC_S)); ++ ++ for (i = 0; i < nand->ecc.steps; i++) { ++ /* Write data */ ++ if (buf) ++ mt7621_nfc_write_data(nfc, page_data_ptr(nand, buf, i), ++ nand->ecc.size); ++ else ++ mt7621_nfc_write_data_empty(nfc, nand->ecc.size); ++ ++ /* Write FDM */ ++ mt7621_nfc_write_data(nfc, oob_fdm_ptr(nand, i), ++ NFI_FDM_SIZE); ++ ++ /* Write dummy ECC parity data */ ++ mt7621_nfc_write_data_empty(nfc, nfc->spare_per_sector - ++ NFI_FDM_SIZE); ++ } ++ ++ mt7621_nfc_wait_write_completion(nfc, nand); ++ ++ nfi_write16(nfc, NFI_CON, 0); ++ ++ return nand_prog_page_end_op(nand); ++} ++ ++static int mt7621_nfc_write_oob_hwecc(struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_write_page_hwecc(nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_write_oob_raw(struct nand_chip *nand, int page) ++{ ++ return mt7621_nfc_write_page_raw(nand, NULL, 1, page); ++} ++ ++static int mt7621_nfc_init_chip(struct mt7621_nfc *nfc) ++{ ++ struct nand_chip *nand = &nfc->nand; ++ struct mtd_info *mtd; ++ int ret; ++ ++ nand->controller = &nfc->controller; ++ nand_set_controller_data(nand, (void *)nfc); ++ nand_set_flash_node(nand, nfc->dev->of_node); ++ ++ nand->options |= NAND_USE_BOUNCE_BUFFER | NAND_NO_SUBPAGE_WRITE; ++ if (!nfc->nfi_clk) ++ nand->options |= NAND_KEEP_TIMINGS; ++ ++ nand->ecc.mode = NAND_ECC_HW_SYNDROME; ++ nand->ecc.read_page = mt7621_nfc_read_page_hwecc; ++ nand->ecc.read_page_raw = mt7621_nfc_read_page_raw; ++ nand->ecc.write_page = mt7621_nfc_write_page_hwecc; ++ nand->ecc.write_page_raw = mt7621_nfc_write_page_raw; ++ nand->ecc.read_oob = mt7621_nfc_read_oob_hwecc; ++ nand->ecc.read_oob_raw = mt7621_nfc_read_oob_raw; ++ nand->ecc.write_oob = mt7621_nfc_write_oob_hwecc; ++ nand->ecc.write_oob_raw = mt7621_nfc_write_oob_raw; ++ ++ mtd = nand_to_mtd(nand); ++ mtd->owner = THIS_MODULE; ++ mtd->dev.parent = nfc->dev; ++ mtd->name = MT7621_NFC_NAME; ++ mtd_set_ooblayout(mtd, &mt7621_nfc_ooblayout_ops); ++ ++ mt7621_nfc_hw_init(nfc); ++ ++ ret = nand_scan(nand, 1); ++ if (ret) ++ return ret; ++ ++ ret = mtd_device_register(mtd, NULL, 0); ++ if (ret) { ++ dev_err(nfc->dev, "Failed to register MTD: %d\n", ret); ++ nand_release(nand); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mt7621_nfc_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mt7621_nfc *nfc; ++ struct resource *res; ++ int ret; ++ ++ nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL); ++ if (!nfc) ++ return -ENOMEM; ++ ++ nand_controller_init(&nfc->controller); ++ nfc->controller.ops = &mt7621_nfc_controller_ops; ++ nfc->dev = dev; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nfi"); ++ nfc->nfi_regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(nfc->nfi_regs)) { ++ ret = PTR_ERR(nfc->nfi_regs); ++ return ret; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecc"); ++ nfc->ecc_regs = devm_ioremap_resource(dev, res); ++ if (IS_ERR(nfc->ecc_regs)) { ++ ret = PTR_ERR(nfc->ecc_regs); ++ return ret; ++ } ++ ++ nfc->nfi_clk = devm_clk_get(dev, "nfi_clk"); ++ if (IS_ERR(nfc->nfi_clk)) { ++ dev_warn(dev, "nfi clk not provided\n"); ++ nfc->nfi_clk = NULL; ++ } else { ++ ret = clk_prepare_enable(nfc->nfi_clk); ++ if (ret) { ++ dev_err(dev, "Failed to enable nfi core clock\n"); ++ return ret; ++ } ++ } ++ ++ platform_set_drvdata(pdev, nfc); ++ ++ ret = mt7621_nfc_init_chip(nfc); ++ if (ret) { ++ dev_err(dev, "Failed to initialize nand chip\n"); ++ goto clk_disable; ++ } ++ ++ return 0; ++ ++clk_disable: ++ clk_disable_unprepare(nfc->nfi_clk); ++ ++ return ret; ++} ++ ++static int mt7621_nfc_remove(struct platform_device *pdev) ++{ ++ struct mt7621_nfc *nfc = platform_get_drvdata(pdev); ++ ++ nand_release(&nfc->nand); ++ clk_disable_unprepare(nfc->nfi_clk); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_nfc_id_table[] = { ++ { .compatible = "mediatek,mt7621-nfc" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, match); ++ ++static struct platform_driver mt7621_nfc_driver = { ++ .probe = mt7621_nfc_probe, ++ .remove = mt7621_nfc_remove, ++ .driver = { ++ .name = MT7621_NFC_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_nfc_id_table, ++ }, ++}; ++module_platform_driver(mt7621_nfc_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Weijie Gao "); ++MODULE_DESCRIPTION("MediaTek MT7621 NAND Flash Controller driver"); diff --git a/target/linux/ramips/patches-5.4/0301-dt-bindings-add-documentation-for-mt7621-nand-driver.patch b/target/linux/ramips/patches-5.4/0301-dt-bindings-add-documentation-for-mt7621-nand-driver.patch new file mode 100644 index 0000000000..3d122c10c0 --- /dev/null +++ b/target/linux/ramips/patches-5.4/0301-dt-bindings-add-documentation-for-mt7621-nand-driver.patch @@ -0,0 +1,85 @@ +From 3d5f4da8296b23eb3abf8b13122b0d06a215e79c Mon Sep 17 00:00:00 2001 +From: Weijie Gao +Date: Wed, 1 Apr 2020 02:07:59 +0800 +Subject: [PATCH 2/2] dt-bindings: add documentation for mt7621-nand driver + +This patch adds documentation for MediaTek MT7621 NAND flash controller +driver. + +Signed-off-by: Weijie Gao +--- + .../bindings/mtd/mediatek,mt7621-nfc.yaml | 68 ++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/mtd/mediatek,mt7621-nfc.yaml +@@ -0,0 +1,68 @@ ++# SPDX-License-Identifier: GPL-2.0 ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mtd/mediatek,mt7621-nfc.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek MT7621 SoC NAND Flash Controller (NFC) DT binding ++ ++maintainers: ++ - Weijie Gao ++ ++description: | ++ This driver uses a single node to describe both NAND Flash controller ++ interface (NFI) and ECC engine for MT7621 SoC. ++ MT7621 supports only one chip select. ++ ++properties: ++ "#address-cells": false ++ "#size-cells": false ++ ++ compatible: ++ enum: ++ - mediatek,mt7621-nfc ++ ++ reg: ++ items: ++ - description: Register base of NFI core ++ - description: Register base of ECC engine ++ ++ reg-names: ++ items: ++ - const: nfi ++ - const: ecc ++ ++ clocks: ++ items: ++ - description: Source clock for NFI core, fixed 125MHz ++ ++ clock-names: ++ items: ++ - const: nfi_clk ++ ++required: ++ - compatible ++ - reg ++ - reg-names ++ - clocks ++ - clock-names ++ ++examples: ++ - | ++ nficlock: nficlock { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ ++ clock-frequency = <125000000>; ++ }; ++ ++ nand@1e003000 { ++ compatible = "mediatek,mt7621-nfc"; ++ ++ reg = <0x1e003000 0x800 ++ 0x1e003800 0x800>; ++ reg-names = "nfi", "ecc"; ++ ++ clocks = <&nficlock>; ++ clock-names = "nfi_clk"; ++ }; From ae6b4d3f86bd428acb876b2a665922f71bcaa7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20van=20Dorst?= Date: Wed, 1 Apr 2020 10:01:20 +0200 Subject: [PATCH 25/35] ramips: correct MTC WR1201 LAN ports names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LAN ports of MTC WR1201 are reversed, so correct their names Signed-off-by: René van Dorst Signed-off-by: DENG Qingfang --- target/linux/ramips/dts/mt7621_mtc_wr1201.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts index eca7b3b0bb..66b4f92852 100644 --- a/target/linux/ramips/dts/mt7621_mtc_wr1201.dts +++ b/target/linux/ramips/dts/mt7621_mtc_wr1201.dts @@ -112,22 +112,22 @@ ports { port@0 { status = "okay"; - label = "lan1"; + label = "lan4"; }; port@1 { status = "okay"; - label = "lan2"; + label = "lan3"; }; port@2 { status = "okay"; - label = "lan3"; + label = "lan2"; }; port@3 { status = "okay"; - label = "lan4"; + label = "lan1"; }; port@4 { From 3624721ef1532cdd4ff645b6e435a8aa792eec34 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Fri, 3 Apr 2020 22:57:15 +0800 Subject: [PATCH 26/35] generic: backport support for MT7530 DSA port mirroring Signed-off-by: DENG Qingfang --- ...t7530-add-support-for-port-mirroring.patch | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch diff --git a/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch b/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch new file mode 100644 index 0000000000..39e351e279 --- /dev/null +++ b/target/linux/generic/backport-5.4/745-v5.7-net-dsa-mt7530-add-support-for-port-mirroring.patch @@ -0,0 +1,123 @@ +From 37feab6076aa816ed72fe836759a485353241916 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Fri, 6 Mar 2020 20:35:35 +0800 +Subject: net: dsa: mt7530: add support for port mirroring + +Add support for configuring port mirroring through the cls_matchall +classifier. We do a full ingress and/or egress capture towards a +capture port. +MT7530 supports one monitor port and multiple mirrored ports. + +Signed-off-by: DENG Qingfang +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.h | 7 ++++++ + 2 files changed, 67 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1222,6 +1222,64 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port, + return 0; + } + ++static int mt7530_port_mirror_add(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror, ++ bool ingress) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ /* Check for existent entry */ ++ if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) ++ return -EEXIST; ++ ++ val = mt7530_read(priv, MT7530_MFC); ++ ++ /* MT7530 only supports one monitor port */ ++ if (val & MIRROR_EN && MIRROR_PORT(val) != mirror->to_local_port) ++ return -EEXIST; ++ ++ val |= MIRROR_EN; ++ val &= ~MIRROR_MASK; ++ val |= mirror->to_local_port; ++ mt7530_write(priv, MT7530_MFC, val); ++ ++ val = mt7530_read(priv, MT7530_PCR_P(port)); ++ if (ingress) { ++ val |= PORT_RX_MIR; ++ priv->mirror_rx |= BIT(port); ++ } else { ++ val |= PORT_TX_MIR; ++ priv->mirror_tx |= BIT(port); ++ } ++ mt7530_write(priv, MT7530_PCR_P(port), val); ++ ++ return 0; ++} ++ ++static void mt7530_port_mirror_del(struct dsa_switch *ds, int port, ++ struct dsa_mall_mirror_tc_entry *mirror) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ u32 val; ++ ++ val = mt7530_read(priv, MT7530_PCR_P(port)); ++ if (mirror->ingress) { ++ val &= ~PORT_RX_MIR; ++ priv->mirror_rx &= ~BIT(port); ++ } else { ++ val &= ~PORT_TX_MIR; ++ priv->mirror_tx &= ~BIT(port); ++ } ++ mt7530_write(priv, MT7530_PCR_P(port), val); ++ ++ if (!priv->mirror_rx && !priv->mirror_tx) { ++ val = mt7530_read(priv, MT7530_MFC); ++ val &= ~MIRROR_EN; ++ mt7530_write(priv, MT7530_MFC, val); ++ } ++} ++ + static enum dsa_tag_protocol + mtk_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol mp) +@@ -1613,6 +1671,8 @@ static const struct dsa_switch_ops mt7530_switch_ops = { + .port_vlan_prepare = mt7530_port_vlan_prepare, + .port_vlan_add = mt7530_port_vlan_add, + .port_vlan_del = mt7530_port_vlan_del, ++ .port_mirror_add = mt7530_port_mirror_add, ++ .port_mirror_del = mt7530_port_mirror_del, + .phylink_validate = mt7530_phylink_validate, + .phylink_mac_link_state = mt7530_phylink_mac_link_state, + .phylink_mac_config = mt7530_phylink_mac_config, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -36,6 +36,9 @@ enum { + #define CPU_EN BIT(7) + #define CPU_PORT(x) ((x) << 4) + #define CPU_MASK (0xf << 4) ++#define MIRROR_EN BIT(3) ++#define MIRROR_PORT(x) ((x) & 0x7) ++#define MIRROR_MASK 0x7 + + /* Registers for address table access */ + #define MT7530_ATA1 0x74 +@@ -141,6 +144,8 @@ enum mt7530_stp_state { + + /* Register for port control */ + #define MT7530_PCR_P(x) (0x2004 + ((x) * 0x100)) ++#define PORT_TX_MIR BIT(9) ++#define PORT_RX_MIR BIT(8) + #define PORT_VLAN(x) ((x) & 0x3) + + enum mt7530_port_mode { +@@ -460,6 +465,8 @@ struct mt7530_priv { + phy_interface_t p6_interface; + phy_interface_t p5_interface; + unsigned int p5_intf_sel; ++ u8 mirror_rx; ++ u8 mirror_tx; + + struct mt7530_port ports[MT7530_NUM_PORTS]; + /* protect among processes for registers access*/ From 764cc5c6a6c9aeaae5c7d8fdfc60aa651733e1a5 Mon Sep 17 00:00:00 2001 From: DENG Qingfang Date: Sat, 4 Apr 2020 12:10:32 +0800 Subject: [PATCH 27/35] generic: mt7530: fix null pointer dereferencing in port5 setup The 2nd gmac of mediatek soc ethernet may not be connected to a PHY and a phy-handle isn't always available. Unfortunately, mt7530 dsa driver assumes that the 2nd gmac is always connected to switch port 5 and setup mt7530 according to phy address of 2nd gmac node, causing null pointer dereferencing when phy-handle isn't defined in dts. This commit fix this setup code by checking return value of of_parse_phandle before using it. Signed-off-by: DENG Qingfang --- ...ix-null-pointer-dereferencing-in-por.patch | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 target/linux/generic/backport-5.4/746-stable-net-dsa-mt7530-fix-null-pointer-dereferencing-in-por.patch diff --git a/target/linux/generic/backport-5.4/746-stable-net-dsa-mt7530-fix-null-pointer-dereferencing-in-por.patch b/target/linux/generic/backport-5.4/746-stable-net-dsa-mt7530-fix-null-pointer-dereferencing-in-por.patch new file mode 100644 index 0000000000..1775bfb32c --- /dev/null +++ b/target/linux/generic/backport-5.4/746-stable-net-dsa-mt7530-fix-null-pointer-dereferencing-in-por.patch @@ -0,0 +1,39 @@ +From 0452800f6db4ed0a42ffb15867c0acfd68829f6a Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Fri, 3 Apr 2020 19:28:24 +0800 +Subject: net: dsa: mt7530: fix null pointer dereferencing in port5 setup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The 2nd gmac of mediatek soc ethernet may not be connected to a PHY +and a phy-handle isn't always available. +Unfortunately, mt7530 dsa driver assumes that the 2nd gmac is always +connected to switch port 5 and setup mt7530 according to phy address +of 2nd gmac node, causing null pointer dereferencing when phy-handle +isn't defined in dts. +This commit fix this setup code by checking return value of +of_parse_phandle before using it. + +Fixes: 38f790a80560 ("net: dsa: mt7530: Add support for port 5") +Signed-off-by: Chuanhong Guo +Reviewed-by: Vivien Didelot +Reviewed-by: Florian Fainelli +Tested-by: René van Dorst +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1411,6 +1411,9 @@ mt7530_setup(struct dsa_switch *ds) + continue; + + phy_node = of_parse_phandle(mac_np, "phy-handle", 0); ++ if (!phy_node) ++ continue; ++ + if (phy_node->parent == priv->dev->of_node->parent) { + interface = of_get_phy_mode(mac_np); + id = of_mdio_parse_addr(ds->dev, phy_node); From a8d62a4eb1ce53beb901b212ce7e474eb70341ca Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sat, 4 Apr 2020 12:44:28 +0800 Subject: [PATCH 28/35] ramips: remove set_preinit_iface script This script isn't suitable for mt7621 anymore due to switching to DSA and it needs a different preinit script. Generic preinit logic in package/base-files has the ability to parse board.json and pick preinit iface accordingly. Just remove this script instead of moving it into subtargets. Signed-off-by: Chuanhong Guo --- .../lib/preinit/07_set_preinit_iface_ramips | 59 ------------------- 1 file changed, 59 deletions(-) delete mode 100644 target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips diff --git a/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips b/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips deleted file mode 100644 index 68c1285eb4..0000000000 --- a/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/sh -# -# Copyright (C) 2013 OpenWrt.org -# - -. /lib/functions.sh - -ramips_switchdev_from_soc() { - # The ethernet switch driver enables VLAN by default, but - # failsafe uses eth0, making the device unreachable: - # https://dev.openwrt.org/ticket/18768 - - local switchdev - local RT3X5X=$(grep -E "(RT3.5|RT5350|MT7628|MT7688|MT7620|MT7621)" /proc/cpuinfo) - - [ -n "$RT3X5X" ] || return 1 - - case "$RT3X5X" in - *MT7620*) - switchdev=mt7620 - ;; - *MT7621*) - switchdev=mt7530 - ;; - *) - switchdev=rt305x - ;; - esac - - echo "$switchdev" -} - -ramips_switchdev_from_board() { - # For these devices, external ethernet switch should be used - # instead of the SoC internal switch. - - local switchdev - local board=$(board_name) - - case "$board" in - esac - - echo "$switchdev" -} - -ramips_set_preinit_iface() { - local switchdev=$(ramips_switchdev_from_board) - [ -n "$switchdev" ] || switchdev=$(ramips_switchdev_from_soc) - - if [ -n "$switchdev" ]; then - swconfig dev $switchdev set reset 1 - swconfig dev $switchdev set enable_vlan 0 - swconfig dev $switchdev set apply 1 - fi - - ifname=eth0 -} - -boot_hook_add preinit_main ramips_set_preinit_iface From 838f1fbb50e91ebaf1d34f9666ae6b65eb49df5c Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sat, 4 Apr 2020 15:20:46 +0800 Subject: [PATCH 29/35] ramips: mt7621: disable image for mikrotik_rbm11g It's unknown which switch port is used on mikrotik_rbm11g. Disable this image until someone with actual device fixes this problem. Signed-off-by: Chuanhong Guo --- target/linux/ramips/image/mt7621.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index a4484b408f..cdae42f3e4 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -497,6 +497,7 @@ TARGET_DEVICES += mikrotik_rb750gr3 define Device/mikrotik_rbm11g $(Device/MikroTik) DEVICE_MODEL := RouterBOARD M11G + DEFAULT := n # disabled due to unknown port assignment endef TARGET_DEVICES += mikrotik_rbm11g From 4d979a4d1969b59e462ea4633eeb8c69111261c5 Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Sat, 4 Apr 2020 16:30:16 +0800 Subject: [PATCH 30/35] ramips: mt7621: bringup dsa master on preinit DSA requires master netdev to be up before any of its slave ports. Bring it up during preinit so that the first lan port can be used on failsafe. Signed-off-by: Chuanhong Guo --- .../lib/preinit/07_mt7621_bringup_dsa_master | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 target/linux/ramips/mt7621/base-files/lib/preinit/07_mt7621_bringup_dsa_master diff --git a/target/linux/ramips/mt7621/base-files/lib/preinit/07_mt7621_bringup_dsa_master b/target/linux/ramips/mt7621/base-files/lib/preinit/07_mt7621_bringup_dsa_master new file mode 100644 index 0000000000..7a11252168 --- /dev/null +++ b/target/linux/ramips/mt7621/base-files/lib/preinit/07_mt7621_bringup_dsa_master @@ -0,0 +1,22 @@ +#!/bin/sh + +. /lib/functions.sh + +mt7621_bringup_dsa_master() { + local board=$(board_name) + local masterif + + case "$board" in + ubiquiti,edgerouterx|\ + ubiquiti,edgerouterx-sfp) + masterif="dsa" + ;; + *) + masterif="eth0" + ;; + esac + + ifconfig $masterif up +} + +boot_hook_add preinit_main mt7621_bringup_dsa_master \ No newline at end of file From e714cf4195b5798f40a3442c01233ce4783ef0ad Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 28 Mar 2020 19:31:23 +0900 Subject: [PATCH 31/35] kernel: rtl8367b: fix DEBUG register address for extif2 RTL8367B_CHIP_DEBUG1_REG (0x1304) is for external interface 1. For external interface 2, use RTL8367B_CHIP_DEBUG2_REG (0x13e2) instead. Fixes: 9801d61c4a ("kernel: rtl8367b: add configuration for extif2") Signed-off-by: INAGAKI Hiroshi --- target/linux/generic/files/drivers/net/phy/rtl8367b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index e7fe79302a..de1976f13a 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -798,7 +798,7 @@ static int rtl8367b_extif_set_mode(struct rtl8366_smi *smi, int id, (7 << RTL8367B_DEBUG1_DN_SHIFT(id)) | (7 << RTL8367B_DEBUG1_DP_SHIFT(id))); } else { - REG_RMW(smi, RTL8367B_CHIP_DEBUG1_REG, + REG_RMW(smi, RTL8367B_CHIP_DEBUG2_REG, RTL8367B_DEBUG2_DRI_EXT2 | RTL8367B_DEBUG2_DRI_EXT2_RG | RTL8367B_DEBUG2_SLR_EXT2 | From 817e1323322c9d58464330a15994e8693b48b9c5 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Mon, 30 Mar 2020 15:19:50 +0900 Subject: [PATCH 32/35] kernel: rtl8367b: use id as a bit offset for BYPASS_LINE_RATE In RTL8367B (RTL8367RB/RTL8367R-VB), the driver in GPL tars of the devices with this switch directly uses the ID of external interface as a bit offset. We should use the same way. ref (RTL8367B): - ASUS RT-N56U - TP-Link Archer C2 v1 ref (RTL8367): - TP-Link TL-WR2543ND v1 Signed-off-by: INAGAKI Hiroshi --- target/linux/generic/files/drivers/net/phy/rtl8367b.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/target/linux/generic/files/drivers/net/phy/rtl8367b.c b/target/linux/generic/files/drivers/net/phy/rtl8367b.c index de1976f13a..1b1d5001a3 100644 --- a/target/linux/generic/files/drivers/net/phy/rtl8367b.c +++ b/target/linux/generic/files/drivers/net/phy/rtl8367b.c @@ -813,8 +813,7 @@ static int rtl8367b_extif_set_mode(struct rtl8366_smi *smi, int id, case RTL8367_EXTIF_MODE_TMII_MAC: case RTL8367_EXTIF_MODE_TMII_PHY: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), BIT((id + 1) % 2)); + REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, BIT(id), BIT(id)); break; case RTL8367_EXTIF_MODE_GMII: @@ -827,8 +826,7 @@ static int rtl8367b_extif_set_mode(struct rtl8366_smi *smi, int id, case RTL8367_EXTIF_MODE_MII_MAC: case RTL8367_EXTIF_MODE_MII_PHY: case RTL8367_EXTIF_MODE_DISABLED: - REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, - BIT((id + 1) % 2), 0); + REG_RMW(smi, RTL8367B_BYPASS_LINE_RATE_REG, BIT(id), 0); REG_RMW(smi, RTL8367B_EXT_RGMXF_REG(id), BIT(6), 0); break; From fdac4c085daccd774b4eba6b8c3fca2739cbb8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibaut=20VAR=C3=88NE?= Date: Wed, 18 Mar 2020 10:35:26 +0100 Subject: [PATCH 33/35] ath79: improve mikrotik-caldata.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce unnecessary flash wear and be tidy: - Run the extraction only if necessary - Extract temporary file to /tmp - cleanup after execution Tested-by: Roger Pueyo Centelles Signed-off-by: Thibaut VARÈNE --- .../base-files/lib/functions/mikrotik-caldata.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/target/linux/ath79/mikrotik/base-files/lib/functions/mikrotik-caldata.sh b/target/linux/ath79/mikrotik/base-files/lib/functions/mikrotik-caldata.sh index 9c4016ee5d..71a1bf02f3 100644 --- a/target/linux/ath79/mikrotik/base-files/lib/functions/mikrotik-caldata.sh +++ b/target/linux/ath79/mikrotik/base-files/lib/functions/mikrotik-caldata.sh @@ -9,13 +9,18 @@ mikrotik_caldata_extract() { local offset=$(($2)) local count=$(($3)) local mtd - local erdfile="/lib/firmware/erd.bin" + local erdfile="/tmp/erd.bin" + local fwfile="/lib/firmware/${FIRMWARE}" + + [ -e $fwfile ] && exit 0 mtd=$(find_mtd_chardev $part) [ -n "$mtd" ] || caldata_die "no mtd device found for partition $part" rbextract -e $mtd $erdfile - dd if=$erdfile of=/lib/firmware/$FIRMWARE iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ + dd if=$erdfile of=$fwfile iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \ caldata_die "failed to extract calibration data from $mtd" + + rm -f $erdfile } From c14c6902f597b5b7410da32842b31c6229b3a998 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Thu, 2 Apr 2020 19:30:17 +0100 Subject: [PATCH 34/35] treewide: convert sed -r to posix -E Signed-off-by: Kevin Darbyshire-Bryant --- include/image.mk | 2 +- package/base-files/files/lib/upgrade/common.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/image.mk b/include/image.mk index 441f55b741..984b64fb9c 100644 --- a/include/image.mk +++ b/include/image.mk @@ -45,7 +45,7 @@ IMG_PREFIX:=$(VERSION_DIST_SANITIZED)-$(IMG_PREFIX_VERNUM)$(IMG_PREFIX_VERCODE)$ IMG_ROOTFS:=$(IMG_PREFIX)-rootfs IMG_COMBINED:=$(IMG_PREFIX)-combined IMG_PART_SIGNATURE:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | cut -b1-8) -IMG_PART_DISKGUID:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.{10})../\1-\2-\3-\4-\500/') +IMG_PART_DISKGUID:=$(shell echo $(SOURCE_DATE_EPOCH)$(LINUX_VERMAGIC) | mkhash md5 | sed -E 's/(.{8})(.{4})(.{4})(.{4})(.{10})../\1-\2-\3-\4-\500/') MKFS_DEVTABLE_OPT := -D $(INCLUDE_DIR)/device_table.txt diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh index 2cbc69e5dd..49c2fa0e7b 100644 --- a/package/base-files/files/lib/upgrade/common.sh +++ b/package/base-files/files/lib/upgrade/common.sh @@ -5,7 +5,7 @@ RAM_ROOT=/tmp/root export BACKUP_FILE=sysupgrade.tgz # file extracted by preinit [ -x /usr/bin/ldd ] || ldd() { LD_TRACE_LOADED_OBJECTS=1 $*; } -libs() { ldd $* 2>/dev/null | sed -r 's/(.* => )?(.*) .*/\2/'; } +libs() { ldd $* 2>/dev/null | sed -E 's/(.* => )?(.*) .*/\2/'; } install_file() { # [ ... ] local target dest dir From 02640f014719a994e2e538b2cb6376a189cd39de Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Sat, 4 Apr 2020 09:20:08 +0100 Subject: [PATCH 35/35] umdns: suppress address-of-packed-member warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc 8 & 9 appear to be more picky with regards access alignment to packed structures, leading to this warning in dns.c: dns.c:261:2: error: converting a packed ‘struct dns_question’ pointer (alignment 1) to a ‘uint16_t’ {aka ‘short unsigned int’} pointer (alignment 2) may result in an unaligned pointer value [-Werror=address-of-packed-member] 261 | uint16_t *swap = (uint16_t *) q; Work around what I think is a false positive by turning the warning off. Not ideal, but not quite as not ideal as build failure. Signed-off-by: Kevin Darbyshire-Bryant --- package/network/services/umdns/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/network/services/umdns/Makefile b/package/network/services/umdns/Makefile index ffbc3fed35..7dbbea322a 100644 --- a/package/network/services/umdns/Makefile +++ b/package/network/services/umdns/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=umdns -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL=$(PROJECT_GIT)/project/mdnsd.git PKG_SOURCE_PROTO:=git @@ -30,7 +30,7 @@ define Package/umdns DEPENDS:=+libubox +libubus +libblobmsg-json endef -TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include -Wno-address-of-packed-member define Package/umdns/conffiles /etc/config/umdns