From: Felix Fietkau Date: Sat, 29 Sep 2018 15:03:27 +0000 (+0200) Subject: sunxi: remove linux 4.9 support X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=2ad995ccfe36365d428ebe62fa999d9a3554cece;p=openwrt%2Fstaging%2Fneocturne.git sunxi: remove linux 4.9 support Signed-off-by: Felix Fietkau --- diff --git a/target/linux/sunxi/config-4.9 b/target/linux/sunxi/config-4.9 deleted file mode 100644 index 4a74fd1f4f..0000000000 --- a/target/linux/sunxi/config-4.9 +++ /dev/null @@ -1,574 +0,0 @@ -# CONFIG_AHCI_SUNXI is not set -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_ARCH_AXXIA is not set -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -CONFIG_ARCH_HAS_RESET_CONTROLLER=y -CONFIG_ARCH_HAS_SG_CHAIN=y -CONFIG_ARCH_HAS_TICK_BROADCAST=y -CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -CONFIG_ARCH_MULTIPLATFORM=y -# CONFIG_ARCH_MULTI_CPU_AUTO is not set -CONFIG_ARCH_MULTI_V6_V7=y -CONFIG_ARCH_MULTI_V7=y -CONFIG_ARCH_NR_GPIO=416 -CONFIG_ARCH_PHYS_ADDR_T_64BIT=y -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -CONFIG_ARCH_SUNXI=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -CONFIG_ARCH_SUPPORTS_UPROBES=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y -CONFIG_ARM=y -CONFIG_ARM_APPENDED_DTB=y -CONFIG_ARM_ARCH_TIMER=y -CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y -CONFIG_ARM_ATAG_DTB_COMPAT=y -# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set -CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y -CONFIG_ARM_CPU_SUSPEND=y -CONFIG_ARM_ERRATA_643719=y -CONFIG_ARM_GIC=y -CONFIG_ARM_HAS_SG_CHAIN=y -CONFIG_ARM_HEAVY_MB=y -CONFIG_ARM_L1_CACHE_SHIFT=6 -CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_LPAE=y -CONFIG_ARM_PATCH_IDIV=y -CONFIG_ARM_PATCH_PHYS_VIRT=y -CONFIG_ARM_PMU=y -CONFIG_ARM_PSCI=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ARM_THUMB=y -# CONFIG_ARM_THUMBEE is not set -CONFIG_ARM_UNWIND=y -CONFIG_ARM_VIRT_EXT=y -CONFIG_ATA=y -CONFIG_ATAGS=y -# CONFIG_ATA_SFF is not set -CONFIG_AUTO_ZRELADDR=y -CONFIG_AXP20X_POWER=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_BACKLIGHT_PWM=y -CONFIG_BINFMT_MISC=y -CONFIG_BLK_DEV_LOOP=y -CONFIG_BOUNCE=y -# CONFIG_BPF_SYSCALL is not set -CONFIG_CACHE_L2X0=y -CONFIG_CAN=y -CONFIG_CLKDEV_LOOKUP=y -CONFIG_CLKSRC_MMIO=y -CONFIG_CLKSRC_OF=y -CONFIG_CLKSRC_PROBE=y -CONFIG_CLONE_BACKWARDS=y -CONFIG_COMMON_CLK=y -CONFIG_COMPACTION=y -CONFIG_CONFIGFS_FS=y -CONFIG_CONNECTOR=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_COREDUMP=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_CPUFREQ_DT=y -CONFIG_CPUFREQ_DT_PLATDEV=y -CONFIG_CPU_32v6K=y -CONFIG_CPU_32v7=y -CONFIG_CPU_ABRT_EV7=y -# CONFIG_CPU_BIG_ENDIAN is not set -# CONFIG_CPU_BPREDICT_DISABLE is not set -CONFIG_CPU_CACHE_V7=y -CONFIG_CPU_CACHE_VIPT=y -CONFIG_CPU_COPY_V6=y -CONFIG_CPU_CP15=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_ATTR_SET=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_HAS_ASID=y -# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_PABRT_V7=y -CONFIG_CPU_PM=y -CONFIG_CPU_RMAP=y -CONFIG_CPU_THERMAL=y -CONFIG_CPU_TLB_V7=y -CONFIG_CPU_V7=y -CONFIG_CRC16=y -CONFIG_CRC_T10DIF=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_CRC32=y -CONFIG_CRYPTO_CRC32C=y -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_DEV_SUN4I_SS=y -CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_HW=y -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_NULL2=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_WORKQUEUE=y -CONFIG_DCACHE_WORD_ACCESS=y -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" -CONFIG_DEBUG_MEMORY_INIT=y -# CONFIG_DEBUG_UART_8250 is not set -# CONFIG_DEBUG_USER is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_IOSCHED="cfq" -CONFIG_DMADEVICES=y -CONFIG_DMA_ENGINE=y -CONFIG_DMA_OF=y -CONFIG_DMA_SUN4I=y -CONFIG_DMA_SUN6I=y -CONFIG_DMA_VIRTUAL_CHANNELS=y -CONFIG_DNOTIFY=y -CONFIG_DTC=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_DWMAC_DWC_QOS_ETH is not set -CONFIG_DWMAC_GENERIC=y -# CONFIG_DWMAC_SUN8I is not set -CONFIG_DWMAC_SUNXI=y -CONFIG_DYNAMIC_DEBUG=y -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -CONFIG_ELF_CORE=y -# CONFIG_EMBEDDED is not set -CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_EXT4_FS=y -CONFIG_EXTCON=y -# CONFIG_F2FS_CHECK_FS is not set -CONFIG_F2FS_FS=y -# CONFIG_F2FS_FS_SECURITY is not set -CONFIG_F2FS_FS_XATTR=y -CONFIG_F2FS_STAT_FS=y -CONFIG_FAT_FS=y -CONFIG_FB=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB_CMDLINE=y -CONFIG_FB_FOREIGN_ENDIAN=y -CONFIG_FB_LITTLE_ENDIAN=y -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_SIMPLE=y -CONFIG_FB_TILEBLITTING=y -CONFIG_FIXED_PHY=y -CONFIG_FIX_EARLYCON_MEM=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -CONFIG_FONT_SUPPORT=y -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FRAME_WARN=2048 -CONFIG_FREEZER=y -CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y -CONFIG_GENERIC_ALLOCATOR=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_GENERIC_IDLE_POLL_SETUP=y -CONFIG_GENERIC_IO=y -CONFIG_GENERIC_IRQ_CHIP=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_IRQ_SHOW_LEVEL=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_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GLOB=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_AXP209=y -CONFIG_GPIO_SYSFS=y -CONFIG_HANDLE_DOMAIN_IRQ=y -CONFIG_HARDIRQS_SW_RESEND=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_AUDITSYSCALL=y -CONFIG_HAVE_ARCH_BITREVERSE=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y -CONFIG_HAVE_ARM_ARCH_TIMER=y -CONFIG_HAVE_ARM_SMCCC=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_C_RECORDMCOUNT=y -CONFIG_HAVE_DEBUG_KMEMLEAK=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=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_RCU_GUP=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y -CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y -CONFIG_HAVE_KVM_EVENTFD=y -CONFIG_HAVE_KVM_IRQCHIP=y -CONFIG_HAVE_KVM_IRQFD=y -CONFIG_HAVE_KVM_IRQ_ROUTING=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y -CONFIG_HAVE_NET_DSA=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_RCU_TABLE_FREE=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_SMP=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_UID16=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_HOTPLUG_CPU=y -# CONFIG_HUGETLBFS is not set -CONFIG_HWMON=y -CONFIG_HW_CONSOLE=y -CONFIG_HW_RANDOM=y -CONFIG_HW_RANDOM_TIMERIOMEM=y -CONFIG_HZ_FIXED=0 -CONFIG_I2C=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_COMPAT=y -CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_MV64XXX=y -CONFIG_I2C_SUN6I_P2WI=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT=y -CONFIG_INPUT_AXP20X_PEK=y -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_IOMMU_HELPER=y -CONFIG_IOSCHED_CFQ=y -CONFIG_IRQCHIP=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_IRQ_WORK=y -CONFIG_JBD2=y -CONFIG_KALLSYMS=y -# CONFIG_KERNEL_MODE_NEON is not set -CONFIG_KEYBOARD_SUN4I_LRADC=y -CONFIG_KSM=y -CONFIG_KVM=y -CONFIG_KVM_ARM_HOST=y -CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y -CONFIG_KVM_MMIO=y -CONFIG_KVM_VFIO=y -CONFIG_LCD_CLASS_DEVICE=y -CONFIG_LCD_PLATFORM=y -CONFIG_LEDS_GPIO=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_LIBFDT=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_CLUT224=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_MACH_SUN4I=y -CONFIG_MACH_SUN5I=y -CONFIG_MACH_SUN6I=y -CONFIG_MACH_SUN7I=y -CONFIG_MACH_SUN8I=y -CONFIG_MACH_SUN9I=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_MDIO_BOARDINFO=y -CONFIG_MDIO_SUN4I=y -CONFIG_MEDIA_SUPPORT=y -# CONFIG_MFD_AC100 is not set -CONFIG_MFD_AXP20X=y -CONFIG_MFD_AXP20X_I2C=y -CONFIG_MFD_AXP20X_RSB=y -CONFIG_MFD_CORE=y -CONFIG_MFD_SUN6I_PRCM=y -CONFIG_MFD_SYSCON=y -CONFIG_MIGHT_HAVE_CACHE_L2X0=y -CONFIG_MIGHT_HAVE_PCI=y -CONFIG_MIGRATION=y -CONFIG_MMC=y -CONFIG_MMC_BLOCK=y -# CONFIG_MMC_BLOCK_BOUNCE is not set -CONFIG_MMC_SUNXI=y -CONFIG_MMU_NOTIFIER=y -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_MODULES_USE_ELF_REL=y -# CONFIG_MTD is not set -CONFIG_MULTI_IRQ_HANDLER=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEON=y -CONFIG_NET_FLOW_LIMIT=y -CONFIG_NET_PTP_CLASSIFY=y -CONFIG_NET_VENDOR_ALLWINNER=y -CONFIG_NLS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NO_BOOTMEM=y -CONFIG_NO_HZ=y -CONFIG_NO_HZ_COMMON=y -CONFIG_NO_HZ_IDLE=y -CONFIG_NR_CPUS=8 -CONFIG_NVMEM=y -CONFIG_NVMEM_SUNXI_SID=y -CONFIG_OF=y -CONFIG_OF_ADDRESS=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_RESERVED_MEM=y -CONFIG_OLD_SIGACTION=y -CONFIG_OLD_SIGSUSPEND3=y -CONFIG_OUTER_CACHE=y -CONFIG_OUTER_CACHE_SYNC=y -CONFIG_PADATA=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PARTITION_ADVANCED is not set -# CONFIG_PCI_DOMAINS_GENERIC is not set -# CONFIG_PCI_SYSCALL is not set -CONFIG_PERF_EVENTS=y -CONFIG_PERF_USE_VMALLOC=y -CONFIG_PGTABLE_LEVELS=3 -CONFIG_PHYLIB=y -CONFIG_PHYS_ADDR_T_64BIT=y -CONFIG_PHY_SUN4I_USB=y -CONFIG_PHY_SUN9I_USB=y -CONFIG_PINCTRL=y -CONFIG_PINCTRL_GR8=y -# CONFIG_PINCTRL_SINGLE is not set -CONFIG_PINCTRL_SUN4I_A10=y -CONFIG_PINCTRL_SUN5I_A10S=y -CONFIG_PINCTRL_SUN5I_A13=y -CONFIG_PINCTRL_SUN6I_A31=y -CONFIG_PINCTRL_SUN6I_A31S=y -CONFIG_PINCTRL_SUN6I_A31_R=y -CONFIG_PINCTRL_SUN7I_A20=y -CONFIG_PINCTRL_SUN8I_A23=y -CONFIG_PINCTRL_SUN8I_A23_R=y -CONFIG_PINCTRL_SUN8I_A33=y -CONFIG_PINCTRL_SUN8I_A83T=y -CONFIG_PINCTRL_SUN8I_H3=y -CONFIG_PINCTRL_SUN8I_H3_R=y -CONFIG_PINCTRL_SUN9I_A80=y -CONFIG_PINCTRL_SUN9I_A80_R=y -CONFIG_PINCTRL_SUNXI=y -# CONFIG_PL310_ERRATA_588369 is not set -# CONFIG_PL310_ERRATA_727915 is not set -# CONFIG_PL310_ERRATA_753970 is not set -# CONFIG_PL310_ERRATA_769419 is not set -CONFIG_PM=y -CONFIG_PM_CLK=y -# CONFIG_PM_DEBUG is not set -CONFIG_PM_OPP=y -CONFIG_PM_SLEEP=y -CONFIG_PM_SLEEP_SMP=y -CONFIG_POWER_RESET=y -CONFIG_POWER_SUPPLY=y -CONFIG_PPS=y -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_NOTIFIERS=y -CONFIG_PREEMPT_RCU=y -CONFIG_PRINTK_TIME=y -CONFIG_PROC_EVENTS=y -CONFIG_PTP_1588_CLOCK=y -CONFIG_PWM=y -CONFIG_PWM_SUN4I=y -CONFIG_PWM_SYSFS=y -CONFIG_RATIONAL=y -# CONFIG_RCU_BOOST is not set -CONFIG_RCU_STALL_COMMON=y -CONFIG_REGMAP=y -CONFIG_REGMAP_I2C=y -CONFIG_REGMAP_IRQ=y -CONFIG_REGMAP_MMIO=y -CONFIG_REGMAP_SPI=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_AXP20X=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_GPIO=y -CONFIG_RELAY=y -CONFIG_RESET_CONTROLLER=y -CONFIG_RESET_SUNXI=y -CONFIG_RFS_ACCEL=y -CONFIG_RPS=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_SATA_PMP=y -# CONFIG_SCHED_INFO is not set -CONFIG_SCSI=y -CONFIG_SDIO_UART=y -CONFIG_SECURITYFS=y -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y -CONFIG_SERIAL_8250_DW=y -CONFIG_SERIAL_8250_FSL=y -CONFIG_SERIAL_8250_NR_UARTS=8 -CONFIG_SERIAL_8250_RUNTIME_UARTS=8 -CONFIG_SERIAL_OF_PLATFORM=y -CONFIG_SERIO=y -CONFIG_SERIO_SERPORT=y -CONFIG_SG_POOL=y -CONFIG_SMP=y -CONFIG_SMP_ON_UP=y -CONFIG_SND=y -CONFIG_SND_COMPRESS_OFFLOAD=y -CONFIG_SND_JACK=y -CONFIG_SND_JACK_INPUT_DEV=y -CONFIG_SND_PCM=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_I2C_AND_SPI=y -# CONFIG_SND_SUN4I_I2S is not set -# CONFIG_SND_SUN4I_SPDIF is not set -CONFIG_SOUND=y -CONFIG_SPARSE_IRQ=y -CONFIG_SPI=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_SUN4I=y -CONFIG_SPI_SUN6I=y -CONFIG_SRCU=y -CONFIG_STMMAC_ETH=y -CONFIG_STMMAC_PLATFORM=y -CONFIG_STRICT_DEVMEM=y -# CONFIG_SUN4I_EMAC is not set -CONFIG_SUN4I_TIMER=y -# CONFIG_SUN50I_A64_CCU is not set -CONFIG_SUN5I_HSTIMER=y -CONFIG_SUN6I_A31_CCU=y -CONFIG_SUN8I_A23_CCU=y -CONFIG_SUN8I_A33_CCU=y -CONFIG_SUN8I_H3_CCU=y -CONFIG_SUNXI_CCU=y -CONFIG_SUNXI_CCU_DIV=y -CONFIG_SUNXI_CCU_FRAC=y -CONFIG_SUNXI_CCU_GATE=y -CONFIG_SUNXI_CCU_MP=y -CONFIG_SUNXI_CCU_MULT=y -CONFIG_SUNXI_CCU_MUX=y -CONFIG_SUNXI_CCU_NK=y -CONFIG_SUNXI_CCU_NKM=y -CONFIG_SUNXI_CCU_NKMP=y -CONFIG_SUNXI_CCU_NM=y -CONFIG_SUNXI_CCU_PHASE=y -CONFIG_SUNXI_RSB=y -CONFIG_SUNXI_SRAM=y -CONFIG_SUNXI_WATCHDOG=y -CONFIG_SUSPEND=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SWCONFIG=y -CONFIG_SWCONFIG_B53=y -# CONFIG_SWCONFIG_B53_MMAP_DRIVER is not set -CONFIG_SWCONFIG_B53_PHY_DRIVER=y -CONFIG_SWCONFIG_B53_PHY_FIXUP=y -# CONFIG_SWCONFIG_B53_SRAB_DRIVER is not set -CONFIG_SWIOTLB=y -CONFIG_SWPHY=y -CONFIG_SWP_EMULATE=y -CONFIG_SYSFS_SYSCALL=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_SYS_SUPPORTS_HUGETLBFS=y -CONFIG_THERMAL=y -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -CONFIG_THERMAL_GOV_STEP_WISE=y -CONFIG_THERMAL_HWMON=y -CONFIG_THERMAL_OF=y -# CONFIG_THUMB2_KERNEL is not set -CONFIG_TICK_CPU_ACCOUNTING=y -CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TOUCHSCREEN_PROPERTIES=y -CONFIG_TOUCHSCREEN_SUN4I=y -CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" -CONFIG_UNINLINE_SPIN_UNLOCK=y -CONFIG_USB=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_COMMON=y -CONFIG_USB_DWC2=y -CONFIG_USB_DWC2_HOST=y -# CONFIG_USB_DWC2_TRACK_MISSED_SOFS is not set -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_HCD_PLATFORM=y -CONFIG_USB_GADGET=y -CONFIG_USB_NET_DRIVERS=y -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_OHCI_HCD_PLATFORM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_SUPPORT=y -CONFIG_USERIO=y -CONFIG_USE_OF=y -CONFIG_VDSO=y -CONFIG_VECTORS_BASE=0xffff0000 -CONFIG_VFAT_FS=y -CONFIG_VFP=y -CONFIG_VFPv3=y -CONFIG_VHOST=y -CONFIG_VHOST_NET=y -CONFIG_VIRTUALIZATION=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_CONSOLE_SLEEP=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_WATCHDOG_CORE=y -# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set -CONFIG_XPS=y -CONFIG_XZ_DEC_ARM=y -CONFIG_XZ_DEC_BCJ=y -CONFIG_ZBOOT_ROM_BSS=0 -CONFIG_ZBOOT_ROM_TEXT=0 diff --git a/target/linux/sunxi/patches-4.9/0002-clk-sunxi-ng-Rename-the-internal-structures.patch b/target/linux/sunxi/patches-4.9/0002-clk-sunxi-ng-Rename-the-internal-structures.patch deleted file mode 100644 index f3e485d88a..0000000000 --- a/target/linux/sunxi/patches-4.9/0002-clk-sunxi-ng-Rename-the-internal-structures.patch +++ /dev/null @@ -1,239 +0,0 @@ -From a501a14e38cc4d8e9c91bb508cdca7032d53f717 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 30 Sep 2016 10:05:32 +0200 -Subject: clk: sunxi-ng: Rename the internal structures - -Rename the structures meant to be embedded in other structures to make it -consistent with the mux structure name - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - drivers/clk/sunxi-ng/ccu_div.h | 6 +++--- - drivers/clk/sunxi-ng/ccu_frac.c | 12 ++++++------ - drivers/clk/sunxi-ng/ccu_frac.h | 14 +++++++------- - drivers/clk/sunxi-ng/ccu_mp.h | 4 ++-- - drivers/clk/sunxi-ng/ccu_mult.h | 4 ++-- - drivers/clk/sunxi-ng/ccu_nk.h | 4 ++-- - drivers/clk/sunxi-ng/ccu_nkm.h | 6 +++--- - drivers/clk/sunxi-ng/ccu_nkmp.h | 8 ++++---- - drivers/clk/sunxi-ng/ccu_nm.h | 6 +++--- - 9 files changed, 32 insertions(+), 32 deletions(-) - ---- a/drivers/clk/sunxi-ng/ccu_div.h -+++ b/drivers/clk/sunxi-ng/ccu_div.h -@@ -20,7 +20,7 @@ - #include "ccu_mux.h" - - /** -- * struct _ccu_div - Internal divider description -+ * struct ccu_div_internal - Internal divider description - * @shift: Bit offset of the divider in its register - * @width: Width of the divider field in its register - * @max: Maximum value allowed for that divider. This is the -@@ -36,7 +36,7 @@ - * It is basically a wrapper around the clk_divider functions - * arguments. - */ --struct _ccu_div { -+struct ccu_div_internal { - u8 shift; - u8 width; - -@@ -78,7 +78,7 @@ struct _ccu_div { - struct ccu_div { - u32 enable; - -- struct _ccu_div div; -+ struct ccu_div_internal div; - struct ccu_mux_internal mux; - struct ccu_common common; - }; ---- a/drivers/clk/sunxi-ng/ccu_frac.c -+++ b/drivers/clk/sunxi-ng/ccu_frac.c -@@ -14,7 +14,7 @@ - #include "ccu_frac.h" - - bool ccu_frac_helper_is_enabled(struct ccu_common *common, -- struct _ccu_frac *cf) -+ struct ccu_frac_internal *cf) - { - if (!(common->features & CCU_FEATURE_FRACTIONAL)) - return false; -@@ -23,7 +23,7 @@ bool ccu_frac_helper_is_enabled(struct c - } - - void ccu_frac_helper_enable(struct ccu_common *common, -- struct _ccu_frac *cf) -+ struct ccu_frac_internal *cf) - { - unsigned long flags; - u32 reg; -@@ -38,7 +38,7 @@ void ccu_frac_helper_enable(struct ccu_c - } - - void ccu_frac_helper_disable(struct ccu_common *common, -- struct _ccu_frac *cf) -+ struct ccu_frac_internal *cf) - { - unsigned long flags; - u32 reg; -@@ -53,7 +53,7 @@ void ccu_frac_helper_disable(struct ccu_ - } - - bool ccu_frac_helper_has_rate(struct ccu_common *common, -- struct _ccu_frac *cf, -+ struct ccu_frac_internal *cf, - unsigned long rate) - { - if (!(common->features & CCU_FEATURE_FRACTIONAL)) -@@ -63,7 +63,7 @@ bool ccu_frac_helper_has_rate(struct ccu - } - - unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, -- struct _ccu_frac *cf) -+ struct ccu_frac_internal *cf) - { - u32 reg; - -@@ -84,7 +84,7 @@ unsigned long ccu_frac_helper_read_rate( - } - - int ccu_frac_helper_set_rate(struct ccu_common *common, -- struct _ccu_frac *cf, -+ struct ccu_frac_internal *cf, - unsigned long rate) - { - unsigned long flags; ---- a/drivers/clk/sunxi-ng/ccu_frac.h -+++ b/drivers/clk/sunxi-ng/ccu_frac.h -@@ -18,7 +18,7 @@ - - #include "ccu_common.h" - --struct _ccu_frac { -+struct ccu_frac_internal { - u32 enable; - u32 select; - -@@ -33,21 +33,21 @@ struct _ccu_frac { - } - - bool ccu_frac_helper_is_enabled(struct ccu_common *common, -- struct _ccu_frac *cf); -+ struct ccu_frac_internal *cf); - void ccu_frac_helper_enable(struct ccu_common *common, -- struct _ccu_frac *cf); -+ struct ccu_frac_internal *cf); - void ccu_frac_helper_disable(struct ccu_common *common, -- struct _ccu_frac *cf); -+ struct ccu_frac_internal *cf); - - bool ccu_frac_helper_has_rate(struct ccu_common *common, -- struct _ccu_frac *cf, -+ struct ccu_frac_internal *cf, - unsigned long rate); - - unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, -- struct _ccu_frac *cf); -+ struct ccu_frac_internal *cf); - - int ccu_frac_helper_set_rate(struct ccu_common *common, -- struct _ccu_frac *cf, -+ struct ccu_frac_internal *cf, - unsigned long rate); - - #endif /* _CCU_FRAC_H_ */ ---- a/drivers/clk/sunxi-ng/ccu_mp.h -+++ b/drivers/clk/sunxi-ng/ccu_mp.h -@@ -29,8 +29,8 @@ - struct ccu_mp { - u32 enable; - -- struct _ccu_div m; -- struct _ccu_div p; -+ struct ccu_div_internal m; -+ struct ccu_div_internal p; - struct ccu_mux_internal mux; - struct ccu_common common; - }; ---- a/drivers/clk/sunxi-ng/ccu_mult.h -+++ b/drivers/clk/sunxi-ng/ccu_mult.h -@@ -4,7 +4,7 @@ - #include "ccu_common.h" - #include "ccu_mux.h" - --struct _ccu_mult { -+struct ccu_mult_internal { - u8 shift; - u8 width; - }; -@@ -18,7 +18,7 @@ struct _ccu_mult { - struct ccu_mult { - u32 enable; - -- struct _ccu_mult mult; -+ struct ccu_mult_internal mult; - struct ccu_mux_internal mux; - struct ccu_common common; - }; ---- a/drivers/clk/sunxi-ng/ccu_nk.h -+++ b/drivers/clk/sunxi-ng/ccu_nk.h -@@ -30,8 +30,8 @@ struct ccu_nk { - u32 enable; - u32 lock; - -- struct _ccu_mult n; -- struct _ccu_mult k; -+ struct ccu_mult_internal n; -+ struct ccu_mult_internal k; - - unsigned int fixed_post_div; - ---- a/drivers/clk/sunxi-ng/ccu_nkm.h -+++ b/drivers/clk/sunxi-ng/ccu_nkm.h -@@ -29,9 +29,9 @@ struct ccu_nkm { - u32 enable; - u32 lock; - -- struct _ccu_mult n; -- struct _ccu_mult k; -- struct _ccu_div m; -+ struct ccu_mult_internal n; -+ struct ccu_mult_internal k; -+ struct ccu_div_internal m; - struct ccu_mux_internal mux; - - struct ccu_common common; ---- a/drivers/clk/sunxi-ng/ccu_nkmp.h -+++ b/drivers/clk/sunxi-ng/ccu_nkmp.h -@@ -29,10 +29,10 @@ struct ccu_nkmp { - u32 enable; - u32 lock; - -- struct _ccu_mult n; -- struct _ccu_mult k; -- struct _ccu_div m; -- struct _ccu_div p; -+ struct ccu_mult_internal n; -+ struct ccu_mult_internal k; -+ struct ccu_div_internal m; -+ struct ccu_div_internal p; - - struct ccu_common common; - }; ---- a/drivers/clk/sunxi-ng/ccu_nm.h -+++ b/drivers/clk/sunxi-ng/ccu_nm.h -@@ -30,9 +30,9 @@ struct ccu_nm { - u32 enable; - u32 lock; - -- struct _ccu_mult n; -- struct _ccu_div m; -- struct _ccu_frac frac; -+ struct ccu_mult_internal n; -+ struct ccu_div_internal m; -+ struct ccu_frac_internal frac; - - struct ccu_common common; - }; diff --git a/target/linux/sunxi/patches-4.9/0003-clk-sunxi-ng-Remove-the-use-of-rational-computations.patch b/target/linux/sunxi/patches-4.9/0003-clk-sunxi-ng-Remove-the-use-of-rational-computations.patch deleted file mode 100644 index 9146a2bb42..0000000000 --- a/target/linux/sunxi/patches-4.9/0003-clk-sunxi-ng-Remove-the-use-of-rational-computations.patch +++ /dev/null @@ -1,239 +0,0 @@ -From ee28648cb2b4d4ab5c2eb8199ea86675fe19016b Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 29 Sep 2016 22:53:12 +0200 -Subject: clk: sunxi-ng: Remove the use of rational computations - -While the rational library works great, it doesn't really allow us to add -more constraints, like the minimum. - -Remove that in order to be able to deal with the constraints we'll need. - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - drivers/clk/sunxi-ng/Kconfig | 3 --- - drivers/clk/sunxi-ng/ccu_nkm.c | 31 ++++++++++++----------- - drivers/clk/sunxi-ng/ccu_nkmp.c | 37 ++++++++++++++-------------- - drivers/clk/sunxi-ng/ccu_nm.c | 54 +++++++++++++++++++++++++++++++---------- - 4 files changed, 74 insertions(+), 51 deletions(-) - ---- a/drivers/clk/sunxi-ng/Kconfig -+++ b/drivers/clk/sunxi-ng/Kconfig -@@ -36,17 +36,14 @@ config SUNXI_CCU_NK - - config SUNXI_CCU_NKM - bool -- select RATIONAL - select SUNXI_CCU_GATE - - config SUNXI_CCU_NKMP - bool -- select RATIONAL - select SUNXI_CCU_GATE - - config SUNXI_CCU_NM - bool -- select RATIONAL - select SUNXI_CCU_FRAC - select SUNXI_CCU_GATE - ---- a/drivers/clk/sunxi-ng/ccu_nkm.c -+++ b/drivers/clk/sunxi-ng/ccu_nkm.c -@@ -9,7 +9,6 @@ - */ - - #include --#include - - #include "ccu_gate.h" - #include "ccu_nkm.h" -@@ -28,21 +27,21 @@ static void ccu_nkm_find_best(unsigned l - unsigned long _n, _k, _m; - - for (_k = 1; _k <= nkm->max_k; _k++) { -- unsigned long tmp_rate; -- -- rational_best_approximation(rate / _k, parent, -- nkm->max_n, nkm->max_m, &_n, &_m); -- -- tmp_rate = parent * _n * _k / _m; -- -- if (tmp_rate > rate) -- continue; -- -- if ((rate - tmp_rate) < (rate - best_rate)) { -- best_rate = tmp_rate; -- best_n = _n; -- best_k = _k; -- best_m = _m; -+ for (_n = 1; _n <= nkm->max_n; _n++) { -+ for (_m = 1; _n <= nkm->max_m; _m++) { -+ unsigned long tmp_rate; -+ -+ tmp_rate = parent * _n * _k / _m; -+ -+ if (tmp_rate > rate) -+ continue; -+ if ((rate - tmp_rate) < (rate - best_rate)) { -+ best_rate = tmp_rate; -+ best_n = _n; -+ best_k = _k; -+ best_m = _m; -+ } -+ } - } - } - ---- a/drivers/clk/sunxi-ng/ccu_nkmp.c -+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c -@@ -9,7 +9,6 @@ - */ - - #include --#include - - #include "ccu_gate.h" - #include "ccu_nkmp.h" -@@ -29,24 +28,24 @@ static void ccu_nkmp_find_best(unsigned - unsigned long _n, _k, _m, _p; - - for (_k = 1; _k <= nkmp->max_k; _k++) { -- for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { -- unsigned long tmp_rate; -- -- rational_best_approximation(rate / _k, parent / _p, -- nkmp->max_n, nkmp->max_m, -- &_n, &_m); -- -- tmp_rate = parent * _n * _k / (_m * _p); -- -- if (tmp_rate > rate) -- continue; -- -- if ((rate - tmp_rate) < (rate - best_rate)) { -- best_rate = tmp_rate; -- best_n = _n; -- best_k = _k; -- best_m = _m; -- best_p = _p; -+ for (_n = 1; _n <= nkmp->max_n; _n++) { -+ for (_m = 1; _n <= nkmp->max_m; _m++) { -+ for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { -+ unsigned long tmp_rate; -+ -+ tmp_rate = parent * _n * _k / (_m * _p); -+ -+ if (tmp_rate > rate) -+ continue; -+ -+ if ((rate - tmp_rate) < (rate - best_rate)) { -+ best_rate = tmp_rate; -+ best_n = _n; -+ best_k = _k; -+ best_m = _m; -+ best_p = _p; -+ } -+ } - } - } - } ---- a/drivers/clk/sunxi-ng/ccu_nm.c -+++ b/drivers/clk/sunxi-ng/ccu_nm.c -@@ -9,12 +9,42 @@ - */ - - #include --#include - - #include "ccu_frac.h" - #include "ccu_gate.h" - #include "ccu_nm.h" - -+struct _ccu_nm { -+ unsigned long n, max_n; -+ unsigned long m, max_m; -+}; -+ -+static void ccu_nm_find_best(unsigned long parent, unsigned long rate, -+ struct _ccu_nm *nm) -+{ -+ unsigned long best_rate = 0; -+ unsigned long best_n = 0, best_m = 0; -+ unsigned long _n, _m; -+ -+ for (_n = 1; _n <= nm->max_n; _n++) { -+ for (_m = 1; _n <= nm->max_m; _m++) { -+ unsigned long tmp_rate = parent * _n / _m; -+ -+ if (tmp_rate > rate) -+ continue; -+ -+ if ((rate - tmp_rate) < (rate - best_rate)) { -+ best_rate = tmp_rate; -+ best_n = _n; -+ best_m = _m; -+ } -+ } -+ } -+ -+ nm->n = best_n; -+ nm->m = best_m; -+} -+ - static void ccu_nm_disable(struct clk_hw *hw) - { - struct ccu_nm *nm = hw_to_ccu_nm(hw); -@@ -61,24 +91,22 @@ static long ccu_nm_round_rate(struct clk - unsigned long *parent_rate) - { - struct ccu_nm *nm = hw_to_ccu_nm(hw); -- unsigned long max_n, max_m; -- unsigned long n, m; -+ struct _ccu_nm _nm; - -- max_n = 1 << nm->n.width; -- max_m = nm->m.max ?: 1 << nm->m.width; -+ _nm.max_n = 1 << nm->n.width; -+ _nm.max_m = nm->m.max ?: 1 << nm->m.width; - -- rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m); -+ ccu_nm_find_best(*parent_rate, rate, &_nm); - -- return *parent_rate * n / m; -+ return *parent_rate * _nm.n / _nm.m; - } - - static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) - { - struct ccu_nm *nm = hw_to_ccu_nm(hw); -+ struct _ccu_nm _nm; - unsigned long flags; -- unsigned long max_n, max_m; -- unsigned long n, m; - u32 reg; - - if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) -@@ -86,10 +114,10 @@ static int ccu_nm_set_rate(struct clk_hw - else - ccu_frac_helper_disable(&nm->common, &nm->frac); - -- max_n = 1 << nm->n.width; -- max_m = nm->m.max ?: 1 << nm->m.width; -+ _nm.max_n = 1 << nm->n.width; -+ _nm.max_m = nm->m.max ?: 1 << nm->m.width; - -- rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m); -+ ccu_nm_find_best(parent_rate, rate, &_nm); - - spin_lock_irqsave(nm->common.lock, flags); - -@@ -97,7 +125,7 @@ static int ccu_nm_set_rate(struct clk_hw - reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift); - reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); - -- writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift), -+ writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift), - nm->common.base + nm->common.reg); - - spin_unlock_irqrestore(nm->common.lock, flags); diff --git a/target/linux/sunxi/patches-4.9/0004-clk-sunxi-ng-Finish-to-convert-to-structures-for-arg.patch b/target/linux/sunxi/patches-4.9/0004-clk-sunxi-ng-Finish-to-convert-to-structures-for-arg.patch deleted file mode 100644 index 4b91892b81..0000000000 --- a/target/linux/sunxi/patches-4.9/0004-clk-sunxi-ng-Finish-to-convert-to-structures-for-arg.patch +++ /dev/null @@ -1,182 +0,0 @@ -From b8302c7267dedaeeb1bf38143f099defbf16dce8 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 29 Sep 2016 23:50:21 +0200 -Subject: clk: sunxi-ng: Finish to convert to structures for arguments - -Some clocks still use an explicit list of arguments, which make it a bit -more tedious to add new parameters. - -Convert those over to a structure pointer argument to add as many -arguments as possible without having to many noise in our patches, or a -very long list of arguments. - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - drivers/clk/sunxi-ng/ccu_mult.c | 28 ++++++++++++++++++++-------- - drivers/clk/sunxi-ng/ccu_nk.c | 39 ++++++++++++++++++++++----------------- - 2 files changed, 42 insertions(+), 25 deletions(-) - ---- a/drivers/clk/sunxi-ng/ccu_mult.c -+++ b/drivers/clk/sunxi-ng/ccu_mult.c -@@ -13,10 +13,20 @@ - #include "ccu_gate.h" - #include "ccu_mult.h" - -+struct _ccu_mult { -+ unsigned long mult, max; -+}; -+ - static void ccu_mult_find_best(unsigned long parent, unsigned long rate, -- unsigned int max_n, unsigned int *n) -+ struct _ccu_mult *mult) - { -- *n = rate / parent; -+ int _mult; -+ -+ _mult = rate / parent; -+ if (_mult > mult->max) -+ _mult = mult->max; -+ -+ mult->mult = _mult; - } - - static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, -@@ -25,11 +35,12 @@ static unsigned long ccu_mult_round_rate - void *data) - { - struct ccu_mult *cm = data; -- unsigned int n; -+ struct _ccu_mult _cm; - -- ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); -+ _cm.max = 1 << cm->mult.width; -+ ccu_mult_find_best(parent_rate, rate, &_cm); - -- return parent_rate * n; -+ return parent_rate * _cm.mult; - } - - static void ccu_mult_disable(struct clk_hw *hw) -@@ -83,21 +94,22 @@ static int ccu_mult_set_rate(struct clk_ - unsigned long parent_rate) - { - struct ccu_mult *cm = hw_to_ccu_mult(hw); -+ struct _ccu_mult _cm; - unsigned long flags; -- unsigned int n; - u32 reg; - - ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, - &parent_rate); - -- ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); -+ _cm.max = 1 << cm->mult.width; -+ ccu_mult_find_best(parent_rate, rate, &_cm); - - spin_lock_irqsave(cm->common.lock, flags); - - reg = readl(cm->common.base + cm->common.reg); - reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift); - -- writel(reg | ((n - 1) << cm->mult.shift), -+ writel(reg | ((_cm.mult - 1) << cm->mult.shift), - cm->common.base + cm->common.reg); - - spin_unlock_irqrestore(cm->common.lock, flags); ---- a/drivers/clk/sunxi-ng/ccu_nk.c -+++ b/drivers/clk/sunxi-ng/ccu_nk.c -@@ -9,21 +9,24 @@ - */ - - #include --#include - - #include "ccu_gate.h" - #include "ccu_nk.h" - -+struct _ccu_nk { -+ unsigned long n, max_n; -+ unsigned long k, max_k; -+}; -+ - static void ccu_nk_find_best(unsigned long parent, unsigned long rate, -- unsigned int max_n, unsigned int max_k, -- unsigned int *n, unsigned int *k) -+ struct _ccu_nk *nk) - { - unsigned long best_rate = 0; - unsigned int best_k = 0, best_n = 0; - unsigned int _k, _n; - -- for (_k = 1; _k <= max_k; _k++) { -- for (_n = 1; _n <= max_n; _n++) { -+ for (_k = 1; _k <= nk->max_k; _k++) { -+ for (_n = 1; _n <= nk->max_n; _n++) { - unsigned long tmp_rate = parent * _n * _k; - - if (tmp_rate > rate) -@@ -37,8 +40,8 @@ static void ccu_nk_find_best(unsigned lo - } - } - -- *k = best_k; -- *n = best_n; -+ nk->k = best_k; -+ nk->n = best_n; - } - - static void ccu_nk_disable(struct clk_hw *hw) -@@ -89,16 +92,17 @@ static long ccu_nk_round_rate(struct clk - unsigned long *parent_rate) - { - struct ccu_nk *nk = hw_to_ccu_nk(hw); -- unsigned int n, k; -+ struct _ccu_nk _nk; - - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= nk->fixed_post_div; - -- ccu_nk_find_best(*parent_rate, rate, -- 1 << nk->n.width, 1 << nk->k.width, -- &n, &k); -+ _nk.max_n = 1 << nk->n.width; -+ _nk.max_k = 1 << nk->k.width; -+ -+ ccu_nk_find_best(*parent_rate, rate, &_nk); -+ rate = *parent_rate * _nk.n * _nk.k; - -- rate = *parent_rate * n * k; - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate = rate / nk->fixed_post_div; - -@@ -110,15 +114,16 @@ static int ccu_nk_set_rate(struct clk_hw - { - struct ccu_nk *nk = hw_to_ccu_nk(hw); - unsigned long flags; -- unsigned int n, k; -+ struct _ccu_nk _nk; - u32 reg; - - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate = rate * nk->fixed_post_div; - -- ccu_nk_find_best(parent_rate, rate, -- 1 << nk->n.width, 1 << nk->k.width, -- &n, &k); -+ _nk.max_n = 1 << nk->n.width; -+ _nk.max_k = 1 << nk->k.width; -+ -+ ccu_nk_find_best(parent_rate, rate, &_nk); - - spin_lock_irqsave(nk->common.lock, flags); - -@@ -126,7 +131,7 @@ static int ccu_nk_set_rate(struct clk_hw - reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift); - reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift); - -- writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift), -+ writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift), - nk->common.base + nk->common.reg); - - spin_unlock_irqrestore(nk->common.lock, flags); diff --git a/target/linux/sunxi/patches-4.9/0005-clk-sunxi-ng-Add-minimums-for-all-the-relevant-struc.patch b/target/linux/sunxi/patches-4.9/0005-clk-sunxi-ng-Add-minimums-for-all-the-relevant-struc.patch deleted file mode 100644 index 0165ade138..0000000000 --- a/target/linux/sunxi/patches-4.9/0005-clk-sunxi-ng-Add-minimums-for-all-the-relevant-struc.patch +++ /dev/null @@ -1,256 +0,0 @@ -From 6e0d50daa97f4bf9706e343b4f71171e88921209 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 29 Sep 2016 22:57:26 +0200 -Subject: clk: sunxi-ng: Add minimums for all the relevant structures and - clocks - -Modify the current clocks we have to be able to specify the minimum for -each clocks we support, just like we support the max. - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - drivers/clk/sunxi-ng/ccu_mult.c | 7 ++++++- - drivers/clk/sunxi-ng/ccu_nk.c | 12 ++++++++---- - drivers/clk/sunxi-ng/ccu_nkm.c | 18 ++++++++++++------ - drivers/clk/sunxi-ng/ccu_nkmp.c | 24 ++++++++++++++++-------- - drivers/clk/sunxi-ng/ccu_nm.c | 12 ++++++++---- - 5 files changed, 50 insertions(+), 23 deletions(-) - ---- a/drivers/clk/sunxi-ng/ccu_mult.c -+++ b/drivers/clk/sunxi-ng/ccu_mult.c -@@ -14,7 +14,7 @@ - #include "ccu_mult.h" - - struct _ccu_mult { -- unsigned long mult, max; -+ unsigned long mult, min, max; - }; - - static void ccu_mult_find_best(unsigned long parent, unsigned long rate, -@@ -23,6 +23,9 @@ static void ccu_mult_find_best(unsigned - int _mult; - - _mult = rate / parent; -+ if (_mult < mult->min) -+ _mult = mult->min; -+ - if (_mult > mult->max) - _mult = mult->max; - -@@ -37,6 +40,7 @@ static unsigned long ccu_mult_round_rate - struct ccu_mult *cm = data; - struct _ccu_mult _cm; - -+ _cm.min = 1; - _cm.max = 1 << cm->mult.width; - ccu_mult_find_best(parent_rate, rate, &_cm); - -@@ -101,6 +105,7 @@ static int ccu_mult_set_rate(struct clk_ - ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, - &parent_rate); - -+ _cm.min = 1; - _cm.max = 1 << cm->mult.width; - ccu_mult_find_best(parent_rate, rate, &_cm); - ---- a/drivers/clk/sunxi-ng/ccu_nk.c -+++ b/drivers/clk/sunxi-ng/ccu_nk.c -@@ -14,8 +14,8 @@ - #include "ccu_nk.h" - - struct _ccu_nk { -- unsigned long n, max_n; -- unsigned long k, max_k; -+ unsigned long n, min_n, max_n; -+ unsigned long k, min_k, max_k; - }; - - static void ccu_nk_find_best(unsigned long parent, unsigned long rate, -@@ -25,8 +25,8 @@ static void ccu_nk_find_best(unsigned lo - unsigned int best_k = 0, best_n = 0; - unsigned int _k, _n; - -- for (_k = 1; _k <= nk->max_k; _k++) { -- for (_n = 1; _n <= nk->max_n; _n++) { -+ for (_k = nk->min_k; _k <= nk->max_k; _k++) { -+ for (_n = nk->min_n; _n <= nk->max_n; _n++) { - unsigned long tmp_rate = parent * _n * _k; - - if (tmp_rate > rate) -@@ -97,7 +97,9 @@ static long ccu_nk_round_rate(struct clk - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= nk->fixed_post_div; - -+ _nk.min_n = 1; - _nk.max_n = 1 << nk->n.width; -+ _nk.min_k = 1; - _nk.max_k = 1 << nk->k.width; - - ccu_nk_find_best(*parent_rate, rate, &_nk); -@@ -120,7 +122,9 @@ static int ccu_nk_set_rate(struct clk_hw - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate = rate * nk->fixed_post_div; - -+ _nk.min_n = 1; - _nk.max_n = 1 << nk->n.width; -+ _nk.min_k = 1; - _nk.max_k = 1 << nk->k.width; - - ccu_nk_find_best(parent_rate, rate, &_nk); ---- a/drivers/clk/sunxi-ng/ccu_nkm.c -+++ b/drivers/clk/sunxi-ng/ccu_nkm.c -@@ -14,9 +14,9 @@ - #include "ccu_nkm.h" - - struct _ccu_nkm { -- unsigned long n, max_n; -- unsigned long k, max_k; -- unsigned long m, max_m; -+ unsigned long n, min_n, max_n; -+ unsigned long k, min_k, max_k; -+ unsigned long m, min_m, max_m; - }; - - static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, -@@ -26,9 +26,9 @@ static void ccu_nkm_find_best(unsigned l - unsigned long best_n = 0, best_k = 0, best_m = 0; - unsigned long _n, _k, _m; - -- for (_k = 1; _k <= nkm->max_k; _k++) { -- for (_n = 1; _n <= nkm->max_n; _n++) { -- for (_m = 1; _n <= nkm->max_m; _m++) { -+ for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { -+ for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { -+ for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { - unsigned long tmp_rate; - - tmp_rate = parent * _n * _k / _m; -@@ -100,8 +100,11 @@ static unsigned long ccu_nkm_round_rate( - struct ccu_nkm *nkm = data; - struct _ccu_nkm _nkm; - -+ _nkm.min_n = 1; - _nkm.max_n = 1 << nkm->n.width; -+ _nkm.min_k = 1; - _nkm.max_k = 1 << nkm->k.width; -+ _nkm.min_m = 1; - _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; - - ccu_nkm_find_best(parent_rate, rate, &_nkm); -@@ -126,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_h - unsigned long flags; - u32 reg; - -+ _nkm.min_n = 1; - _nkm.max_n = 1 << nkm->n.width; -+ _nkm.min_k = 1; - _nkm.max_k = 1 << nkm->k.width; -+ _nkm.min_m = 1; - _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; - - ccu_nkm_find_best(parent_rate, rate, &_nkm); ---- a/drivers/clk/sunxi-ng/ccu_nkmp.c -+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c -@@ -14,10 +14,10 @@ - #include "ccu_nkmp.h" - - struct _ccu_nkmp { -- unsigned long n, max_n; -- unsigned long k, max_k; -- unsigned long m, max_m; -- unsigned long p, max_p; -+ unsigned long n, min_n, max_n; -+ unsigned long k, min_k, max_k; -+ unsigned long m, min_m, max_m; -+ unsigned long p, min_p, max_p; - }; - - static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, -@@ -27,10 +27,10 @@ static void ccu_nkmp_find_best(unsigned - unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0; - unsigned long _n, _k, _m, _p; - -- for (_k = 1; _k <= nkmp->max_k; _k++) { -- for (_n = 1; _n <= nkmp->max_n; _n++) { -- for (_m = 1; _n <= nkmp->max_m; _m++) { -- for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { -+ for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) { -+ for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) { -+ for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) { -+ for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) { - unsigned long tmp_rate; - - tmp_rate = parent * _n * _k / (_m * _p); -@@ -107,9 +107,13 @@ static long ccu_nkmp_round_rate(struct c - struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); - struct _ccu_nkmp _nkmp; - -+ _nkmp.min_n = 1; - _nkmp.max_n = 1 << nkmp->n.width; -+ _nkmp.min_k = 1; - _nkmp.max_k = 1 << nkmp->k.width; -+ _nkmp.min_m = 1; - _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; -+ _nkmp.min_p = 1; - _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); - - ccu_nkmp_find_best(*parent_rate, rate, &_nkmp); -@@ -125,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_ - unsigned long flags; - u32 reg; - -+ _nkmp.min_n = 1; - _nkmp.max_n = 1 << nkmp->n.width; -+ _nkmp.min_k = 1; - _nkmp.max_k = 1 << nkmp->k.width; -+ _nkmp.min_m = 1; - _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; -+ _nkmp.min_p = 1; - _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); - - ccu_nkmp_find_best(parent_rate, rate, &_nkmp); ---- a/drivers/clk/sunxi-ng/ccu_nm.c -+++ b/drivers/clk/sunxi-ng/ccu_nm.c -@@ -15,8 +15,8 @@ - #include "ccu_nm.h" - - struct _ccu_nm { -- unsigned long n, max_n; -- unsigned long m, max_m; -+ unsigned long n, min_n, max_n; -+ unsigned long m, min_m, max_m; - }; - - static void ccu_nm_find_best(unsigned long parent, unsigned long rate, -@@ -26,8 +26,8 @@ static void ccu_nm_find_best(unsigned lo - unsigned long best_n = 0, best_m = 0; - unsigned long _n, _m; - -- for (_n = 1; _n <= nm->max_n; _n++) { -- for (_m = 1; _n <= nm->max_m; _m++) { -+ for (_n = nm->min_n; _n <= nm->max_n; _n++) { -+ for (_m = nm->min_m; _m <= nm->max_m; _m++) { - unsigned long tmp_rate = parent * _n / _m; - - if (tmp_rate > rate) -@@ -93,7 +93,9 @@ static long ccu_nm_round_rate(struct clk - struct ccu_nm *nm = hw_to_ccu_nm(hw); - struct _ccu_nm _nm; - -+ _nm.min_n = 1; - _nm.max_n = 1 << nm->n.width; -+ _nm.min_m = 1; - _nm.max_m = nm->m.max ?: 1 << nm->m.width; - - ccu_nm_find_best(*parent_rate, rate, &_nm); -@@ -114,7 +116,9 @@ static int ccu_nm_set_rate(struct clk_hw - else - ccu_frac_helper_disable(&nm->common, &nm->frac); - -+ _nm.min_n = 1; - _nm.max_n = 1 << nm->n.width; -+ _nm.min_m = 1; - _nm.max_m = nm->m.max ?: 1 << nm->m.width; - - ccu_nm_find_best(parent_rate, rate, &_nm); diff --git a/target/linux/sunxi/patches-4.9/0006-clk-sunxi-ng-Implement-minimum-for-multipliers.patch b/target/linux/sunxi/patches-4.9/0006-clk-sunxi-ng-Implement-minimum-for-multipliers.patch deleted file mode 100644 index 668d596493..0000000000 --- a/target/linux/sunxi/patches-4.9/0006-clk-sunxi-ng-Implement-minimum-for-multipliers.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 2beaa601c849e72683a2dd0fe6fd77763f19f051 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Fri, 30 Sep 2016 22:16:51 +0200 -Subject: clk: sunxi-ng: Implement minimum for multipliers - -Allow the CCU drivers to specify a multiplier for their clocks. - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - drivers/clk/sunxi-ng/ccu_mult.c | 2 +- - drivers/clk/sunxi-ng/ccu_mult.h | 13 +++++++++---- - drivers/clk/sunxi-ng/ccu_nk.c | 8 ++++---- - drivers/clk/sunxi-ng/ccu_nkm.c | 8 ++++---- - drivers/clk/sunxi-ng/ccu_nkmp.c | 4 ++-- - drivers/clk/sunxi-ng/ccu_nm.c | 2 +- - 6 files changed, 21 insertions(+), 16 deletions(-) - ---- a/drivers/clk/sunxi-ng/ccu_mult.c -+++ b/drivers/clk/sunxi-ng/ccu_mult.c -@@ -105,7 +105,7 @@ static int ccu_mult_set_rate(struct clk_ - ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, - &parent_rate); - -- _cm.min = 1; -+ _cm.min = cm->mult.min; - _cm.max = 1 << cm->mult.width; - ccu_mult_find_best(parent_rate, rate, &_cm); - ---- a/drivers/clk/sunxi-ng/ccu_mult.h -+++ b/drivers/clk/sunxi-ng/ccu_mult.h -@@ -7,14 +7,19 @@ - struct ccu_mult_internal { - u8 shift; - u8 width; -+ u8 min; - }; - --#define _SUNXI_CCU_MULT(_shift, _width) \ -- { \ -- .shift = _shift, \ -- .width = _width, \ -+#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min) \ -+ { \ -+ .shift = _shift, \ -+ .width = _width, \ -+ .min = _min, \ - } - -+#define _SUNXI_CCU_MULT(_shift, _width) \ -+ _SUNXI_CCU_MULT_MIN(_shift, _width, 1) -+ - struct ccu_mult { - u32 enable; - ---- a/drivers/clk/sunxi-ng/ccu_nk.c -+++ b/drivers/clk/sunxi-ng/ccu_nk.c -@@ -97,9 +97,9 @@ static long ccu_nk_round_rate(struct clk - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate *= nk->fixed_post_div; - -- _nk.min_n = 1; -+ _nk.min_n = nk->n.min; - _nk.max_n = 1 << nk->n.width; -- _nk.min_k = 1; -+ _nk.min_k = nk->k.min; - _nk.max_k = 1 << nk->k.width; - - ccu_nk_find_best(*parent_rate, rate, &_nk); -@@ -122,9 +122,9 @@ static int ccu_nk_set_rate(struct clk_hw - if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) - rate = rate * nk->fixed_post_div; - -- _nk.min_n = 1; -+ _nk.min_n = nk->n.min; - _nk.max_n = 1 << nk->n.width; -- _nk.min_k = 1; -+ _nk.min_k = nk->k.min; - _nk.max_k = 1 << nk->k.width; - - ccu_nk_find_best(parent_rate, rate, &_nk); ---- a/drivers/clk/sunxi-ng/ccu_nkm.c -+++ b/drivers/clk/sunxi-ng/ccu_nkm.c -@@ -100,9 +100,9 @@ static unsigned long ccu_nkm_round_rate( - struct ccu_nkm *nkm = data; - struct _ccu_nkm _nkm; - -- _nkm.min_n = 1; -+ _nkm.min_n = nkm->n.min; - _nkm.max_n = 1 << nkm->n.width; -- _nkm.min_k = 1; -+ _nkm.min_k = nkm->k.min; - _nkm.max_k = 1 << nkm->k.width; - _nkm.min_m = 1; - _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; -@@ -129,9 +129,9 @@ static int ccu_nkm_set_rate(struct clk_h - unsigned long flags; - u32 reg; - -- _nkm.min_n = 1; -+ _nkm.min_n = nkm->n.min; - _nkm.max_n = 1 << nkm->n.width; -- _nkm.min_k = 1; -+ _nkm.min_k = nkm->k.min; - _nkm.max_k = 1 << nkm->k.width; - _nkm.min_m = 1; - _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; ---- a/drivers/clk/sunxi-ng/ccu_nkmp.c -+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c -@@ -107,9 +107,9 @@ static long ccu_nkmp_round_rate(struct c - struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); - struct _ccu_nkmp _nkmp; - -- _nkmp.min_n = 1; -+ _nkmp.min_n = nkmp->n.min; - _nkmp.max_n = 1 << nkmp->n.width; -- _nkmp.min_k = 1; -+ _nkmp.min_k = nkmp->k.min; - _nkmp.max_k = 1 << nkmp->k.width; - _nkmp.min_m = 1; - _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; ---- a/drivers/clk/sunxi-ng/ccu_nm.c -+++ b/drivers/clk/sunxi-ng/ccu_nm.c -@@ -93,7 +93,7 @@ static long ccu_nm_round_rate(struct clk - struct ccu_nm *nm = hw_to_ccu_nm(hw); - struct _ccu_nm _nm; - -- _nm.min_n = 1; -+ _nm.min_n = nm->n.min; - _nm.max_n = 1 << nm->n.width; - _nm.min_m = 1; - _nm.max_m = nm->m.max ?: 1 << nm->m.width; diff --git a/target/linux/sunxi/patches-4.9/0007-clk-sunxi-ng-Add-A64-clocks.patch b/target/linux/sunxi/patches-4.9/0007-clk-sunxi-ng-Add-A64-clocks.patch deleted file mode 100644 index 1039a83b41..0000000000 --- a/target/linux/sunxi/patches-4.9/0007-clk-sunxi-ng-Add-A64-clocks.patch +++ /dev/null @@ -1,1295 +0,0 @@ -From c6a0637460c29799f1e63a6a4a65bda22caf4a54 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Wed, 6 Jul 2016 08:31:34 +0200 -Subject: clk: sunxi-ng: Add A64 clocks - -Add the A64 CCU clocks set. - -Acked-by: Rob Herring -Acked-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard ---- - .../devicetree/bindings/clock/sunxi-ccu.txt | 1 + - drivers/clk/sunxi-ng/Kconfig | 11 + - drivers/clk/sunxi-ng/Makefile | 1 + - drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 915 +++++++++++++++++++++ - drivers/clk/sunxi-ng/ccu-sun50i-a64.h | 72 ++ - include/dt-bindings/clock/sun50i-a64-ccu.h | 134 +++ - include/dt-bindings/reset/sun50i-a64-ccu.h | 98 +++ - 7 files changed, 1232 insertions(+) - create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a64.c - create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a64.h - create mode 100644 include/dt-bindings/clock/sun50i-a64-ccu.h - create mode 100644 include/dt-bindings/reset/sun50i-a64-ccu.h - ---- a/Documentation/devicetree/bindings/clock/sunxi-ccu.txt -+++ b/Documentation/devicetree/bindings/clock/sunxi-ccu.txt -@@ -7,6 +7,7 @@ Required properties : - - "allwinner,sun8i-a23-ccu" - - "allwinner,sun8i-a33-ccu" - - "allwinner,sun8i-h3-ccu" -+ - "allwinner,sun50i-a64-ccu" - - - reg: Must contain the registers base address and length - - clocks: phandle to the oscillators feeding the CCU. Two are needed: ---- a/drivers/clk/sunxi-ng/Kconfig -+++ b/drivers/clk/sunxi-ng/Kconfig -@@ -54,6 +54,17 @@ config SUNXI_CCU_MP - - # SoC Drivers - -+config SUN50I_A64_CCU -+ bool "Support for the Allwinner A64 CCU" -+ select SUNXI_CCU_DIV -+ select SUNXI_CCU_NK -+ select SUNXI_CCU_NKM -+ select SUNXI_CCU_NKMP -+ select SUNXI_CCU_NM -+ select SUNXI_CCU_MP -+ select SUNXI_CCU_PHASE -+ default ARM64 && ARCH_SUNXI -+ - config SUN6I_A31_CCU - bool "Support for the Allwinner A31/A31s CCU" - select SUNXI_CCU_DIV ---- a/drivers/clk/sunxi-ng/Makefile -+++ b/drivers/clk/sunxi-ng/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_SUNXI_CCU_NM) += ccu_nm.o - obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o - - # SoC support -+obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o - obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o - obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o - obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o ---- /dev/null -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c -@@ -0,0 +1,915 @@ -+/* -+ * Copyright (c) 2016 Maxime Ripard. All rights reserved. -+ * -+ * 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 "ccu_common.h" -+#include "ccu_reset.h" -+ -+#include "ccu_div.h" -+#include "ccu_gate.h" -+#include "ccu_mp.h" -+#include "ccu_mult.h" -+#include "ccu_nk.h" -+#include "ccu_nkm.h" -+#include "ccu_nkmp.h" -+#include "ccu_nm.h" -+#include "ccu_phase.h" -+ -+#include "ccu-sun50i-a64.h" -+ -+static struct ccu_nkmp pll_cpux_clk = { -+ .enable = BIT(31), -+ .lock = BIT(28), -+ .n = _SUNXI_CCU_MULT(8, 5), -+ .k = _SUNXI_CCU_MULT(4, 2), -+ .m = _SUNXI_CCU_DIV(0, 2), -+ .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), -+ .common = { -+ .reg = 0x000, -+ .hw.init = CLK_HW_INIT("pll-cpux", -+ "osc24M", -+ &ccu_nkmp_ops, -+ CLK_SET_RATE_UNGATE), -+ }, -+}; -+ -+/* -+ * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from -+ * the base (2x, 4x and 8x), and one variable divider (the one true -+ * pll audio). -+ * -+ * We don't have any need for the variable divider for now, so we just -+ * hardcode it to match with the clock names -+ */ -+#define SUN50I_A64_PLL_AUDIO_REG 0x008 -+ -+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", -+ "osc24M", 0x008, -+ 8, 7, /* N */ -+ 0, 5, /* M */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", -+ "osc24M", 0x010, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", -+ "osc24M", 0x018, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", -+ "osc24M", 0x020, -+ 8, 5, /* N */ -+ 4, 2, /* K */ -+ 0, 2, /* M */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static struct ccu_nk pll_periph0_clk = { -+ .enable = BIT(31), -+ .lock = BIT(28), -+ .n = _SUNXI_CCU_MULT(8, 5), -+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), -+ .fixed_post_div = 2, -+ .common = { -+ .reg = 0x028, -+ .features = CCU_FEATURE_FIXED_POSTDIV, -+ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", -+ &ccu_nk_ops, CLK_SET_RATE_UNGATE), -+ }, -+}; -+ -+static struct ccu_nk pll_periph1_clk = { -+ .enable = BIT(31), -+ .lock = BIT(28), -+ .n = _SUNXI_CCU_MULT(8, 5), -+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), -+ .fixed_post_div = 2, -+ .common = { -+ .reg = 0x02c, -+ .features = CCU_FEATURE_FIXED_POSTDIV, -+ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", -+ &ccu_nk_ops, CLK_SET_RATE_UNGATE), -+ }, -+}; -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", -+ "osc24M", 0x030, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", -+ "osc24M", 0x038, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+/* -+ * The output function can be changed to something more complex that -+ * we do not handle yet. -+ * -+ * Hardcode the mode so that we don't fall in that case. -+ */ -+#define SUN50I_A64_PLL_MIPI_REG 0x040 -+ -+struct ccu_nkm pll_mipi_clk = { -+ .enable = BIT(31), -+ .lock = BIT(28), -+ .n = _SUNXI_CCU_MULT(8, 4), -+ .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), -+ .m = _SUNXI_CCU_DIV(0, 4), -+ .common = { -+ .reg = 0x040, -+ .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", -+ &ccu_nkm_ops, CLK_SET_RATE_UNGATE), -+ }, -+}; -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic", -+ "osc24M", 0x044, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", -+ "osc24M", 0x048, -+ 8, 7, /* N */ -+ 0, 4, /* M */ -+ BIT(24), /* frac enable */ -+ BIT(25), /* frac select */ -+ 270000000, /* frac rate 0 */ -+ 297000000, /* frac rate 1 */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", -+ "osc24M", 0x04c, -+ 8, 7, /* N */ -+ 0, 2, /* M */ -+ BIT(31), /* gate */ -+ BIT(28), /* lock */ -+ CLK_SET_RATE_UNGATE); -+ -+static const char * const cpux_parents[] = { "osc32k", "osc24M", -+ "pll-cpux" , "pll-cpux" }; -+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, -+ 0x050, 16, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); -+ -+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); -+ -+static const char * const ahb1_parents[] = { "osc32k", "osc24M", -+ "axi" , "pll-periph0" }; -+static struct ccu_div ahb1_clk = { -+ .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), -+ -+ .mux = { -+ .shift = 12, -+ .width = 2, -+ -+ .variable_prediv = { -+ .index = 3, -+ .shift = 6, -+ .width = 2, -+ }, -+ }, -+ -+ .common = { -+ .reg = 0x054, -+ .features = CCU_FEATURE_VARIABLE_PREDIV, -+ .hw.init = CLK_HW_INIT_PARENTS("ahb1", -+ ahb1_parents, -+ &ccu_div_ops, -+ 0), -+ }, -+}; -+ -+static struct clk_div_table apb1_div_table[] = { -+ { .val = 0, .div = 2 }, -+ { .val = 1, .div = 2 }, -+ { .val = 2, .div = 4 }, -+ { .val = 3, .div = 8 }, -+ { /* Sentinel */ }, -+}; -+static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", -+ 0x054, 8, 2, apb1_div_table, 0); -+ -+static const char * const apb2_parents[] = { "osc32k", "osc24M", -+ "pll-periph0-2x" , -+ "pll-periph0-2x" }; -+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, -+ 0, 5, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ 0); -+ -+static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" }; -+static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = { -+ { .index = 1, .div = 2 }, -+}; -+static struct ccu_mux ahb2_clk = { -+ .mux = { -+ .shift = 0, -+ .width = 1, -+ .fixed_predivs = ahb2_fixed_predivs, -+ .n_predivs = ARRAY_SIZE(ahb2_fixed_predivs), -+ }, -+ -+ .common = { -+ .reg = 0x05c, -+ .features = CCU_FEATURE_FIXED_PREDIV, -+ .hw.init = CLK_HW_INIT_PARENTS("ahb2", -+ ahb2_parents, -+ &ccu_mux_ops, -+ 0), -+ }, -+}; -+ -+static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", -+ 0x060, BIT(1), 0); -+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", -+ 0x060, BIT(5), 0); -+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", -+ 0x060, BIT(6), 0); -+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", -+ 0x060, BIT(8), 0); -+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", -+ 0x060, BIT(9), 0); -+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", -+ 0x060, BIT(10), 0); -+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", -+ 0x060, BIT(13), 0); -+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", -+ 0x060, BIT(14), 0); -+static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2", -+ 0x060, BIT(17), 0); -+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", -+ 0x060, BIT(18), 0); -+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", -+ 0x060, BIT(19), 0); -+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", -+ 0x060, BIT(20), 0); -+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", -+ 0x060, BIT(21), 0); -+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", -+ 0x060, BIT(23), 0); -+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", -+ 0x060, BIT(24), 0); -+static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2", -+ 0x060, BIT(25), 0); -+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", -+ 0x060, BIT(28), 0); -+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb2", -+ 0x060, BIT(29), 0); -+ -+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", -+ 0x064, BIT(0), 0); -+static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1", -+ 0x064, BIT(3), 0); -+static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1", -+ 0x064, BIT(4), 0); -+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", -+ 0x064, BIT(5), 0); -+static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1", -+ 0x064, BIT(8), 0); -+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1", -+ 0x064, BIT(11), 0); -+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", -+ 0x064, BIT(12), 0); -+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", -+ 0x064, BIT(20), 0); -+static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1", -+ 0x064, BIT(21), 0); -+static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1", -+ 0x064, BIT(22), 0); -+ -+static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", -+ 0x068, BIT(0), 0); -+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", -+ 0x068, BIT(1), 0); -+static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", -+ 0x068, BIT(5), 0); -+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", -+ 0x068, BIT(8), 0); -+static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", -+ 0x068, BIT(12), 0); -+static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", -+ 0x068, BIT(13), 0); -+static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", -+ 0x068, BIT(14), 0); -+ -+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", -+ 0x06c, BIT(0), 0); -+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", -+ 0x06c, BIT(1), 0); -+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", -+ 0x06c, BIT(2), 0); -+static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", -+ 0x06c, BIT(5), 0); -+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", -+ 0x06c, BIT(16), 0); -+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", -+ 0x06c, BIT(17), 0); -+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", -+ 0x06c, BIT(18), 0); -+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", -+ 0x06c, BIT(19), 0); -+static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", -+ 0x06c, BIT(20), 0); -+ -+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", -+ 0x070, BIT(7), 0); -+ -+static struct clk_div_table ths_div_table[] = { -+ { .val = 0, .div = 1 }, -+ { .val = 1, .div = 2 }, -+ { .val = 2, .div = 4 }, -+ { .val = 3, .div = 6 }, -+}; -+static const char * const ths_parents[] = { "osc24M" }; -+static struct ccu_div ths_clk = { -+ .enable = BIT(31), -+ .div = _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table), -+ .mux = _SUNXI_CCU_MUX(24, 2), -+ .common = { -+ .reg = 0x074, -+ .hw.init = CLK_HW_INIT_PARENTS("ths", -+ ths_parents, -+ &ccu_div_ops, -+ 0), -+ }, -+}; -+ -+static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", -+ "pll-periph1" }; -+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x", -+ "pll-periph1-2x" }; -+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; -+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 4, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_default_parents, 0x09c, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, -+ 0, 4, /* M */ -+ 16, 2, /* P */ -+ 24, 2, /* mux */ -+ BIT(31), /* gate */ -+ 0); -+ -+static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", -+ "pll-audio-2x", "pll-audio" }; -+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, -+ 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, -+ 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, -+ 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio", -+ 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", -+ 0x0cc, BIT(8), 0); -+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", -+ 0x0cc, BIT(9), 0); -+static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic", -+ 0x0cc, BIT(10), 0); -+static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M", -+ 0x0cc, BIT(11), 0); -+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", -+ 0x0cc, BIT(16), 0); -+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "usb-ohci0", -+ 0x0cc, BIT(17), 0); -+ -+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; -+static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, -+ 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL); -+ -+static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", -+ 0x100, BIT(0), 0); -+static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram", -+ 0x100, BIT(1), 0); -+static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", -+ 0x100, BIT(2), 0); -+static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", -+ 0x100, BIT(3), 0); -+ -+static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, -+ 0x104, 0, 4, 24, 3, BIT(31), 0); -+ -+static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; -+static const u8 tcon0_table[] = { 0, 2, }; -+static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents, -+ tcon0_table, 0x118, 24, 3, BIT(31), -+ CLK_SET_RATE_PARENT); -+ -+static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" }; -+static const u8 tcon1_table[] = { 0, 2, }; -+struct ccu_div tcon1_clk = { -+ .enable = BIT(31), -+ .div = _SUNXI_CCU_DIV(0, 4), -+ .mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table), -+ .common = { -+ .reg = 0x11c, -+ .hw.init = CLK_HW_INIT_PARENTS("tcon1", -+ tcon1_parents, -+ &ccu_div_ops, -+ CLK_SET_RATE_PARENT), -+ }, -+}; -+ -+static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, -+ 0x124, 0, 4, 24, 3, BIT(31), 0); -+ -+static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", -+ 0x130, BIT(31), 0); -+ -+static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, -+ 0x134, 16, 4, 24, 3, BIT(31), 0); -+ -+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", "pll-periph1" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, -+ 0x134, 0, 5, 8, 3, BIT(15), 0); -+ -+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", -+ 0x13c, 16, 3, BIT(31), 0); -+ -+static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", -+ 0x140, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x", -+ 0x140, BIT(30), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", -+ 0x144, BIT(31), 0); -+ -+static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, -+ 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", -+ 0x154, BIT(31), 0); -+ -+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", -+ "pll-ddr0", "pll-ddr1" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, -+ 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); -+ -+static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" }; -+static const u8 dsi_dphy_table[] = { 0, 2, }; -+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy", -+ dsi_dphy_parents, dsi_dphy_table, -+ 0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT); -+ -+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", -+ 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); -+ -+/* Fixed Factor clocks */ -+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0); -+ -+/* We hardcode the divider to 4 for now */ -+static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", -+ "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); -+static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", -+ "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); -+static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", -+ "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); -+static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", -+ "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); -+static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", -+ "pll-periph0", 1, 2, 0); -+static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", -+ "pll-periph1", 1, 2, 0); -+static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", -+ "pll-video0", 1, 2, CLK_SET_RATE_PARENT); -+ -+static struct ccu_common *sun50i_a64_ccu_clks[] = { -+ &pll_cpux_clk.common, -+ &pll_audio_base_clk.common, -+ &pll_video0_clk.common, -+ &pll_ve_clk.common, -+ &pll_ddr0_clk.common, -+ &pll_periph0_clk.common, -+ &pll_periph1_clk.common, -+ &pll_video1_clk.common, -+ &pll_gpu_clk.common, -+ &pll_mipi_clk.common, -+ &pll_hsic_clk.common, -+ &pll_de_clk.common, -+ &pll_ddr1_clk.common, -+ &cpux_clk.common, -+ &axi_clk.common, -+ &ahb1_clk.common, -+ &apb1_clk.common, -+ &apb2_clk.common, -+ &ahb2_clk.common, -+ &bus_mipi_dsi_clk.common, -+ &bus_ce_clk.common, -+ &bus_dma_clk.common, -+ &bus_mmc0_clk.common, -+ &bus_mmc1_clk.common, -+ &bus_mmc2_clk.common, -+ &bus_nand_clk.common, -+ &bus_dram_clk.common, -+ &bus_emac_clk.common, -+ &bus_ts_clk.common, -+ &bus_hstimer_clk.common, -+ &bus_spi0_clk.common, -+ &bus_spi1_clk.common, -+ &bus_otg_clk.common, -+ &bus_ehci0_clk.common, -+ &bus_ehci1_clk.common, -+ &bus_ohci0_clk.common, -+ &bus_ohci1_clk.common, -+ &bus_ve_clk.common, -+ &bus_tcon0_clk.common, -+ &bus_tcon1_clk.common, -+ &bus_deinterlace_clk.common, -+ &bus_csi_clk.common, -+ &bus_hdmi_clk.common, -+ &bus_de_clk.common, -+ &bus_gpu_clk.common, -+ &bus_msgbox_clk.common, -+ &bus_spinlock_clk.common, -+ &bus_codec_clk.common, -+ &bus_spdif_clk.common, -+ &bus_pio_clk.common, -+ &bus_ths_clk.common, -+ &bus_i2s0_clk.common, -+ &bus_i2s1_clk.common, -+ &bus_i2s2_clk.common, -+ &bus_i2c0_clk.common, -+ &bus_i2c1_clk.common, -+ &bus_i2c2_clk.common, -+ &bus_scr_clk.common, -+ &bus_uart0_clk.common, -+ &bus_uart1_clk.common, -+ &bus_uart2_clk.common, -+ &bus_uart3_clk.common, -+ &bus_uart4_clk.common, -+ &bus_dbg_clk.common, -+ &ths_clk.common, -+ &nand_clk.common, -+ &mmc0_clk.common, -+ &mmc1_clk.common, -+ &mmc2_clk.common, -+ &ts_clk.common, -+ &ce_clk.common, -+ &spi0_clk.common, -+ &spi1_clk.common, -+ &i2s0_clk.common, -+ &i2s1_clk.common, -+ &i2s2_clk.common, -+ &spdif_clk.common, -+ &usb_phy0_clk.common, -+ &usb_phy1_clk.common, -+ &usb_hsic_clk.common, -+ &usb_hsic_12m_clk.common, -+ &usb_ohci0_clk.common, -+ &usb_ohci1_clk.common, -+ &dram_clk.common, -+ &dram_ve_clk.common, -+ &dram_csi_clk.common, -+ &dram_deinterlace_clk.common, -+ &dram_ts_clk.common, -+ &de_clk.common, -+ &tcon0_clk.common, -+ &tcon1_clk.common, -+ &deinterlace_clk.common, -+ &csi_misc_clk.common, -+ &csi_sclk_clk.common, -+ &csi_mclk_clk.common, -+ &ve_clk.common, -+ &ac_dig_clk.common, -+ &ac_dig_4x_clk.common, -+ &avs_clk.common, -+ &hdmi_clk.common, -+ &hdmi_ddc_clk.common, -+ &mbus_clk.common, -+ &dsi_dphy_clk.common, -+ &gpu_clk.common, -+}; -+ -+static struct clk_hw_onecell_data sun50i_a64_hw_clks = { -+ .hws = { -+ [CLK_OSC_12M] = &osc12M_clk.hw, -+ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, -+ [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, -+ [CLK_PLL_AUDIO] = &pll_audio_clk.hw, -+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, -+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, -+ [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, -+ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, -+ [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, -+ [CLK_PLL_VE] = &pll_ve_clk.common.hw, -+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, -+ [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, -+ [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, -+ [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, -+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, -+ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, -+ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, -+ [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, -+ [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw, -+ [CLK_PLL_DE] = &pll_de_clk.common.hw, -+ [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, -+ [CLK_CPUX] = &cpux_clk.common.hw, -+ [CLK_AXI] = &axi_clk.common.hw, -+ [CLK_AHB1] = &ahb1_clk.common.hw, -+ [CLK_APB1] = &apb1_clk.common.hw, -+ [CLK_APB2] = &apb2_clk.common.hw, -+ [CLK_AHB2] = &ahb2_clk.common.hw, -+ [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, -+ [CLK_BUS_CE] = &bus_ce_clk.common.hw, -+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw, -+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, -+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, -+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, -+ [CLK_BUS_NAND] = &bus_nand_clk.common.hw, -+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, -+ [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, -+ [CLK_BUS_TS] = &bus_ts_clk.common.hw, -+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, -+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, -+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, -+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw, -+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, -+ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, -+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, -+ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, -+ [CLK_BUS_VE] = &bus_ve_clk.common.hw, -+ [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw, -+ [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw, -+ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, -+ [CLK_BUS_CSI] = &bus_csi_clk.common.hw, -+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, -+ [CLK_BUS_DE] = &bus_de_clk.common.hw, -+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, -+ [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, -+ [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, -+ [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, -+ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, -+ [CLK_BUS_PIO] = &bus_pio_clk.common.hw, -+ [CLK_BUS_THS] = &bus_ths_clk.common.hw, -+ [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, -+ [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, -+ [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, -+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, -+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, -+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, -+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, -+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, -+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, -+ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, -+ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, -+ [CLK_BUS_SCR] = &bus_scr_clk.common.hw, -+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, -+ [CLK_THS] = &ths_clk.common.hw, -+ [CLK_NAND] = &nand_clk.common.hw, -+ [CLK_MMC0] = &mmc0_clk.common.hw, -+ [CLK_MMC1] = &mmc1_clk.common.hw, -+ [CLK_MMC2] = &mmc2_clk.common.hw, -+ [CLK_TS] = &ts_clk.common.hw, -+ [CLK_CE] = &ce_clk.common.hw, -+ [CLK_SPI0] = &spi0_clk.common.hw, -+ [CLK_SPI1] = &spi1_clk.common.hw, -+ [CLK_I2S0] = &i2s0_clk.common.hw, -+ [CLK_I2S1] = &i2s1_clk.common.hw, -+ [CLK_I2S2] = &i2s2_clk.common.hw, -+ [CLK_SPDIF] = &spdif_clk.common.hw, -+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, -+ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, -+ [CLK_USB_HSIC] = &usb_hsic_clk.common.hw, -+ [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw, -+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, -+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, -+ [CLK_DRAM] = &dram_clk.common.hw, -+ [CLK_DRAM_VE] = &dram_ve_clk.common.hw, -+ [CLK_DRAM_CSI] = &dram_csi_clk.common.hw, -+ [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, -+ [CLK_DRAM_TS] = &dram_ts_clk.common.hw, -+ [CLK_DE] = &de_clk.common.hw, -+ [CLK_TCON0] = &tcon0_clk.common.hw, -+ [CLK_TCON1] = &tcon1_clk.common.hw, -+ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, -+ [CLK_CSI_MISC] = &csi_misc_clk.common.hw, -+ [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, -+ [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, -+ [CLK_VE] = &ve_clk.common.hw, -+ [CLK_AC_DIG] = &ac_dig_clk.common.hw, -+ [CLK_AC_DIG_4X] = &ac_dig_4x_clk.common.hw, -+ [CLK_AVS] = &avs_clk.common.hw, -+ [CLK_HDMI] = &hdmi_clk.common.hw, -+ [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw, -+ [CLK_MBUS] = &mbus_clk.common.hw, -+ [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, -+ [CLK_GPU] = &gpu_clk.common.hw, -+ }, -+ .num = CLK_NUMBER, -+}; -+ -+static struct ccu_reset_map sun50i_a64_ccu_resets[] = { -+ [RST_USB_PHY0] = { 0x0cc, BIT(0) }, -+ [RST_USB_PHY1] = { 0x0cc, BIT(1) }, -+ [RST_USB_HSIC] = { 0x0cc, BIT(2) }, -+ -+ [RST_DRAM] = { 0x0f4, BIT(31) }, -+ [RST_MBUS] = { 0x0fc, BIT(31) }, -+ -+ [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, -+ [RST_BUS_CE] = { 0x2c0, BIT(5) }, -+ [RST_BUS_DMA] = { 0x2c0, BIT(6) }, -+ [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, -+ [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, -+ [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, -+ [RST_BUS_NAND] = { 0x2c0, BIT(13) }, -+ [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, -+ [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, -+ [RST_BUS_TS] = { 0x2c0, BIT(18) }, -+ [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, -+ [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, -+ [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, -+ [RST_BUS_OTG] = { 0x2c0, BIT(23) }, -+ [RST_BUS_EHCI0] = { 0x2c0, BIT(24) }, -+ [RST_BUS_EHCI1] = { 0x2c0, BIT(25) }, -+ [RST_BUS_OHCI0] = { 0x2c0, BIT(28) }, -+ [RST_BUS_OHCI1] = { 0x2c0, BIT(29) }, -+ -+ [RST_BUS_VE] = { 0x2c4, BIT(0) }, -+ [RST_BUS_TCON0] = { 0x2c4, BIT(3) }, -+ [RST_BUS_TCON1] = { 0x2c4, BIT(4) }, -+ [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, -+ [RST_BUS_CSI] = { 0x2c4, BIT(8) }, -+ [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, -+ [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, -+ [RST_BUS_DE] = { 0x2c4, BIT(12) }, -+ [RST_BUS_GPU] = { 0x2c4, BIT(20) }, -+ [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) }, -+ [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) }, -+ [RST_BUS_DBG] = { 0x2c4, BIT(31) }, -+ -+ [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, -+ -+ [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, -+ [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, -+ [RST_BUS_THS] = { 0x2d0, BIT(8) }, -+ [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, -+ [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, -+ [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, -+ -+ [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, -+ [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, -+ [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, -+ [RST_BUS_SCR] = { 0x2d8, BIT(5) }, -+ [RST_BUS_UART0] = { 0x2d8, BIT(16) }, -+ [RST_BUS_UART1] = { 0x2d8, BIT(17) }, -+ [RST_BUS_UART2] = { 0x2d8, BIT(18) }, -+ [RST_BUS_UART3] = { 0x2d8, BIT(19) }, -+ [RST_BUS_UART4] = { 0x2d8, BIT(20) }, -+}; -+ -+static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = { -+ .ccu_clks = sun50i_a64_ccu_clks, -+ .num_ccu_clks = ARRAY_SIZE(sun50i_a64_ccu_clks), -+ -+ .hw_clks = &sun50i_a64_hw_clks, -+ -+ .resets = sun50i_a64_ccu_resets, -+ .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets), -+}; -+ -+static int sun50i_a64_ccu_probe(struct platform_device *pdev) -+{ -+ struct resource *res; -+ void __iomem *reg; -+ u32 val; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ reg = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(reg)) -+ return PTR_ERR(reg); -+ -+ /* Force the PLL-Audio-1x divider to 4 */ -+ val = readl(reg + SUN50I_A64_PLL_AUDIO_REG); -+ val &= ~GENMASK(19, 16); -+ writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG); -+ -+ writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); -+ -+ return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); -+} -+ -+static const struct of_device_id sun50i_a64_ccu_ids[] = { -+ { .compatible = "allwinner,sun50i-a64-ccu" }, -+ { } -+}; -+ -+static struct platform_driver sun50i_a64_ccu_driver = { -+ .probe = sun50i_a64_ccu_probe, -+ .driver = { -+ .name = "sun50i-a64-ccu", -+ .of_match_table = sun50i_a64_ccu_ids, -+ }, -+}; -+builtin_platform_driver(sun50i_a64_ccu_driver); ---- /dev/null -+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.h -@@ -0,0 +1,72 @@ -+/* -+ * Copyright 2016 Maxime Ripard -+ * -+ * Maxime Ripard -+ * -+ * 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 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. -+ */ -+ -+#ifndef _CCU_SUN50I_A64_H_ -+#define _CCU_SUN50I_A64_H_ -+ -+#include -+#include -+ -+#define CLK_OSC_12M 0 -+#define CLK_PLL_CPUX 1 -+#define CLK_PLL_AUDIO_BASE 2 -+#define CLK_PLL_AUDIO 3 -+#define CLK_PLL_AUDIO_2X 4 -+#define CLK_PLL_AUDIO_4X 5 -+#define CLK_PLL_AUDIO_8X 6 -+#define CLK_PLL_VIDEO0 7 -+#define CLK_PLL_VIDEO0_2X 8 -+#define CLK_PLL_VE 9 -+#define CLK_PLL_DDR0 10 -+#define CLK_PLL_PERIPH0 11 -+#define CLK_PLL_PERIPH0_2X 12 -+#define CLK_PLL_PERIPH1 13 -+#define CLK_PLL_PERIPH1_2X 14 -+#define CLK_PLL_VIDEO1 15 -+#define CLK_PLL_GPU 16 -+#define CLK_PLL_MIPI 17 -+#define CLK_PLL_HSIC 18 -+#define CLK_PLL_DE 19 -+#define CLK_PLL_DDR1 20 -+#define CLK_CPUX 21 -+#define CLK_AXI 22 -+#define CLK_APB 23 -+#define CLK_AHB1 24 -+#define CLK_APB1 25 -+#define CLK_APB2 26 -+#define CLK_AHB2 27 -+ -+/* All the bus gates are exported */ -+ -+/* The first bunch of module clocks are exported */ -+ -+#define CLK_USB_OHCI0_12M 90 -+ -+#define CLK_USB_OHCI1_12M 92 -+ -+#define CLK_DRAM 94 -+ -+/* All the DRAM gates are exported */ -+ -+/* Some more module clocks are exported */ -+ -+#define CLK_MBUS 112 -+ -+/* And the DSI and GPU module clock is exported */ -+ -+#define CLK_NUMBER (CLK_GPU + 1) -+ -+#endif /* _CCU_SUN50I_A64_H_ */ ---- /dev/null -+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h -@@ -0,0 +1,134 @@ -+/* -+ * Copyright (C) 2016 Maxime Ripard -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_ -+#define _DT_BINDINGS_CLK_SUN50I_A64_H_ -+ -+#define CLK_BUS_MIPI_DSI 28 -+#define CLK_BUS_CE 29 -+#define CLK_BUS_DMA 30 -+#define CLK_BUS_MMC0 31 -+#define CLK_BUS_MMC1 32 -+#define CLK_BUS_MMC2 33 -+#define CLK_BUS_NAND 34 -+#define CLK_BUS_DRAM 35 -+#define CLK_BUS_EMAC 36 -+#define CLK_BUS_TS 37 -+#define CLK_BUS_HSTIMER 38 -+#define CLK_BUS_SPI0 39 -+#define CLK_BUS_SPI1 40 -+#define CLK_BUS_OTG 41 -+#define CLK_BUS_EHCI0 42 -+#define CLK_BUS_EHCI1 43 -+#define CLK_BUS_OHCI0 44 -+#define CLK_BUS_OHCI1 45 -+#define CLK_BUS_VE 46 -+#define CLK_BUS_TCON0 47 -+#define CLK_BUS_TCON1 48 -+#define CLK_BUS_DEINTERLACE 49 -+#define CLK_BUS_CSI 50 -+#define CLK_BUS_HDMI 51 -+#define CLK_BUS_DE 52 -+#define CLK_BUS_GPU 53 -+#define CLK_BUS_MSGBOX 54 -+#define CLK_BUS_SPINLOCK 55 -+#define CLK_BUS_CODEC 56 -+#define CLK_BUS_SPDIF 57 -+#define CLK_BUS_PIO 58 -+#define CLK_BUS_THS 59 -+#define CLK_BUS_I2S0 60 -+#define CLK_BUS_I2S1 61 -+#define CLK_BUS_I2S2 62 -+#define CLK_BUS_I2C0 63 -+#define CLK_BUS_I2C1 64 -+#define CLK_BUS_I2C2 65 -+#define CLK_BUS_SCR 66 -+#define CLK_BUS_UART0 67 -+#define CLK_BUS_UART1 68 -+#define CLK_BUS_UART2 69 -+#define CLK_BUS_UART3 70 -+#define CLK_BUS_UART4 71 -+#define CLK_BUS_DBG 72 -+#define CLK_THS 73 -+#define CLK_NAND 74 -+#define CLK_MMC0 75 -+#define CLK_MMC1 76 -+#define CLK_MMC2 77 -+#define CLK_TS 78 -+#define CLK_CE 79 -+#define CLK_SPI0 80 -+#define CLK_SPI1 81 -+#define CLK_I2S0 82 -+#define CLK_I2S1 83 -+#define CLK_I2S2 84 -+#define CLK_SPDIF 85 -+#define CLK_USB_PHY0 86 -+#define CLK_USB_PHY1 87 -+#define CLK_USB_HSIC 88 -+#define CLK_USB_HSIC_12M 89 -+ -+#define CLK_USB_OHCI0 91 -+ -+#define CLK_USB_OHCI1 93 -+ -+#define CLK_DRAM_VE 95 -+#define CLK_DRAM_CSI 96 -+#define CLK_DRAM_DEINTERLACE 97 -+#define CLK_DRAM_TS 98 -+#define CLK_DE 99 -+#define CLK_TCON0 100 -+#define CLK_TCON1 101 -+#define CLK_DEINTERLACE 102 -+#define CLK_CSI_MISC 103 -+#define CLK_CSI_SCLK 104 -+#define CLK_CSI_MCLK 105 -+#define CLK_VE 106 -+#define CLK_AC_DIG 107 -+#define CLK_AC_DIG_4X 108 -+#define CLK_AVS 109 -+#define CLK_HDMI 110 -+#define CLK_HDMI_DDC 111 -+ -+#define CLK_DSI_DPHY 113 -+#define CLK_GPU 114 -+ -+#endif /* _DT_BINDINGS_CLK_SUN50I_H_ */ ---- /dev/null -+++ b/include/dt-bindings/reset/sun50i-a64-ccu.h -@@ -0,0 +1,98 @@ -+/* -+ * Copyright (C) 2016 Maxime Ripard -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef _DT_BINDINGS_RST_SUN50I_A64_H_ -+#define _DT_BINDINGS_RST_SUN50I_A64_H_ -+ -+#define RST_USB_PHY0 0 -+#define RST_USB_PHY1 1 -+#define RST_USB_HSIC 2 -+#define RST_DRAM 3 -+#define RST_MBUS 4 -+#define RST_BUS_MIPI_DSI 5 -+#define RST_BUS_CE 6 -+#define RST_BUS_DMA 7 -+#define RST_BUS_MMC0 8 -+#define RST_BUS_MMC1 9 -+#define RST_BUS_MMC2 10 -+#define RST_BUS_NAND 11 -+#define RST_BUS_DRAM 12 -+#define RST_BUS_EMAC 13 -+#define RST_BUS_TS 14 -+#define RST_BUS_HSTIMER 15 -+#define RST_BUS_SPI0 16 -+#define RST_BUS_SPI1 17 -+#define RST_BUS_OTG 18 -+#define RST_BUS_EHCI0 19 -+#define RST_BUS_EHCI1 20 -+#define RST_BUS_OHCI0 21 -+#define RST_BUS_OHCI1 22 -+#define RST_BUS_VE 23 -+#define RST_BUS_TCON0 24 -+#define RST_BUS_TCON1 25 -+#define RST_BUS_DEINTERLACE 26 -+#define RST_BUS_CSI 27 -+#define RST_BUS_HDMI0 28 -+#define RST_BUS_HDMI1 29 -+#define RST_BUS_DE 30 -+#define RST_BUS_GPU 31 -+#define RST_BUS_MSGBOX 32 -+#define RST_BUS_SPINLOCK 33 -+#define RST_BUS_DBG 34 -+#define RST_BUS_LVDS 35 -+#define RST_BUS_CODEC 36 -+#define RST_BUS_SPDIF 37 -+#define RST_BUS_THS 38 -+#define RST_BUS_I2S0 39 -+#define RST_BUS_I2S1 40 -+#define RST_BUS_I2S2 41 -+#define RST_BUS_I2C0 42 -+#define RST_BUS_I2C1 43 -+#define RST_BUS_I2C2 44 -+#define RST_BUS_SCR 45 -+#define RST_BUS_UART0 46 -+#define RST_BUS_UART1 47 -+#define RST_BUS_UART2 48 -+#define RST_BUS_UART3 49 -+#define RST_BUS_UART4 50 -+ -+#endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */ diff --git a/target/linux/sunxi/patches-4.9/0010-arm64-dts-add-Allwinner-A64-SoC-.dtsi.patch b/target/linux/sunxi/patches-4.9/0010-arm64-dts-add-Allwinner-A64-SoC-.dtsi.patch deleted file mode 100644 index eaaba96fc1..0000000000 --- a/target/linux/sunxi/patches-4.9/0010-arm64-dts-add-Allwinner-A64-SoC-.dtsi.patch +++ /dev/null @@ -1,311 +0,0 @@ -From 6bc37fac30cf01c39feb17834090089304bd1d31 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Mon, 18 Jan 2016 10:24:31 +0000 -Subject: arm64: dts: add Allwinner A64 SoC .dtsi - -The Allwinner A64 SoC is a low-cost chip with 4 ARM Cortex-A53 cores -and the typical tablet / TV box peripherals. -The SoC is based on the (32-bit) Allwinner H3 chip, sharing most of -the peripherals and the memory map. -Although the cores are proper 64-bit ones, the whole SoC is actually -limited to 4GB (including all the supported DRAM), so we use 32-bit -address and size cells. This has the nice feature of us being able to -reuse the DT for 32-bit kernels as well. -This .dtsi lists the hardware that we support so far. - -Signed-off-by: Andre Przywara -Acked-by: Rob Herring -Acked-by: Chen-Yu Tsai -[Maxime: Convert to CCU binding, drop the MMC support for now] -Signed-off-by: Maxime Ripard ---- - Documentation/devicetree/bindings/arm/sunxi.txt | 1 + - MAINTAINERS | 1 + - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 263 ++++++++++++++++++++++++ - 3 files changed, 265 insertions(+) - create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi - ---- a/Documentation/devicetree/bindings/arm/sunxi.txt -+++ b/Documentation/devicetree/bindings/arm/sunxi.txt -@@ -14,4 +14,5 @@ using one of the following compatible st - allwinner,sun8i-a83t - allwinner,sun8i-h3 - allwinner,sun9i-a80 -+ allwinner,sun50i-a64 - nextthing,gr8 ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1026,6 +1026,7 @@ L: linux-arm-kernel@lists.infradead.org - S: Maintained - N: sun[x456789]i - F: arch/arm/boot/dts/ntc-gr8* -+F: arch/arm64/boot/dts/allwinner/ - - ARM/Allwinner SoC Clock Support - M: Emilio López ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -0,0 +1,263 @@ -+/* -+ * Copyright (C) 2016 ARM Ltd. -+ * based on the Allwinner H3 dtsi: -+ * Copyright (C) 2015 Jens Kuske -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+/ { -+ interrupt-parent = <&gic>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu0: cpu@0 { -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ device_type = "cpu"; -+ reg = <0>; -+ enable-method = "psci"; -+ }; -+ -+ cpu1: cpu@1 { -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ device_type = "cpu"; -+ reg = <1>; -+ enable-method = "psci"; -+ }; -+ -+ cpu2: cpu@2 { -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ device_type = "cpu"; -+ reg = <2>; -+ enable-method = "psci"; -+ }; -+ -+ cpu3: cpu@3 { -+ compatible = "arm,cortex-a53", "arm,armv8"; -+ device_type = "cpu"; -+ reg = <3>; -+ enable-method = "psci"; -+ }; -+ }; -+ -+ osc24M: osc24M_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <24000000>; -+ clock-output-names = "osc24M"; -+ }; -+ -+ osc32k: osc32k_clk { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <32768>; -+ clock-output-names = "osc32k"; -+ }; -+ -+ psci { -+ compatible = "arm,psci-0.2"; -+ method = "smc"; -+ }; -+ -+ timer { -+ compatible = "arm,armv8-timer"; -+ interrupts = , -+ , -+ , -+ ; -+ }; -+ -+ soc { -+ compatible = "simple-bus"; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ ranges; -+ -+ ccu: clock@01c20000 { -+ compatible = "allwinner,sun50i-a64-ccu"; -+ reg = <0x01c20000 0x400>; -+ clocks = <&osc24M>, <&osc32k>; -+ clock-names = "hosc", "losc"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; -+ -+ pio: pinctrl@1c20800 { -+ compatible = "allwinner,sun50i-a64-pinctrl"; -+ reg = <0x01c20800 0x400>; -+ interrupts = , -+ , -+ ; -+ clocks = <&ccu CLK_BUS_PIO>; -+ gpio-controller; -+ #gpio-cells = <3>; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ -+ i2c1_pins: i2c1_pins { -+ pins = "PH2", "PH3"; -+ function = "i2c1"; -+ }; -+ -+ uart0_pins_a: uart0@0 { -+ pins = "PB8", "PB9"; -+ function = "uart0"; -+ }; -+ }; -+ -+ uart0: serial@1c28000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x01c28000 0x400>; -+ interrupts = ; -+ reg-shift = <2>; -+ reg-io-width = <4>; -+ clocks = <&ccu CLK_BUS_UART0>; -+ resets = <&ccu RST_BUS_UART0>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@1c28400 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x01c28400 0x400>; -+ interrupts = ; -+ reg-shift = <2>; -+ reg-io-width = <4>; -+ clocks = <&ccu CLK_BUS_UART1>; -+ resets = <&ccu RST_BUS_UART1>; -+ status = "disabled"; -+ }; -+ -+ uart2: serial@1c28800 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x01c28800 0x400>; -+ interrupts = ; -+ reg-shift = <2>; -+ reg-io-width = <4>; -+ clocks = <&ccu CLK_BUS_UART2>; -+ resets = <&ccu RST_BUS_UART2>; -+ status = "disabled"; -+ }; -+ -+ uart3: serial@1c28c00 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x01c28c00 0x400>; -+ interrupts = ; -+ reg-shift = <2>; -+ reg-io-width = <4>; -+ clocks = <&ccu CLK_BUS_UART3>; -+ resets = <&ccu RST_BUS_UART3>; -+ status = "disabled"; -+ }; -+ -+ uart4: serial@1c29000 { -+ compatible = "snps,dw-apb-uart"; -+ reg = <0x01c29000 0x400>; -+ interrupts = ; -+ reg-shift = <2>; -+ reg-io-width = <4>; -+ clocks = <&ccu CLK_BUS_UART4>; -+ resets = <&ccu RST_BUS_UART4>; -+ status = "disabled"; -+ }; -+ -+ i2c0: i2c@1c2ac00 { -+ compatible = "allwinner,sun6i-a31-i2c"; -+ reg = <0x01c2ac00 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2C0>; -+ resets = <&ccu RST_BUS_I2C0>; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ i2c1: i2c@1c2b000 { -+ compatible = "allwinner,sun6i-a31-i2c"; -+ reg = <0x01c2b000 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2C1>; -+ resets = <&ccu RST_BUS_I2C1>; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ i2c2: i2c@1c2b400 { -+ compatible = "allwinner,sun6i-a31-i2c"; -+ reg = <0x01c2b400 0x400>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_I2C2>; -+ resets = <&ccu RST_BUS_I2C2>; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ gic: interrupt-controller@1c81000 { -+ compatible = "arm,gic-400"; -+ reg = <0x01c81000 0x1000>, -+ <0x01c82000 0x2000>, -+ <0x01c84000 0x2000>, -+ <0x01c86000 0x2000>; -+ interrupts = ; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ }; -+ -+ rtc: rtc@1f00000 { -+ compatible = "allwinner,sun6i-a31-rtc"; -+ reg = <0x01f00000 0x54>; -+ interrupts = , -+ ; -+ }; -+ }; -+}; diff --git a/target/linux/sunxi/patches-4.9/0011-arm64-dts-add-Pine64-support.patch b/target/linux/sunxi/patches-4.9/0011-arm64-dts-add-Pine64-support.patch deleted file mode 100644 index 9960588ab8..0000000000 --- a/target/linux/sunxi/patches-4.9/0011-arm64-dts-add-Pine64-support.patch +++ /dev/null @@ -1,176 +0,0 @@ -From 4e3886081848b7ea16452a92c4324acaab644d49 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Tue, 19 Jan 2016 10:36:39 +0000 -Subject: arm64: dts: add Pine64 support - -The Pine64 is a cost-efficient development board based on the -Allwinner A64 SoC. -There are three models: the basic version with Fast Ethernet and -512 MB of DRAM (Pine64) and two Pine64+ versions, which both -feature Gigabit Ethernet and additional connectors for touchscreens -and a camera. Or as my son put it: "Those are smaller and these are -missing." ;-) -The two Pine64+ models just differ in the amount of DRAM -(1GB vs. 2GB). Since U-Boot will figure out the right size for us and -patches the DT accordingly we just need to provide one DT for the -Pine64+. - -Signed-off-by: Andre Przywara -[Maxime: Removed the common DTSI and include directly the pine64 DTS] -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/Makefile | 1 + - arch/arm64/boot/dts/allwinner/Makefile | 5 ++ - .../boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 50 +++++++++++++++ - .../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 74 ++++++++++++++++++++++ - 4 files changed, 130 insertions(+) - create mode 100644 arch/arm64/boot/dts/allwinner/Makefile - create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts - create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts - ---- a/arch/arm64/boot/dts/Makefile -+++ b/arch/arm64/boot/dts/Makefile -@@ -1,4 +1,5 @@ - dts-dirs += al -+dts-dirs += allwinner - dts-dirs += altera - dts-dirs += amd - dts-dirs += amlogic ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/Makefile -@@ -0,0 +1,5 @@ -+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb -+ -+always := $(dtb-y) -+subdir-y := $(dts-dirs) -+clean-files := *.dtb ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (c) 2016 ARM Ltd. -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This library 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 library 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include "sun50i-a64-pine64.dts" -+ -+/ { -+ model = "Pine64+"; -+ compatible = "pine64,pine64-plus", "allwinner,sun50i-a64"; -+ -+ /* TODO: Camera, Ethernet PHY, touchscreen, etc. */ -+}; ---- /dev/null -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -0,0 +1,74 @@ -+/* -+ * Copyright (c) 2016 ARM Ltd. -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This library 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 library 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+ -+#include "sun50i-a64.dtsi" -+ -+/ { -+ model = "Pine64"; -+ compatible = "pine64,pine64", "allwinner,sun50i-a64"; -+ -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins_a>; -+ status = "okay"; -+}; -+ -+&i2c1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&i2c1_pins>; -+ status = "okay"; -+}; -+ -+&i2c1_pins { -+ bias-pull-up; -+}; diff --git a/target/linux/sunxi/patches-4.9/0012-arm64-dts-fix-build-errors-from-missing-dependencies.patch b/target/linux/sunxi/patches-4.9/0012-arm64-dts-fix-build-errors-from-missing-dependencies.patch deleted file mode 100644 index 1719b682b3..0000000000 --- a/target/linux/sunxi/patches-4.9/0012-arm64-dts-fix-build-errors-from-missing-dependencies.patch +++ /dev/null @@ -1,134 +0,0 @@ -From f98121f3ef3d36f4d040b11ab38f15387f6eefa2 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Wed, 30 Nov 2016 15:08:55 +0100 -Subject: arm64: dts: fix build errors from missing dependencies - -Two branches were incorrectly sent without having the necessary -header file changes. Rather than back those out now, I'm replacing -the symbolic names for the clks and resets with the numeric -values to get 'make allmodconfig dtbs' back to work. - -After the header file changes are merged, we can revert this -patch. - -Fixes: 6bc37fa ("arm64: dts: add Allwinner A64 SoC .dtsi") -Fixes: 50784e6 ("dts: arm64: db820c: add pmic pins specific dts file") -Acked-by: Andre Przywara -Acked-by: Maxime Ripard -Acked-by: Srinivas Kandagatla -Signed-off-by: Arnd Bergmann ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 36 ++++++++++------------ - .../boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi | 2 +- - 2 files changed, 18 insertions(+), 20 deletions(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -42,10 +42,8 @@ - * OTHER DEALINGS IN THE SOFTWARE. - */ - --#include - #include - #include --#include - - / { - interrupt-parent = <&gic>; -@@ -137,7 +135,7 @@ - interrupts = , - , - ; -- clocks = <&ccu CLK_BUS_PIO>; -+ clocks = <&ccu 58>; - gpio-controller; - #gpio-cells = <3>; - interrupt-controller; -@@ -160,8 +158,8 @@ - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; -- clocks = <&ccu CLK_BUS_UART0>; -- resets = <&ccu RST_BUS_UART0>; -+ clocks = <&ccu 67>; -+ resets = <&ccu 46>; - status = "disabled"; - }; - -@@ -171,8 +169,8 @@ - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; -- clocks = <&ccu CLK_BUS_UART1>; -- resets = <&ccu RST_BUS_UART1>; -+ clocks = <&ccu 68>; -+ resets = <&ccu 47>; - status = "disabled"; - }; - -@@ -182,8 +180,8 @@ - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; -- clocks = <&ccu CLK_BUS_UART2>; -- resets = <&ccu RST_BUS_UART2>; -+ clocks = <&ccu 69>; -+ resets = <&ccu 48>; - status = "disabled"; - }; - -@@ -193,8 +191,8 @@ - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; -- clocks = <&ccu CLK_BUS_UART3>; -- resets = <&ccu RST_BUS_UART3>; -+ clocks = <&ccu 70>; -+ resets = <&ccu 49>; - status = "disabled"; - }; - -@@ -204,8 +202,8 @@ - interrupts = ; - reg-shift = <2>; - reg-io-width = <4>; -- clocks = <&ccu CLK_BUS_UART4>; -- resets = <&ccu RST_BUS_UART4>; -+ clocks = <&ccu 71>; -+ resets = <&ccu 50>; - status = "disabled"; - }; - -@@ -213,8 +211,8 @@ - compatible = "allwinner,sun6i-a31-i2c"; - reg = <0x01c2ac00 0x400>; - interrupts = ; -- clocks = <&ccu CLK_BUS_I2C0>; -- resets = <&ccu RST_BUS_I2C0>; -+ clocks = <&ccu 63>; -+ resets = <&ccu 42>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; -@@ -224,8 +222,8 @@ - compatible = "allwinner,sun6i-a31-i2c"; - reg = <0x01c2b000 0x400>; - interrupts = ; -- clocks = <&ccu CLK_BUS_I2C1>; -- resets = <&ccu RST_BUS_I2C1>; -+ clocks = <&ccu 64>; -+ resets = <&ccu 43>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; -@@ -235,8 +233,8 @@ - compatible = "allwinner,sun6i-a31-i2c"; - reg = <0x01c2b400 0x400>; - interrupts = ; -- clocks = <&ccu CLK_BUS_I2C2>; -- resets = <&ccu RST_BUS_I2C2>; -+ clocks = <&ccu 65>; -+ resets = <&ccu 44>; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; diff --git a/target/linux/sunxi/patches-4.9/0013-arm64-dts-allwinner-add-USB1-related-nodes-of-Allwin.patch b/target/linux/sunxi/patches-4.9/0013-arm64-dts-allwinner-add-USB1-related-nodes-of-Allwin.patch deleted file mode 100644 index f96570c858..0000000000 --- a/target/linux/sunxi/patches-4.9/0013-arm64-dts-allwinner-add-USB1-related-nodes-of-Allwin.patch +++ /dev/null @@ -1,84 +0,0 @@ -From a004ee350177ece3c059831ea49293d62aea7ca6 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 22 Nov 2016 23:58:29 +0800 -Subject: arm64: dts: allwinner: add USB1-related nodes of Allwinner A64 - -Allwinner A64 have two HCI USB controllers, a OTG controller and a USB -PHY device which have two ports. One of the port is wired to both a HCI -USB controller and the OTG controller, which is currently not supported. -The another one is only wired to a HCI controller, and the device node of -OHCI/EHCI controller of the port can be added now. - -Also the A64 USB PHY device node is also added for the HCI controllers to -work. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 46 +++++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -42,8 +42,10 @@ - * OTHER DEALINGS IN THE SOFTWARE. - */ - -+#include - #include - #include -+#include - - / { - interrupt-parent = <&gic>; -@@ -120,6 +122,50 @@ - #size-cells = <1>; - ranges; - -+ usbphy: phy@01c19400 { -+ compatible = "allwinner,sun50i-a64-usb-phy"; -+ reg = <0x01c19400 0x14>, -+ <0x01c1b800 0x4>; -+ reg-names = "phy_ctrl", -+ "pmu1"; -+ clocks = <&ccu CLK_USB_PHY0>, -+ <&ccu CLK_USB_PHY1>; -+ clock-names = "usb0_phy", -+ "usb1_phy"; -+ resets = <&ccu RST_USB_PHY0>, -+ <&ccu RST_USB_PHY1>; -+ reset-names = "usb0_reset", -+ "usb1_reset"; -+ status = "disabled"; -+ #phy-cells = <1>; -+ }; -+ -+ ehci1: usb@01c1b000 { -+ compatible = "allwinner,sun50i-a64-ehci", "generic-ehci"; -+ reg = <0x01c1b000 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI1>, -+ <&ccu CLK_BUS_EHCI1>, -+ <&ccu CLK_USB_OHCI1>; -+ resets = <&ccu RST_BUS_OHCI1>, -+ <&ccu RST_BUS_EHCI1>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ -+ ohci1: usb@01c1b400 { -+ compatible = "allwinner,sun50i-a64-ohci", "generic-ohci"; -+ reg = <0x01c1b400 0x100>; -+ interrupts = ; -+ clocks = <&ccu CLK_BUS_OHCI1>, -+ <&ccu CLK_USB_OHCI1>; -+ resets = <&ccu RST_BUS_OHCI1>; -+ phys = <&usbphy 1>; -+ phy-names = "usb"; -+ status = "disabled"; -+ }; -+ - ccu: clock@01c20000 { - compatible = "allwinner,sun50i-a64-ccu"; - reg = <0x01c20000 0x400>; diff --git a/target/linux/sunxi/patches-4.9/0014-arm64-dts-allwinner-sort-the-nodes-in-sun50i-a64-pin.patch b/target/linux/sunxi/patches-4.9/0014-arm64-dts-allwinner-sort-the-nodes-in-sun50i-a64-pin.patch deleted file mode 100644 index 4c7d6dafe2..0000000000 --- a/target/linux/sunxi/patches-4.9/0014-arm64-dts-allwinner-sort-the-nodes-in-sun50i-a64-pin.patch +++ /dev/null @@ -1,40 +0,0 @@ -From ac93c09cdbaf1229c21f67a5db1c3c6df7d503e5 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 22 Nov 2016 23:58:30 +0800 -Subject: arm64: dts: allwinner: sort the nodes in sun50i-a64-pine64.dts - -In this dts file, uart0 node is put before i2c1. - -Move the uart0 node to the end to satisfy alphebetical order. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -57,12 +57,6 @@ - }; - }; - --&uart0 { -- pinctrl-names = "default"; -- pinctrl-0 = <&uart0_pins_a>; -- status = "okay"; --}; -- - &i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; -@@ -72,3 +66,9 @@ - &i2c1_pins { - bias-pull-up; - }; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins_a>; -+ status = "okay"; -+}; diff --git a/target/linux/sunxi/patches-4.9/0015-arm64-dts-allwinner-enable-EHCI1-OHCI1-and-USB-PHY-n.patch b/target/linux/sunxi/patches-4.9/0015-arm64-dts-allwinner-enable-EHCI1-OHCI1-and-USB-PHY-n.patch deleted file mode 100644 index 451ec595c9..0000000000 --- a/target/linux/sunxi/patches-4.9/0015-arm64-dts-allwinner-enable-EHCI1-OHCI1-and-USB-PHY-n.patch +++ /dev/null @@ -1,47 +0,0 @@ -From d49f9dbc8f0c4521fa56477d051a3bd1158f2595 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 22 Nov 2016 23:58:31 +0800 -Subject: arm64: dts: allwinner: enable EHCI1, OHCI1 and USB PHY nodes in - Pine64 - -Pine64 have two USB Type-A ports, which are wired to the two ports of -A64 USB PHY, and the lower port is the EHCI/OHCI1 port. - -Enable the necessary nodes to enable the lower USB port to work. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -57,6 +57,10 @@ - }; - }; - -+&ehci1 { -+ status = "okay"; -+}; -+ - &i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; -@@ -67,8 +71,16 @@ - bias-pull-up; - }; - -+&ohci1 { -+ status = "okay"; -+}; -+ - &uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&uart0_pins_a>; - status = "okay"; - }; -+ -+&usbphy { -+ status = "okay"; -+}; diff --git a/target/linux/sunxi/patches-4.9/0016-arm64-dts-add-MUSB-node-to-Allwinner-A64-dtsi.patch b/target/linux/sunxi/patches-4.9/0016-arm64-dts-add-MUSB-node-to-Allwinner-A64-dtsi.patch deleted file mode 100644 index 804d00521b..0000000000 --- a/target/linux/sunxi/patches-4.9/0016-arm64-dts-add-MUSB-node-to-Allwinner-A64-dtsi.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 972a3ecdf27f3ebdd1ce0dccd1b548ef3c04b8ed Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Wed, 23 Nov 2016 00:59:01 +0800 -Subject: arm64: dts: add MUSB node to Allwinner A64 dtsi - -Allwinner A64 SoC has a MUSB controller like the one in A33, so add -a node for it, just use the compatible of A33 MUSB. - -Host mode is tested to work properly on Pine64 and will be added into -the device tree of Pine64 in next patch. - -Peripheral mode is also tested on Pine64, by changing dr_mode property -of usb_otg node and use a non-standard USB Type-A to Type-A cable. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -122,6 +122,19 @@ - #size-cells = <1>; - ranges; - -+ usb_otg: usb@01c19000 { -+ compatible = "allwinner,sun8i-a33-musb"; -+ reg = <0x01c19000 0x0400>; -+ clocks = <&ccu CLK_BUS_OTG>; -+ resets = <&ccu RST_BUS_OTG>; -+ interrupts = ; -+ interrupt-names = "mc"; -+ phys = <&usbphy 0>; -+ phy-names = "usb"; -+ extcon = <&usbphy 0>; -+ status = "disabled"; -+ }; -+ - usbphy: phy@01c19400 { - compatible = "allwinner,sun50i-a64-usb-phy"; - reg = <0x01c19400 0x14>, diff --git a/target/linux/sunxi/patches-4.9/0017-arm64-dts-enable-the-MUSB-controller-of-Pine64-in-ho.patch b/target/linux/sunxi/patches-4.9/0017-arm64-dts-enable-the-MUSB-controller-of-Pine64-in-ho.patch deleted file mode 100644 index 3992ab6510..0000000000 --- a/target/linux/sunxi/patches-4.9/0017-arm64-dts-enable-the-MUSB-controller-of-Pine64-in-ho.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f57e8384c5d2417fd8707c577d8e622fc1570b6c Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Wed, 23 Nov 2016 00:59:02 +0800 -Subject: arm64: dts: enable the MUSB controller of Pine64 in host-only mode - -A64 has a MUSB controller wired to the USB PHY 0, which is connected -to the upper USB Type-A port of Pine64. - -As the port is a Type-A female port, enable it in host-only mode in the -device tree, which makes devices with USB Type-A male port can work on -this port (which is originally designed by Pine64 team). - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -81,6 +81,11 @@ - status = "okay"; - }; - -+&usb_otg { -+ dr_mode = "host"; -+ status = "okay"; -+}; -+ - &usbphy { - status = "okay"; - }; diff --git a/target/linux/sunxi/patches-4.9/0018-arm64-dts-allwinner-Remove-no-longer-used-pinctrl-su.patch b/target/linux/sunxi/patches-4.9/0018-arm64-dts-allwinner-Remove-no-longer-used-pinctrl-su.patch deleted file mode 100644 index d2d54e937f..0000000000 --- a/target/linux/sunxi/patches-4.9/0018-arm64-dts-allwinner-Remove-no-longer-used-pinctrl-su.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 4f9758302ccaf753cd4ba6a5eb740392a4d24773 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Tue, 24 Jan 2017 10:32:29 +0800 -Subject: arm64: dts: allwinner: Remove no longer used pinctrl/sun4i-a10.h - header - -All dts files for the sunxi platform have been switched to the generic -pinconf bindings. As a result, the sunxi specific pinctrl macros are -no longer used. - -Remove the #include entry with the following command: - - sed -i -e '/pinctrl\/sun4i-a10.h/D' \ - arch/arm64/boot/dts/allwinner/*.dts? - -Signed-off-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 - - 1 file changed, 1 deletion(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -44,7 +44,6 @@ - - #include - #include --#include - #include - - / { diff --git a/target/linux/sunxi/patches-4.9/0019-arm64-allwinner-a64-Add-MMC-nodes.patch b/target/linux/sunxi/patches-4.9/0019-arm64-allwinner-a64-Add-MMC-nodes.patch deleted file mode 100644 index 1f91e9bead..0000000000 --- a/target/linux/sunxi/patches-4.9/0019-arm64-allwinner-a64-Add-MMC-nodes.patch +++ /dev/null @@ -1,69 +0,0 @@ -From f3dff3478a8a7b09f9a92023955a151584658893 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Thu, 6 Oct 2016 02:25:22 +0100 -Subject: arm64: allwinner: a64: Add MMC nodes - -The A64 has 3 MMC controllers, one of them being especially targeted to -eMMC. Among other things, it has a data strobe signal and a 8 bits data -width. - -The two other are more usual controllers that will have a 4 bits width at -most and no data strobe signal, which limits it to more usual SD or MMC -peripherals. - -Signed-off-by: Andre Przywara -Signed-off-by: Maxime Ripard -Tested-by: Florian Vaussard -Acked-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 39 +++++++++++++++++++++++++++ - 1 file changed, 39 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -121,6 +121,45 @@ - #size-cells = <1>; - ranges; - -+ mmc0: mmc@1c0f000 { -+ compatible = "allwinner,sun50i-a64-mmc"; -+ reg = <0x01c0f000 0x1000>; -+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>; -+ clock-names = "ahb", "mmc"; -+ resets = <&ccu RST_BUS_MMC0>; -+ reset-names = "ahb"; -+ interrupts = ; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ mmc1: mmc@1c10000 { -+ compatible = "allwinner,sun50i-a64-mmc"; -+ reg = <0x01c10000 0x1000>; -+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>; -+ clock-names = "ahb", "mmc"; -+ resets = <&ccu RST_BUS_MMC1>; -+ reset-names = "ahb"; -+ interrupts = ; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ -+ mmc2: mmc@1c11000 { -+ compatible = "allwinner,sun50i-a64-emmc"; -+ reg = <0x01c11000 0x1000>; -+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>; -+ clock-names = "ahb", "mmc"; -+ resets = <&ccu RST_BUS_MMC2>; -+ reset-names = "ahb"; -+ interrupts = ; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ - usb_otg: usb@01c19000 { - compatible = "allwinner,sun8i-a33-musb"; - reg = <0x01c19000 0x0400>; diff --git a/target/linux/sunxi/patches-4.9/0020-arm64-allwinner-a64-Add-MMC-pinctrl-nodes.patch b/target/linux/sunxi/patches-4.9/0020-arm64-allwinner-a64-Add-MMC-pinctrl-nodes.patch deleted file mode 100644 index f5af0f819a..0000000000 --- a/target/linux/sunxi/patches-4.9/0020-arm64-allwinner-a64-Add-MMC-pinctrl-nodes.patch +++ /dev/null @@ -1,50 +0,0 @@ -From a3e8f4926248b3c12933aacec4432e9b6de004bb Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 9 Jan 2017 16:39:15 +0100 -Subject: arm64: allwinner: a64: Add MMC pinctrl nodes - -The A64 only has a single set of pins for each MMC controller. Since we -already have boards that require all of them, let's add them to the DTSI. - -Reviewed-by: Andre Przywara -Signed-off-by: Maxime Ripard -Tested-by: Florian Vaussard -Acked-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -243,6 +243,31 @@ - function = "i2c1"; - }; - -+ mmc0_pins: mmc0-pins { -+ pins = "PF0", "PF1", "PF2", "PF3", -+ "PF4", "PF5"; -+ function = "mmc0"; -+ drive-strength = <30>; -+ bias-pull-up; -+ }; -+ -+ mmc1_pins: mmc1-pins { -+ pins = "PG0", "PG1", "PG2", "PG3", -+ "PG4", "PG5"; -+ function = "mmc1"; -+ drive-strength = <30>; -+ bias-pull-up; -+ }; -+ -+ mmc2_pins: mmc2-pins { -+ pins = "PC1", "PC5", "PC6", "PC8", "PC9", -+ "PC10","PC11", "PC12", "PC13", -+ "PC14", "PC15", "PC16"; -+ function = "mmc2"; -+ drive-strength = <30>; -+ bias-pull-up; -+ }; -+ - uart0_pins_a: uart0@0 { - pins = "PB8", "PB9"; - function = "uart0"; diff --git a/target/linux/sunxi/patches-4.9/0022-arm64-allwinner-pine64-add-MMC-support.patch b/target/linux/sunxi/patches-4.9/0022-arm64-allwinner-pine64-add-MMC-support.patch deleted file mode 100644 index c60e5104cf..0000000000 --- a/target/linux/sunxi/patches-4.9/0022-arm64-allwinner-pine64-add-MMC-support.patch +++ /dev/null @@ -1,62 +0,0 @@ -From ebe3ae29c6314217edf40d9ee23c36d610ff0fb8 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Tue, 10 Jan 2017 01:22:31 +0000 -Subject: arm64: allwinner: pine64: add MMC support - -All Pine64 boards connect an micro-SD card slot to the first MMC -controller. -Enable the respective DT node and specify the (always-on) regulator -and card-detect pin. -As a micro-SD slot does not feature a write-protect switch, we disable -this feature. - -Signed-off-by: Andre Przywara -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -44,6 +44,8 @@ - - #include "sun50i-a64.dtsi" - -+#include -+ - / { - model = "Pine64"; - compatible = "pine64,pine64", "allwinner,sun50i-a64"; -@@ -55,6 +57,13 @@ - chosen { - stdout-path = "serial0:115200n8"; - }; -+ -+ reg_vcc3v3: vcc3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vcc3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; - }; - - &ehci1 { -@@ -71,6 +80,17 @@ - bias-pull-up; - }; - -+&mmc0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins>; -+ vmmc-supply = <®_vcc3v3>; -+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; -+ cd-inverted; -+ disable-wp; -+ bus-width = <4>; -+ status = "okay"; -+}; -+ - &ohci1 { - status = "okay"; - }; diff --git a/target/linux/sunxi/patches-4.9/0023-arm64-allwinner-a64-add-UART1-pin-nodes.patch b/target/linux/sunxi/patches-4.9/0023-arm64-allwinner-a64-add-UART1-pin-nodes.patch deleted file mode 100644 index 998d51435f..0000000000 --- a/target/linux/sunxi/patches-4.9/0023-arm64-allwinner-a64-add-UART1-pin-nodes.patch +++ /dev/null @@ -1,35 +0,0 @@ -From e7ba733d32cc9487b62b07219ad911c77764a681 Mon Sep 17 00:00:00 2001 -From: Andre Przywara -Date: Tue, 10 Jan 2017 01:22:32 +0000 -Subject: arm64: allwinner: a64: add UART1 pin nodes - -On many boards UART1 connects to a Bluetooth chip, so add the pinctrl -nodes for the only pins providing access to that UART. That includes -those pins for hardware flow control (RTS/CTS). - -Signed-off-by: Andre Przywara -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 10 ++++++++++ - 1 file changed, 10 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -272,6 +272,16 @@ - pins = "PB8", "PB9"; - function = "uart0"; - }; -+ -+ uart1_pins: uart1_pins { -+ pins = "PG6", "PG7"; -+ function = "uart1"; -+ }; -+ -+ uart1_rts_cts_pins: uart1_rts_cts_pins { -+ pins = "PG8", "PG9"; -+ function = "uart1"; -+ }; - }; - - uart0: serial@1c28000 { diff --git a/target/linux/sunxi/patches-4.9/0024-arm64-allwinner-a64-add-r_ccu-node.patch b/target/linux/sunxi/patches-4.9/0024-arm64-allwinner-a64-add-r_ccu-node.patch deleted file mode 100644 index 19a3589708..0000000000 --- a/target/linux/sunxi/patches-4.9/0024-arm64-allwinner-a64-add-r_ccu-node.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 791a9e001d3ba3b552888b0bf3c592a50b71f57e Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 4 Apr 2017 17:50:58 +0800 -Subject: arm64: allwinner: a64: add r_ccu node - -A64 SoC have a CCU (r_ccu) in PRCM block. - -Add the device node for it. - -The mux 3 of R_CCU is an internal oscillator, which is 16MHz according -to the user manual, and has only 30% accuracy based on our experience -on older SoCs. The real mesaured value of it on two Pine64 boards is -around 11MHz, which is around 70% of 16MHz. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -98,6 +98,14 @@ - clock-output-names = "osc32k"; - }; - -+ iosc: internal-osc-clk { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <16000000>; -+ clock-accuracy = <300000000>; -+ clock-output-names = "iosc"; -+ }; -+ - psci { - compatible = "arm,psci-0.2"; - method = "smc"; -@@ -389,5 +397,14 @@ - interrupts = , - ; - }; -+ -+ r_ccu: clock@1f01400 { -+ compatible = "allwinner,sun50i-a64-r-ccu"; -+ reg = <0x01f01400 0x100>; -+ clocks = <&osc24M>, <&osc32k>, <&iosc>; -+ clock-names = "hosc", "losc", "iosc"; -+ #clock-cells = <1>; -+ #reset-cells = <1>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-4.9/0025-arm64-allwinner-a64-add-R_PIO-pinctrl-node.patch b/target/linux/sunxi/patches-4.9/0025-arm64-allwinner-a64-add-R_PIO-pinctrl-node.patch deleted file mode 100644 index ff541ce63e..0000000000 --- a/target/linux/sunxi/patches-4.9/0025-arm64-allwinner-a64-add-R_PIO-pinctrl-node.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ec4279053a6434f685246e022be95d2a62f8c608 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Tue, 4 Apr 2017 17:51:00 +0800 -Subject: arm64: allwinner: a64: add R_PIO pinctrl node - -Allwinner A64 have a dedicated pin controller to manage the PL pin bank. -As the driver and the required clock support are added, add the device -node for it. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -406,5 +406,17 @@ - #clock-cells = <1>; - #reset-cells = <1>; - }; -+ -+ r_pio: pinctrl@01f02c00 { -+ compatible = "allwinner,sun50i-a64-r-pinctrl"; -+ reg = <0x01f02c00 0x400>; -+ interrupts = ; -+ clocks = <&r_ccu 3>, <&osc24M>, <&osc32k>; -+ clock-names = "apb", "hosc", "losc"; -+ gpio-controller; -+ #gpio-cells = <3>; -+ interrupt-controller; -+ #interrupt-cells = <3>; -+ }; - }; - }; diff --git a/target/linux/sunxi/patches-4.9/0026-arm64-allwinner-a64-add-pmu0-regs-for-USB-PHY.patch b/target/linux/sunxi/patches-4.9/0026-arm64-allwinner-a64-add-pmu0-regs-for-USB-PHY.patch deleted file mode 100644 index 0d7803775e..0000000000 --- a/target/linux/sunxi/patches-4.9/0026-arm64-allwinner-a64-add-pmu0-regs-for-USB-PHY.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0d98479738b950e30bb4f782d60099d44076ad67 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Wed, 5 Apr 2017 22:30:34 +0800 -Subject: arm64: allwinner: a64: add pmu0 regs for USB PHY - -The USB PHY in A64 has a "pmu0" region, which controls the EHCI/OHCI -controller pair that can be connected to the PHY0. - -Add the MMIO region for PHY node. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -184,8 +184,10 @@ - usbphy: phy@01c19400 { - compatible = "allwinner,sun50i-a64-usb-phy"; - reg = <0x01c19400 0x14>, -+ <0x01c1a800 0x4>, - <0x01c1b800 0x4>; - reg-names = "phy_ctrl", -+ "pmu0", - "pmu1"; - clocks = <&ccu CLK_USB_PHY0>, - <&ccu CLK_USB_PHY1>; diff --git a/target/linux/sunxi/patches-4.9/0027-arm64-allwinner-a64-Add-PLL_PERIPH0-clock-to-the-R_C.patch b/target/linux/sunxi/patches-4.9/0027-arm64-allwinner-a64-Add-PLL_PERIPH0-clock-to-the-R_C.patch deleted file mode 100644 index 319dba6591..0000000000 --- a/target/linux/sunxi/patches-4.9/0027-arm64-allwinner-a64-Add-PLL_PERIPH0-clock-to-the-R_C.patch +++ /dev/null @@ -1,32 +0,0 @@ -From f74994a94063bc85ac1d6ad677ed06b5279c101f Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Wed, 31 May 2017 15:58:24 +0800 -Subject: arm64: allwinner: a64: Add PLL_PERIPH0 clock to the R_CCU - -The AR100 clock within the R_CCU (PRCM) has the PLL_PERIPH0 as one of -its parents. - -This adds the reference in the device tree describing this relationship. -This patch uses a raw number for the clock index to ease merging by -avoiding cross tree dependencies. - -Signed-off-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -403,8 +403,9 @@ - r_ccu: clock@1f01400 { - compatible = "allwinner,sun50i-a64-r-ccu"; - reg = <0x01f01400 0x100>; -- clocks = <&osc24M>, <&osc32k>, <&iosc>; -- clock-names = "hosc", "losc", "iosc"; -+ clocks = <&osc24M>, <&osc32k>, <&iosc>, -+ <&ccu 11>; -+ clock-names = "hosc", "losc", "iosc", "pll-periph"; - #clock-cells = <1>; - #reset-cells = <1>; - }; diff --git a/target/linux/sunxi/patches-4.9/0030-pinctrl-sunxi-Rework-the-pin-config-building-code.patch b/target/linux/sunxi/patches-4.9/0030-pinctrl-sunxi-Rework-the-pin-config-building-code.patch deleted file mode 100644 index 498581712d..0000000000 --- a/target/linux/sunxi/patches-4.9/0030-pinctrl-sunxi-Rework-the-pin-config-building-code.patch +++ /dev/null @@ -1,251 +0,0 @@ -From f233dbca6227703eaae2f67d6d9c79819773f16b Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 11 Oct 2016 17:45:59 +0200 -Subject: pinctrl: sunxi: Rework the pin config building code - -In order to support more easily the generic pinctrl properties, rework the -pinctrl maps configuration and split it into several sub-functions. - -One of the side-effects from that rework is that we only parse the pin -configuration once, since it's going to be common to every pin, instead of -having to parsing once for each pin. - -Signed-off-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 178 +++++++++++++++++++++++++--------- - 1 file changed, 130 insertions(+), 48 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -145,6 +145,110 @@ static int sunxi_pctrl_get_group_pins(st - return 0; - } - -+static bool sunxi_pctrl_has_bias_prop(struct device_node *node) -+{ -+ return of_find_property(node, "allwinner,pull", NULL); -+} -+ -+static bool sunxi_pctrl_has_drive_prop(struct device_node *node) -+{ -+ return of_find_property(node, "allwinner,drive", NULL); -+} -+ -+static int sunxi_pctrl_parse_bias_prop(struct device_node *node) -+{ -+ u32 val; -+ -+ if (of_property_read_u32(node, "allwinner,pull", &val)) -+ return -EINVAL; -+ -+ switch (val) { -+ case 1: -+ return PIN_CONFIG_BIAS_PULL_UP; -+ case 2: -+ return PIN_CONFIG_BIAS_PULL_DOWN; -+ } -+ -+ return -EINVAL; -+} -+ -+static int sunxi_pctrl_parse_drive_prop(struct device_node *node) -+{ -+ u32 val; -+ -+ if (of_property_read_u32(node, "allwinner,drive", &val)) -+ return -EINVAL; -+ -+ return (val + 1) * 10; -+} -+ -+static const char *sunxi_pctrl_parse_function_prop(struct device_node *node) -+{ -+ const char *function; -+ int ret; -+ -+ ret = of_property_read_string(node, "allwinner,function", &function); -+ if (!ret) -+ return function; -+ -+ return NULL; -+} -+ -+static const char *sunxi_pctrl_find_pins_prop(struct device_node *node, -+ int *npins) -+{ -+ int count; -+ -+ count = of_property_count_strings(node, "allwinner,pins"); -+ if (count > 0) { -+ *npins = count; -+ return "allwinner,pins"; -+ } -+ -+ return NULL; -+} -+ -+static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, -+ unsigned int *len) -+{ -+ unsigned long *pinconfig; -+ unsigned int configlen = 0, idx = 0; -+ -+ if (sunxi_pctrl_has_drive_prop(node)) -+ configlen++; -+ if (sunxi_pctrl_has_bias_prop(node)) -+ configlen++; -+ -+ pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); -+ if (!pinconfig) -+ return NULL; -+ -+ if (sunxi_pctrl_has_drive_prop(node)) { -+ int drive = sunxi_pctrl_parse_drive_prop(node); -+ if (drive < 0) -+ goto err_free; -+ -+ pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, -+ drive); -+ } -+ -+ if (sunxi_pctrl_has_bias_prop(node)) { -+ int pull = sunxi_pctrl_parse_bias_prop(node); -+ if (pull < 0) -+ goto err_free; -+ -+ pinconfig[idx++] = pinconf_to_config_packed(pull, 0); -+ } -+ -+ -+ *len = configlen; -+ return pinconfig; -+ -+err_free: -+ kfree(pinconfig); -+ return NULL; -+} -+ - static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *node, - struct pinctrl_map **map, -@@ -153,38 +257,45 @@ static int sunxi_pctrl_dt_node_to_map(st - struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); - unsigned long *pinconfig; - struct property *prop; -- const char *function; -+ const char *function, *pin_prop; - const char *group; -- int ret, nmaps, i = 0; -- u32 val; -+ int ret, npins, nmaps, configlen = 0, i = 0; - - *map = NULL; - *num_maps = 0; - -- ret = of_property_read_string(node, "allwinner,function", &function); -- if (ret) { -- dev_err(pctl->dev, -- "missing allwinner,function property in node %s\n", -+ function = sunxi_pctrl_parse_function_prop(node); -+ if (!function) { -+ dev_err(pctl->dev, "missing function property in node %s\n", - node->name); - return -EINVAL; - } - -- nmaps = of_property_count_strings(node, "allwinner,pins") * 2; -- if (nmaps < 0) { -- dev_err(pctl->dev, -- "missing allwinner,pins property in node %s\n", -+ pin_prop = sunxi_pctrl_find_pins_prop(node, &npins); -+ if (!pin_prop) { -+ dev_err(pctl->dev, "missing pins property in node %s\n", - node->name); - return -EINVAL; - } - -+ /* -+ * We have two maps for each pin: one for the function, one -+ * for the configuration (bias, strength, etc) -+ */ -+ nmaps = npins * 2; - *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); - if (!*map) - return -ENOMEM; - -- of_property_for_each_string(node, "allwinner,pins", prop, group) { -+ pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); -+ if (!pinconfig) { -+ ret = -EINVAL; -+ goto err_free_map; -+ } -+ -+ of_property_for_each_string(node, pin_prop, prop, group) { - struct sunxi_pinctrl_group *grp = - sunxi_pinctrl_find_group_by_name(pctl, group); -- int j = 0, configlen = 0; - - if (!grp) { - dev_err(pctl->dev, "unknown pin %s", group); -@@ -207,34 +318,6 @@ static int sunxi_pctrl_dt_node_to_map(st - - (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; - (*map)[i].data.configs.group_or_pin = group; -- -- if (of_find_property(node, "allwinner,drive", NULL)) -- configlen++; -- if (of_find_property(node, "allwinner,pull", NULL)) -- configlen++; -- -- pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); -- if (!pinconfig) { -- kfree(*map); -- return -ENOMEM; -- } -- -- if (!of_property_read_u32(node, "allwinner,drive", &val)) { -- u16 strength = (val + 1) * 10; -- pinconfig[j++] = -- pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, -- strength); -- } -- -- if (!of_property_read_u32(node, "allwinner,pull", &val)) { -- enum pin_config_param pull = PIN_CONFIG_END; -- if (val == 1) -- pull = PIN_CONFIG_BIAS_PULL_UP; -- else if (val == 2) -- pull = PIN_CONFIG_BIAS_PULL_DOWN; -- pinconfig[j++] = pinconf_to_config_packed(pull, 0); -- } -- - (*map)[i].data.configs.configs = pinconfig; - (*map)[i].data.configs.num_configs = configlen; - -@@ -244,19 +327,18 @@ static int sunxi_pctrl_dt_node_to_map(st - *num_maps = nmaps; - - return 0; -+ -+err_free_map: -+ kfree(map); -+ return ret; - } - - static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev, - struct pinctrl_map *map, - unsigned num_maps) - { -- int i; -- -- for (i = 0; i < num_maps; i++) { -- if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) -- kfree(map[i].data.configs.configs); -- } -- -+ /* All the maps have the same pin config, free only the first one */ -+ kfree(map[0].data.configs.configs); - kfree(map); - } - diff --git a/target/linux/sunxi/patches-4.9/0031-pinctrl-sunxi-Use-macros-from-bindings-header-file-f.patch b/target/linux/sunxi/patches-4.9/0031-pinctrl-sunxi-Use-macros-from-bindings-header-file-f.patch deleted file mode 100644 index 39be965422..0000000000 --- a/target/linux/sunxi/patches-4.9/0031-pinctrl-sunxi-Use-macros-from-bindings-header-file-f.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 42676fa4aa87eda4fc762df495d4bde2ddc4bfce Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 11 Oct 2016 17:46:00 +0200 -Subject: pinctrl: sunxi: Use macros from bindings header file for DT parsing - -Since we have some bindings header for our hardcoded flags, let's use them -when we can. - -Acked-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -28,6 +28,8 @@ - #include - #include - -+#include -+ - #include "../core.h" - #include "pinctrl-sunxi.h" - -@@ -163,9 +165,9 @@ static int sunxi_pctrl_parse_bias_prop(s - return -EINVAL; - - switch (val) { -- case 1: -+ case SUN4I_PINCTRL_PULL_UP: - return PIN_CONFIG_BIAS_PULL_UP; -- case 2: -+ case SUN4I_PINCTRL_PULL_DOWN: - return PIN_CONFIG_BIAS_PULL_DOWN; - } - diff --git a/target/linux/sunxi/patches-4.9/0032-pinctrl-sunxi-Handle-bias-disable.patch b/target/linux/sunxi/patches-4.9/0032-pinctrl-sunxi-Handle-bias-disable.patch deleted file mode 100644 index 61d6102c92..0000000000 --- a/target/linux/sunxi/patches-4.9/0032-pinctrl-sunxi-Handle-bias-disable.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 07fe64ba213f36ca8f6ffd8c4d5893f022744fdb Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Tue, 11 Oct 2016 17:46:01 +0200 -Subject: pinctrl: sunxi: Handle bias disable - -So far, putting NO_PULL in allwinner,pull was ignored, behaving like if -that property was not there at all. - -Obviously, this is not the right thing to do, and in that case, we really -need to just disable the bias. - -Acked-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -165,6 +165,8 @@ static int sunxi_pctrl_parse_bias_prop(s - return -EINVAL; - - switch (val) { -+ case SUN4I_PINCTRL_NO_PULL: -+ return PIN_CONFIG_BIAS_DISABLE; - case SUN4I_PINCTRL_PULL_UP: - return PIN_CONFIG_BIAS_PULL_UP; - case SUN4I_PINCTRL_PULL_DOWN: -@@ -401,6 +403,12 @@ static int sunxi_pconf_group_set(struct - | dlevel << sunxi_dlevel_offset(pin), - pctl->membase + sunxi_dlevel_reg(pin)); - break; -+ case PIN_CONFIG_BIAS_DISABLE: -+ val = readl(pctl->membase + sunxi_pull_reg(pin)); -+ mask = PULL_PINS_MASK << sunxi_pull_offset(pin); -+ writel((val & ~mask), -+ pctl->membase + sunxi_pull_reg(pin)); -+ break; - case PIN_CONFIG_BIAS_PULL_UP: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); diff --git a/target/linux/sunxi/patches-4.9/0033-pinctrl-sunxi-Support-generic-binding.patch b/target/linux/sunxi/patches-4.9/0033-pinctrl-sunxi-Support-generic-binding.patch deleted file mode 100644 index 35c6876812..0000000000 --- a/target/linux/sunxi/patches-4.9/0033-pinctrl-sunxi-Support-generic-binding.patch +++ /dev/null @@ -1,106 +0,0 @@ -From cefbf1a1b29531a970bc2908a50a75d6474fcc38 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 20 Oct 2016 15:49:03 +0200 -Subject: pinctrl: sunxi: Support generic binding - -Our bindings are mostly irrelevant now that we have generic pinctrl -bindings that cover exactly the same uses cases. - -Add support for the new ones, and obviously keep our old binding support in -order to keep the ABI stable. - -Acked-by: Chen-Yu Tsai -Signed-off-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 48 +++++++++++++++++++++++++++++++++-- - 1 file changed, 46 insertions(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -149,18 +149,33 @@ static int sunxi_pctrl_get_group_pins(st - - static bool sunxi_pctrl_has_bias_prop(struct device_node *node) - { -- return of_find_property(node, "allwinner,pull", NULL); -+ return of_find_property(node, "bias-pull-up", NULL) || -+ of_find_property(node, "bias-pull-down", NULL) || -+ of_find_property(node, "bias-disable", NULL) || -+ of_find_property(node, "allwinner,pull", NULL); - } - - static bool sunxi_pctrl_has_drive_prop(struct device_node *node) - { -- return of_find_property(node, "allwinner,drive", NULL); -+ return of_find_property(node, "drive-strength", NULL) || -+ of_find_property(node, "allwinner,drive", NULL); - } - - static int sunxi_pctrl_parse_bias_prop(struct device_node *node) - { - u32 val; - -+ /* Try the new style binding */ -+ if (of_find_property(node, "bias-pull-up", NULL)) -+ return PIN_CONFIG_BIAS_PULL_UP; -+ -+ if (of_find_property(node, "bias-pull-down", NULL)) -+ return PIN_CONFIG_BIAS_PULL_DOWN; -+ -+ if (of_find_property(node, "bias-disable", NULL)) -+ return PIN_CONFIG_BIAS_DISABLE; -+ -+ /* And fall back to the old binding */ - if (of_property_read_u32(node, "allwinner,pull", &val)) - return -EINVAL; - -@@ -180,6 +195,21 @@ static int sunxi_pctrl_parse_drive_prop( - { - u32 val; - -+ /* Try the new style binding */ -+ if (!of_property_read_u32(node, "drive-strength", &val)) { -+ /* We can't go below 10mA ... */ -+ if (val < 10) -+ return -EINVAL; -+ -+ /* ... and only up to 40 mA ... */ -+ if (val > 40) -+ val = 40; -+ -+ /* by steps of 10 mA */ -+ return rounddown(val, 10); -+ } -+ -+ /* And then fall back to the old binding */ - if (of_property_read_u32(node, "allwinner,drive", &val)) - return -EINVAL; - -@@ -191,6 +221,12 @@ static const char *sunxi_pctrl_parse_fun - const char *function; - int ret; - -+ /* Try the generic binding */ -+ ret = of_property_read_string(node, "function", &function); -+ if (!ret) -+ return function; -+ -+ /* And fall back to our legacy one */ - ret = of_property_read_string(node, "allwinner,function", &function); - if (!ret) - return function; -@@ -203,6 +239,14 @@ static const char *sunxi_pctrl_find_pins - { - int count; - -+ /* Try the generic binding */ -+ count = of_property_count_strings(node, "pins"); -+ if (count > 0) { -+ *npins = count; -+ return "pins"; -+ } -+ -+ /* And fall back to our legacy one */ - count = of_property_count_strings(node, "allwinner,pins"); - if (count > 0) { - *npins = count; diff --git a/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch b/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch deleted file mode 100644 index 119ab2b8f9..0000000000 --- a/target/linux/sunxi/patches-4.9/0034-pinctrl-sunxi-Deal-with-configless-pins.patch +++ /dev/null @@ -1,128 +0,0 @@ -From e11dee2e98f8abc99ad5336796576a827853ccfa Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Thu, 20 Oct 2016 15:49:02 +0200 -Subject: pinctrl: sunxi: Deal with configless pins - -Even though the our binding had the assumption that the allwinner,pull and -allwinner,drive properties were optional, the code never took that into -account. - -Fix that. - -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 51 +++++++++++++++++++++++++---------- - 1 file changed, 37 insertions(+), 14 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -261,20 +261,29 @@ static unsigned long *sunxi_pctrl_build_ - { - unsigned long *pinconfig; - unsigned int configlen = 0, idx = 0; -+ int ret; - - if (sunxi_pctrl_has_drive_prop(node)) - configlen++; - if (sunxi_pctrl_has_bias_prop(node)) - configlen++; - -+ /* -+ * If we don't have any configuration, bail out -+ */ -+ if (!configlen) -+ return NULL; -+ - pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); - if (!pinconfig) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - if (sunxi_pctrl_has_drive_prop(node)) { - int drive = sunxi_pctrl_parse_drive_prop(node); -- if (drive < 0) -+ if (drive < 0) { -+ ret = drive; - goto err_free; -+ } - - pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, - drive); -@@ -282,8 +291,10 @@ static unsigned long *sunxi_pctrl_build_ - - if (sunxi_pctrl_has_bias_prop(node)) { - int pull = sunxi_pctrl_parse_bias_prop(node); -- if (pull < 0) -+ if (pull < 0) { -+ ret = pull; - goto err_free; -+ } - - pinconfig[idx++] = pinconf_to_config_packed(pull, 0); - } -@@ -294,7 +305,7 @@ static unsigned long *sunxi_pctrl_build_ - - err_free: - kfree(pinconfig); -- return NULL; -+ return ERR_PTR(ret); - } - - static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, -@@ -328,7 +339,10 @@ static int sunxi_pctrl_dt_node_to_map(st - - /* - * We have two maps for each pin: one for the function, one -- * for the configuration (bias, strength, etc) -+ * for the configuration (bias, strength, etc). -+ * -+ * We might be slightly overshooting, since we might not have -+ * any configuration. - */ - nmaps = npins * 2; - *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); -@@ -336,8 +350,8 @@ static int sunxi_pctrl_dt_node_to_map(st - return -ENOMEM; - - pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); -- if (!pinconfig) { -- ret = -EINVAL; -+ if (IS_ERR(pinconfig)) { -+ ret = PTR_ERR(pinconfig); - goto err_free_map; - } - -@@ -364,15 +378,24 @@ static int sunxi_pctrl_dt_node_to_map(st - - i++; - -- (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; -- (*map)[i].data.configs.group_or_pin = group; -- (*map)[i].data.configs.configs = pinconfig; -- (*map)[i].data.configs.num_configs = configlen; -- -- i++; -+ if (pinconfig) { -+ (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; -+ (*map)[i].data.configs.group_or_pin = group; -+ (*map)[i].data.configs.configs = pinconfig; -+ (*map)[i].data.configs.num_configs = configlen; -+ i++; -+ } - } - -- *num_maps = nmaps; -+ *num_maps = i; -+ -+ /* -+ * We know have the number of maps we need, we can resize our -+ * map array -+ */ -+ *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); -+ if (!map) -+ return -ENOMEM; - - return 0; - diff --git a/target/linux/sunxi/patches-4.9/0035-pinctrl-sunxi-make-bool-drivers-explicitly-non-modul.patch b/target/linux/sunxi/patches-4.9/0035-pinctrl-sunxi-make-bool-drivers-explicitly-non-modul.patch deleted file mode 100644 index 8ab535c30f..0000000000 --- a/target/linux/sunxi/patches-4.9/0035-pinctrl-sunxi-make-bool-drivers-explicitly-non-modul.patch +++ /dev/null @@ -1,437 +0,0 @@ -From 0c8c6ba00cbf2c0a6164aa41d43d017d65caf321 Mon Sep 17 00:00:00 2001 -From: Paul Gortmaker -Date: Sat, 29 Oct 2016 20:00:30 -0400 -Subject: pinctrl: sunxi: make bool drivers explicitly non-modular - -None of the Kconfigs for any of these drivers are tristate, -meaning that they currently are not being built as a module by anyone. - -Lets remove the modular code that is essentially orphaned, so that -when reading the drivers there is no doubt they are builtin-only. All -drivers get essentially the same change, so they are handled in batch. - -Changes are (1) use builtin_platform_driver, (2) use init.h header -(3) delete module_exit related code, (4) delete MODULE_DEVICE_TABLE, -and (5) delete MODULE_LICENCE/MODULE_AUTHOR and associated tags. - -Since module_platform_driver() uses the same init level priority as -builtin_platform_driver() the init ordering remains unchanged with -this commit. - -Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. - -We do delete the MODULE_LICENSE etc. tags since all that information -is already contained at the top of each file in the comments. - -Cc: Boris Brezillon -Cc: Chen-Yu Tsai -Cc: Hans de Goede -Cc: Linus Walleij -Cc: Patrice Chotard -Cc: Hongzhou Yang -Cc: Fabian Frederick -Cc: Maxime Coquelin -Cc: Vishnu Patekar -Cc: Mylene Josserand -Cc: linux-gpio@vger.kernel.org -Cc: linux-arm-kernel@lists.infradead.org -Signed-off-by: Paul Gortmaker -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-gr8.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c | 10 ++-------- - drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c | 11 ++--------- - drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c | 10 ++-------- - drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c | 9 ++------- - drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c | 9 ++------- - 13 files changed, 26 insertions(+), 95 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-gr8.c -+++ b/drivers/pinctrl/sunxi/pinctrl-gr8.c -@@ -12,7 +12,7 @@ - * warranty of any kind, whether express or implied. - */ - --#include -+#include - #include - #include - #include -@@ -525,7 +525,6 @@ static const struct of_device_id sun5i_g - { .compatible = "nextthing,gr8-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun5i_gr8_pinctrl_match); - - static struct platform_driver sun5i_gr8_pinctrl_driver = { - .probe = sun5i_gr8_pinctrl_probe, -@@ -534,8 +533,4 @@ static struct platform_driver sun5i_gr8_ - .of_match_table = sun5i_gr8_pinctrl_match, - }, - }; --module_platform_driver(sun5i_gr8_pinctrl_driver); -- --MODULE_AUTHOR("Mylene Josserand -+#include - #include - #include - #include -@@ -1036,7 +1036,6 @@ static const struct of_device_id sun4i_a - { .compatible = "allwinner,sun4i-a10-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun4i_a10_pinctrl_match); - - static struct platform_driver sun4i_a10_pinctrl_driver = { - .probe = sun4i_a10_pinctrl_probe, -@@ -1045,8 +1044,4 @@ static struct platform_driver sun4i_a10_ - .of_match_table = sun4i_a10_pinctrl_match, - }, - }; --module_platform_driver(sun4i_a10_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -674,7 +674,6 @@ static const struct of_device_id sun5i_a - { .compatible = "allwinner,sun5i-a10s-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun5i_a10s_pinctrl_match); - - static struct platform_driver sun5i_a10s_pinctrl_driver = { - .probe = sun5i_a10s_pinctrl_probe, -@@ -683,8 +682,4 @@ static struct platform_driver sun5i_a10s - .of_match_table = sun5i_a10s_pinctrl_match, - }, - }; --module_platform_driver(sun5i_a10s_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -392,7 +392,6 @@ static const struct of_device_id sun5i_a - { .compatible = "allwinner,sun5i-a13-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun5i_a13_pinctrl_match); - - static struct platform_driver sun5i_a13_pinctrl_driver = { - .probe = sun5i_a13_pinctrl_probe, -@@ -401,8 +400,4 @@ static struct platform_driver sun5i_a13_ - .of_match_table = sun5i_a13_pinctrl_match, - }, - }; --module_platform_driver(sun5i_a13_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -136,7 +136,6 @@ static const struct of_device_id sun6i_a - { .compatible = "allwinner,sun6i-a31-r-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun6i_a31_r_pinctrl_match); - - static struct platform_driver sun6i_a31_r_pinctrl_driver = { - .probe = sun6i_a31_r_pinctrl_probe, -@@ -145,9 +144,4 @@ static struct platform_driver sun6i_a31_ - .of_match_table = sun6i_a31_r_pinctrl_match, - }, - }; --module_platform_driver(sun6i_a31_r_pinctrl_driver); -- --MODULE_AUTHOR("Boris Brezillon -+#include - #include - #include - #include -@@ -934,7 +934,6 @@ static const struct of_device_id sun6i_a - { .compatible = "allwinner,sun6i-a31-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun6i_a31_pinctrl_match); - - static struct platform_driver sun6i_a31_pinctrl_driver = { - .probe = sun6i_a31_pinctrl_probe, -@@ -943,8 +942,4 @@ static struct platform_driver sun6i_a31_ - .of_match_table = sun6i_a31_pinctrl_match, - }, - }; --module_platform_driver(sun6i_a31_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -798,7 +798,6 @@ static const struct of_device_id sun6i_a - { .compatible = "allwinner,sun6i-a31s-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun6i_a31s_pinctrl_match); - - static struct platform_driver sun6i_a31s_pinctrl_driver = { - .probe = sun6i_a31s_pinctrl_probe, -@@ -807,8 +806,4 @@ static struct platform_driver sun6i_a31s - .of_match_table = sun6i_a31s_pinctrl_match, - }, - }; --module_platform_driver(sun6i_a31s_pinctrl_driver); -- --MODULE_AUTHOR("Hans de Goede "); --MODULE_DESCRIPTION("Allwinner A31s pinctrl driver"); --MODULE_LICENSE("GPL"); -+builtin_platform_driver(sun6i_a31s_pinctrl_driver); ---- a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c -@@ -10,7 +10,7 @@ - * warranty of any kind, whether express or implied. - */ - --#include -+#include - #include - #include - #include -@@ -1045,7 +1045,6 @@ static const struct of_device_id sun7i_a - { .compatible = "allwinner,sun7i-a20-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun7i_a20_pinctrl_match); - - static struct platform_driver sun7i_a20_pinctrl_driver = { - .probe = sun7i_a20_pinctrl_probe, -@@ -1054,8 +1053,4 @@ static struct platform_driver sun7i_a20_ - .of_match_table = sun7i_a20_pinctrl_match, - }, - }; --module_platform_driver(sun7i_a20_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -123,7 +123,6 @@ static const struct of_device_id sun8i_a - { .compatible = "allwinner,sun8i-a23-r-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match); - - static struct platform_driver sun8i_a23_r_pinctrl_driver = { - .probe = sun8i_a23_r_pinctrl_probe, -@@ -132,10 +131,4 @@ static struct platform_driver sun8i_a23_ - .of_match_table = sun8i_a23_r_pinctrl_match, - }, - }; --module_platform_driver(sun8i_a23_r_pinctrl_driver); -- --MODULE_AUTHOR("Chen-Yu Tsai "); --MODULE_AUTHOR("Boris Brezillon -+#include - #include - #include - #include -@@ -575,7 +575,6 @@ static const struct of_device_id sun8i_a - { .compatible = "allwinner,sun8i-a23-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match); - - static struct platform_driver sun8i_a23_pinctrl_driver = { - .probe = sun8i_a23_pinctrl_probe, -@@ -584,9 +583,4 @@ static struct platform_driver sun8i_a23_ - .of_match_table = sun8i_a23_pinctrl_match, - }, - }; --module_platform_driver(sun8i_a23_pinctrl_driver); -- --MODULE_AUTHOR("Chen-Yu Tsai "); --MODULE_AUTHOR("Maxime Ripard -+#include - #include - #include - #include -@@ -498,7 +498,6 @@ static const struct of_device_id sun8i_a - { .compatible = "allwinner,sun8i-a33-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun8i_a33_pinctrl_match); - - static struct platform_driver sun8i_a33_pinctrl_driver = { - .probe = sun8i_a33_pinctrl_probe, -@@ -507,8 +506,4 @@ static struct platform_driver sun8i_a33_ - .of_match_table = sun8i_a33_pinctrl_match, - }, - }; --module_platform_driver(sun8i_a33_pinctrl_driver); -- --MODULE_AUTHOR("Vishnu Patekar "); --MODULE_DESCRIPTION("Allwinner a33 pinctrl driver"); --MODULE_LICENSE("GPL"); -+builtin_platform_driver(sun8i_a33_pinctrl_driver); ---- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c -@@ -12,7 +12,7 @@ - * warranty of any kind, whether express or implied. - */ - --#include -+#include - #include - #include - #include -@@ -587,7 +587,6 @@ static const struct of_device_id sun8i_a - { .compatible = "allwinner,sun8i-a83t-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun8i_a83t_pinctrl_match); - - static struct platform_driver sun8i_a83t_pinctrl_driver = { - .probe = sun8i_a83t_pinctrl_probe, -@@ -596,8 +595,4 @@ static struct platform_driver sun8i_a83t - .of_match_table = sun8i_a83t_pinctrl_match, - }, - }; --module_platform_driver(sun8i_a83t_pinctrl_driver); -- --MODULE_AUTHOR("Vishnu Patekar "); --MODULE_DESCRIPTION("Allwinner a83t pinctrl driver"); --MODULE_LICENSE("GPL"); -+builtin_platform_driver(sun8i_a83t_pinctrl_driver); ---- a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c -@@ -10,7 +10,7 @@ - * warranty of any kind, whether express or implied. - */ - --#include -+#include - #include - #include - #include -@@ -733,7 +733,6 @@ static const struct of_device_id sun9i_a - { .compatible = "allwinner,sun9i-a80-pinctrl", }, - {} - }; --MODULE_DEVICE_TABLE(of, sun9i_a80_pinctrl_match); - - static struct platform_driver sun9i_a80_pinctrl_driver = { - .probe = sun9i_a80_pinctrl_probe, -@@ -742,8 +741,4 @@ static struct platform_driver sun9i_a80_ - .of_match_table = sun9i_a80_pinctrl_match, - }, - }; --module_platform_driver(sun9i_a80_pinctrl_driver); -- --MODULE_AUTHOR("Maxime Ripard "); --MODULE_DESCRIPTION("Allwinner A80 pinctrl driver"); --MODULE_LICENSE("GPL"); -+builtin_platform_driver(sun9i_a80_pinctrl_driver); diff --git a/target/linux/sunxi/patches-4.9/0036-pinctrl-sunxi-Free-configs-in-pinctrl_map-only-if-it.patch b/target/linux/sunxi/patches-4.9/0036-pinctrl-sunxi-Free-configs-in-pinctrl_map-only-if-it.patch deleted file mode 100644 index 02c5f568c8..0000000000 --- a/target/linux/sunxi/patches-4.9/0036-pinctrl-sunxi-Free-configs-in-pinctrl_map-only-if-it.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 88f01a1bd0e0dbd01b65907023dbe53cf524ea2a Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Fri, 11 Nov 2016 10:35:10 +0800 -Subject: pinctrl: sunxi: Free configs in pinctrl_map only if it is a config - map - -In the recently refactored sunxi pinctrl library, we are only allocating -one set of pin configs for each pinmux setting node. When the pinctrl_map -structure is freed, the pin configs should also be freed. However the -code assumed the first map would contain the configs, which actually -never happens, as the mux function map gets added first. - -The proper way to do this is to look through all the maps and free the -first one whose type is actually PIN_MAP_TYPE_CONFIGS_GROUP. - -Also slightly expand the comment explaining this. - -Fixes: f233dbca6227 ("pinctrl: sunxi: Rework the pin config building code") -Signed-off-by: Chen-Yu Tsai -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 17 +++++++++++++++-- - 1 file changed, 15 insertions(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -408,8 +408,21 @@ static void sunxi_pctrl_dt_free_map(stru - struct pinctrl_map *map, - unsigned num_maps) - { -- /* All the maps have the same pin config, free only the first one */ -- kfree(map[0].data.configs.configs); -+ int i; -+ -+ /* pin config is never in the first map */ -+ for (i = 1; i < num_maps; i++) { -+ if (map[i].type != PIN_MAP_TYPE_CONFIGS_GROUP) -+ continue; -+ -+ /* -+ * All the maps share the same pin config, -+ * free only the first one we find. -+ */ -+ kfree(map[i].data.configs.configs); -+ break; -+ } -+ - kfree(map); - } - diff --git a/target/linux/sunxi/patches-4.9/0037-pinctrl-sunxi-Fix-PIN_CONFIG_BIAS_PULL_-DOWN-UP-argu.patch b/target/linux/sunxi/patches-4.9/0037-pinctrl-sunxi-Fix-PIN_CONFIG_BIAS_PULL_-DOWN-UP-argu.patch deleted file mode 100644 index 4921240f79..0000000000 --- a/target/linux/sunxi/patches-4.9/0037-pinctrl-sunxi-Fix-PIN_CONFIG_BIAS_PULL_-DOWN-UP-argu.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 223dba00b4072efc590c7d648f230db1b44186b9 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Fri, 11 Nov 2016 17:50:34 +0800 -Subject: pinctrl: sunxi: Fix PIN_CONFIG_BIAS_PULL_{DOWN,UP} argument - -According to pinconf-generic.h, the argument for -PIN_CONFIG_BIAS_PULL_{DOWN,UP} is non-zero if the bias is enabled -with a pull up/down resistor, zero if it is directly connected -to VDD or ground. - -Since Allwinner hardware uses a weak pull resistor internally, -the argument should be 1. - -Signed-off-by: Chen-Yu Tsai -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -291,12 +291,16 @@ static unsigned long *sunxi_pctrl_build_ - - if (sunxi_pctrl_has_bias_prop(node)) { - int pull = sunxi_pctrl_parse_bias_prop(node); -+ int arg = 0; - if (pull < 0) { - ret = pull; - goto err_free; - } - -- pinconfig[idx++] = pinconf_to_config_packed(pull, 0); -+ if (pull != PIN_CONFIG_BIAS_DISABLE) -+ arg = 1; /* hardware uses weak pull resistors */ -+ -+ pinconfig[idx++] = pinconf_to_config_packed(pull, arg); - } - - diff --git a/target/linux/sunxi/patches-4.9/0038-pinctrl-sunxi-Add-support-for-fetching-pinconf-setti.patch b/target/linux/sunxi/patches-4.9/0038-pinctrl-sunxi-Add-support-for-fetching-pinconf-setti.patch deleted file mode 100644 index d7972197ff..0000000000 --- a/target/linux/sunxi/patches-4.9/0038-pinctrl-sunxi-Add-support-for-fetching-pinconf-setti.patch +++ /dev/null @@ -1,158 +0,0 @@ -From c5fda170e87a4bdaeb278f7e50f7a1f654e94eb5 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Fri, 11 Nov 2016 17:50:35 +0800 -Subject: pinctrl: sunxi: Add support for fetching pinconf settings from - hardware - -The sunxi pinctrl driver only caches whatever pinconf setting was last -set on a given pingroup. This is not particularly helpful, nor is it -correct. - -Fix this by actually reading the hardware registers and returning -the correct results or error codes. Also filter out unsupported -pinconf settings. Since this driver has a peculiar setup of 1 pin -per group, we can support both pin and pingroup pinconf setting -read back with the same code. The sunxi_pconf_reg helper and code -structure is inspired by pinctrl-msm. - -With this done we can also claim to support generic pinconf, by -setting .is_generic = true in pinconf_ops. - -Also remove the cached config value. The behavior of this was never -correct, as it only cached 1 setting instead of all of them. Since -we can now read back settings directly from the hardware, it is no -longer required. - -Signed-off-by: Chen-Yu Tsai -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 86 +++++++++++++++++++++++++++++++++-- - drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 - - 2 files changed, 81 insertions(+), 6 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -438,15 +438,91 @@ static const struct pinctrl_ops sunxi_pc - .get_group_pins = sunxi_pctrl_get_group_pins, - }; - -+static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param, -+ u32 *offset, u32 *shift, u32 *mask) -+{ -+ switch (param) { -+ case PIN_CONFIG_DRIVE_STRENGTH: -+ *offset = sunxi_dlevel_reg(pin); -+ *shift = sunxi_dlevel_offset(pin); -+ *mask = DLEVEL_PINS_MASK; -+ break; -+ -+ case PIN_CONFIG_BIAS_PULL_UP: -+ case PIN_CONFIG_BIAS_PULL_DOWN: -+ case PIN_CONFIG_BIAS_DISABLE: -+ *offset = sunxi_pull_reg(pin); -+ *shift = sunxi_pull_offset(pin); -+ *mask = PULL_PINS_MASK; -+ break; -+ -+ default: -+ return -ENOTSUPP; -+ } -+ -+ return 0; -+} -+ -+static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin, -+ unsigned long *config) -+{ -+ struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ enum pin_config_param param = pinconf_to_config_param(*config); -+ u32 offset, shift, mask, val; -+ u16 arg; -+ int ret; -+ -+ pin -= pctl->desc->pin_base; -+ -+ ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); -+ if (ret < 0) -+ return ret; -+ -+ val = (readl(pctl->membase + offset) >> shift) & mask; -+ -+ switch (pinconf_to_config_param(*config)) { -+ case PIN_CONFIG_DRIVE_STRENGTH: -+ arg = (val + 1) * 10; -+ break; -+ -+ case PIN_CONFIG_BIAS_PULL_UP: -+ if (val != SUN4I_PINCTRL_PULL_UP) -+ return -EINVAL; -+ arg = 1; /* hardware is weak pull-up */ -+ break; -+ -+ case PIN_CONFIG_BIAS_PULL_DOWN: -+ if (val != SUN4I_PINCTRL_PULL_DOWN) -+ return -EINVAL; -+ arg = 1; /* hardware is weak pull-down */ -+ break; -+ -+ case PIN_CONFIG_BIAS_DISABLE: -+ if (val != SUN4I_PINCTRL_NO_PULL) -+ return -EINVAL; -+ arg = 0; -+ break; -+ -+ default: -+ /* sunxi_pconf_reg should catch anything unsupported */ -+ WARN_ON(1); -+ return -ENOTSUPP; -+ } -+ -+ *config = pinconf_to_config_packed(param, arg); -+ -+ return 0; -+} -+ - static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev, - unsigned group, - unsigned long *config) - { - struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); -+ struct sunxi_pinctrl_group *g = &pctl->groups[group]; - -- *config = pctl->groups[group].config; -- -- return 0; -+ /* We only support 1 pin per group. Chain it to the pin callback */ -+ return sunxi_pconf_get(pctldev, g->pin, config); - } - - static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, -@@ -508,8 +584,6 @@ static int sunxi_pconf_group_set(struct - default: - break; - } -- /* cache the config value */ -- g->config = configs[i]; - } /* for each config */ - - spin_unlock_irqrestore(&pctl->lock, flags); -@@ -518,6 +592,8 @@ static int sunxi_pconf_group_set(struct - } - - static const struct pinconf_ops sunxi_pconf_ops = { -+ .is_generic = true, -+ .pin_config_get = sunxi_pconf_get, - .pin_config_group_get = sunxi_pconf_group_get, - .pin_config_group_set = sunxi_pconf_group_set, - }; ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h -@@ -109,7 +109,6 @@ struct sunxi_pinctrl_function { - - struct sunxi_pinctrl_group { - const char *name; -- unsigned long config; - unsigned pin; - }; - diff --git a/target/linux/sunxi/patches-4.9/0039-pinctrl-sunxi-Make-sunxi_pconf_group_set-use-sunxi_p.patch b/target/linux/sunxi/patches-4.9/0039-pinctrl-sunxi-Make-sunxi_pconf_group_set-use-sunxi_p.patch deleted file mode 100644 index 7555933f63..0000000000 --- a/target/linux/sunxi/patches-4.9/0039-pinctrl-sunxi-Make-sunxi_pconf_group_set-use-sunxi_p.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 51814827190214986c452a166718bf12d32211c7 Mon Sep 17 00:00:00 2001 -From: Chen-Yu Tsai -Date: Fri, 11 Nov 2016 17:50:36 +0800 -Subject: pinctrl: sunxi: Make sunxi_pconf_group_set use sunxi_pconf_reg helper - -The sunxi_pconf_reg helper introduced in the last patch gives us the -chance to rework sunxi_pconf_group_set to have it match the structure -of sunxi_pconf_(group_)get and make it easier to understand. - -For each config to set, it: - - 1. checks if the parameter is supported. - 2. checks if the argument is within limits. - 3. converts argument to the register value. - 4. writes to the register with spinlock held. - -As a result the function now blocks unsupported config parameters, -instead of silently ignoring them. - -Signed-off-by: Chen-Yu Tsai -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 64 +++++++++++++++++------------------ - 1 file changed, 32 insertions(+), 32 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -532,23 +532,27 @@ static int sunxi_pconf_group_set(struct - { - struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); - struct sunxi_pinctrl_group *g = &pctl->groups[group]; -- unsigned long flags; - unsigned pin = g->pin - pctl->desc->pin_base; -- u32 val, mask; -- u16 strength; -- u8 dlevel; - int i; - -- spin_lock_irqsave(&pctl->lock, flags); -- - for (i = 0; i < num_configs; i++) { -- switch (pinconf_to_config_param(configs[i])) { -+ enum pin_config_param param; -+ unsigned long flags; -+ u32 offset, shift, mask, reg; -+ u16 arg, val; -+ int ret; -+ -+ param = pinconf_to_config_param(configs[i]); -+ arg = pinconf_to_config_argument(configs[i]); -+ -+ ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); -+ if (ret < 0) -+ return ret; -+ -+ switch (param) { - case PIN_CONFIG_DRIVE_STRENGTH: -- strength = pinconf_to_config_argument(configs[i]); -- if (strength > 40) { -- spin_unlock_irqrestore(&pctl->lock, flags); -+ if (arg < 10 || arg > 40) - return -EINVAL; -- } - /* - * We convert from mA to what the register expects: - * 0: 10mA -@@ -556,37 +560,33 @@ static int sunxi_pconf_group_set(struct - * 2: 30mA - * 3: 40mA - */ -- dlevel = strength / 10 - 1; -- val = readl(pctl->membase + sunxi_dlevel_reg(pin)); -- mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(pin); -- writel((val & ~mask) -- | dlevel << sunxi_dlevel_offset(pin), -- pctl->membase + sunxi_dlevel_reg(pin)); -+ val = arg / 10 - 1; - break; - case PIN_CONFIG_BIAS_DISABLE: -- val = readl(pctl->membase + sunxi_pull_reg(pin)); -- mask = PULL_PINS_MASK << sunxi_pull_offset(pin); -- writel((val & ~mask), -- pctl->membase + sunxi_pull_reg(pin)); -+ val = 0; - break; - case PIN_CONFIG_BIAS_PULL_UP: -- val = readl(pctl->membase + sunxi_pull_reg(pin)); -- mask = PULL_PINS_MASK << sunxi_pull_offset(pin); -- writel((val & ~mask) | 1 << sunxi_pull_offset(pin), -- pctl->membase + sunxi_pull_reg(pin)); -+ if (arg == 0) -+ return -EINVAL; -+ val = 1; - break; - case PIN_CONFIG_BIAS_PULL_DOWN: -- val = readl(pctl->membase + sunxi_pull_reg(pin)); -- mask = PULL_PINS_MASK << sunxi_pull_offset(pin); -- writel((val & ~mask) | 2 << sunxi_pull_offset(pin), -- pctl->membase + sunxi_pull_reg(pin)); -+ if (arg == 0) -+ return -EINVAL; -+ val = 2; - break; - default: -- break; -+ /* sunxi_pconf_reg should catch anything unsupported */ -+ WARN_ON(1); -+ return -ENOTSUPP; - } -- } /* for each config */ - -- spin_unlock_irqrestore(&pctl->lock, flags); -+ spin_lock_irqsave(&pctl->lock, flags); -+ reg = readl(pctl->membase + offset); -+ reg &= ~(mask << shift); -+ writel(reg | val << shift, pctl->membase + offset); -+ spin_unlock_irqrestore(&pctl->lock, flags); -+ } /* for each config */ - - return 0; - } diff --git a/target/linux/sunxi/patches-4.9/0040-pinctrl-sunxi-Add-support-for-interrupt-debouncing.patch b/target/linux/sunxi/patches-4.9/0040-pinctrl-sunxi-Add-support-for-interrupt-debouncing.patch deleted file mode 100644 index 01cbe31bef..0000000000 --- a/target/linux/sunxi/patches-4.9/0040-pinctrl-sunxi-Add-support-for-interrupt-debouncing.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 7c926492d38a3feef4b4b29c91b7c03eb1b8b546 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 14 Nov 2016 21:53:03 +0100 -Subject: pinctrl: sunxi: Add support for interrupt debouncing - -The pin controller found in the Allwinner SoCs has support for interrupts -debouncing. - -However, this is not done per-pin, preventing us from using the generic -pinconf binding for that, but per irq bank, which, depending on the SoC, -ranges from one to five. - -Introduce a device-wide property to deal with this using a microsecond -resolution. We can re-use the per-pin input-debounce property for that, so -let's do it! - -Signed-off-by: Maxime Ripard -Acked-by: Rob Herring -Signed-off-by: Linus Walleij ---- - .../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 14 ++++ - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 84 ++++++++++++++++++++++ - drivers/pinctrl/sunxi/pinctrl-sunxi.h | 7 ++ - 3 files changed, 105 insertions(+) - ---- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt -+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt -@@ -28,6 +28,20 @@ Required properties: - - reg: Should contain the register physical address and length for the - pin controller. - -+- clocks: phandle to the clocks feeding the pin controller: -+ - "apb": the gated APB parent clock -+ - "hosc": the high frequency oscillator in the system -+ - "losc": the low frequency oscillator in the system -+ -+Note: For backward compatibility reasons, the hosc and losc clocks are only -+required if you need to use the optional input-debounce property. Any new -+device tree should set them. -+ -+Optional properties: -+ - input-debounce: Array of debouncing periods in microseconds. One period per -+ irq bank found in the controller. 0 if no setup required. -+ -+ - Please refer to pinctrl-bindings.txt in this directory for details of the - common pinctrl bindings used by client devices. - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -1122,6 +1122,88 @@ static int sunxi_pinctrl_build_state(str - return 0; - } - -+static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff) -+{ -+ unsigned long clock = clk_get_rate(clk); -+ unsigned int best_diff = ~0, best_div; -+ int i; -+ -+ for (i = 0; i < 8; i++) { -+ int cur_diff = abs(freq - (clock >> i)); -+ -+ if (cur_diff < best_diff) { -+ best_diff = cur_diff; -+ best_div = i; -+ } -+ } -+ -+ *diff = best_diff; -+ return best_div; -+} -+ -+static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl, -+ struct device_node *node) -+{ -+ unsigned int hosc_diff, losc_diff; -+ unsigned int hosc_div, losc_div; -+ struct clk *hosc, *losc; -+ u8 div, src; -+ int i, ret; -+ -+ /* Deal with old DTs that didn't have the oscillators */ -+ if (of_count_phandle_with_args(node, "clocks", "#clock-cells") != 3) -+ return 0; -+ -+ /* If we don't have any setup, bail out */ -+ if (!of_find_property(node, "input-debounce", NULL)) -+ return 0; -+ -+ losc = devm_clk_get(pctl->dev, "losc"); -+ if (IS_ERR(losc)) -+ return PTR_ERR(losc); -+ -+ hosc = devm_clk_get(pctl->dev, "hosc"); -+ if (IS_ERR(hosc)) -+ return PTR_ERR(hosc); -+ -+ for (i = 0; i < pctl->desc->irq_banks; i++) { -+ unsigned long debounce_freq; -+ u32 debounce; -+ -+ ret = of_property_read_u32_index(node, "input-debounce", -+ i, &debounce); -+ if (ret) -+ return ret; -+ -+ if (!debounce) -+ continue; -+ -+ debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC, debounce); -+ losc_div = sunxi_pinctrl_get_debounce_div(losc, -+ debounce_freq, -+ &losc_diff); -+ -+ hosc_div = sunxi_pinctrl_get_debounce_div(hosc, -+ debounce_freq, -+ &hosc_diff); -+ -+ if (hosc_diff < losc_diff) { -+ div = hosc_div; -+ src = 1; -+ } else { -+ div = losc_div; -+ src = 0; -+ } -+ -+ writel(src | div << 4, -+ pctl->membase + -+ sunxi_irq_debounce_reg_from_bank(i, -+ pctl->desc->irq_bank_base)); -+ } -+ -+ return 0; -+} -+ - int sunxi_pinctrl_init(struct platform_device *pdev, - const struct sunxi_pinctrl_desc *desc) - { -@@ -1284,6 +1366,8 @@ int sunxi_pinctrl_init(struct platform_d - pctl); - } - -+ sunxi_pinctrl_setup_debounce(pctl, node); -+ - dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); - - return 0; ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h -@@ -69,6 +69,8 @@ - #define IRQ_STATUS_IRQ_BITS 1 - #define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1) - -+#define IRQ_DEBOUNCE_REG 0x218 -+ - #define IRQ_MEM_SIZE 0x20 - - #define IRQ_EDGE_RISING 0x00 -@@ -265,6 +267,11 @@ static inline u32 sunxi_irq_ctrl_offset( - return irq_num * IRQ_CTRL_IRQ_BITS; - } - -+static inline u32 sunxi_irq_debounce_reg_from_bank(u8 bank, unsigned bank_base) -+{ -+ return IRQ_DEBOUNCE_REG + (bank_base + bank) * IRQ_MEM_SIZE; -+} -+ - static inline u32 sunxi_irq_status_reg_from_bank(u8 bank, unsigned bank_base) - { - return IRQ_STATUS_REG + (bank_base + bank) * IRQ_MEM_SIZE; diff --git a/target/linux/sunxi/patches-4.9/0041-pinctrl-sunxi-fix-theoretical-uninitialized-variable.patch b/target/linux/sunxi/patches-4.9/0041-pinctrl-sunxi-fix-theoretical-uninitialized-variable.patch deleted file mode 100644 index 69de015b67..0000000000 --- a/target/linux/sunxi/patches-4.9/0041-pinctrl-sunxi-fix-theoretical-uninitialized-variable.patch +++ /dev/null @@ -1,40 +0,0 @@ -From d8a22212737314cc02692cc90eda7d844fa20257 Mon Sep 17 00:00:00 2001 -From: Arnd Bergmann -Date: Wed, 16 Nov 2016 15:18:18 +0100 -Subject: pinctrl: sunxi: fix theoretical uninitialized variable access - -gcc warns about a way that it could use an uninitialized variable: - -drivers/pinctrl/sunxi/pinctrl-sunxi.c: In function 'sunxi_pinctrl_init': -drivers/pinctrl/sunxi/pinctrl-sunxi.c:1191:8: error: 'best_div' may be used uninitialized in this function [-Werror=maybe-uninitialized] - -This cannot really happen except if 'freq' is UINT_MAX and 'clock' is -zero, and both of these are forbidden. To shut up the warning anyway, -this changes the logic to initialize the return code to the first -divider value before looking at the others. - -Fixes: 7c926492d38a ("pinctrl: sunxi: Add support for interrupt debouncing") -Signed-off-by: Arnd Bergmann -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -1125,10 +1125,13 @@ static int sunxi_pinctrl_build_state(str - static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff) - { - unsigned long clock = clk_get_rate(clk); -- unsigned int best_diff = ~0, best_div; -+ unsigned int best_diff, best_div; - int i; - -- for (i = 0; i < 8; i++) { -+ best_diff = abs(freq - clock); -+ best_div = 0; -+ -+ for (i = 1; i < 8; i++) { - int cur_diff = abs(freq - (clock >> i)); - - if (cur_diff < best_diff) { diff --git a/target/linux/sunxi/patches-4.9/0042-pinctrl-sunxi-Testing-the-wrong-variable.patch b/target/linux/sunxi/patches-4.9/0042-pinctrl-sunxi-Testing-the-wrong-variable.patch deleted file mode 100644 index 8ed4f27b4c..0000000000 --- a/target/linux/sunxi/patches-4.9/0042-pinctrl-sunxi-Testing-the-wrong-variable.patch +++ /dev/null @@ -1,35 +0,0 @@ -From b3cde198b17f504643cc1eeffc4623f03326f436 Mon Sep 17 00:00:00 2001 -From: Dan Carpenter -Date: Fri, 18 Nov 2016 14:35:57 +0300 -Subject: pinctrl: sunxi: Testing the wrong variable - -Smatch complains that we dereference "map" before testing it for NULL -which is true. We should be testing "*map" instead. Also on the error -path, we should free *map and set it to NULL. - -Signed-off-by: Dan Carpenter -Acked-by: Maxime Ripard -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -398,13 +398,14 @@ static int sunxi_pctrl_dt_node_to_map(st - * map array - */ - *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); -- if (!map) -+ if (!*map) - return -ENOMEM; - - return 0; - - err_free_map: -- kfree(map); -+ kfree(*map); -+ *map = NULL; - return ret; - } - diff --git a/target/linux/sunxi/patches-4.9/0043-pinctrl-sunxi-Don-t-enforce-bias-disable-for-now.patch b/target/linux/sunxi/patches-4.9/0043-pinctrl-sunxi-Don-t-enforce-bias-disable-for-now.patch deleted file mode 100644 index d6e639af52..0000000000 --- a/target/linux/sunxi/patches-4.9/0043-pinctrl-sunxi-Don-t-enforce-bias-disable-for-now.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 2154d94b40ea2a5de05245521371d0461bb0d669 Mon Sep 17 00:00:00 2001 -From: Maxime Ripard -Date: Mon, 23 Jan 2017 09:21:30 +0100 -Subject: pinctrl: sunxi: Don't enforce bias disable (for now) - -Commit 07fe64ba213f ("pinctrl: sunxi: Handle bias disable") actually -enforced enforced the disabling of the pull up/down resistors instead of -ignoring it like it was done before. - -This was part of a wider rework to switch to the generic pinconf bindings, -and was meant to be merged together with DT patches that were switching to -it, and removing what was considered default values by both the binding and -the boards. This included no bias on a pin. - -However, those DT patches were delayed to 4.11, which would be fine only -for a significant number boards having the bias setup wrong, which in turns -break the MMC on those boards (and possibly other devices too). - -In order to avoid conflicts as much as possible, bring back the old -behaviour for 4.10, and we'll revert that commit once all the DT bits will -have landed. - -Tested-by: Priit Laes -Signed-off-by: Maxime Ripard -Acked-by: Chen-Yu Tsai -Signed-off-by: Linus Walleij ---- - drivers/pinctrl/sunxi/pinctrl-sunxi.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c -+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c -@@ -564,8 +564,7 @@ static int sunxi_pconf_group_set(struct - val = arg / 10 - 1; - break; - case PIN_CONFIG_BIAS_DISABLE: -- val = 0; -- break; -+ continue; - case PIN_CONFIG_BIAS_PULL_UP: - if (arg == 0) - return -EINVAL; diff --git a/target/linux/sunxi/patches-4.9/0045-arm-dts-sun8i-add-common-dtsi-file-for-nanopi-SBCs.patch b/target/linux/sunxi/patches-4.9/0045-arm-dts-sun8i-add-common-dtsi-file-for-nanopi-SBCs.patch deleted file mode 100644 index c304f7937f..0000000000 --- a/target/linux/sunxi/patches-4.9/0045-arm-dts-sun8i-add-common-dtsi-file-for-nanopi-SBCs.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 49f01c9e14b3476cbdf9623c4812c43f6485830b Mon Sep 17 00:00:00 2001 -From: Milo Kim -Date: Fri, 28 Oct 2016 15:59:01 +0900 -Subject: ARM: dts: sun8i: Add common dtsi file for NanoPi SBCs - -(backported from kernel 4.13) - -This patch provides a common file for NanoPi M1 and Neo SBC. - -Those have common features below. - * UART0 - * 2 LEDs - * USB host (EHCI3, OHCI3) and PHY - * MicroSD - * GPIO key switch - -Cc: James Pettigrew -Signed-off-by: Milo Kim -Signed-off-by: Maxime Ripard - ---- /dev/null -+++ b/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi -@@ -0,0 +1,137 @@ -+/* -+ * Copyright (C) 2016 James Pettigrew -+ * Copyright (C) 2016 Milo Kim -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "sun8i-h3.dtsi" -+#include "sunxi-common-regulators.dtsi" -+ -+#include -+#include -+ -+/ { -+ aliases { -+ serial0 = &uart0; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&leds_npi>, <&leds_r_npi>; -+ -+ status { -+ label = "nanopi:blue:status"; -+ gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "heartbeat"; -+ }; -+ -+ pwr { -+ label = "nanopi:green:pwr"; -+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ }; -+ -+ r_gpio_keys { -+ compatible = "gpio-keys"; -+ input-name = "k1"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&sw_r_npi>; -+ -+ k1@0 { -+ label = "k1"; -+ linux,code = ; -+ gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; -+ -+&ehci3 { -+ status = "okay"; -+}; -+ -+&mmc0 { -+ bus-width = <4>; -+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; -+ cd-inverted; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; -+ status = "okay"; -+ vmmc-supply = <®_vcc3v3>; -+}; -+ -+&ohci3 { -+ status = "okay"; -+}; -+ -+&pio { -+ leds_npi: led_pins@0 { -+ pins = "PA10"; -+ function = "gpio_out"; -+ }; -+}; -+ -+&r_pio { -+ leds_r_npi: led_pins@0 { -+ pins = "PL10"; -+ function = "gpio_out"; -+ }; -+ -+ sw_r_npi: key_pins@0 { -+ pins = "PL3"; -+ function = "gpio_in"; -+ }; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins_a>; -+ status = "okay"; -+}; -+ -+&usbphy { -+ status = "okay"; -+}; diff --git a/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch b/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch deleted file mode 100644 index 22d62f0960..0000000000 --- a/target/linux/sunxi/patches-4.9/0050-stmmac-form-4-10.patch +++ /dev/null @@ -1,3497 +0,0 @@ ---- a/Documentation/devicetree/bindings/net/stmmac.txt -+++ b/Documentation/devicetree/bindings/net/stmmac.txt -@@ -1,7 +1,7 @@ - * STMicroelectronics 10/100/1000 Ethernet driver (GMAC) - - Required properties: --- compatible: Should be "snps,dwmac-" "snps,dwmac" -+- compatible: Should be "snps,dwmac-", "snps,dwmac" - For backwards compatibility: "st,spear600-gmac" is also supported. - - reg: Address and length of the register set for the device - - interrupt-parent: Should be the phandle for the interrupt controller -@@ -34,7 +34,13 @@ Optional properties: - platforms. - - tx-fifo-depth: See ethernet.txt file in the same directory - - rx-fifo-depth: See ethernet.txt file in the same directory --- snps,pbl Programmable Burst Length -+- snps,pbl Programmable Burst Length (tx and rx) -+- snps,txpbl Tx Programmable Burst Length. Only for GMAC and newer. -+ If set, DMA tx will use this value rather than snps,pbl. -+- snps,rxpbl Rx Programmable Burst Length. Only for GMAC and newer. -+ If set, DMA rx will use this value rather than snps,pbl. -+- snps,no-pbl-x8 Don't multiply the pbl/txpbl/rxpbl values by 8. -+ For core rev < 3.50, don't multiply the values by 4. - - snps,aal Address-Aligned Beats - - snps,fixed-burst Program the DMA to use the fixed burst mode - - snps,mixed-burst Program the DMA to use the mixed burst mode -@@ -50,6 +56,8 @@ Optional properties: - - snps,ps-speed: port selection speed that can be passed to the core when - PCS is supported. For example, this is used in case of SGMII - and MAC2MAC connection. -+- snps,tso: this enables the TSO feature otherwise it will be managed by -+ MAC HW capability register. Only for GMAC4 and newer. - - AXI BUS Mode parameters: below the list of all the parameters to program the - AXI register inside the DMA module: - - snps,lpi_en: enable Low Power Interface -@@ -62,8 +70,6 @@ Optional properties: - - snps,fb: fixed-burst - - snps,mb: mixed-burst - - snps,rb: rebuild INCRx Burst -- - snps,tso: this enables the TSO feature otherwise it will be managed by -- MAC HW capability register. - - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus. - - Examples: ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -69,6 +69,17 @@ config DWMAC_MESON - the stmmac device driver. This driver is used for Meson6, - Meson8, Meson8b and GXBB SoCs. - -+config DWMAC_OXNAS -+ tristate "Oxford Semiconductor OXNAS dwmac support" -+ default ARCH_OXNAS -+ depends on OF && COMMON_CLK && (ARCH_OXNAS || COMPILE_TEST) -+ select MFD_SYSCON -+ help -+ Support for Ethernet controller on Oxford Semiconductor OXNAS SoCs. -+ -+ This selects the Oxford Semiconductor OXNASSoC glue layer support for -+ the stmmac device driver. This driver is used for OX820. -+ - config DWMAC_ROCKCHIP - tristate "Rockchip dwmac support" - default ARCH_ROCKCHIP ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac- - obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o - obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o - obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o -+obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o - obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o - obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o - obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o ---- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -@@ -34,7 +34,7 @@ static int stmmac_jumbo_frm(void *p, str - unsigned int entry = priv->cur_tx; - struct dma_desc *desc = priv->dma_tx + entry; - unsigned int nopaged_len = skb_headlen(skb); -- unsigned int bmax; -+ unsigned int bmax, des2; - unsigned int i = 1, len; - - if (priv->plat->enh_desc) -@@ -44,11 +44,12 @@ static int stmmac_jumbo_frm(void *p, str - - len = nopaged_len - bmax; - -- desc->des2 = dma_map_single(priv->device, skb->data, -- bmax, DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, skb->data, -+ bmax, DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = bmax; - /* do not close the descriptor and do not set own bit */ - priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE, -@@ -60,12 +61,13 @@ static int stmmac_jumbo_frm(void *p, str - desc = priv->dma_tx + entry; - - if (len > bmax) { -- desc->des2 = dma_map_single(priv->device, -- (skb->data + bmax * i), -- bmax, DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, -+ (skb->data + bmax * i), -+ bmax, DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = bmax; - priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum, - STMMAC_CHAIN_MODE, 1, -@@ -73,12 +75,13 @@ static int stmmac_jumbo_frm(void *p, str - len -= bmax; - i++; - } else { -- desc->des2 = dma_map_single(priv->device, -- (skb->data + bmax * i), len, -- DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, -+ (skb->data + bmax * i), len, -+ DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = len; - /* last descriptor can be set now */ - priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, -@@ -119,19 +122,19 @@ static void stmmac_init_dma_chain(void * - struct dma_extended_desc *p = (struct dma_extended_desc *)des; - for (i = 0; i < (size - 1); i++) { - dma_phy += sizeof(struct dma_extended_desc); -- p->basic.des3 = (unsigned int)dma_phy; -+ p->basic.des3 = cpu_to_le32((unsigned int)dma_phy); - p++; - } -- p->basic.des3 = (unsigned int)phy_addr; -+ p->basic.des3 = cpu_to_le32((unsigned int)phy_addr); - - } else { - struct dma_desc *p = (struct dma_desc *)des; - for (i = 0; i < (size - 1); i++) { - dma_phy += sizeof(struct dma_desc); -- p->des3 = (unsigned int)dma_phy; -+ p->des3 = cpu_to_le32((unsigned int)dma_phy); - p++; - } -- p->des3 = (unsigned int)phy_addr; -+ p->des3 = cpu_to_le32((unsigned int)phy_addr); - } - } - -@@ -144,10 +147,10 @@ static void stmmac_refill_desc3(void *pr - * 1588-2002 time stamping is enabled, hence reinitialize it - * to keep explicit chaining in the descriptor. - */ -- p->des3 = (unsigned int)(priv->dma_rx_phy + -- (((priv->dirty_rx) + 1) % -- DMA_RX_SIZE) * -- sizeof(struct dma_desc)); -+ p->des3 = cpu_to_le32((unsigned int)(priv->dma_rx_phy + -+ (((priv->dirty_rx) + 1) % -+ DMA_RX_SIZE) * -+ sizeof(struct dma_desc))); - } - - static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) -@@ -161,9 +164,9 @@ static void stmmac_clean_desc3(void *pri - * 1588-2002 time stamping is enabled, hence reinitialize it - * to keep explicit chaining in the descriptor. - */ -- p->des3 = (unsigned int)((priv->dma_tx_phy + -- ((priv->dirty_tx + 1) % DMA_TX_SIZE)) -- * sizeof(struct dma_desc)); -+ p->des3 = cpu_to_le32((unsigned int)((priv->dma_tx_phy + -+ ((priv->dirty_tx + 1) % DMA_TX_SIZE)) -+ * sizeof(struct dma_desc))); - } - - const struct stmmac_mode_ops chain_mode_ops = { ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -44,6 +44,7 @@ - #define DWMAC_CORE_4_00 0x40 - #define STMMAC_CHAN0 0 /* Always supported and default for all chips */ - -+/* These need to be power of two, and >= 4 */ - #define DMA_TX_SIZE 512 - #define DMA_RX_SIZE 512 - #define STMMAC_GET_ENTRY(x, size) ((x + 1) & (size - 1)) -@@ -411,8 +412,8 @@ extern const struct stmmac_desc_ops ndes - struct stmmac_dma_ops { - /* DMA core initialization */ - int (*reset)(void __iomem *ioaddr); -- void (*init)(void __iomem *ioaddr, int pbl, int fb, int mb, -- int aal, u32 dma_tx, u32 dma_rx, int atds); -+ void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds); - /* Configure the AXI Bus Mode Register */ - void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi); - /* Dump DMA registers */ -@@ -506,6 +507,12 @@ struct mac_link { - struct mii_regs { - unsigned int addr; /* MII Address */ - unsigned int data; /* MII Data */ -+ unsigned int addr_shift; /* MII address shift */ -+ unsigned int reg_shift; /* MII reg shift */ -+ unsigned int addr_mask; /* MII address mask */ -+ unsigned int reg_mask; /* MII reg mask */ -+ unsigned int clk_csr_shift; -+ unsigned int clk_csr_mask; - }; - - /* Helpers to manage the descriptors for chain and ring modes */ ---- a/drivers/net/ethernet/stmicro/stmmac/descs.h -+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h -@@ -87,7 +87,7 @@ - #define TDES0_ERROR_SUMMARY BIT(15) - #define TDES0_IP_HEADER_ERROR BIT(16) - #define TDES0_TIME_STAMP_STATUS BIT(17) --#define TDES0_OWN BIT(31) -+#define TDES0_OWN ((u32)BIT(31)) /* silence sparse */ - /* TDES1 */ - #define TDES1_BUFFER1_SIZE_MASK GENMASK(10, 0) - #define TDES1_BUFFER2_SIZE_MASK GENMASK(21, 11) -@@ -130,7 +130,7 @@ - #define ETDES0_FIRST_SEGMENT BIT(28) - #define ETDES0_LAST_SEGMENT BIT(29) - #define ETDES0_INTERRUPT BIT(30) --#define ETDES0_OWN BIT(31) -+#define ETDES0_OWN ((u32)BIT(31)) /* silence sparse */ - /* TDES1 */ - #define ETDES1_BUFFER1_SIZE_MASK GENMASK(12, 0) - #define ETDES1_BUFFER2_SIZE_MASK GENMASK(28, 16) -@@ -170,19 +170,19 @@ - - /* Basic descriptor structure for normal and alternate descriptors */ - struct dma_desc { -- unsigned int des0; -- unsigned int des1; -- unsigned int des2; -- unsigned int des3; -+ __le32 des0; -+ __le32 des1; -+ __le32 des2; -+ __le32 des3; - }; - - /* Extended descriptor structure (e.g. >= databook 3.50a) */ - struct dma_extended_desc { - struct dma_desc basic; /* Basic descriptors */ -- unsigned int des4; /* Extended Status */ -- unsigned int des5; /* Reserved */ -- unsigned int des6; /* Tx/Rx Timestamp Low */ -- unsigned int des7; /* Tx/Rx Timestamp High */ -+ __le32 des4; /* Extended Status */ -+ __le32 des5; /* Reserved */ -+ __le32 des6; /* Tx/Rx Timestamp Low */ -+ __le32 des7; /* Tx/Rx Timestamp High */ - }; - - /* Transmit checksum insertion control */ ---- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h -+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h -@@ -35,47 +35,50 @@ - /* Enhanced descriptors */ - static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end) - { -- p->des1 |= ((BUF_SIZE_8KiB - 1) << ERDES1_BUFFER2_SIZE_SHIFT) -- & ERDES1_BUFFER2_SIZE_MASK; -+ p->des1 |= cpu_to_le32(((BUF_SIZE_8KiB - 1) -+ << ERDES1_BUFFER2_SIZE_SHIFT) -+ & ERDES1_BUFFER2_SIZE_MASK); - - if (end) -- p->des1 |= ERDES1_END_RING; -+ p->des1 |= cpu_to_le32(ERDES1_END_RING); - } - - static inline void enh_desc_end_tx_desc_on_ring(struct dma_desc *p, int end) - { - if (end) -- p->des0 |= ETDES0_END_RING; -+ p->des0 |= cpu_to_le32(ETDES0_END_RING); - else -- p->des0 &= ~ETDES0_END_RING; -+ p->des0 &= cpu_to_le32(~ETDES0_END_RING); - } - - static inline void enh_set_tx_desc_len_on_ring(struct dma_desc *p, int len) - { - if (unlikely(len > BUF_SIZE_4KiB)) { -- p->des1 |= (((len - BUF_SIZE_4KiB) << ETDES1_BUFFER2_SIZE_SHIFT) -+ p->des1 |= cpu_to_le32((((len - BUF_SIZE_4KiB) -+ << ETDES1_BUFFER2_SIZE_SHIFT) - & ETDES1_BUFFER2_SIZE_MASK) | (BUF_SIZE_4KiB -- & ETDES1_BUFFER1_SIZE_MASK); -+ & ETDES1_BUFFER1_SIZE_MASK)); - } else -- p->des1 |= (len & ETDES1_BUFFER1_SIZE_MASK); -+ p->des1 |= cpu_to_le32((len & ETDES1_BUFFER1_SIZE_MASK)); - } - - /* Normal descriptors */ - static inline void ndesc_rx_set_on_ring(struct dma_desc *p, int end) - { -- p->des1 |= ((BUF_SIZE_2KiB - 1) << RDES1_BUFFER2_SIZE_SHIFT) -- & RDES1_BUFFER2_SIZE_MASK; -+ p->des1 |= cpu_to_le32(((BUF_SIZE_2KiB - 1) -+ << RDES1_BUFFER2_SIZE_SHIFT) -+ & RDES1_BUFFER2_SIZE_MASK); - - if (end) -- p->des1 |= RDES1_END_RING; -+ p->des1 |= cpu_to_le32(RDES1_END_RING); - } - - static inline void ndesc_end_tx_desc_on_ring(struct dma_desc *p, int end) - { - if (end) -- p->des1 |= TDES1_END_RING; -+ p->des1 |= cpu_to_le32(TDES1_END_RING); - else -- p->des1 &= ~TDES1_END_RING; -+ p->des1 &= cpu_to_le32(~TDES1_END_RING); - } - - static inline void norm_set_tx_desc_len_on_ring(struct dma_desc *p, int len) -@@ -83,10 +86,11 @@ static inline void norm_set_tx_desc_len_ - if (unlikely(len > BUF_SIZE_2KiB)) { - unsigned int buffer1 = (BUF_SIZE_2KiB - 1) - & TDES1_BUFFER1_SIZE_MASK; -- p->des1 |= ((((len - buffer1) << TDES1_BUFFER2_SIZE_SHIFT) -- & TDES1_BUFFER2_SIZE_MASK) | buffer1); -+ p->des1 |= cpu_to_le32((((len - buffer1) -+ << TDES1_BUFFER2_SIZE_SHIFT) -+ & TDES1_BUFFER2_SIZE_MASK) | buffer1); - } else -- p->des1 |= (len & TDES1_BUFFER1_SIZE_MASK); -+ p->des1 |= cpu_to_le32((len & TDES1_BUFFER1_SIZE_MASK)); - } - - /* Specific functions used for Chain mode */ -@@ -94,32 +98,32 @@ static inline void norm_set_tx_desc_len_ - /* Enhanced descriptors */ - static inline void ehn_desc_rx_set_on_chain(struct dma_desc *p) - { -- p->des1 |= ERDES1_SECOND_ADDRESS_CHAINED; -+ p->des1 |= cpu_to_le32(ERDES1_SECOND_ADDRESS_CHAINED); - } - - static inline void enh_desc_end_tx_desc_on_chain(struct dma_desc *p) - { -- p->des0 |= ETDES0_SECOND_ADDRESS_CHAINED; -+ p->des0 |= cpu_to_le32(ETDES0_SECOND_ADDRESS_CHAINED); - } - - static inline void enh_set_tx_desc_len_on_chain(struct dma_desc *p, int len) - { -- p->des1 |= (len & ETDES1_BUFFER1_SIZE_MASK); -+ p->des1 |= cpu_to_le32(len & ETDES1_BUFFER1_SIZE_MASK); - } - - /* Normal descriptors */ - static inline void ndesc_rx_set_on_chain(struct dma_desc *p, int end) - { -- p->des1 |= RDES1_SECOND_ADDRESS_CHAINED; -+ p->des1 |= cpu_to_le32(RDES1_SECOND_ADDRESS_CHAINED); - } - - static inline void ndesc_tx_set_on_chain(struct dma_desc *p) - { -- p->des1 |= TDES1_SECOND_ADDRESS_CHAINED; -+ p->des1 |= cpu_to_le32(TDES1_SECOND_ADDRESS_CHAINED); - } - - static inline void norm_set_tx_desc_len_on_chain(struct dma_desc *p, int len) - { -- p->des1 |= len & TDES1_BUFFER1_SIZE_MASK; -+ p->des1 |= cpu_to_le32(len & TDES1_BUFFER1_SIZE_MASK); - } - #endif /* __DESC_COM_H__ */ ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c -@@ -71,9 +71,12 @@ err_remove_config_dt: - - static const struct of_device_id dwmac_generic_match[] = { - { .compatible = "st,spear600-gmac"}, -+ { .compatible = "snps,dwmac-3.50a"}, - { .compatible = "snps,dwmac-3.610"}, - { .compatible = "snps,dwmac-3.70a"}, - { .compatible = "snps,dwmac-3.710"}, -+ { .compatible = "snps,dwmac-4.00"}, -+ { .compatible = "snps,dwmac-4.10a"}, - { .compatible = "snps,dwmac"}, - { } - }; ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-oxnas.c -@@ -0,0 +1,194 @@ -+/* -+ * Oxford Semiconductor OXNAS DWMAC glue layer -+ * -+ * Copyright (C) 2016 Neil Armstrong -+ * Copyright (C) 2014 Daniel Golle -+ * Copyright (C) 2013 Ma Haijun -+ * Copyright (C) 2012 John Crispin -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "stmmac_platform.h" -+ -+/* System Control regmap offsets */ -+#define OXNAS_DWMAC_CTRL_REGOFFSET 0x78 -+#define OXNAS_DWMAC_DELAY_REGOFFSET 0x100 -+ -+/* Control Register */ -+#define DWMAC_CKEN_RX_IN 14 -+#define DWMAC_CKEN_RXN_OUT 13 -+#define DWMAC_CKEN_RX_OUT 12 -+#define DWMAC_CKEN_TX_IN 10 -+#define DWMAC_CKEN_TXN_OUT 9 -+#define DWMAC_CKEN_TX_OUT 8 -+#define DWMAC_RX_SOURCE 7 -+#define DWMAC_TX_SOURCE 6 -+#define DWMAC_LOW_TX_SOURCE 4 -+#define DWMAC_AUTO_TX_SOURCE 3 -+#define DWMAC_RGMII 2 -+#define DWMAC_SIMPLE_MUX 1 -+#define DWMAC_CKEN_GTX 0 -+ -+/* Delay register */ -+#define DWMAC_TX_VARDELAY_SHIFT 0 -+#define DWMAC_TXN_VARDELAY_SHIFT 8 -+#define DWMAC_RX_VARDELAY_SHIFT 16 -+#define DWMAC_RXN_VARDELAY_SHIFT 24 -+#define DWMAC_TX_VARDELAY(d) ((d) << DWMAC_TX_VARDELAY_SHIFT) -+#define DWMAC_TXN_VARDELAY(d) ((d) << DWMAC_TXN_VARDELAY_SHIFT) -+#define DWMAC_RX_VARDELAY(d) ((d) << DWMAC_RX_VARDELAY_SHIFT) -+#define DWMAC_RXN_VARDELAY(d) ((d) << DWMAC_RXN_VARDELAY_SHIFT) -+ -+struct oxnas_dwmac { -+ struct device *dev; -+ struct clk *clk; -+ struct regmap *regmap; -+}; -+ -+static int oxnas_dwmac_init(struct platform_device *pdev, void *priv) -+{ -+ struct oxnas_dwmac *dwmac = priv; -+ unsigned int value; -+ int ret; -+ -+ /* Reset HW here before changing the glue configuration */ -+ ret = device_reset(dwmac->dev); -+ if (ret) -+ return ret; -+ -+ ret = clk_prepare_enable(dwmac->clk); -+ if (ret) -+ return ret; -+ -+ ret = regmap_read(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, &value); -+ if (ret < 0) { -+ clk_disable_unprepare(dwmac->clk); -+ return ret; -+ } -+ -+ /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ -+ value |= BIT(DWMAC_CKEN_GTX) | -+ /* Use simple mux for 25/125 Mhz clock switching */ -+ BIT(DWMAC_SIMPLE_MUX) | -+ /* set auto switch tx clock source */ -+ BIT(DWMAC_AUTO_TX_SOURCE) | -+ /* enable tx & rx vardelay */ -+ BIT(DWMAC_CKEN_TX_OUT) | -+ BIT(DWMAC_CKEN_TXN_OUT) | -+ BIT(DWMAC_CKEN_TX_IN) | -+ BIT(DWMAC_CKEN_RX_OUT) | -+ BIT(DWMAC_CKEN_RXN_OUT) | -+ BIT(DWMAC_CKEN_RX_IN); -+ regmap_write(dwmac->regmap, OXNAS_DWMAC_CTRL_REGOFFSET, value); -+ -+ /* set tx & rx vardelay */ -+ value = DWMAC_TX_VARDELAY(4) | -+ DWMAC_TXN_VARDELAY(2) | -+ DWMAC_RX_VARDELAY(10) | -+ DWMAC_RXN_VARDELAY(8); -+ regmap_write(dwmac->regmap, OXNAS_DWMAC_DELAY_REGOFFSET, value); -+ -+ return 0; -+} -+ -+static void oxnas_dwmac_exit(struct platform_device *pdev, void *priv) -+{ -+ struct oxnas_dwmac *dwmac = priv; -+ -+ clk_disable_unprepare(dwmac->clk); -+} -+ -+static int oxnas_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct oxnas_dwmac *dwmac; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); -+ if (!dwmac) { -+ ret = -ENOMEM; -+ goto err_remove_config_dt; -+ } -+ -+ dwmac->dev = &pdev->dev; -+ plat_dat->bsp_priv = dwmac; -+ plat_dat->init = oxnas_dwmac_init; -+ plat_dat->exit = oxnas_dwmac_exit; -+ -+ dwmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "oxsemi,sys-ctrl"); -+ if (IS_ERR(dwmac->regmap)) { -+ dev_err(&pdev->dev, "failed to have sysctrl regmap\n"); -+ ret = PTR_ERR(dwmac->regmap); -+ goto err_remove_config_dt; -+ } -+ -+ dwmac->clk = devm_clk_get(&pdev->dev, "gmac"); -+ if (IS_ERR(dwmac->clk)) { -+ ret = PTR_ERR(dwmac->clk); -+ goto err_remove_config_dt; -+ } -+ -+ ret = oxnas_dwmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ goto err_remove_config_dt; -+ -+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+ if (ret) -+ goto err_dwmac_exit; -+ -+ -+ return 0; -+ -+err_dwmac_exit: -+ oxnas_dwmac_exit(pdev, plat_dat->bsp_priv); -+err_remove_config_dt: -+ stmmac_remove_config_dt(pdev, plat_dat); -+ -+ return ret; -+} -+ -+static const struct of_device_id oxnas_dwmac_match[] = { -+ { .compatible = "oxsemi,ox820-dwmac" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, oxnas_dwmac_match); -+ -+static struct platform_driver oxnas_dwmac_driver = { -+ .probe = oxnas_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "oxnas-dwmac", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = oxnas_dwmac_match, -+ }, -+}; -+module_platform_driver(oxnas_dwmac_driver); -+ -+MODULE_AUTHOR("Neil Armstrong "); -+MODULE_DESCRIPTION("Oxford Semiconductor OXNAS DWMAC glue layer"); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -864,6 +864,10 @@ static int rk_gmac_powerup(struct rk_pri - int ret; - struct device *dev = &bsp_priv->pdev->dev; - -+ ret = gmac_clk_enable(bsp_priv, true); -+ if (ret) -+ return ret; -+ - /*rmii or rgmii*/ - if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) { - dev_info(dev, "init for RGMII\n"); -@@ -880,10 +884,6 @@ static int rk_gmac_powerup(struct rk_pri - if (ret) - return ret; - -- ret = gmac_clk_enable(bsp_priv, true); -- if (ret) -- return ret; -- - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - -@@ -901,44 +901,6 @@ static void rk_gmac_powerdown(struct rk_ - gmac_clk_enable(gmac, false); - } - --static int rk_gmac_init(struct platform_device *pdev, void *priv) --{ -- struct rk_priv_data *bsp_priv = priv; -- -- return rk_gmac_powerup(bsp_priv); --} -- --static void rk_gmac_exit(struct platform_device *pdev, void *priv) --{ -- struct rk_priv_data *bsp_priv = priv; -- -- rk_gmac_powerdown(bsp_priv); --} -- --static void rk_gmac_suspend(struct platform_device *pdev, void *priv) --{ -- struct rk_priv_data *bsp_priv = priv; -- -- /* Keep the PHY up if we use Wake-on-Lan. */ -- if (device_may_wakeup(&pdev->dev)) -- return; -- -- rk_gmac_powerdown(bsp_priv); -- bsp_priv->suspended = true; --} -- --static void rk_gmac_resume(struct platform_device *pdev, void *priv) --{ -- struct rk_priv_data *bsp_priv = priv; -- -- /* The PHY was up for Wake-on-Lan. */ -- if (!bsp_priv->suspended) -- return; -- -- rk_gmac_powerup(bsp_priv); -- bsp_priv->suspended = false; --} -- - static void rk_fix_speed(void *priv, unsigned int speed) - { - struct rk_priv_data *bsp_priv = priv; -@@ -974,11 +936,7 @@ static int rk_gmac_probe(struct platform - return PTR_ERR(plat_dat); - - plat_dat->has_gmac = true; -- plat_dat->init = rk_gmac_init; -- plat_dat->exit = rk_gmac_exit; - plat_dat->fix_mac_speed = rk_fix_speed; -- plat_dat->suspend = rk_gmac_suspend; -- plat_dat->resume = rk_gmac_resume; - - plat_dat->bsp_priv = rk_gmac_setup(pdev, data); - if (IS_ERR(plat_dat->bsp_priv)) { -@@ -986,24 +944,65 @@ static int rk_gmac_probe(struct platform - goto err_remove_config_dt; - } - -- ret = rk_gmac_init(pdev, plat_dat->bsp_priv); -+ ret = rk_gmac_powerup(plat_dat->bsp_priv); - if (ret) - goto err_remove_config_dt; - - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - if (ret) -- goto err_gmac_exit; -+ goto err_gmac_powerdown; - - return 0; - --err_gmac_exit: -- rk_gmac_exit(pdev, plat_dat->bsp_priv); -+err_gmac_powerdown: -+ rk_gmac_powerdown(plat_dat->bsp_priv); - err_remove_config_dt: - stmmac_remove_config_dt(pdev, plat_dat); - - return ret; - } - -+static int rk_gmac_remove(struct platform_device *pdev) -+{ -+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(&pdev->dev); -+ int ret = stmmac_dvr_remove(&pdev->dev); -+ -+ rk_gmac_powerdown(bsp_priv); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int rk_gmac_suspend(struct device *dev) -+{ -+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev); -+ int ret = stmmac_suspend(dev); -+ -+ /* Keep the PHY up if we use Wake-on-Lan. */ -+ if (!device_may_wakeup(dev)) { -+ rk_gmac_powerdown(bsp_priv); -+ bsp_priv->suspended = true; -+ } -+ -+ return ret; -+} -+ -+static int rk_gmac_resume(struct device *dev) -+{ -+ struct rk_priv_data *bsp_priv = get_stmmac_bsp_priv(dev); -+ -+ /* The PHY was up for Wake-on-Lan. */ -+ if (bsp_priv->suspended) { -+ rk_gmac_powerup(bsp_priv); -+ bsp_priv->suspended = false; -+ } -+ -+ return stmmac_resume(dev); -+} -+#endif /* CONFIG_PM_SLEEP */ -+ -+static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume); -+ - static const struct of_device_id rk_gmac_dwmac_match[] = { - { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, - { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, -@@ -1016,10 +1015,10 @@ MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_ma - - static struct platform_driver rk_gmac_dwmac_driver = { - .probe = rk_gmac_probe, -- .remove = stmmac_pltfr_remove, -+ .remove = rk_gmac_remove, - .driver = { - .name = "rk_gmac-dwmac", -- .pm = &stmmac_pltfr_pm_ops, -+ .pm = &rk_gmac_pm_ops, - .of_match_table = rk_gmac_dwmac_match, - }, - }; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -390,8 +390,8 @@ static int socfpga_dwmac_resume(struct d - * control register 0, and can be modified by the phy driver - * framework. - */ -- if (priv->phydev) -- phy_resume(priv->phydev); -+ if (ndev->phydev) -+ phy_resume(ndev->phydev); - - return stmmac_resume(dev); - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c -@@ -126,8 +126,8 @@ struct sti_dwmac { - struct clk *clk; /* PHY clock */ - u32 ctrl_reg; /* GMAC glue-logic control register */ - int clk_sel_reg; /* GMAC ext clk selection register */ -- struct device *dev; - struct regmap *regmap; -+ bool gmac_en; - u32 speed; - void (*fix_retime_src)(void *priv, unsigned int speed); - }; -@@ -191,7 +191,7 @@ static void stih4xx_fix_retime_src(void - } - } - -- if (src == TX_RETIME_SRC_CLKGEN && dwmac->clk && freq) -+ if (src == TX_RETIME_SRC_CLKGEN && freq) - clk_set_rate(dwmac->clk, freq); - - regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK, -@@ -222,26 +222,20 @@ static void stid127_fix_retime_src(void - freq = DWMAC_2_5MHZ; - } - -- if (dwmac->clk && freq) -+ if (freq) - clk_set_rate(dwmac->clk, freq); - - regmap_update_bits(dwmac->regmap, reg, STID127_RETIME_SRC_MASK, val); - } - --static int sti_dwmac_init(struct platform_device *pdev, void *priv) -+static int sti_dwmac_set_mode(struct sti_dwmac *dwmac) - { -- struct sti_dwmac *dwmac = priv; - struct regmap *regmap = dwmac->regmap; - int iface = dwmac->interface; -- struct device *dev = dwmac->dev; -- struct device_node *np = dev->of_node; - u32 reg = dwmac->ctrl_reg; - u32 val; - -- if (dwmac->clk) -- clk_prepare_enable(dwmac->clk); -- -- if (of_property_read_bool(np, "st,gmac_en")) -+ if (dwmac->gmac_en) - regmap_update_bits(regmap, reg, EN_MASK, EN); - - regmap_update_bits(regmap, reg, MII_PHY_SEL_MASK, phy_intf_sels[iface]); -@@ -249,18 +243,11 @@ static int sti_dwmac_init(struct platfor - val = (iface == PHY_INTERFACE_MODE_REVMII) ? 0 : ENMII; - regmap_update_bits(regmap, reg, ENMII_MASK, val); - -- dwmac->fix_retime_src(priv, dwmac->speed); -+ dwmac->fix_retime_src(dwmac, dwmac->speed); - - return 0; - } - --static void sti_dwmac_exit(struct platform_device *pdev, void *priv) --{ -- struct sti_dwmac *dwmac = priv; -- -- if (dwmac->clk) -- clk_disable_unprepare(dwmac->clk); --} - static int sti_dwmac_parse_data(struct sti_dwmac *dwmac, - struct platform_device *pdev) - { -@@ -270,9 +257,6 @@ static int sti_dwmac_parse_data(struct s - struct regmap *regmap; - int err; - -- if (!np) -- return -EINVAL; -- - /* clk selection from extra syscfg register */ - dwmac->clk_sel_reg = -ENXIO; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sti-clkconf"); -@@ -289,9 +273,9 @@ static int sti_dwmac_parse_data(struct s - return err; - } - -- dwmac->dev = dev; - dwmac->interface = of_get_phy_mode(np); - dwmac->regmap = regmap; -+ dwmac->gmac_en = of_property_read_bool(np, "st,gmac_en"); - dwmac->ext_phyclk = of_property_read_bool(np, "st,ext-phyclk"); - dwmac->tx_retime_src = TX_RETIME_SRC_NA; - dwmac->speed = SPEED_100; -@@ -359,28 +343,65 @@ static int sti_dwmac_probe(struct platfo - dwmac->fix_retime_src = data->fix_retime_src; - - plat_dat->bsp_priv = dwmac; -- plat_dat->init = sti_dwmac_init; -- plat_dat->exit = sti_dwmac_exit; - plat_dat->fix_mac_speed = data->fix_retime_src; - -- ret = sti_dwmac_init(pdev, plat_dat->bsp_priv); -+ ret = clk_prepare_enable(dwmac->clk); - if (ret) - goto err_remove_config_dt; - -+ ret = sti_dwmac_set_mode(dwmac); -+ if (ret) -+ goto disable_clk; -+ - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - if (ret) -- goto err_dwmac_exit; -+ goto disable_clk; - - return 0; - --err_dwmac_exit: -- sti_dwmac_exit(pdev, plat_dat->bsp_priv); -+disable_clk: -+ clk_disable_unprepare(dwmac->clk); - err_remove_config_dt: - stmmac_remove_config_dt(pdev, plat_dat); - - return ret; - } - -+static int sti_dwmac_remove(struct platform_device *pdev) -+{ -+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(&pdev->dev); -+ int ret = stmmac_dvr_remove(&pdev->dev); -+ -+ clk_disable_unprepare(dwmac->clk); -+ -+ return ret; -+} -+ -+#ifdef CONFIG_PM_SLEEP -+static int sti_dwmac_suspend(struct device *dev) -+{ -+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); -+ int ret = stmmac_suspend(dev); -+ -+ clk_disable_unprepare(dwmac->clk); -+ -+ return ret; -+} -+ -+static int sti_dwmac_resume(struct device *dev) -+{ -+ struct sti_dwmac *dwmac = get_stmmac_bsp_priv(dev); -+ -+ clk_prepare_enable(dwmac->clk); -+ sti_dwmac_set_mode(dwmac); -+ -+ return stmmac_resume(dev); -+} -+#endif /* CONFIG_PM_SLEEP */ -+ -+static SIMPLE_DEV_PM_OPS(sti_dwmac_pm_ops, sti_dwmac_suspend, -+ sti_dwmac_resume); -+ - static const struct sti_dwmac_of_data stih4xx_dwmac_data = { - .fix_retime_src = stih4xx_fix_retime_src, - }; -@@ -400,10 +421,10 @@ MODULE_DEVICE_TABLE(of, sti_dwmac_match) - - static struct platform_driver sti_dwmac_driver = { - .probe = sti_dwmac_probe, -- .remove = stmmac_pltfr_remove, -+ .remove = sti_dwmac_remove, - .driver = { - .name = "sti-dwmac", -- .pm = &stmmac_pltfr_pm_ops, -+ .pm = &sti_dwmac_pm_ops, - .of_match_table = sti_dwmac_match, - }, - }; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h -@@ -225,7 +225,7 @@ enum rx_tx_priority_ratio { - - #define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */ - #define DMA_BUS_MODE_MB 0x04000000 /* Mixed burst */ --#define DMA_BUS_MODE_RPBL_MASK 0x003e0000 /* Rx-Programmable Burst Len */ -+#define DMA_BUS_MODE_RPBL_MASK 0x007e0000 /* Rx-Programmable Burst Len */ - #define DMA_BUS_MODE_RPBL_SHIFT 17 - #define DMA_BUS_MODE_USP 0x00800000 - #define DMA_BUS_MODE_MAXPBL 0x01000000 ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -@@ -538,6 +538,12 @@ struct mac_device_info *dwmac1000_setup( - mac->link.speed = GMAC_CONTROL_FES; - mac->mii.addr = GMAC_MII_ADDR; - mac->mii.data = GMAC_MII_DATA; -+ mac->mii.addr_shift = 11; -+ mac->mii.addr_mask = 0x0000F800; -+ mac->mii.reg_shift = 6; -+ mac->mii.reg_mask = 0x000007C0; -+ mac->mii.clk_csr_shift = 2; -+ mac->mii.clk_csr_mask = GENMASK(5, 2); - - /* Get and dump the chip ID */ - *synopsys_id = stmmac_get_synopsys_id(hwid); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -84,37 +84,39 @@ static void dwmac1000_dma_axi(void __iom - writel(value, ioaddr + DMA_AXI_BUS_MODE); - } - --static void dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, -- int aal, u32 dma_tx, u32 dma_rx, int atds) -+static void dwmac1000_dma_init(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds) - { - u32 value = readl(ioaddr + DMA_BUS_MODE); -+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; - - /* - * Set the DMA PBL (Programmable Burst Length) mode. - * - * Note: before stmmac core 3.50 this mode bit was 4xPBL, and - * post 3.5 mode bit acts as 8*PBL. -- * -- * This configuration doesn't take care about the Separate PBL -- * so only the bits: 13-8 are programmed with the PBL passed from the -- * platform. - */ -- value |= DMA_BUS_MODE_MAXPBL; -- value &= ~DMA_BUS_MODE_PBL_MASK; -- value |= (pbl << DMA_BUS_MODE_PBL_SHIFT); -+ if (dma_cfg->pblx8) -+ value |= DMA_BUS_MODE_MAXPBL; -+ value |= DMA_BUS_MODE_USP; -+ value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK); -+ value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT); -+ value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); - - /* Set the Fixed burst mode */ -- if (fb) -+ if (dma_cfg->fixed_burst) - value |= DMA_BUS_MODE_FB; - - /* Mixed Burst has no effect when fb is set */ -- if (mb) -+ if (dma_cfg->mixed_burst) - value |= DMA_BUS_MODE_MB; - - if (atds) - value |= DMA_BUS_MODE_ATDS; - -- if (aal) -+ if (dma_cfg->aal) - value |= DMA_BUS_MODE_AAL; - - writel(value, ioaddr + DMA_BUS_MODE); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -@@ -192,6 +192,13 @@ struct mac_device_info *dwmac100_setup(v - mac->link.speed = 0; - mac->mii.addr = MAC_MII_ADDR; - mac->mii.data = MAC_MII_DATA; -+ mac->mii.addr_shift = 11; -+ mac->mii.addr_mask = 0x0000F800; -+ mac->mii.reg_shift = 6; -+ mac->mii.reg_mask = 0x000007C0; -+ mac->mii.clk_csr_shift = 2; -+ mac->mii.clk_csr_mask = GENMASK(5, 2); -+ - /* Synopsys Id is not available on old chips */ - *synopsys_id = 0; - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -@@ -32,11 +32,12 @@ - #include "dwmac100.h" - #include "dwmac_dma.h" - --static void dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, -- int aal, u32 dma_tx, u32 dma_rx, int atds) -+static void dwmac100_dma_init(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds) - { - /* Enable Application Access by writing to DMA CSR0 */ -- writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT), -+ writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT), - ioaddr + DMA_BUS_MODE); - - /* Mask interrupts by writing to CSR7 */ ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -@@ -155,8 +155,11 @@ enum power_event { - #define MTL_CHAN_RX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x38) - - #define MTL_OP_MODE_RSF BIT(5) -+#define MTL_OP_MODE_TXQEN BIT(3) - #define MTL_OP_MODE_TSF BIT(1) - -+#define MTL_OP_MODE_TQS_MASK GENMASK(24, 16) -+ - #define MTL_OP_MODE_TTC_MASK 0x70 - #define MTL_OP_MODE_TTC_SHIFT 4 - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -430,6 +430,12 @@ struct mac_device_info *dwmac4_setup(voi - mac->link.speed = GMAC_CONFIG_FES; - mac->mii.addr = GMAC_MDIO_ADDR; - mac->mii.data = GMAC_MDIO_DATA; -+ mac->mii.addr_shift = 21; -+ mac->mii.addr_mask = GENMASK(25, 21); -+ mac->mii.reg_shift = 16; -+ mac->mii.reg_mask = GENMASK(20, 16); -+ mac->mii.clk_csr_shift = 8; -+ mac->mii.clk_csr_mask = GENMASK(11, 8); - - /* Get and dump the chip ID */ - *synopsys_id = stmmac_get_synopsys_id(hwid); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -@@ -23,7 +23,7 @@ static int dwmac4_wrback_get_tx_status(v - unsigned int tdes3; - int ret = tx_done; - -- tdes3 = p->des3; -+ tdes3 = le32_to_cpu(p->des3); - - /* Get tx owner first */ - if (unlikely(tdes3 & TDES3_OWN)) -@@ -77,9 +77,9 @@ static int dwmac4_wrback_get_rx_status(v - struct dma_desc *p) - { - struct net_device_stats *stats = (struct net_device_stats *)data; -- unsigned int rdes1 = p->des1; -- unsigned int rdes2 = p->des2; -- unsigned int rdes3 = p->des3; -+ unsigned int rdes1 = le32_to_cpu(p->des1); -+ unsigned int rdes2 = le32_to_cpu(p->des2); -+ unsigned int rdes3 = le32_to_cpu(p->des3); - int message_type; - int ret = good_frame; - -@@ -176,47 +176,48 @@ static int dwmac4_wrback_get_rx_status(v - - static int dwmac4_rd_get_tx_len(struct dma_desc *p) - { -- return (p->des2 & TDES2_BUFFER1_SIZE_MASK); -+ return (le32_to_cpu(p->des2) & TDES2_BUFFER1_SIZE_MASK); - } - - static int dwmac4_get_tx_owner(struct dma_desc *p) - { -- return (p->des3 & TDES3_OWN) >> TDES3_OWN_SHIFT; -+ return (le32_to_cpu(p->des3) & TDES3_OWN) >> TDES3_OWN_SHIFT; - } - - static void dwmac4_set_tx_owner(struct dma_desc *p) - { -- p->des3 |= TDES3_OWN; -+ p->des3 |= cpu_to_le32(TDES3_OWN); - } - - static void dwmac4_set_rx_owner(struct dma_desc *p) - { -- p->des3 |= RDES3_OWN; -+ p->des3 |= cpu_to_le32(RDES3_OWN); - } - - static int dwmac4_get_tx_ls(struct dma_desc *p) - { -- return (p->des3 & TDES3_LAST_DESCRIPTOR) >> TDES3_LAST_DESCRIPTOR_SHIFT; -+ return (le32_to_cpu(p->des3) & TDES3_LAST_DESCRIPTOR) -+ >> TDES3_LAST_DESCRIPTOR_SHIFT; - } - - static int dwmac4_wrback_get_rx_frame_len(struct dma_desc *p, int rx_coe) - { -- return (p->des3 & RDES3_PACKET_SIZE_MASK); -+ return (le32_to_cpu(p->des3) & RDES3_PACKET_SIZE_MASK); - } - - static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p) - { -- p->des2 |= TDES2_TIMESTAMP_ENABLE; -+ p->des2 |= cpu_to_le32(TDES2_TIMESTAMP_ENABLE); - } - - static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p) - { - /* Context type from W/B descriptor must be zero */ -- if (p->des3 & TDES3_CONTEXT_TYPE) -+ if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE) - return -EINVAL; - - /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */ -- if (p->des3 & TDES3_TIMESTAMP_STATUS) -+ if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS) - return 0; - - return 1; -@@ -227,9 +228,9 @@ static inline u64 dwmac4_get_timestamp(v - struct dma_desc *p = (struct dma_desc *)desc; - u64 ns; - -- ns = p->des0; -+ ns = le32_to_cpu(p->des0); - /* convert high/sec time stamp value to nanosecond */ -- ns += p->des1 * 1000000000ULL; -+ ns += le32_to_cpu(p->des1) * 1000000000ULL; - - return ns; - } -@@ -264,7 +265,7 @@ static int dwmac4_wrback_get_rx_timestam - - /* Get the status from normal w/b descriptor */ - if (likely(p->des3 & TDES3_RS1V)) { -- if (likely(p->des1 & RDES1_TIMESTAMP_AVAILABLE)) { -+ if (likely(le32_to_cpu(p->des1) & RDES1_TIMESTAMP_AVAILABLE)) { - int i = 0; - - /* Check if timestamp is OK from context descriptor */ -@@ -287,10 +288,10 @@ exit: - static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, - int mode, int end) - { -- p->des3 = RDES3_OWN | RDES3_BUFFER1_VALID_ADDR; -+ p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR); - - if (!disable_rx_ic) -- p->des3 |= RDES3_INT_ON_COMPLETION_EN; -+ p->des3 |= cpu_to_le32(RDES3_INT_ON_COMPLETION_EN); - } - - static void dwmac4_rd_init_tx_desc(struct dma_desc *p, int mode, int end) -@@ -305,9 +306,9 @@ static void dwmac4_rd_prepare_tx_desc(st - bool csum_flag, int mode, bool tx_own, - bool ls) - { -- unsigned int tdes3 = p->des3; -+ unsigned int tdes3 = le32_to_cpu(p->des3); - -- p->des2 |= (len & TDES2_BUFFER1_SIZE_MASK); -+ p->des2 |= cpu_to_le32(len & TDES2_BUFFER1_SIZE_MASK); - - if (is_fs) - tdes3 |= TDES3_FIRST_DESCRIPTOR; -@@ -333,9 +334,9 @@ static void dwmac4_rd_prepare_tx_desc(st - * descriptors for the same frame has to be set before, to - * avoid race condition. - */ -- wmb(); -+ dma_wmb(); - -- p->des3 = tdes3; -+ p->des3 = cpu_to_le32(tdes3); - } - - static void dwmac4_rd_prepare_tso_tx_desc(struct dma_desc *p, int is_fs, -@@ -343,14 +344,14 @@ static void dwmac4_rd_prepare_tso_tx_des - bool ls, unsigned int tcphdrlen, - unsigned int tcppayloadlen) - { -- unsigned int tdes3 = p->des3; -+ unsigned int tdes3 = le32_to_cpu(p->des3); - - if (len1) -- p->des2 |= (len1 & TDES2_BUFFER1_SIZE_MASK); -+ p->des2 |= cpu_to_le32((len1 & TDES2_BUFFER1_SIZE_MASK)); - - if (len2) -- p->des2 |= (len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT) -- & TDES2_BUFFER2_SIZE_MASK; -+ p->des2 |= cpu_to_le32((len2 << TDES2_BUFFER2_SIZE_MASK_SHIFT) -+ & TDES2_BUFFER2_SIZE_MASK); - - if (is_fs) { - tdes3 |= TDES3_FIRST_DESCRIPTOR | -@@ -376,9 +377,9 @@ static void dwmac4_rd_prepare_tso_tx_des - * descriptors for the same frame has to be set before, to - * avoid race condition. - */ -- wmb(); -+ dma_wmb(); - -- p->des3 = tdes3; -+ p->des3 = cpu_to_le32(tdes3); - } - - static void dwmac4_release_tx_desc(struct dma_desc *p, int mode) -@@ -389,7 +390,7 @@ static void dwmac4_release_tx_desc(struc - - static void dwmac4_rd_set_tx_ic(struct dma_desc *p) - { -- p->des2 |= TDES2_INTERRUPT_ON_COMPLETION; -+ p->des2 |= cpu_to_le32(TDES2_INTERRUPT_ON_COMPLETION); - } - - static void dwmac4_display_ring(void *head, unsigned int size, bool rx) -@@ -402,7 +403,8 @@ static void dwmac4_display_ring(void *he - for (i = 0; i < size; i++) { - pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(p), -- p->des0, p->des1, p->des2, p->des3); -+ le32_to_cpu(p->des0), le32_to_cpu(p->des1), -+ le32_to_cpu(p->des2), le32_to_cpu(p->des3)); - p++; - } - } -@@ -411,8 +413,8 @@ static void dwmac4_set_mss_ctxt(struct d - { - p->des0 = 0; - p->des1 = 0; -- p->des2 = mss; -- p->des3 = TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV; -+ p->des2 = cpu_to_le32(mss); -+ p->des3 = cpu_to_le32(TDES3_CONTEXT_TYPE | TDES3_CTXT_TCMSSV); - } - - const struct stmmac_desc_ops dwmac4_desc_ops = { ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -@@ -71,25 +71,29 @@ static void dwmac4_dma_axi(void __iomem - writel(value, ioaddr + DMA_SYS_BUS_MODE); - } - --static void dwmac4_dma_init_channel(void __iomem *ioaddr, int pbl, -+static void dwmac4_dma_init_channel(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, - u32 dma_tx_phy, u32 dma_rx_phy, - u32 channel) - { - u32 value; -+ int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -+ int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; - - /* set PBL for each channels. Currently we affect same configuration - * on each channel - */ - value = readl(ioaddr + DMA_CHAN_CONTROL(channel)); -- value = value | DMA_BUS_MODE_PBL; -+ if (dma_cfg->pblx8) -+ value = value | DMA_BUS_MODE_PBL; - writel(value, ioaddr + DMA_CHAN_CONTROL(channel)); - - value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)); -- value = value | (pbl << DMA_BUS_MODE_PBL_SHIFT); -+ value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT); - writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel)); - - value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)); -- value = value | (pbl << DMA_BUS_MODE_RPBL_SHIFT); -+ value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); - writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel)); - - /* Mask interrupts by writing to CSR7 */ -@@ -99,27 +103,28 @@ static void dwmac4_dma_init_channel(void - writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)); - } - --static void dwmac4_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, -- int aal, u32 dma_tx, u32 dma_rx, int atds) -+static void dwmac4_dma_init(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds) - { - u32 value = readl(ioaddr + DMA_SYS_BUS_MODE); - int i; - - /* Set the Fixed burst mode */ -- if (fb) -+ if (dma_cfg->fixed_burst) - value |= DMA_SYS_BUS_FB; - - /* Mixed Burst has no effect when fb is set */ -- if (mb) -+ if (dma_cfg->mixed_burst) - value |= DMA_SYS_BUS_MB; - -- if (aal) -+ if (dma_cfg->aal) - value |= DMA_SYS_BUS_AAL; - - writel(value, ioaddr + DMA_SYS_BUS_MODE); - - for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) -- dwmac4_dma_init_channel(ioaddr, pbl, dma_tx, dma_rx, i); -+ dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i); - } - - static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel) -@@ -215,7 +220,17 @@ static void dwmac4_dma_chan_op_mode(void - else - mtl_tx_op |= MTL_OP_MODE_TTC_512; - } -- -+ /* For an IP with DWC_EQOS_NUM_TXQ == 1, the fields TXQEN and TQS are RO -+ * with reset values: TXQEN on, TQS == DWC_EQOS_TXFIFO_SIZE. -+ * For an IP with DWC_EQOS_NUM_TXQ > 1, the fields TXQEN and TQS are R/W -+ * with reset values: TXQEN off, TQS 256 bytes. -+ * -+ * Write the bits in both cases, since it will have no effect when RO. -+ * For DWC_EQOS_NUM_TXQ > 1, the top bits in MTL_OP_MODE_TQS_MASK might -+ * be RO, however, writing the whole TQS field will result in a value -+ * equal to DWC_EQOS_TXFIFO_SIZE, just like for DWC_EQOS_NUM_TXQ == 1. -+ */ -+ mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK; - writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); - - mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel)); ---- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -@@ -30,7 +30,7 @@ static int enh_desc_get_tx_status(void * - struct dma_desc *p, void __iomem *ioaddr) - { - struct net_device_stats *stats = (struct net_device_stats *)data; -- unsigned int tdes0 = p->des0; -+ unsigned int tdes0 = le32_to_cpu(p->des0); - int ret = tx_done; - - /* Get tx owner first */ -@@ -95,7 +95,7 @@ static int enh_desc_get_tx_status(void * - - static int enh_desc_get_tx_len(struct dma_desc *p) - { -- return (p->des1 & ETDES1_BUFFER1_SIZE_MASK); -+ return (le32_to_cpu(p->des1) & ETDES1_BUFFER1_SIZE_MASK); - } - - static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err) -@@ -134,8 +134,8 @@ static int enh_desc_coe_rdes0(int ipc_er - static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x, - struct dma_extended_desc *p) - { -- unsigned int rdes0 = p->basic.des0; -- unsigned int rdes4 = p->des4; -+ unsigned int rdes0 = le32_to_cpu(p->basic.des0); -+ unsigned int rdes4 = le32_to_cpu(p->des4); - - if (unlikely(rdes0 & ERDES0_RX_MAC_ADDR)) { - int message_type = (rdes4 & ERDES4_MSG_TYPE_MASK) >> 8; -@@ -199,7 +199,7 @@ static int enh_desc_get_rx_status(void * - struct dma_desc *p) - { - struct net_device_stats *stats = (struct net_device_stats *)data; -- unsigned int rdes0 = p->des0; -+ unsigned int rdes0 = le32_to_cpu(p->des0); - int ret = good_frame; - - if (unlikely(rdes0 & RDES0_OWN)) -@@ -265,8 +265,8 @@ static int enh_desc_get_rx_status(void * - static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, - int mode, int end) - { -- p->des0 |= RDES0_OWN; -- p->des1 |= ((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK); -+ p->des0 |= cpu_to_le32(RDES0_OWN); -+ p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK); - - if (mode == STMMAC_CHAIN_MODE) - ehn_desc_rx_set_on_chain(p); -@@ -274,12 +274,12 @@ static void enh_desc_init_rx_desc(struct - ehn_desc_rx_set_on_ring(p, end); - - if (disable_rx_ic) -- p->des1 |= ERDES1_DISABLE_IC; -+ p->des1 |= cpu_to_le32(ERDES1_DISABLE_IC); - } - - static void enh_desc_init_tx_desc(struct dma_desc *p, int mode, int end) - { -- p->des0 &= ~ETDES0_OWN; -+ p->des0 &= cpu_to_le32(~ETDES0_OWN); - if (mode == STMMAC_CHAIN_MODE) - enh_desc_end_tx_desc_on_chain(p); - else -@@ -288,27 +288,27 @@ static void enh_desc_init_tx_desc(struct - - static int enh_desc_get_tx_owner(struct dma_desc *p) - { -- return (p->des0 & ETDES0_OWN) >> 31; -+ return (le32_to_cpu(p->des0) & ETDES0_OWN) >> 31; - } - - static void enh_desc_set_tx_owner(struct dma_desc *p) - { -- p->des0 |= ETDES0_OWN; -+ p->des0 |= cpu_to_le32(ETDES0_OWN); - } - - static void enh_desc_set_rx_owner(struct dma_desc *p) - { -- p->des0 |= RDES0_OWN; -+ p->des0 |= cpu_to_le32(RDES0_OWN); - } - - static int enh_desc_get_tx_ls(struct dma_desc *p) - { -- return (p->des0 & ETDES0_LAST_SEGMENT) >> 29; -+ return (le32_to_cpu(p->des0) & ETDES0_LAST_SEGMENT) >> 29; - } - - static void enh_desc_release_tx_desc(struct dma_desc *p, int mode) - { -- int ter = (p->des0 & ETDES0_END_RING) >> 21; -+ int ter = (le32_to_cpu(p->des0) & ETDES0_END_RING) >> 21; - - memset(p, 0, offsetof(struct dma_desc, des2)); - if (mode == STMMAC_CHAIN_MODE) -@@ -321,7 +321,7 @@ static void enh_desc_prepare_tx_desc(str - bool csum_flag, int mode, bool tx_own, - bool ls) - { -- unsigned int tdes0 = p->des0; -+ unsigned int tdes0 = le32_to_cpu(p->des0); - - if (mode == STMMAC_CHAIN_MODE) - enh_set_tx_desc_len_on_chain(p, len); -@@ -350,14 +350,14 @@ static void enh_desc_prepare_tx_desc(str - * descriptors for the same frame has to be set before, to - * avoid race condition. - */ -- wmb(); -+ dma_wmb(); - -- p->des0 = tdes0; -+ p->des0 = cpu_to_le32(tdes0); - } - - static void enh_desc_set_tx_ic(struct dma_desc *p) - { -- p->des0 |= ETDES0_INTERRUPT; -+ p->des0 |= cpu_to_le32(ETDES0_INTERRUPT); - } - - static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) -@@ -372,18 +372,18 @@ static int enh_desc_get_rx_frame_len(str - if (rx_coe_type == STMMAC_RX_COE_TYPE1) - csum = 2; - -- return (((p->des0 & RDES0_FRAME_LEN_MASK) >> RDES0_FRAME_LEN_SHIFT) - -- csum); -+ return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK) -+ >> RDES0_FRAME_LEN_SHIFT) - csum); - } - - static void enh_desc_enable_tx_timestamp(struct dma_desc *p) - { -- p->des0 |= ETDES0_TIME_STAMP_ENABLE; -+ p->des0 |= cpu_to_le32(ETDES0_TIME_STAMP_ENABLE); - } - - static int enh_desc_get_tx_timestamp_status(struct dma_desc *p) - { -- return (p->des0 & ETDES0_TIME_STAMP_STATUS) >> 17; -+ return (le32_to_cpu(p->des0) & ETDES0_TIME_STAMP_STATUS) >> 17; - } - - static u64 enh_desc_get_timestamp(void *desc, u32 ats) -@@ -392,13 +392,13 @@ static u64 enh_desc_get_timestamp(void * - - if (ats) { - struct dma_extended_desc *p = (struct dma_extended_desc *)desc; -- ns = p->des6; -+ ns = le32_to_cpu(p->des6); - /* convert high/sec time stamp value to nanosecond */ -- ns += p->des7 * 1000000000ULL; -+ ns += le32_to_cpu(p->des7) * 1000000000ULL; - } else { - struct dma_desc *p = (struct dma_desc *)desc; -- ns = p->des2; -- ns += p->des3 * 1000000000ULL; -+ ns = le32_to_cpu(p->des2); -+ ns += le32_to_cpu(p->des3) * 1000000000ULL; - } - - return ns; -@@ -408,10 +408,11 @@ static int enh_desc_get_rx_timestamp_sta - { - if (ats) { - struct dma_extended_desc *p = (struct dma_extended_desc *)desc; -- return (p->basic.des0 & RDES0_IPC_CSUM_ERROR) >> 7; -+ return (le32_to_cpu(p->basic.des0) & RDES0_IPC_CSUM_ERROR) >> 7; - } else { - struct dma_desc *p = (struct dma_desc *)desc; -- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff)) -+ if ((le32_to_cpu(p->des2) == 0xffffffff) && -+ (le32_to_cpu(p->des3) == 0xffffffff)) - /* timestamp is corrupted, hence don't store it */ - return 0; - else ---- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -@@ -30,8 +30,8 @@ static int ndesc_get_tx_status(void *dat - struct dma_desc *p, void __iomem *ioaddr) - { - struct net_device_stats *stats = (struct net_device_stats *)data; -- unsigned int tdes0 = p->des0; -- unsigned int tdes1 = p->des1; -+ unsigned int tdes0 = le32_to_cpu(p->des0); -+ unsigned int tdes1 = le32_to_cpu(p->des1); - int ret = tx_done; - - /* Get tx owner first */ -@@ -77,7 +77,7 @@ static int ndesc_get_tx_status(void *dat - - static int ndesc_get_tx_len(struct dma_desc *p) - { -- return (p->des1 & RDES1_BUFFER1_SIZE_MASK); -+ return (le32_to_cpu(p->des1) & RDES1_BUFFER1_SIZE_MASK); - } - - /* This function verifies if each incoming frame has some errors -@@ -88,7 +88,7 @@ static int ndesc_get_rx_status(void *dat - struct dma_desc *p) - { - int ret = good_frame; -- unsigned int rdes0 = p->des0; -+ unsigned int rdes0 = le32_to_cpu(p->des0); - struct net_device_stats *stats = (struct net_device_stats *)data; - - if (unlikely(rdes0 & RDES0_OWN)) -@@ -141,8 +141,8 @@ static int ndesc_get_rx_status(void *dat - static void ndesc_init_rx_desc(struct dma_desc *p, int disable_rx_ic, int mode, - int end) - { -- p->des0 |= RDES0_OWN; -- p->des1 |= (BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK; -+ p->des0 |= cpu_to_le32(RDES0_OWN); -+ p->des1 |= cpu_to_le32((BUF_SIZE_2KiB - 1) & RDES1_BUFFER1_SIZE_MASK); - - if (mode == STMMAC_CHAIN_MODE) - ndesc_rx_set_on_chain(p, end); -@@ -150,12 +150,12 @@ static void ndesc_init_rx_desc(struct dm - ndesc_rx_set_on_ring(p, end); - - if (disable_rx_ic) -- p->des1 |= RDES1_DISABLE_IC; -+ p->des1 |= cpu_to_le32(RDES1_DISABLE_IC); - } - - static void ndesc_init_tx_desc(struct dma_desc *p, int mode, int end) - { -- p->des0 &= ~TDES0_OWN; -+ p->des0 &= cpu_to_le32(~TDES0_OWN); - if (mode == STMMAC_CHAIN_MODE) - ndesc_tx_set_on_chain(p); - else -@@ -164,27 +164,27 @@ static void ndesc_init_tx_desc(struct dm - - static int ndesc_get_tx_owner(struct dma_desc *p) - { -- return (p->des0 & TDES0_OWN) >> 31; -+ return (le32_to_cpu(p->des0) & TDES0_OWN) >> 31; - } - - static void ndesc_set_tx_owner(struct dma_desc *p) - { -- p->des0 |= TDES0_OWN; -+ p->des0 |= cpu_to_le32(TDES0_OWN); - } - - static void ndesc_set_rx_owner(struct dma_desc *p) - { -- p->des0 |= RDES0_OWN; -+ p->des0 |= cpu_to_le32(RDES0_OWN); - } - - static int ndesc_get_tx_ls(struct dma_desc *p) - { -- return (p->des1 & TDES1_LAST_SEGMENT) >> 30; -+ return (le32_to_cpu(p->des1) & TDES1_LAST_SEGMENT) >> 30; - } - - static void ndesc_release_tx_desc(struct dma_desc *p, int mode) - { -- int ter = (p->des1 & TDES1_END_RING) >> 25; -+ int ter = (le32_to_cpu(p->des1) & TDES1_END_RING) >> 25; - - memset(p, 0, offsetof(struct dma_desc, des2)); - if (mode == STMMAC_CHAIN_MODE) -@@ -197,7 +197,7 @@ static void ndesc_prepare_tx_desc(struct - bool csum_flag, int mode, bool tx_own, - bool ls) - { -- unsigned int tdes1 = p->des1; -+ unsigned int tdes1 = le32_to_cpu(p->des1); - - if (is_fs) - tdes1 |= TDES1_FIRST_SEGMENT; -@@ -212,7 +212,7 @@ static void ndesc_prepare_tx_desc(struct - if (ls) - tdes1 |= TDES1_LAST_SEGMENT; - -- p->des1 = tdes1; -+ p->des1 = cpu_to_le32(tdes1); - - if (mode == STMMAC_CHAIN_MODE) - norm_set_tx_desc_len_on_chain(p, len); -@@ -220,12 +220,12 @@ static void ndesc_prepare_tx_desc(struct - norm_set_tx_desc_len_on_ring(p, len); - - if (tx_own) -- p->des0 |= TDES0_OWN; -+ p->des0 |= cpu_to_le32(TDES0_OWN); - } - - static void ndesc_set_tx_ic(struct dma_desc *p) - { -- p->des1 |= TDES1_INTERRUPT; -+ p->des1 |= cpu_to_le32(TDES1_INTERRUPT); - } - - static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type) -@@ -241,19 +241,20 @@ static int ndesc_get_rx_frame_len(struct - if (rx_coe_type == STMMAC_RX_COE_TYPE1) - csum = 2; - -- return (((p->des0 & RDES0_FRAME_LEN_MASK) >> RDES0_FRAME_LEN_SHIFT) - -+ return (((le32_to_cpu(p->des0) & RDES0_FRAME_LEN_MASK) -+ >> RDES0_FRAME_LEN_SHIFT) - - csum); - - } - - static void ndesc_enable_tx_timestamp(struct dma_desc *p) - { -- p->des1 |= TDES1_TIME_STAMP_ENABLE; -+ p->des1 |= cpu_to_le32(TDES1_TIME_STAMP_ENABLE); - } - - static int ndesc_get_tx_timestamp_status(struct dma_desc *p) - { -- return (p->des0 & TDES0_TIME_STAMP_STATUS) >> 17; -+ return (le32_to_cpu(p->des0) & TDES0_TIME_STAMP_STATUS) >> 17; - } - - static u64 ndesc_get_timestamp(void *desc, u32 ats) -@@ -261,9 +262,9 @@ static u64 ndesc_get_timestamp(void *des - struct dma_desc *p = (struct dma_desc *)desc; - u64 ns; - -- ns = p->des2; -+ ns = le32_to_cpu(p->des2); - /* convert high/sec time stamp value to nanosecond */ -- ns += p->des3 * 1000000000ULL; -+ ns += le32_to_cpu(p->des3) * 1000000000ULL; - - return ns; - } -@@ -272,7 +273,8 @@ static int ndesc_get_rx_timestamp_status - { - struct dma_desc *p = (struct dma_desc *)desc; - -- if ((p->des2 == 0xffffffff) && (p->des3 == 0xffffffff)) -+ if ((le32_to_cpu(p->des2) == 0xffffffff) && -+ (le32_to_cpu(p->des3) == 0xffffffff)) - /* timestamp is corrupted, hence don't store it */ - return 0; - else ---- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -@@ -34,7 +34,7 @@ static int stmmac_jumbo_frm(void *p, str - unsigned int entry = priv->cur_tx; - struct dma_desc *desc; - unsigned int nopaged_len = skb_headlen(skb); -- unsigned int bmax, len; -+ unsigned int bmax, len, des2; - - if (priv->extend_desc) - desc = (struct dma_desc *)(priv->dma_etx + entry); -@@ -50,16 +50,17 @@ static int stmmac_jumbo_frm(void *p, str - - if (nopaged_len > BUF_SIZE_8KiB) { - -- desc->des2 = dma_map_single(priv->device, skb->data, -- bmax, DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, skb->data, bmax, -+ DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; - -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = bmax; - priv->tx_skbuff_dma[entry].is_jumbo = true; - -- desc->des3 = desc->des2 + BUF_SIZE_4KiB; -+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, - STMMAC_RING_MODE, 0, false); - priv->tx_skbuff[entry] = NULL; -@@ -70,26 +71,28 @@ static int stmmac_jumbo_frm(void *p, str - else - desc = priv->dma_tx + entry; - -- desc->des2 = dma_map_single(priv->device, skb->data + bmax, -- len, DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, skb->data + bmax, len, -+ DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = len; - priv->tx_skbuff_dma[entry].is_jumbo = true; - -- desc->des3 = desc->des2 + BUF_SIZE_4KiB; -+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, - STMMAC_RING_MODE, 1, true); - } else { -- desc->des2 = dma_map_single(priv->device, skb->data, -- nopaged_len, DMA_TO_DEVICE); -- if (dma_mapping_error(priv->device, desc->des2)) -+ des2 = dma_map_single(priv->device, skb->data, -+ nopaged_len, DMA_TO_DEVICE); -+ desc->des2 = cpu_to_le32(des2); -+ if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -+ priv->tx_skbuff_dma[entry].buf = des2; - priv->tx_skbuff_dma[entry].len = nopaged_len; - priv->tx_skbuff_dma[entry].is_jumbo = true; -- desc->des3 = desc->des2 + BUF_SIZE_4KiB; -+ desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum, - STMMAC_RING_MODE, 0, true); - } -@@ -115,13 +118,13 @@ static void stmmac_refill_desc3(void *pr - - /* Fill DES3 in case of RING mode */ - if (priv->dma_buf_sz >= BUF_SIZE_8KiB) -- p->des3 = p->des2 + BUF_SIZE_8KiB; -+ p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); - } - - /* In ring mode we need to fill the desc3 because it is used as buffer */ - static void stmmac_init_desc3(struct dma_desc *p) - { -- p->des3 = p->des2 + BUF_SIZE_8KiB; -+ p->des3 = cpu_to_le32(le32_to_cpu(p->des2) + BUF_SIZE_8KiB); - } - - static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -64,7 +64,6 @@ struct stmmac_priv { - dma_addr_t dma_tx_phy; - int tx_coalesce; - int hwts_tx_en; -- spinlock_t tx_lock; - bool tx_path_in_lpi_mode; - struct timer_list txtimer; - bool tso; -@@ -90,7 +89,6 @@ struct stmmac_priv { - struct mac_device_info *hw; - spinlock_t lock; - -- struct phy_device *phydev ____cacheline_aligned_in_smp; - int oldlink; - int speed; - int oldduplex; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -263,7 +263,7 @@ static void stmmac_ethtool_getdrvinfo(st - { - struct stmmac_priv *priv = netdev_priv(dev); - -- if (priv->plat->has_gmac) -+ if (priv->plat->has_gmac || priv->plat->has_gmac4) - strlcpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver)); - else - strlcpy(info->driver, MAC100_ETHTOOL_NAME, -@@ -272,25 +272,26 @@ static void stmmac_ethtool_getdrvinfo(st - strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version)); - } - --static int stmmac_ethtool_getsettings(struct net_device *dev, -- struct ethtool_cmd *cmd) -+static int stmmac_ethtool_get_link_ksettings(struct net_device *dev, -+ struct ethtool_link_ksettings *cmd) - { - struct stmmac_priv *priv = netdev_priv(dev); -- struct phy_device *phy = priv->phydev; -+ struct phy_device *phy = dev->phydev; - int rc; - - if (priv->hw->pcs & STMMAC_PCS_RGMII || - priv->hw->pcs & STMMAC_PCS_SGMII) { - struct rgmii_adv adv; -+ u32 supported, advertising, lp_advertising; - - if (!priv->xstats.pcs_link) { -- ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN); -- cmd->duplex = DUPLEX_UNKNOWN; -+ cmd->base.speed = SPEED_UNKNOWN; -+ cmd->base.duplex = DUPLEX_UNKNOWN; - return 0; - } -- cmd->duplex = priv->xstats.pcs_duplex; -+ cmd->base.duplex = priv->xstats.pcs_duplex; - -- ethtool_cmd_speed_set(cmd, priv->xstats.pcs_speed); -+ cmd->base.speed = priv->xstats.pcs_speed; - - /* Get and convert ADV/LP_ADV from the HW AN registers */ - if (!priv->hw->mac->pcs_get_adv_lp) -@@ -300,45 +301,59 @@ static int stmmac_ethtool_getsettings(st - - /* Encoding of PSE bits is defined in 802.3z, 37.2.1.4 */ - -+ ethtool_convert_link_mode_to_legacy_u32( -+ &supported, cmd->link_modes.supported); -+ ethtool_convert_link_mode_to_legacy_u32( -+ &advertising, cmd->link_modes.advertising); -+ ethtool_convert_link_mode_to_legacy_u32( -+ &lp_advertising, cmd->link_modes.lp_advertising); -+ - if (adv.pause & STMMAC_PCS_PAUSE) -- cmd->advertising |= ADVERTISED_Pause; -+ advertising |= ADVERTISED_Pause; - if (adv.pause & STMMAC_PCS_ASYM_PAUSE) -- cmd->advertising |= ADVERTISED_Asym_Pause; -+ advertising |= ADVERTISED_Asym_Pause; - if (adv.lp_pause & STMMAC_PCS_PAUSE) -- cmd->lp_advertising |= ADVERTISED_Pause; -+ lp_advertising |= ADVERTISED_Pause; - if (adv.lp_pause & STMMAC_PCS_ASYM_PAUSE) -- cmd->lp_advertising |= ADVERTISED_Asym_Pause; -+ lp_advertising |= ADVERTISED_Asym_Pause; - - /* Reg49[3] always set because ANE is always supported */ -- cmd->autoneg = ADVERTISED_Autoneg; -- cmd->supported |= SUPPORTED_Autoneg; -- cmd->advertising |= ADVERTISED_Autoneg; -- cmd->lp_advertising |= ADVERTISED_Autoneg; -+ cmd->base.autoneg = ADVERTISED_Autoneg; -+ supported |= SUPPORTED_Autoneg; -+ advertising |= ADVERTISED_Autoneg; -+ lp_advertising |= ADVERTISED_Autoneg; - - if (adv.duplex) { -- cmd->supported |= (SUPPORTED_1000baseT_Full | -- SUPPORTED_100baseT_Full | -- SUPPORTED_10baseT_Full); -- cmd->advertising |= (ADVERTISED_1000baseT_Full | -- ADVERTISED_100baseT_Full | -- ADVERTISED_10baseT_Full); -+ supported |= (SUPPORTED_1000baseT_Full | -+ SUPPORTED_100baseT_Full | -+ SUPPORTED_10baseT_Full); -+ advertising |= (ADVERTISED_1000baseT_Full | -+ ADVERTISED_100baseT_Full | -+ ADVERTISED_10baseT_Full); - } else { -- cmd->supported |= (SUPPORTED_1000baseT_Half | -- SUPPORTED_100baseT_Half | -- SUPPORTED_10baseT_Half); -- cmd->advertising |= (ADVERTISED_1000baseT_Half | -- ADVERTISED_100baseT_Half | -- ADVERTISED_10baseT_Half); -+ supported |= (SUPPORTED_1000baseT_Half | -+ SUPPORTED_100baseT_Half | -+ SUPPORTED_10baseT_Half); -+ advertising |= (ADVERTISED_1000baseT_Half | -+ ADVERTISED_100baseT_Half | -+ ADVERTISED_10baseT_Half); - } - if (adv.lp_duplex) -- cmd->lp_advertising |= (ADVERTISED_1000baseT_Full | -- ADVERTISED_100baseT_Full | -- ADVERTISED_10baseT_Full); -+ lp_advertising |= (ADVERTISED_1000baseT_Full | -+ ADVERTISED_100baseT_Full | -+ ADVERTISED_10baseT_Full); - else -- cmd->lp_advertising |= (ADVERTISED_1000baseT_Half | -- ADVERTISED_100baseT_Half | -- ADVERTISED_10baseT_Half); -- cmd->port = PORT_OTHER; -+ lp_advertising |= (ADVERTISED_1000baseT_Half | -+ ADVERTISED_100baseT_Half | -+ ADVERTISED_10baseT_Half); -+ cmd->base.port = PORT_OTHER; -+ -+ ethtool_convert_legacy_u32_to_link_mode( -+ cmd->link_modes.supported, supported); -+ ethtool_convert_legacy_u32_to_link_mode( -+ cmd->link_modes.advertising, advertising); -+ ethtool_convert_legacy_u32_to_link_mode( -+ cmd->link_modes.lp_advertising, lp_advertising); - - return 0; - } -@@ -353,16 +368,16 @@ static int stmmac_ethtool_getsettings(st - "link speed / duplex setting\n", dev->name); - return -EBUSY; - } -- cmd->transceiver = XCVR_INTERNAL; -- rc = phy_ethtool_gset(phy, cmd); -+ rc = phy_ethtool_ksettings_get(phy, cmd); - return rc; - } - --static int stmmac_ethtool_setsettings(struct net_device *dev, -- struct ethtool_cmd *cmd) -+static int -+stmmac_ethtool_set_link_ksettings(struct net_device *dev, -+ const struct ethtool_link_ksettings *cmd) - { - struct stmmac_priv *priv = netdev_priv(dev); -- struct phy_device *phy = priv->phydev; -+ struct phy_device *phy = dev->phydev; - int rc; - - if (priv->hw->pcs & STMMAC_PCS_RGMII || -@@ -370,7 +385,7 @@ static int stmmac_ethtool_setsettings(st - u32 mask = ADVERTISED_Autoneg | ADVERTISED_Pause; - - /* Only support ANE */ -- if (cmd->autoneg != AUTONEG_ENABLE) -+ if (cmd->base.autoneg != AUTONEG_ENABLE) - return -EINVAL; - - mask &= (ADVERTISED_1000baseT_Half | -@@ -391,9 +406,7 @@ static int stmmac_ethtool_setsettings(st - return 0; - } - -- spin_lock(&priv->lock); -- rc = phy_ethtool_sset(phy, cmd); -- spin_unlock(&priv->lock); -+ rc = phy_ethtool_ksettings_set(phy, cmd); - - return rc; - } -@@ -433,7 +446,7 @@ static void stmmac_ethtool_gregs(struct - - memset(reg_space, 0x0, REG_SPACE_SIZE); - -- if (!priv->plat->has_gmac) { -+ if (!(priv->plat->has_gmac || priv->plat->has_gmac4)) { - /* MAC registers */ - for (i = 0; i < 12; i++) - reg_space[i] = readl(priv->ioaddr + (i * 4)); -@@ -471,12 +484,12 @@ stmmac_get_pauseparam(struct net_device - if (!adv_lp.pause) - return; - } else { -- if (!(priv->phydev->supported & SUPPORTED_Pause) || -- !(priv->phydev->supported & SUPPORTED_Asym_Pause)) -+ if (!(netdev->phydev->supported & SUPPORTED_Pause) || -+ !(netdev->phydev->supported & SUPPORTED_Asym_Pause)) - return; - } - -- pause->autoneg = priv->phydev->autoneg; -+ pause->autoneg = netdev->phydev->autoneg; - - if (priv->flow_ctrl & FLOW_RX) - pause->rx_pause = 1; -@@ -490,7 +503,7 @@ stmmac_set_pauseparam(struct net_device - struct ethtool_pauseparam *pause) - { - struct stmmac_priv *priv = netdev_priv(netdev); -- struct phy_device *phy = priv->phydev; -+ struct phy_device *phy = netdev->phydev; - int new_pause = FLOW_OFF; - - if (priv->hw->pcs && priv->hw->mac->pcs_get_adv_lp) { -@@ -550,7 +563,7 @@ static void stmmac_get_ethtool_stats(str - } - } - if (priv->eee_enabled) { -- int val = phy_get_eee_err(priv->phydev); -+ int val = phy_get_eee_err(dev->phydev); - if (val) - priv->xstats.phy_eee_wakeup_error_n = val; - } -@@ -669,7 +682,7 @@ static int stmmac_ethtool_op_get_eee(str - edata->eee_active = priv->eee_active; - edata->tx_lpi_timer = priv->tx_lpi_timer; - -- return phy_ethtool_get_eee(priv->phydev, edata); -+ return phy_ethtool_get_eee(dev->phydev, edata); - } - - static int stmmac_ethtool_op_set_eee(struct net_device *dev, -@@ -694,7 +707,7 @@ static int stmmac_ethtool_op_set_eee(str - priv->tx_lpi_timer = edata->tx_lpi_timer; - } - -- return phy_ethtool_set_eee(priv->phydev, edata); -+ return phy_ethtool_set_eee(dev->phydev, edata); - } - - static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) -@@ -853,8 +866,6 @@ static int stmmac_set_tunable(struct net - static const struct ethtool_ops stmmac_ethtool_ops = { - .begin = stmmac_check_if_running, - .get_drvinfo = stmmac_ethtool_getdrvinfo, -- .get_settings = stmmac_ethtool_getsettings, -- .set_settings = stmmac_ethtool_setsettings, - .get_msglevel = stmmac_ethtool_getmsglevel, - .set_msglevel = stmmac_ethtool_setmsglevel, - .get_regs = stmmac_ethtool_gregs, -@@ -874,6 +885,8 @@ static const struct ethtool_ops stmmac_e - .set_coalesce = stmmac_set_coalesce, - .get_tunable = stmmac_get_tunable, - .set_tunable = stmmac_set_tunable, -+ .get_link_ksettings = stmmac_ethtool_get_link_ksettings, -+ .set_link_ksettings = stmmac_ethtool_set_link_ksettings, - }; - - void stmmac_set_ethtool_ops(struct net_device *netdev) ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -105,8 +105,8 @@ module_param(eee_timer, int, S_IRUGO | S - MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); - #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) - --/* By default the driver will use the ring mode to manage tx and rx descriptors -- * but passing this value so user can force to use the chain instead of the ring -+/* By default the driver will use the ring mode to manage tx and rx descriptors, -+ * but allow user to force to use the chain instead of the ring - */ - static unsigned int chain_mode; - module_param(chain_mode, int, S_IRUGO); -@@ -221,7 +221,8 @@ static inline u32 stmmac_rx_dirty(struct - */ - static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) - { -- struct phy_device *phydev = priv->phydev; -+ struct net_device *ndev = priv->dev; -+ struct phy_device *phydev = ndev->phydev; - - if (likely(priv->plat->fix_mac_speed)) - priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); -@@ -279,6 +280,7 @@ static void stmmac_eee_ctrl_timer(unsign - */ - bool stmmac_eee_init(struct stmmac_priv *priv) - { -+ struct net_device *ndev = priv->dev; - unsigned long flags; - int interface = priv->plat->interface; - bool ret = false; -@@ -301,7 +303,7 @@ bool stmmac_eee_init(struct stmmac_priv - int tx_lpi_timer = priv->tx_lpi_timer; - - /* Check if the PHY supports EEE */ -- if (phy_init_eee(priv->phydev, 1)) { -+ if (phy_init_eee(ndev->phydev, 1)) { - /* To manage at run-time if the EEE cannot be supported - * anymore (for example because the lp caps have been - * changed). -@@ -309,7 +311,7 @@ bool stmmac_eee_init(struct stmmac_priv - */ - spin_lock_irqsave(&priv->lock, flags); - if (priv->eee_active) { -- pr_debug("stmmac: disable EEE\n"); -+ netdev_dbg(priv->dev, "disable EEE\n"); - del_timer_sync(&priv->eee_ctrl_timer); - priv->hw->mac->set_eee_timer(priv->hw, 0, - tx_lpi_timer); -@@ -333,12 +335,12 @@ bool stmmac_eee_init(struct stmmac_priv - tx_lpi_timer); - } - /* Set HW EEE according to the speed */ -- priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link); -+ priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link); - - ret = true; - spin_unlock_irqrestore(&priv->lock, flags); - -- pr_debug("stmmac: Energy-Efficient Ethernet initialized\n"); -+ netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n"); - } - out: - return ret; -@@ -456,8 +458,8 @@ static int stmmac_hwtstamp_ioctl(struct - sizeof(struct hwtstamp_config))) - return -EFAULT; - -- pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", -- __func__, config.flags, config.tx_type, config.rx_filter); -+ netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", -+ __func__, config.flags, config.tx_type, config.rx_filter); - - /* reserved for future extensions */ - if (config.flags) -@@ -712,7 +714,7 @@ static void stmmac_release_ptp(struct st - static void stmmac_adjust_link(struct net_device *dev) - { - struct stmmac_priv *priv = netdev_priv(dev); -- struct phy_device *phydev = priv->phydev; -+ struct phy_device *phydev = dev->phydev; - unsigned long flags; - int new_state = 0; - unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; -@@ -765,9 +767,9 @@ static void stmmac_adjust_link(struct ne - stmmac_hw_fix_mac_speed(priv); - break; - default: -- if (netif_msg_link(priv)) -- pr_warn("%s: Speed (%d) not 10/100\n", -- dev->name, phydev->speed); -+ netif_warn(priv, link, priv->dev, -+ "Speed (%d) not 10/100\n", -+ phydev->speed); - break; - } - -@@ -820,10 +822,10 @@ static void stmmac_check_pcs_mode(struct - (interface == PHY_INTERFACE_MODE_RGMII_ID) || - (interface == PHY_INTERFACE_MODE_RGMII_RXID) || - (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { -- pr_debug("STMMAC: PCS RGMII support enable\n"); -+ netdev_dbg(priv->dev, "PCS RGMII support enabled\n"); - priv->hw->pcs = STMMAC_PCS_RGMII; - } else if (interface == PHY_INTERFACE_MODE_SGMII) { -- pr_debug("STMMAC: PCS SGMII support enable\n"); -+ netdev_dbg(priv->dev, "PCS SGMII support enabled\n"); - priv->hw->pcs = STMMAC_PCS_SGMII; - } - } -@@ -858,15 +860,15 @@ static int stmmac_init_phy(struct net_de - - snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, - priv->plat->phy_addr); -- pr_debug("stmmac_init_phy: trying to attach to %s\n", -- phy_id_fmt); -+ netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__, -+ phy_id_fmt); - - phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, - interface); - } - - if (IS_ERR_OR_NULL(phydev)) { -- pr_err("%s: Could not attach to PHY\n", dev->name); -+ netdev_err(priv->dev, "Could not attach to PHY\n"); - if (!phydev) - return -ENODEV; - -@@ -899,10 +901,8 @@ static int stmmac_init_phy(struct net_de - if (phydev->is_pseudo_fixed_link) - phydev->irq = PHY_POLL; - -- pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" -- " Link = %d\n", dev->name, phydev->phy_id, phydev->link); -- -- priv->phydev = phydev; -+ netdev_dbg(priv->dev, "%s: attached to PHY (UID 0x%x) Link = %d\n", -+ __func__, phydev->phy_id, phydev->link); - - return 0; - } -@@ -988,7 +988,8 @@ static int stmmac_init_rx_buffers(struct - - skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); - if (!skb) { -- pr_err("%s: Rx init fails; skb is NULL\n", __func__); -+ netdev_err(priv->dev, -+ "%s: Rx init fails; skb is NULL\n", __func__); - return -ENOMEM; - } - priv->rx_skbuff[i] = skb; -@@ -996,15 +997,15 @@ static int stmmac_init_rx_buffers(struct - priv->dma_buf_sz, - DMA_FROM_DEVICE); - if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { -- pr_err("%s: DMA mapping error\n", __func__); -+ netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (priv->synopsys_id >= DWMAC_CORE_4_00) -- p->des0 = priv->rx_skbuff_dma[i]; -+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]); - else -- p->des2 = priv->rx_skbuff_dma[i]; -+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[i]); - - if ((priv->hw->mode->init_desc3) && - (priv->dma_buf_sz == BUF_SIZE_16KiB)) -@@ -1046,13 +1047,14 @@ static int init_dma_desc_rings(struct ne - - priv->dma_buf_sz = bfsize; - -- if (netif_msg_probe(priv)) { -- pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, -- (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); -+ netif_dbg(priv, probe, priv->dev, -+ "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", -+ __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy); -+ -+ /* RX INITIALIZATION */ -+ netif_dbg(priv, probe, priv->dev, -+ "SKB addresses:\nskb\t\tskb data\tdma data\n"); - -- /* RX INITIALIZATION */ -- pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n"); -- } - for (i = 0; i < DMA_RX_SIZE; i++) { - struct dma_desc *p; - if (priv->extend_desc) -@@ -1064,10 +1066,9 @@ static int init_dma_desc_rings(struct ne - if (ret) - goto err_init_rx_buffers; - -- if (netif_msg_probe(priv)) -- pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], -- priv->rx_skbuff[i]->data, -- (unsigned int)priv->rx_skbuff_dma[i]); -+ netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n", -+ priv->rx_skbuff[i], priv->rx_skbuff[i]->data, -+ (unsigned int)priv->rx_skbuff_dma[i]); - } - priv->cur_rx = 0; - priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); -@@ -1322,7 +1323,7 @@ static void stmmac_tx_clean(struct stmma - unsigned int bytes_compl = 0, pkts_compl = 0; - unsigned int entry = priv->dirty_tx; - -- spin_lock(&priv->tx_lock); -+ netif_tx_lock(priv->dev); - - priv->xstats.tx_clean++; - -@@ -1398,22 +1399,17 @@ static void stmmac_tx_clean(struct stmma - netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); - - if (unlikely(netif_queue_stopped(priv->dev) && -- stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) { -- netif_tx_lock(priv->dev); -- if (netif_queue_stopped(priv->dev) && -- stmmac_tx_avail(priv) > STMMAC_TX_THRESH) { -- if (netif_msg_tx_done(priv)) -- pr_debug("%s: restart transmit\n", __func__); -- netif_wake_queue(priv->dev); -- } -- netif_tx_unlock(priv->dev); -+ stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) { -+ netif_dbg(priv, tx_done, priv->dev, -+ "%s: restart transmit\n", __func__); -+ netif_wake_queue(priv->dev); - } - - if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { - stmmac_enable_eee_mode(priv); - mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); - } -- spin_unlock(&priv->tx_lock); -+ netif_tx_unlock(priv->dev); - } - - static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) -@@ -1517,7 +1513,7 @@ static void stmmac_mmc_setup(struct stmm - dwmac_mmc_ctrl(priv->mmcaddr, mode); - memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); - } else -- pr_info(" No MAC Management Counters available\n"); -+ netdev_info(priv->dev, "No MAC Management Counters available\n"); - } - - /** -@@ -1530,18 +1526,18 @@ static void stmmac_mmc_setup(struct stmm - static void stmmac_selec_desc_mode(struct stmmac_priv *priv) - { - if (priv->plat->enh_desc) { -- pr_info(" Enhanced/Alternate descriptors\n"); -+ dev_info(priv->device, "Enhanced/Alternate descriptors\n"); - - /* GMAC older than 3.50 has no extended descriptors */ - if (priv->synopsys_id >= DWMAC_CORE_3_50) { -- pr_info("\tEnabled extended descriptors\n"); -+ dev_info(priv->device, "Enabled extended descriptors\n"); - priv->extend_desc = 1; - } else -- pr_warn("Extended descriptors not supported\n"); -+ dev_warn(priv->device, "Extended descriptors not supported\n"); - - priv->hw->desc = &enh_desc_ops; - } else { -- pr_info(" Normal descriptors\n"); -+ dev_info(priv->device, "Normal descriptors\n"); - priv->hw->desc = &ndesc_ops; - } - } -@@ -1582,8 +1578,8 @@ static void stmmac_check_ether_addr(stru - priv->dev->dev_addr, 0); - if (!is_valid_ether_addr(priv->dev->dev_addr)) - eth_hw_addr_random(priv->dev); -- pr_info("%s: device MAC address %pM\n", priv->dev->name, -- priv->dev->dev_addr); -+ netdev_info(priv->dev, "device MAC address %pM\n", -+ priv->dev->dev_addr); - } - } - -@@ -1597,16 +1593,12 @@ static void stmmac_check_ether_addr(stru - */ - static int stmmac_init_dma_engine(struct stmmac_priv *priv) - { -- int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, aal = 0; -- int mixed_burst = 0; - int atds = 0; - int ret = 0; - -- if (priv->plat->dma_cfg) { -- pbl = priv->plat->dma_cfg->pbl; -- fixed_burst = priv->plat->dma_cfg->fixed_burst; -- mixed_burst = priv->plat->dma_cfg->mixed_burst; -- aal = priv->plat->dma_cfg->aal; -+ if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) { -+ dev_err(priv->device, "Invalid DMA configuration\n"); -+ return -EINVAL; - } - - if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) -@@ -1618,8 +1610,8 @@ static int stmmac_init_dma_engine(struct - return ret; - } - -- priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, -- aal, priv->dma_tx_phy, priv->dma_rx_phy, atds); -+ priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, -+ priv->dma_tx_phy, priv->dma_rx_phy, atds); - - if (priv->synopsys_id >= DWMAC_CORE_4_00) { - priv->rx_tail_addr = priv->dma_rx_phy + -@@ -1691,7 +1683,8 @@ static int stmmac_hw_setup(struct net_de - /* DMA initialization and SW reset */ - ret = stmmac_init_dma_engine(priv); - if (ret < 0) { -- pr_err("%s: DMA engine initialization failed\n", __func__); -+ netdev_err(priv->dev, "%s: DMA engine initialization failed\n", -+ __func__); - return ret; - } - -@@ -1720,7 +1713,7 @@ static int stmmac_hw_setup(struct net_de - - ret = priv->hw->mac->rx_ipc(priv->hw); - if (!ret) { -- pr_warn(" RX IPC Checksum Offload disabled\n"); -+ netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); - priv->plat->rx_coe = STMMAC_RX_COE_NONE; - priv->hw->rx_csum = 0; - } -@@ -1745,10 +1738,11 @@ static int stmmac_hw_setup(struct net_de - #ifdef CONFIG_DEBUG_FS - ret = stmmac_init_fs(dev); - if (ret < 0) -- pr_warn("%s: failed debugFS registration\n", __func__); -+ netdev_warn(priv->dev, "%s: failed debugFS registration\n", -+ __func__); - #endif - /* Start the ball rolling... */ -- pr_debug("%s: DMA RX/TX processes started...\n", dev->name); -+ netdev_dbg(priv->dev, "DMA RX/TX processes started...\n"); - priv->hw->dma->start_tx(priv->ioaddr); - priv->hw->dma->start_rx(priv->ioaddr); - -@@ -1803,8 +1797,9 @@ static int stmmac_open(struct net_device - priv->hw->pcs != STMMAC_PCS_RTBI) { - ret = stmmac_init_phy(dev); - if (ret) { -- pr_err("%s: Cannot attach to PHY (error: %d)\n", -- __func__, ret); -+ netdev_err(priv->dev, -+ "%s: Cannot attach to PHY (error: %d)\n", -+ __func__, ret); - return ret; - } - } -@@ -1819,33 +1814,36 @@ static int stmmac_open(struct net_device - - ret = alloc_dma_desc_resources(priv); - if (ret < 0) { -- pr_err("%s: DMA descriptors allocation failed\n", __func__); -+ netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n", -+ __func__); - goto dma_desc_error; - } - - ret = init_dma_desc_rings(dev, GFP_KERNEL); - if (ret < 0) { -- pr_err("%s: DMA descriptors initialization failed\n", __func__); -+ netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n", -+ __func__); - goto init_error; - } - - ret = stmmac_hw_setup(dev, true); - if (ret < 0) { -- pr_err("%s: Hw setup failed\n", __func__); -+ netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); - goto init_error; - } - - stmmac_init_tx_coalesce(priv); - -- if (priv->phydev) -- phy_start(priv->phydev); -+ if (dev->phydev) -+ phy_start(dev->phydev); - - /* Request the IRQ lines */ - ret = request_irq(dev->irq, stmmac_interrupt, - IRQF_SHARED, dev->name, dev); - if (unlikely(ret < 0)) { -- pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", -- __func__, dev->irq, ret); -+ netdev_err(priv->dev, -+ "%s: ERROR: allocating the IRQ %d (error: %d)\n", -+ __func__, dev->irq, ret); - goto init_error; - } - -@@ -1854,8 +1852,9 @@ static int stmmac_open(struct net_device - ret = request_irq(priv->wol_irq, stmmac_interrupt, - IRQF_SHARED, dev->name, dev); - if (unlikely(ret < 0)) { -- pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n", -- __func__, priv->wol_irq, ret); -+ netdev_err(priv->dev, -+ "%s: ERROR: allocating the WoL IRQ %d (%d)\n", -+ __func__, priv->wol_irq, ret); - goto wolirq_error; - } - } -@@ -1865,8 +1864,9 @@ static int stmmac_open(struct net_device - ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, - dev->name, dev); - if (unlikely(ret < 0)) { -- pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n", -- __func__, priv->lpi_irq, ret); -+ netdev_err(priv->dev, -+ "%s: ERROR: allocating the LPI IRQ %d (%d)\n", -+ __func__, priv->lpi_irq, ret); - goto lpiirq_error; - } - } -@@ -1885,8 +1885,8 @@ wolirq_error: - init_error: - free_dma_desc_resources(priv); - dma_desc_error: -- if (priv->phydev) -- phy_disconnect(priv->phydev); -+ if (dev->phydev) -+ phy_disconnect(dev->phydev); - - return ret; - } -@@ -1905,10 +1905,9 @@ static int stmmac_release(struct net_dev - del_timer_sync(&priv->eee_ctrl_timer); - - /* Stop and disconnect the PHY */ -- if (priv->phydev) { -- phy_stop(priv->phydev); -- phy_disconnect(priv->phydev); -- priv->phydev = NULL; -+ if (dev->phydev) { -+ phy_stop(dev->phydev); -+ phy_disconnect(dev->phydev); - } - - netif_stop_queue(dev); -@@ -1968,13 +1967,13 @@ static void stmmac_tso_allocator(struct - priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); - desc = priv->dma_tx + priv->cur_tx; - -- desc->des0 = des + (total_len - tmp_len); -+ desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); - buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? - TSO_MAX_BUFF_SIZE : tmp_len; - - priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, - 0, 1, -- (last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE), -+ (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), - 0, 0); - - tmp_len -= TSO_MAX_BUFF_SIZE; -@@ -2019,8 +2018,6 @@ static netdev_tx_t stmmac_tso_xmit(struc - u8 proto_hdr_len; - int i; - -- spin_lock(&priv->tx_lock); -- - /* Compute header lengths */ - proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - -@@ -2030,9 +2027,10 @@ static netdev_tx_t stmmac_tso_xmit(struc - if (!netif_queue_stopped(dev)) { - netif_stop_queue(dev); - /* This is a hard error, log it. */ -- pr_err("%s: Tx Ring full when queue awake\n", __func__); -+ netdev_err(priv->dev, -+ "%s: Tx Ring full when queue awake\n", -+ __func__); - } -- spin_unlock(&priv->tx_lock); - return NETDEV_TX_BUSY; - } - -@@ -2070,11 +2068,11 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb); - priv->tx_skbuff[first_entry] = skb; - -- first->des0 = des; -+ first->des0 = cpu_to_le32(des); - - /* Fill start of payload in buff2 of first descriptor */ - if (pay_len) -- first->des1 = des + proto_hdr_len; -+ first->des1 = cpu_to_le32(des + proto_hdr_len); - - /* If needed take extra descriptors to fill the remaining payload */ - tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; -@@ -2103,8 +2101,8 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); - - if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { -- if (netif_msg_hw(priv)) -- pr_debug("%s: stop transmitted packets\n", __func__); -+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", -+ __func__); - netif_stop_queue(dev); - } - -@@ -2155,7 +2153,7 @@ static netdev_tx_t stmmac_tso_xmit(struc - * descriptor and then barrier is needed to make sure that - * all is coherent before granting the DMA engine. - */ -- smp_wmb(); -+ dma_wmb(); - - if (netif_msg_pktdata(priv)) { - pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", -@@ -2174,11 +2172,9 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, - STMMAC_CHAN0); - -- spin_unlock(&priv->tx_lock); - return NETDEV_TX_OK; - - dma_map_err: -- spin_unlock(&priv->tx_lock); - dev_err(priv->device, "Tx dma map failed\n"); - dev_kfree_skb(skb); - priv->dev->stats.tx_dropped++; -@@ -2210,14 +2206,13 @@ static netdev_tx_t stmmac_xmit(struct sk - return stmmac_tso_xmit(skb, dev); - } - -- spin_lock(&priv->tx_lock); -- - if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { -- spin_unlock(&priv->tx_lock); - if (!netif_queue_stopped(dev)) { - netif_stop_queue(dev); - /* This is a hard error, log it. */ -- pr_err("%s: Tx Ring full when queue awake\n", __func__); -+ netdev_err(priv->dev, -+ "%s: Tx Ring full when queue awake\n", -+ __func__); - } - return NETDEV_TX_BUSY; - } -@@ -2270,13 +2265,11 @@ static netdev_tx_t stmmac_xmit(struct sk - - priv->tx_skbuff[entry] = NULL; - -- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { -- desc->des0 = des; -- priv->tx_skbuff_dma[entry].buf = desc->des0; -- } else { -- desc->des2 = des; -- priv->tx_skbuff_dma[entry].buf = desc->des2; -- } -+ priv->tx_skbuff_dma[entry].buf = des; -+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) -+ desc->des0 = cpu_to_le32(des); -+ else -+ desc->des2 = cpu_to_le32(des); - - priv->tx_skbuff_dma[entry].map_as_page = true; - priv->tx_skbuff_dma[entry].len = len; -@@ -2294,9 +2287,10 @@ static netdev_tx_t stmmac_xmit(struct sk - if (netif_msg_pktdata(priv)) { - void *tx_head; - -- pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", -- __func__, priv->cur_tx, priv->dirty_tx, first_entry, -- entry, first, nfrags); -+ netdev_dbg(priv->dev, -+ "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", -+ __func__, priv->cur_tx, priv->dirty_tx, first_entry, -+ entry, first, nfrags); - - if (priv->extend_desc) - tx_head = (void *)priv->dma_etx; -@@ -2305,13 +2299,13 @@ static netdev_tx_t stmmac_xmit(struct sk - - priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); - -- pr_debug(">>> frame to be transmitted: "); -+ netdev_dbg(priv->dev, ">>> frame to be transmitted: "); - print_pkt(skb->data, skb->len); - } - - if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { -- if (netif_msg_hw(priv)) -- pr_debug("%s: stop transmitted packets\n", __func__); -+ netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", -+ __func__); - netif_stop_queue(dev); - } - -@@ -2347,13 +2341,11 @@ static netdev_tx_t stmmac_xmit(struct sk - if (dma_mapping_error(priv->device, des)) - goto dma_map_err; - -- if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { -- first->des0 = des; -- priv->tx_skbuff_dma[first_entry].buf = first->des0; -- } else { -- first->des2 = des; -- priv->tx_skbuff_dma[first_entry].buf = first->des2; -- } -+ priv->tx_skbuff_dma[first_entry].buf = des; -+ if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) -+ first->des0 = cpu_to_le32(des); -+ else -+ first->des2 = cpu_to_le32(des); - - priv->tx_skbuff_dma[first_entry].len = nopaged_len; - priv->tx_skbuff_dma[first_entry].last_segment = last_segment; -@@ -2374,7 +2366,7 @@ static netdev_tx_t stmmac_xmit(struct sk - * descriptor and then barrier is needed to make sure that - * all is coherent before granting the DMA engine. - */ -- smp_wmb(); -+ dma_wmb(); - } - - netdev_sent_queue(dev, skb->len); -@@ -2385,12 +2377,10 @@ static netdev_tx_t stmmac_xmit(struct sk - priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, - STMMAC_CHAN0); - -- spin_unlock(&priv->tx_lock); - return NETDEV_TX_OK; - - dma_map_err: -- spin_unlock(&priv->tx_lock); -- dev_err(priv->device, "Tx dma map failed\n"); -+ netdev_err(priv->dev, "Tx DMA map failed\n"); - dev_kfree_skb(skb); - priv->dev->stats.tx_dropped++; - return NETDEV_TX_OK; -@@ -2461,16 +2451,16 @@ static inline void stmmac_rx_refill(stru - DMA_FROM_DEVICE); - if (dma_mapping_error(priv->device, - priv->rx_skbuff_dma[entry])) { -- dev_err(priv->device, "Rx dma map failed\n"); -+ netdev_err(priv->dev, "Rx DMA map failed\n"); - dev_kfree_skb(skb); - break; - } - - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { -- p->des0 = priv->rx_skbuff_dma[entry]; -+ p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]); - p->des1 = 0; - } else { -- p->des2 = priv->rx_skbuff_dma[entry]; -+ p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]); - } - if (priv->hw->mode->refill_desc3) - priv->hw->mode->refill_desc3(priv, p); -@@ -2478,17 +2468,17 @@ static inline void stmmac_rx_refill(stru - if (priv->rx_zeroc_thresh > 0) - priv->rx_zeroc_thresh--; - -- if (netif_msg_rx_status(priv)) -- pr_debug("\trefill entry #%d\n", entry); -+ netif_dbg(priv, rx_status, priv->dev, -+ "refill entry #%d\n", entry); - } -- wmb(); -+ dma_wmb(); - - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) - priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); - else - priv->hw->desc->set_rx_owner(p); - -- wmb(); -+ dma_wmb(); - - entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); - } -@@ -2512,7 +2502,7 @@ static int stmmac_rx(struct stmmac_priv - if (netif_msg_rx_status(priv)) { - void *rx_head; - -- pr_info(">>>>>> %s: descriptor ring:\n", __func__); -+ netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__); - if (priv->extend_desc) - rx_head = (void *)priv->dma_erx; - else -@@ -2574,9 +2564,9 @@ static int stmmac_rx(struct stmmac_priv - unsigned int des; - - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) -- des = p->des0; -+ des = le32_to_cpu(p->des0); - else -- des = p->des2; -+ des = le32_to_cpu(p->des2); - - frame_len = priv->hw->desc->get_rx_frame_len(p, coe); - -@@ -2585,9 +2575,9 @@ static int stmmac_rx(struct stmmac_priv - * ignored - */ - if (frame_len > priv->dma_buf_sz) { -- pr_err("%s: len %d larger than size (%d)\n", -- priv->dev->name, frame_len, -- priv->dma_buf_sz); -+ netdev_err(priv->dev, -+ "len %d larger than size (%d)\n", -+ frame_len, priv->dma_buf_sz); - priv->dev->stats.rx_length_errors++; - break; - } -@@ -2599,11 +2589,11 @@ static int stmmac_rx(struct stmmac_priv - frame_len -= ETH_FCS_LEN; - - if (netif_msg_rx_status(priv)) { -- pr_info("\tdesc: %p [entry %d] buff=0x%x\n", -- p, entry, des); -+ netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n", -+ p, entry, des); - if (frame_len > ETH_FRAME_LEN) -- pr_debug("\tframe size %d, COE: %d\n", -- frame_len, status); -+ netdev_dbg(priv->dev, "frame size %d, COE: %d\n", -+ frame_len, status); - } - - /* The zero-copy is always used for all the sizes -@@ -2640,8 +2630,9 @@ static int stmmac_rx(struct stmmac_priv - } else { - skb = priv->rx_skbuff[entry]; - if (unlikely(!skb)) { -- pr_err("%s: Inconsistent Rx chain\n", -- priv->dev->name); -+ netdev_err(priv->dev, -+ "%s: Inconsistent Rx chain\n", -+ priv->dev->name); - priv->dev->stats.rx_dropped++; - break; - } -@@ -2657,7 +2648,8 @@ static int stmmac_rx(struct stmmac_priv - } - - if (netif_msg_pktdata(priv)) { -- pr_debug("frame received (%dbytes)", frame_len); -+ netdev_dbg(priv->dev, "frame received (%dbytes)", -+ frame_len); - print_pkt(skb->data, frame_len); - } - -@@ -2760,7 +2752,7 @@ static int stmmac_change_mtu(struct net_ - int max_mtu; - - if (netif_running(dev)) { -- pr_err("%s: must be stopped to change its MTU\n", dev->name); -+ netdev_err(priv->dev, "must be stopped to change its MTU\n"); - return -EBUSY; - } - -@@ -2852,7 +2844,7 @@ static irqreturn_t stmmac_interrupt(int - pm_wakeup_event(priv->device, 0); - - if (unlikely(!dev)) { -- pr_err("%s: invalid dev pointer\n", __func__); -+ netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); - return IRQ_NONE; - } - -@@ -2910,7 +2902,6 @@ static void stmmac_poll_controller(struc - */ - static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) - { -- struct stmmac_priv *priv = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - if (!netif_running(dev)) -@@ -2920,9 +2911,9 @@ static int stmmac_ioctl(struct net_devic - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: -- if (!priv->phydev) -+ if (!dev->phydev) - return -EINVAL; -- ret = phy_mii_ioctl(priv->phydev, rq, cmd); -+ ret = phy_mii_ioctl(dev->phydev, rq, cmd); - break; - case SIOCSHWTSTAMP: - ret = stmmac_hwtstamp_ioctl(dev, rq); -@@ -2950,14 +2941,17 @@ static void sysfs_display_ring(void *hea - x = *(u64 *) ep; - seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), -- ep->basic.des0, ep->basic.des1, -- ep->basic.des2, ep->basic.des3); -+ le32_to_cpu(ep->basic.des0), -+ le32_to_cpu(ep->basic.des1), -+ le32_to_cpu(ep->basic.des2), -+ le32_to_cpu(ep->basic.des3)); - ep++; - } else { - x = *(u64 *) p; - seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), -- p->des0, p->des1, p->des2, p->des3); -+ le32_to_cpu(p->des0), le32_to_cpu(p->des1), -+ le32_to_cpu(p->des2), le32_to_cpu(p->des3)); - p++; - } - seq_printf(seq, "\n"); -@@ -2989,6 +2983,8 @@ static int stmmac_sysfs_ring_open(struct - return single_open(file, stmmac_sysfs_ring_read, inode->i_private); - } - -+/* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */ -+ - static const struct file_operations stmmac_rings_status_fops = { - .owner = THIS_MODULE, - .open = stmmac_sysfs_ring_open, -@@ -3011,11 +3007,11 @@ static int stmmac_sysfs_dma_cap_read(str - seq_printf(seq, "\tDMA HW features\n"); - seq_printf(seq, "==============================\n"); - -- seq_printf(seq, "\t10/100 Mbps %s\n", -+ seq_printf(seq, "\t10/100 Mbps: %s\n", - (priv->dma_cap.mbps_10_100) ? "Y" : "N"); -- seq_printf(seq, "\t1000 Mbps %s\n", -+ seq_printf(seq, "\t1000 Mbps: %s\n", - (priv->dma_cap.mbps_1000) ? "Y" : "N"); -- seq_printf(seq, "\tHalf duple %s\n", -+ seq_printf(seq, "\tHalf duplex: %s\n", - (priv->dma_cap.half_duplex) ? "Y" : "N"); - seq_printf(seq, "\tHash Filter: %s\n", - (priv->dma_cap.hash_filter) ? "Y" : "N"); -@@ -3033,9 +3029,9 @@ static int stmmac_sysfs_dma_cap_read(str - (priv->dma_cap.rmon) ? "Y" : "N"); - seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", - (priv->dma_cap.time_stamp) ? "Y" : "N"); -- seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n", -+ seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n", - (priv->dma_cap.atime_stamp) ? "Y" : "N"); -- seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n", -+ seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n", - (priv->dma_cap.eee) ? "Y" : "N"); - seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); - seq_printf(seq, "\tChecksum Offload in TX: %s\n", -@@ -3082,8 +3078,7 @@ static int stmmac_init_fs(struct net_dev - priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); - - if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { -- pr_err("ERROR %s/%s, debugfs create directory failed\n", -- STMMAC_RESOURCE_NAME, dev->name); -+ netdev_err(priv->dev, "ERROR failed to create debugfs directory\n"); - - return -ENOMEM; - } -@@ -3095,7 +3090,7 @@ static int stmmac_init_fs(struct net_dev - &stmmac_rings_status_fops); - - if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { -- pr_info("ERROR creating stmmac ring debugfs file\n"); -+ netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n"); - debugfs_remove_recursive(priv->dbgfs_dir); - - return -ENOMEM; -@@ -3107,7 +3102,7 @@ static int stmmac_init_fs(struct net_dev - dev, &stmmac_dma_cap_fops); - - if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { -- pr_info("ERROR creating stmmac MMC debugfs file\n"); -+ netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n"); - debugfs_remove_recursive(priv->dbgfs_dir); - - return -ENOMEM; -@@ -3179,11 +3174,11 @@ static int stmmac_hw_init(struct stmmac_ - } else { - if (chain_mode) { - priv->hw->mode = &chain_mode_ops; -- pr_info(" Chain mode enabled\n"); -+ dev_info(priv->device, "Chain mode enabled\n"); - priv->mode = STMMAC_CHAIN_MODE; - } else { - priv->hw->mode = &ring_mode_ops; -- pr_info(" Ring mode enabled\n"); -+ dev_info(priv->device, "Ring mode enabled\n"); - priv->mode = STMMAC_RING_MODE; - } - } -@@ -3191,7 +3186,7 @@ static int stmmac_hw_init(struct stmmac_ - /* Get the HW capability (new GMAC newer than 3.50a) */ - priv->hw_cap_support = stmmac_get_hw_features(priv); - if (priv->hw_cap_support) { -- pr_info(" DMA HW capability register supported"); -+ dev_info(priv->device, "DMA HW capability register supported\n"); - - /* We can override some gmac/dma configuration fields: e.g. - * enh_desc, tx_coe (e.g. that are passed through the -@@ -3216,8 +3211,9 @@ static int stmmac_hw_init(struct stmmac_ - else if (priv->dma_cap.rx_coe_type1) - priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; - -- } else -- pr_info(" No HW DMA feature register supported"); -+ } else { -+ dev_info(priv->device, "No HW DMA feature register supported\n"); -+ } - - /* To use alternate (extended), normal or GMAC4 descriptor structures */ - if (priv->synopsys_id >= DWMAC_CORE_4_00) -@@ -3227,20 +3223,20 @@ static int stmmac_hw_init(struct stmmac_ - - if (priv->plat->rx_coe) { - priv->hw->rx_csum = priv->plat->rx_coe; -- pr_info(" RX Checksum Offload Engine supported\n"); -+ dev_info(priv->device, "RX Checksum Offload Engine supported\n"); - if (priv->synopsys_id < DWMAC_CORE_4_00) -- pr_info("\tCOE Type %d\n", priv->hw->rx_csum); -+ dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum); - } - if (priv->plat->tx_coe) -- pr_info(" TX Checksum insertion supported\n"); -+ dev_info(priv->device, "TX Checksum insertion supported\n"); - - if (priv->plat->pmt) { -- pr_info(" Wake-Up On Lan supported\n"); -+ dev_info(priv->device, "Wake-Up On Lan supported\n"); - device_set_wakeup_capable(priv->device, 1); - } - - if (priv->dma_cap.tsoen) -- pr_info(" TSO supported\n"); -+ dev_info(priv->device, "TSO supported\n"); - - return 0; - } -@@ -3299,8 +3295,8 @@ int stmmac_dvr_probe(struct device *devi - - priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); - if (IS_ERR(priv->stmmac_clk)) { -- dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", -- __func__); -+ netdev_warn(priv->dev, "%s: warning: cannot get CSR clock\n", -+ __func__); - /* If failed to obtain stmmac_clk and specific clk_csr value - * is NOT passed from the platform, probe fail. - */ -@@ -3349,7 +3345,7 @@ int stmmac_dvr_probe(struct device *devi - if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { - ndev->hw_features |= NETIF_F_TSO; - priv->tso = true; -- pr_info(" TSO feature enabled\n"); -+ dev_info(priv->device, "TSO feature enabled\n"); - } - ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; - ndev->watchdog_timeo = msecs_to_jiffies(watchdog); -@@ -3369,13 +3365,13 @@ int stmmac_dvr_probe(struct device *devi - */ - if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { - priv->use_riwt = 1; -- pr_info(" Enable RX Mitigation via HW Watchdog Timer\n"); -+ dev_info(priv->device, -+ "Enable RX Mitigation via HW Watchdog Timer\n"); - } - - netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); - - spin_lock_init(&priv->lock); -- spin_lock_init(&priv->tx_lock); - - /* If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be -@@ -3396,15 +3392,17 @@ int stmmac_dvr_probe(struct device *devi - /* MDIO bus Registration */ - ret = stmmac_mdio_register(ndev); - if (ret < 0) { -- pr_debug("%s: MDIO bus (id: %d) registration failed", -- __func__, priv->plat->bus_id); -- goto error_napi_register; -+ dev_err(priv->device, -+ "%s: MDIO bus (id: %d) registration failed", -+ __func__, priv->plat->bus_id); -+ goto error_mdio_register; - } - } - - ret = register_netdev(ndev); - if (ret) { -- pr_err("%s: ERROR %i registering the device\n", __func__, ret); -+ dev_err(priv->device, "%s: ERROR %i registering the device\n", -+ __func__, ret); - goto error_netdev_register; - } - -@@ -3415,7 +3413,7 @@ error_netdev_register: - priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI) - stmmac_mdio_unregister(ndev); --error_napi_register: -+error_mdio_register: - netif_napi_del(&priv->napi); - error_hw_init: - clk_disable_unprepare(priv->pclk); -@@ -3439,7 +3437,7 @@ int stmmac_dvr_remove(struct device *dev - struct net_device *ndev = dev_get_drvdata(dev); - struct stmmac_priv *priv = netdev_priv(ndev); - -- pr_info("%s:\n\tremoving driver", __func__); -+ netdev_info(priv->dev, "%s: removing driver", __func__); - - priv->hw->dma->stop_rx(priv->ioaddr); - priv->hw->dma->stop_tx(priv->ioaddr); -@@ -3477,8 +3475,8 @@ int stmmac_suspend(struct device *dev) - if (!ndev || !netif_running(ndev)) - return 0; - -- if (priv->phydev) -- phy_stop(priv->phydev); -+ if (ndev->phydev) -+ phy_stop(ndev->phydev); - - spin_lock_irqsave(&priv->lock, flags); - -@@ -3572,8 +3570,8 @@ int stmmac_resume(struct device *dev) - - spin_unlock_irqrestore(&priv->lock, flags); - -- if (priv->phydev) -- phy_start(priv->phydev); -+ if (ndev->phydev) -+ phy_start(ndev->phydev); - - return 0; - } ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -@@ -42,13 +42,6 @@ - #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) - #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) - --#define MII_PHY_ADDR_GMAC4_SHIFT 21 --#define MII_PHY_ADDR_GMAC4_MASK GENMASK(25, 21) --#define MII_PHY_REG_GMAC4_SHIFT 16 --#define MII_PHY_REG_GMAC4_MASK GENMASK(20, 16) --#define MII_CSR_CLK_GMAC4_SHIFT 8 --#define MII_CSR_CLK_GMAC4_MASK GENMASK(11, 8) -- - static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr) - { - unsigned long curr; -@@ -68,8 +61,8 @@ static int stmmac_mdio_busy_wait(void __ - /** - * stmmac_mdio_read - * @bus: points to the mii_bus structure -- * @phyaddr: MII addr reg bits 15-11 -- * @phyreg: MII addr reg bits 10-6 -+ * @phyaddr: MII addr -+ * @phyreg: MII reg - * Description: it reads data from the MII register from within the phy device. - * For the 7111 GMAC, we must set the bit 0 in the MII address register while - * accessing the PHY registers. -@@ -83,14 +76,20 @@ static int stmmac_mdio_read(struct mii_b - unsigned int mii_data = priv->hw->mii.data; - - int data; -- u16 regValue = (((phyaddr << 11) & (0x0000F800)) | -- ((phyreg << 6) & (0x000007C0))); -- regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); -+ u32 value = MII_BUSY; -+ -+ value |= (phyaddr << priv->hw->mii.addr_shift) -+ & priv->hw->mii.addr_mask; -+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; -+ value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) -+ & priv->hw->mii.clk_csr_mask; -+ if (priv->plat->has_gmac4) -+ value |= MII_GMAC4_READ; - - if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) - return -EBUSY; - -- writel(regValue, priv->ioaddr + mii_address); -+ writel(value, priv->ioaddr + mii_address); - - if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) - return -EBUSY; -@@ -104,8 +103,8 @@ static int stmmac_mdio_read(struct mii_b - /** - * stmmac_mdio_write - * @bus: points to the mii_bus structure -- * @phyaddr: MII addr reg bits 15-11 -- * @phyreg: MII addr reg bits 10-6 -+ * @phyaddr: MII addr -+ * @phyreg: MII reg - * @phydata: phy data - * Description: it writes the data into the MII register from within the device. - */ -@@ -117,85 +116,18 @@ static int stmmac_mdio_write(struct mii_ - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; - -- u16 value = -- (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) -- | MII_WRITE; -- -- value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); -- -- /* Wait until any existing MII operation is complete */ -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -- return -EBUSY; -- -- /* Set the MII address register to write */ -- writel(phydata, priv->ioaddr + mii_data); -- writel(value, priv->ioaddr + mii_address); -- -- /* Wait until any existing MII operation is complete */ -- return stmmac_mdio_busy_wait(priv->ioaddr, mii_address); --} -- --/** -- * stmmac_mdio_read_gmac4 -- * @bus: points to the mii_bus structure -- * @phyaddr: MII addr reg bits 25-21 -- * @phyreg: MII addr reg bits 20-16 -- * Description: it reads data from the MII register of GMAC4 from within -- * the phy device. -- */ --static int stmmac_mdio_read_gmac4(struct mii_bus *bus, int phyaddr, int phyreg) --{ -- struct net_device *ndev = bus->priv; -- struct stmmac_priv *priv = netdev_priv(ndev); -- unsigned int mii_address = priv->hw->mii.addr; -- unsigned int mii_data = priv->hw->mii.data; -- int data; -- u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) & -- (MII_PHY_ADDR_GMAC4_MASK)) | -- ((phyreg << MII_PHY_REG_GMAC4_SHIFT) & -- (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_READ; -- -- value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK) -- << MII_CSR_CLK_GMAC4_SHIFT); -- -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -- return -EBUSY; -- -- writel(value, priv->ioaddr + mii_address); -- -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -- return -EBUSY; -- -- /* Read the data from the MII data register */ -- data = (int)readl(priv->ioaddr + mii_data); -- -- return data; --} -- --/** -- * stmmac_mdio_write_gmac4 -- * @bus: points to the mii_bus structure -- * @phyaddr: MII addr reg bits 25-21 -- * @phyreg: MII addr reg bits 20-16 -- * @phydata: phy data -- * Description: it writes the data into the MII register of GMAC4 from within -- * the device. -- */ --static int stmmac_mdio_write_gmac4(struct mii_bus *bus, int phyaddr, int phyreg, -- u16 phydata) --{ -- struct net_device *ndev = bus->priv; -- struct stmmac_priv *priv = netdev_priv(ndev); -- unsigned int mii_address = priv->hw->mii.addr; -- unsigned int mii_data = priv->hw->mii.data; -- -- u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) & -- (MII_PHY_ADDR_GMAC4_MASK)) | -- ((phyreg << MII_PHY_REG_GMAC4_SHIFT) & -- (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_WRITE; -+ u32 value = MII_BUSY; - -- value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK) -- << MII_CSR_CLK_GMAC4_SHIFT); -+ value |= (phyaddr << priv->hw->mii.addr_shift) -+ & priv->hw->mii.addr_mask; -+ value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; -+ -+ value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) -+ & priv->hw->mii.clk_csr_mask; -+ if (priv->plat->has_gmac4) -+ value |= MII_GMAC4_WRITE; -+ else -+ value |= MII_WRITE; - - /* Wait until any existing MII operation is complete */ - if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -@@ -260,7 +192,7 @@ int stmmac_mdio_reset(struct mii_bus *bu - #endif - - if (data->phy_reset) { -- pr_debug("stmmac_mdio_reset: calling phy_reset\n"); -+ netdev_dbg(ndev, "stmmac_mdio_reset: calling phy_reset\n"); - data->phy_reset(priv->plat->bsp_priv); - } - -@@ -305,13 +237,8 @@ int stmmac_mdio_register(struct net_devi - #endif - - new_bus->name = "stmmac"; -- if (priv->plat->has_gmac4) { -- new_bus->read = &stmmac_mdio_read_gmac4; -- new_bus->write = &stmmac_mdio_write_gmac4; -- } else { -- new_bus->read = &stmmac_mdio_read; -- new_bus->write = &stmmac_mdio_write; -- } -+ new_bus->read = &stmmac_mdio_read; -+ new_bus->write = &stmmac_mdio_write; - - new_bus->reset = &stmmac_mdio_reset; - snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", -@@ -325,7 +252,7 @@ int stmmac_mdio_register(struct net_devi - else - err = mdiobus_register(new_bus); - if (err != 0) { -- pr_err("%s: Cannot register as MDIO bus\n", new_bus->name); -+ netdev_err(ndev, "Cannot register the MDIO bus\n"); - goto bus_register_fail; - } - -@@ -372,16 +299,16 @@ int stmmac_mdio_register(struct net_devi - irq_str = irq_num; - break; - } -- pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n", -- ndev->name, phydev->phy_id, addr, -- irq_str, phydev_name(phydev), -- act ? " active" : ""); -+ netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", -+ phydev->phy_id, addr, -+ irq_str, phydev_name(phydev), -+ act ? " active" : ""); - found = 1; - } - } - - if (!found && !mdio_node) { -- pr_warn("%s: No PHY found\n", ndev->name); -+ netdev_warn(ndev, "No PHY found\n"); - mdiobus_unregister(new_bus); - mdiobus_free(new_bus); - return -ENODEV; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -81,6 +81,7 @@ static void stmmac_default_data(struct p - plat->mdio_bus_data->phy_mask = 0; - - plat->dma_cfg->pbl = 32; -+ plat->dma_cfg->pblx8 = true; - /* TODO: AXI */ - - /* Set default value for multicast hash bins */ -@@ -88,6 +89,9 @@ static void stmmac_default_data(struct p - - /* Set default value for unicast filter entries */ - plat->unicast_filter_entries = 1; -+ -+ /* Set the maxmtu to a default of JUMBO_LEN */ -+ plat->maxmtu = JUMBO_LEN; - } - - static int quark_default_data(struct plat_stmmacenet_data *plat, -@@ -115,6 +119,7 @@ static int quark_default_data(struct pla - plat->mdio_bus_data->phy_mask = 0; - - plat->dma_cfg->pbl = 16; -+ plat->dma_cfg->pblx8 = true; - plat->dma_cfg->fixed_burst = 1; - /* AXI (TODO) */ - -@@ -124,6 +129,9 @@ static int quark_default_data(struct pla - /* Set default value for unicast filter entries */ - plat->unicast_filter_entries = 1; - -+ /* Set the maxmtu to a default of JUMBO_LEN */ -+ plat->maxmtu = JUMBO_LEN; -+ - return 0; - } - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -292,6 +292,7 @@ stmmac_probe_config_dt(struct platform_d - if (of_device_is_compatible(np, "snps,dwmac-4.00") || - of_device_is_compatible(np, "snps,dwmac-4.10a")) { - plat->has_gmac4 = 1; -+ plat->has_gmac = 0; - plat->pmt = 1; - plat->tso_en = of_property_read_bool(np, "snps,tso"); - } -@@ -303,21 +304,25 @@ stmmac_probe_config_dt(struct platform_d - plat->force_sf_dma_mode = 1; - } - -- if (of_find_property(np, "snps,pbl", NULL)) { -- dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), -- GFP_KERNEL); -- if (!dma_cfg) { -- stmmac_remove_config_dt(pdev, plat); -- return ERR_PTR(-ENOMEM); -- } -- plat->dma_cfg = dma_cfg; -- of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); -- dma_cfg->aal = of_property_read_bool(np, "snps,aal"); -- dma_cfg->fixed_burst = -- of_property_read_bool(np, "snps,fixed-burst"); -- dma_cfg->mixed_burst = -- of_property_read_bool(np, "snps,mixed-burst"); -- } -+ dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), -+ GFP_KERNEL); -+ if (!dma_cfg) { -+ stmmac_remove_config_dt(pdev, plat); -+ return ERR_PTR(-ENOMEM); -+ } -+ plat->dma_cfg = dma_cfg; -+ -+ of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); -+ if (!dma_cfg->pbl) -+ dma_cfg->pbl = DEFAULT_DMA_PBL; -+ of_property_read_u32(np, "snps,txpbl", &dma_cfg->txpbl); -+ of_property_read_u32(np, "snps,rxpbl", &dma_cfg->rxpbl); -+ dma_cfg->pblx8 = !of_property_read_bool(np, "snps,no-pbl-x8"); -+ -+ dma_cfg->aal = of_property_read_bool(np, "snps,aal"); -+ dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst"); -+ dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst"); -+ - plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); - if (plat->force_thresh_dma_mode) { - plat->force_sf_dma_mode = 0; -@@ -445,9 +450,7 @@ static int stmmac_pltfr_suspend(struct d - struct platform_device *pdev = to_platform_device(dev); - - ret = stmmac_suspend(dev); -- if (priv->plat->suspend) -- priv->plat->suspend(pdev, priv->plat->bsp_priv); -- else if (priv->plat->exit) -+ if (priv->plat->exit) - priv->plat->exit(pdev, priv->plat->bsp_priv); - - return ret; -@@ -466,9 +469,7 @@ static int stmmac_pltfr_resume(struct de - struct stmmac_priv *priv = netdev_priv(ndev); - struct platform_device *pdev = to_platform_device(dev); - -- if (priv->plat->resume) -- priv->plat->resume(pdev, priv->plat->bsp_priv); -- else if (priv->plat->init) -+ if (priv->plat->init) - priv->plat->init(pdev, priv->plat->bsp_priv); - - return stmmac_resume(dev); ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -88,6 +88,9 @@ struct stmmac_mdio_bus_data { - - struct stmmac_dma_cfg { - int pbl; -+ int txpbl; -+ int rxpbl; -+ bool pblx8; - int fixed_burst; - int mixed_burst; - bool aal; -@@ -135,8 +138,6 @@ struct plat_stmmacenet_data { - void (*bus_setup)(void __iomem *ioaddr); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); -- void (*suspend)(struct platform_device *pdev, void *priv); -- void (*resume)(struct platform_device *pdev, void *priv); - void *bsp_priv; - struct stmmac_axi *axi; - int has_gmac4; diff --git a/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch b/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch deleted file mode 100644 index 2ce23e2eb5..0000000000 --- a/target/linux/sunxi/patches-4.9/0051-stmmac-form-4-11.patch +++ /dev/null @@ -1,2296 +0,0 @@ ---- a/Documentation/devicetree/bindings/net/stmmac.txt -+++ b/Documentation/devicetree/bindings/net/stmmac.txt -@@ -49,6 +49,8 @@ Optional properties: - - snps,force_sf_dma_mode Force DMA to use the Store and Forward - mode for both tx and rx. This flag is - ignored if force_thresh_dma_mode is set. -+- snps,en-tx-lpi-clockgating Enable gating of the MAC TX clock during -+ TX low-power mode - - snps,multicast-filter-bins: Number of multicast filter hash bins - supported by this device instance - - snps,perfect-filter-entries: Number of perfect filter entries supported -@@ -65,7 +67,6 @@ Optional properties: - - snps,wr_osr_lmt: max write outstanding req. limit - - snps,rd_osr_lmt: max read outstanding req. limit - - snps,kbbe: do not cross 1KiB boundary. -- - snps,axi_all: align address - - snps,blen: this is a vector of supported burst length. - - snps,fb: fixed-burst - - snps,mb: mixed-burst ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -1,5 +1,5 @@ - config STMMAC_ETH -- tristate "STMicroelectronics 10/100/1000 Ethernet driver" -+ tristate "STMicroelectronics 10/100/1000/EQOS Ethernet driver" - depends on HAS_IOMEM && HAS_DMA - select MII - select PHYLIB -@@ -7,9 +7,8 @@ config STMMAC_ETH - select PTP_1588_CLOCK - select RESET_CONTROLLER - ---help--- -- This is the driver for the Ethernet IPs are built around a -- Synopsys IP Core and only tested on the STMicroelectronics -- platforms. -+ This is the driver for the Ethernet IPs built around a -+ Synopsys IP Core. - - if STMMAC_ETH - -@@ -29,6 +28,15 @@ config STMMAC_PLATFORM - - if STMMAC_PLATFORM - -+config DWMAC_DWC_QOS_ETH -+ tristate "Support for snps,dwc-qos-ethernet.txt DT binding." -+ select PHYLIB -+ select CRC32 -+ select MII -+ depends on OF && HAS_DMA -+ help -+ Support for chips using the snps,dwc-qos-ethernet.txt DT binding. -+ - config DWMAC_GENERIC - tristate "Generic driver for DWMAC" - default STMMAC_PLATFORM -@@ -143,11 +151,11 @@ config STMMAC_PCI - tristate "STMMAC PCI bus support" - depends on STMMAC_ETH && PCI - ---help--- -- This is to select the Synopsys DWMAC available on PCI devices, -- if you have a controller with this interface, say Y or M here. -+ This selects the platform specific bus support for the stmmac driver. -+ This driver was tested on XLINX XC2V3000 FF1152AMT0221 -+ D1215994A VIRTEX FPGA board and SNPS QoS IPK Prototyping Kit. - -- This PCI support is tested on XLINX XC2V3000 FF1152AMT0221 -- D1215994A VIRTEX FPGA board. -+ If you have a controller with this interface, say Y or M here. - - If unsure, say N. - endif ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-alt - obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o - obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o - obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o -+obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o - obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o - stmmac-platform-objs:= stmmac_platform.o - dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o ---- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -@@ -16,10 +16,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -71,7 +67,7 @@ struct stmmac_extra_stats { - unsigned long overflow_error; - unsigned long ipc_csum_error; - unsigned long rx_collision; -- unsigned long rx_crc; -+ unsigned long rx_crc_errors; - unsigned long dribbling_bit; - unsigned long rx_length; - unsigned long rx_mii; -@@ -323,6 +319,9 @@ struct dma_features { - /* TX and RX number of channels */ - unsigned int number_rx_channel; - unsigned int number_tx_channel; -+ /* TX and RX number of queues */ -+ unsigned int number_rx_queues; -+ unsigned int number_tx_queues; - /* Alternate (enhanced) DESC mode */ - unsigned int enh_desc; - }; -@@ -340,7 +339,7 @@ struct dma_features { - /* Common MAC defines */ - #define MAC_CTRL_REG 0x00000000 /* MAC Control */ - #define MAC_ENABLE_TX 0x00000008 /* Transmitter Enable */ --#define MAC_RNABLE_RX 0x00000004 /* Receiver Enable */ -+#define MAC_ENABLE_RX 0x00000004 /* Receiver Enable */ - - /* Default LPI timers */ - #define STMMAC_DEFAULT_LIT_LS 0x3E8 -@@ -417,7 +416,7 @@ struct stmmac_dma_ops { - /* Configure the AXI Bus Mode Register */ - void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi); - /* Dump DMA registers */ -- void (*dump_regs) (void __iomem *ioaddr); -+ void (*dump_regs)(void __iomem *ioaddr, u32 *reg_space); - /* Set tx/rx threshold in the csr6 register - * An invalid value enables the store-and-forward mode */ - void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode, -@@ -454,8 +453,10 @@ struct stmmac_ops { - void (*core_init)(struct mac_device_info *hw, int mtu); - /* Enable and verify that the IPC module is supported */ - int (*rx_ipc)(struct mac_device_info *hw); -+ /* Enable RX Queues */ -+ void (*rx_queue_enable)(struct mac_device_info *hw, u32 queue); - /* Dump MAC registers */ -- void (*dump_regs)(struct mac_device_info *hw); -+ void (*dump_regs)(struct mac_device_info *hw, u32 *reg_space); - /* Handle extra events on specific interrupts hw dependent */ - int (*host_irq_status)(struct mac_device_info *hw, - struct stmmac_extra_stats *x); -@@ -471,7 +472,8 @@ struct stmmac_ops { - unsigned int reg_n); - void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr, - unsigned int reg_n); -- void (*set_eee_mode)(struct mac_device_info *hw); -+ void (*set_eee_mode)(struct mac_device_info *hw, -+ bool en_tx_lpi_clockgating); - void (*reset_eee_mode)(struct mac_device_info *hw); - void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw); - void (*set_eee_pls)(struct mac_device_info *hw, int link); ---- a/drivers/net/ethernet/stmicro/stmmac/descs.h -+++ b/drivers/net/ethernet/stmicro/stmmac/descs.h -@@ -11,10 +11,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h -+++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h -@@ -17,10 +17,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c -@@ -0,0 +1,202 @@ -+/* -+ * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver -+ * -+ * Copyright (C) 2016 Joao Pinto -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "stmmac_platform.h" -+ -+static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, -+ struct plat_stmmacenet_data *plat_dat) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ u32 burst_map = 0; -+ u32 bit_index = 0; -+ u32 a_index = 0; -+ -+ if (!plat_dat->axi) { -+ plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL); -+ -+ if (!plat_dat->axi) -+ return -ENOMEM; -+ } -+ -+ plat_dat->axi->axi_lpi_en = of_property_read_bool(np, "snps,en-lpi"); -+ if (of_property_read_u32(np, "snps,write-requests", -+ &plat_dat->axi->axi_wr_osr_lmt)) { -+ /** -+ * Since the register has a reset value of 1, if property -+ * is missing, default to 1. -+ */ -+ plat_dat->axi->axi_wr_osr_lmt = 1; -+ } else { -+ /** -+ * If property exists, to keep the behavior from dwc_eth_qos, -+ * subtract one after parsing. -+ */ -+ plat_dat->axi->axi_wr_osr_lmt--; -+ } -+ -+ if (of_property_read_u32(np, "read,read-requests", -+ &plat_dat->axi->axi_rd_osr_lmt)) { -+ /** -+ * Since the register has a reset value of 1, if property -+ * is missing, default to 1. -+ */ -+ plat_dat->axi->axi_rd_osr_lmt = 1; -+ } else { -+ /** -+ * If property exists, to keep the behavior from dwc_eth_qos, -+ * subtract one after parsing. -+ */ -+ plat_dat->axi->axi_rd_osr_lmt--; -+ } -+ of_property_read_u32(np, "snps,burst-map", &burst_map); -+ -+ /* converts burst-map bitmask to burst array */ -+ for (bit_index = 0; bit_index < 7; bit_index++) { -+ if (burst_map & (1 << bit_index)) { -+ switch (bit_index) { -+ case 0: -+ plat_dat->axi->axi_blen[a_index] = 4; break; -+ case 1: -+ plat_dat->axi->axi_blen[a_index] = 8; break; -+ case 2: -+ plat_dat->axi->axi_blen[a_index] = 16; break; -+ case 3: -+ plat_dat->axi->axi_blen[a_index] = 32; break; -+ case 4: -+ plat_dat->axi->axi_blen[a_index] = 64; break; -+ case 5: -+ plat_dat->axi->axi_blen[a_index] = 128; break; -+ case 6: -+ plat_dat->axi->axi_blen[a_index] = 256; break; -+ default: -+ break; -+ } -+ a_index++; -+ } -+ } -+ -+ /* dwc-qos needs GMAC4, AAL, TSO and PMT */ -+ plat_dat->has_gmac4 = 1; -+ plat_dat->dma_cfg->aal = 1; -+ plat_dat->tso_en = 1; -+ plat_dat->pmt = 1; -+ -+ return 0; -+} -+ -+static int dwc_eth_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct resource *res; -+ int ret; -+ -+ memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); -+ -+ /** -+ * Since stmmac_platform supports name IRQ only, basic platform -+ * resource initialization is done in the glue logic. -+ */ -+ stmmac_res.irq = platform_get_irq(pdev, 0); -+ if (stmmac_res.irq < 0) { -+ if (stmmac_res.irq != -EPROBE_DEFER) -+ dev_err(&pdev->dev, -+ "IRQ configuration information not found\n"); -+ -+ return stmmac_res.irq; -+ } -+ stmmac_res.wol_irq = stmmac_res.irq; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ stmmac_res.addr = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(stmmac_res.addr)) -+ return PTR_ERR(stmmac_res.addr); -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); -+ if (IS_ERR(plat_dat->stmmac_clk)) { -+ dev_err(&pdev->dev, "apb_pclk clock not found.\n"); -+ ret = PTR_ERR(plat_dat->stmmac_clk); -+ plat_dat->stmmac_clk = NULL; -+ goto err_remove_config_dt; -+ } -+ clk_prepare_enable(plat_dat->stmmac_clk); -+ -+ plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk"); -+ if (IS_ERR(plat_dat->pclk)) { -+ dev_err(&pdev->dev, "phy_ref_clk clock not found.\n"); -+ ret = PTR_ERR(plat_dat->pclk); -+ plat_dat->pclk = NULL; -+ goto err_out_clk_dis_phy; -+ } -+ clk_prepare_enable(plat_dat->pclk); -+ -+ ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); -+ if (ret) -+ goto err_out_clk_dis_aper; -+ -+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+ if (ret) -+ goto err_out_clk_dis_aper; -+ -+ return 0; -+ -+err_out_clk_dis_aper: -+ clk_disable_unprepare(plat_dat->pclk); -+err_out_clk_dis_phy: -+ clk_disable_unprepare(plat_dat->stmmac_clk); -+err_remove_config_dt: -+ stmmac_remove_config_dt(pdev, plat_dat); -+ -+ return ret; -+} -+ -+static int dwc_eth_dwmac_remove(struct platform_device *pdev) -+{ -+ return stmmac_pltfr_remove(pdev); -+} -+ -+static const struct of_device_id dwc_eth_dwmac_match[] = { -+ { .compatible = "snps,dwc-qos-ethernet-4.10", }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); -+ -+static struct platform_driver dwc_eth_dwmac_driver = { -+ .probe = dwc_eth_dwmac_probe, -+ .remove = dwc_eth_dwmac_remove, -+ .driver = { -+ .name = "dwc-eth-dwmac", -+ .of_match_table = dwc_eth_dwmac_match, -+ }, -+}; -+module_platform_driver(dwc_eth_dwmac_driver); -+ -+MODULE_AUTHOR("Joao Pinto "); -+MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver"); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c -@@ -35,10 +35,6 @@ - - #define PRG_ETH0_TXDLY_SHIFT 5 - #define PRG_ETH0_TXDLY_MASK GENMASK(6, 5) --#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT) --#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT) --#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT) --#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT) - - /* divider for the result of m250_sel */ - #define PRG_ETH0_CLK_M250_DIV_SHIFT 7 -@@ -69,6 +65,8 @@ struct meson8b_dwmac { - - struct clk_divider m25_div; - struct clk *m25_div_clk; -+ -+ u32 tx_delay_ns; - }; - - static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg, -@@ -181,11 +179,19 @@ static int meson8b_init_prg_eth(struct m - { - int ret; - unsigned long clk_rate; -+ u8 tx_dly_val = 0; - - switch (dwmac->phy_mode) { - case PHY_INTERFACE_MODE_RGMII: -- case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_RXID: -+ /* TX clock delay in ns = "8ns / 4 * tx_dly_val" (where -+ * 8ns are exactly one cycle of the 125MHz RGMII TX clock): -+ * 0ns = 0x0, 2ns = 0x1, 4ns = 0x2, 6ns = 0x3 -+ */ -+ tx_dly_val = dwmac->tx_delay_ns >> 1; -+ /* fall through */ -+ -+ case PHY_INTERFACE_MODE_RGMII_ID: - case PHY_INTERFACE_MODE_RGMII_TXID: - /* Generate a 25MHz clock for the PHY */ - clk_rate = 25 * 1000 * 1000; -@@ -198,9 +204,8 @@ static int meson8b_init_prg_eth(struct m - meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, - PRG_ETH0_INVERTED_RMII_CLK, 0); - -- /* TX clock delay - all known boards use a 1/4 cycle delay */ - meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK, -- PRG_ETH0_TXDLY_QUARTER); -+ tx_dly_val << PRG_ETH0_TXDLY_SHIFT); - break; - - case PHY_INTERFACE_MODE_RMII: -@@ -286,6 +291,11 @@ static int meson8b_dwmac_probe(struct pl - goto err_remove_config_dt; - } - -+ /* use 2ns as fallback since this value was previously hardcoded */ -+ if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns", -+ &dwmac->tx_delay_ns)) -+ dwmac->tx_delay_ns = 2; -+ - ret = meson8b_init_clk(dwmac); - if (ret) - goto err_remove_config_dt; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -302,6 +302,122 @@ static const struct rk_gmac_ops rk3288_o - .set_rmii_speed = rk3288_set_rmii_speed, - }; - -+#define RK3328_GRF_MAC_CON0 0x0900 -+#define RK3328_GRF_MAC_CON1 0x0904 -+ -+/* RK3328_GRF_MAC_CON0 */ -+#define RK3328_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) -+#define RK3328_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) -+ -+/* RK3328_GRF_MAC_CON1 */ -+#define RK3328_GMAC_PHY_INTF_SEL_RGMII \ -+ (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) -+#define RK3328_GMAC_PHY_INTF_SEL_RMII \ -+ (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6)) -+#define RK3328_GMAC_FLOW_CTRL GRF_BIT(3) -+#define RK3328_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3) -+#define RK3328_GMAC_SPEED_10M GRF_CLR_BIT(2) -+#define RK3328_GMAC_SPEED_100M GRF_BIT(2) -+#define RK3328_GMAC_RMII_CLK_25M GRF_BIT(7) -+#define RK3328_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(7) -+#define RK3328_GMAC_CLK_125M (GRF_CLR_BIT(11) | GRF_CLR_BIT(12)) -+#define RK3328_GMAC_CLK_25M (GRF_BIT(11) | GRF_BIT(12)) -+#define RK3328_GMAC_CLK_2_5M (GRF_CLR_BIT(11) | GRF_BIT(12)) -+#define RK3328_GMAC_RMII_MODE GRF_BIT(9) -+#define RK3328_GMAC_RMII_MODE_CLR GRF_CLR_BIT(9) -+#define RK3328_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0) -+#define RK3328_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0) -+#define RK3328_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1) -+#define RK3328_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(0) -+ -+static void rk3328_set_to_rgmii(struct rk_priv_data *bsp_priv, -+ int tx_delay, int rx_delay) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "Missing rockchip,grf property\n"); -+ return; -+ } -+ -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_PHY_INTF_SEL_RGMII | -+ RK3328_GMAC_RMII_MODE_CLR | -+ RK3328_GMAC_RXCLK_DLY_ENABLE | -+ RK3328_GMAC_TXCLK_DLY_ENABLE); -+ -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON0, -+ RK3328_GMAC_CLK_RX_DL_CFG(rx_delay) | -+ RK3328_GMAC_CLK_TX_DL_CFG(tx_delay)); -+} -+ -+static void rk3328_set_to_rmii(struct rk_priv_data *bsp_priv) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "Missing rockchip,grf property\n"); -+ return; -+ } -+ -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_PHY_INTF_SEL_RMII | -+ RK3328_GMAC_RMII_MODE); -+ -+ /* set MAC to RMII mode */ -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, GRF_BIT(11)); -+} -+ -+static void rk3328_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "Missing rockchip,grf property\n"); -+ return; -+ } -+ -+ if (speed == 10) -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_CLK_2_5M); -+ else if (speed == 100) -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_CLK_25M); -+ else if (speed == 1000) -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_CLK_125M); -+ else -+ dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); -+} -+ -+static void rk3328_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) -+{ -+ struct device *dev = &bsp_priv->pdev->dev; -+ -+ if (IS_ERR(bsp_priv->grf)) { -+ dev_err(dev, "Missing rockchip,grf property\n"); -+ return; -+ } -+ -+ if (speed == 10) -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_RMII_CLK_2_5M | -+ RK3328_GMAC_SPEED_10M); -+ else if (speed == 100) -+ regmap_write(bsp_priv->grf, RK3328_GRF_MAC_CON1, -+ RK3328_GMAC_RMII_CLK_25M | -+ RK3328_GMAC_SPEED_100M); -+ else -+ dev_err(dev, "unknown speed value for RMII! speed=%d", speed); -+} -+ -+static const struct rk_gmac_ops rk3328_ops = { -+ .set_to_rgmii = rk3328_set_to_rgmii, -+ .set_to_rmii = rk3328_set_to_rmii, -+ .set_rgmii_speed = rk3328_set_rgmii_speed, -+ .set_rmii_speed = rk3328_set_rmii_speed, -+}; -+ - #define RK3366_GRF_SOC_CON6 0x0418 - #define RK3366_GRF_SOC_CON7 0x041c - -@@ -1006,6 +1122,7 @@ static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, - static const struct of_device_id rk_gmac_dwmac_match[] = { - { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, - { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, -+ { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops }, - { .compatible = "rockchip,rk3366-gmac", .data = &rk3366_ops }, - { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops }, - { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops }, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -351,7 +351,7 @@ static int socfpga_dwmac_probe(struct pl - * mode. Create a copy of the core reset handle so it can be used by - * the driver later. - */ -- dwmac->stmmac_rst = stpriv->stmmac_rst; -+ dwmac->stmmac_rst = stpriv->plat->stmmac_rst; - - ret = socfpga_dwmac_set_phy_mode(dwmac); - if (ret) ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h -@@ -10,10 +10,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -@@ -16,10 +16,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -96,17 +92,13 @@ static int dwmac1000_rx_ipc_enable(struc - return !!(value & GMAC_CONTROL_IPC); - } - --static void dwmac1000_dump_regs(struct mac_device_info *hw) -+static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space) - { - void __iomem *ioaddr = hw->pcsr; - int i; -- pr_info("\tDWMAC1000 regs (base addr = 0x%p)\n", ioaddr); - -- for (i = 0; i < 55; i++) { -- int offset = i * 4; -- pr_info("\tReg No. %d (offset 0x%x): 0x%08x\n", i, -- offset, readl(ioaddr + offset)); -- } -+ for (i = 0; i < 55; i++) -+ reg_space[i] = readl(ioaddr + i * 4); - } - - static void dwmac1000_set_umac_addr(struct mac_device_info *hw, -@@ -347,11 +339,14 @@ static int dwmac1000_irq_status(struct m - return ret; - } - --static void dwmac1000_set_eee_mode(struct mac_device_info *hw) -+static void dwmac1000_set_eee_mode(struct mac_device_info *hw, -+ bool en_tx_lpi_clockgating) - { - void __iomem *ioaddr = hw->pcsr; - u32 value; - -+ /*TODO - en_tx_lpi_clockgating treatment */ -+ - /* Enable the link status receive on RGMII, SGMII ore SMII - * receive path and instruct the transmit to enter in LPI - * state. ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -16,10 +16,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -205,18 +201,14 @@ static void dwmac1000_dma_operation_mode - writel(csr6, ioaddr + DMA_CONTROL); - } - --static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) -+static void dwmac1000_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) - { - int i; -- pr_info(" DMA registers\n"); -- for (i = 0; i < 22; i++) { -- if ((i < 9) || (i > 17)) { -- int offset = i * 4; -- pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i, -- (DMA_BUS_MODE + offset), -- readl(ioaddr + DMA_BUS_MODE + offset)); -- } -- } -+ -+ for (i = 0; i < 22; i++) -+ if ((i < 9) || (i > 17)) -+ reg_space[DMA_BUS_MODE / 4 + i] = -+ readl(ioaddr + DMA_BUS_MODE + i * 4); - } - - static void dwmac1000_get_hw_feature(void __iomem *ioaddr, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -@@ -18,10 +18,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -44,28 +40,18 @@ static void dwmac100_core_init(struct ma - #endif - } - --static void dwmac100_dump_mac_regs(struct mac_device_info *hw) -+static void dwmac100_dump_mac_regs(struct mac_device_info *hw, u32 *reg_space) - { - void __iomem *ioaddr = hw->pcsr; -- pr_info("\t----------------------------------------------\n" -- "\t DWMAC 100 CSR (base addr = 0x%p)\n" -- "\t----------------------------------------------\n", ioaddr); -- pr_info("\tcontrol reg (offset 0x%x): 0x%08x\n", MAC_CONTROL, -- readl(ioaddr + MAC_CONTROL)); -- pr_info("\taddr HI (offset 0x%x): 0x%08x\n ", MAC_ADDR_HIGH, -- readl(ioaddr + MAC_ADDR_HIGH)); -- pr_info("\taddr LO (offset 0x%x): 0x%08x\n", MAC_ADDR_LOW, -- readl(ioaddr + MAC_ADDR_LOW)); -- pr_info("\tmulticast hash HI (offset 0x%x): 0x%08x\n", -- MAC_HASH_HIGH, readl(ioaddr + MAC_HASH_HIGH)); -- pr_info("\tmulticast hash LO (offset 0x%x): 0x%08x\n", -- MAC_HASH_LOW, readl(ioaddr + MAC_HASH_LOW)); -- pr_info("\tflow control (offset 0x%x): 0x%08x\n", -- MAC_FLOW_CTRL, readl(ioaddr + MAC_FLOW_CTRL)); -- pr_info("\tVLAN1 tag (offset 0x%x): 0x%08x\n", MAC_VLAN1, -- readl(ioaddr + MAC_VLAN1)); -- pr_info("\tVLAN2 tag (offset 0x%x): 0x%08x\n", MAC_VLAN2, -- readl(ioaddr + MAC_VLAN2)); -+ -+ reg_space[MAC_CONTROL / 4] = readl(ioaddr + MAC_CONTROL); -+ reg_space[MAC_ADDR_HIGH / 4] = readl(ioaddr + MAC_ADDR_HIGH); -+ reg_space[MAC_ADDR_LOW / 4] = readl(ioaddr + MAC_ADDR_LOW); -+ reg_space[MAC_HASH_HIGH / 4] = readl(ioaddr + MAC_HASH_HIGH); -+ reg_space[MAC_HASH_LOW / 4] = readl(ioaddr + MAC_HASH_LOW); -+ reg_space[MAC_FLOW_CTRL / 4] = readl(ioaddr + MAC_FLOW_CTRL); -+ reg_space[MAC_VLAN1 / 4] = readl(ioaddr + MAC_VLAN1); -+ reg_space[MAC_VLAN2 / 4] = readl(ioaddr + MAC_VLAN2); - } - - static int dwmac100_rx_ipc_enable(struct mac_device_info *hw) ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -@@ -18,10 +18,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -70,19 +66,18 @@ static void dwmac100_dma_operation_mode( - writel(csr6, ioaddr + DMA_CONTROL); - } - --static void dwmac100_dump_dma_regs(void __iomem *ioaddr) -+static void dwmac100_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) - { - int i; - -- pr_debug("DWMAC 100 DMA CSR\n"); - for (i = 0; i < 9; i++) -- pr_debug("\t CSR%d (offset 0x%x): 0x%08x\n", i, -- (DMA_BUS_MODE + i * 4), -- readl(ioaddr + DMA_BUS_MODE + i * 4)); -- -- pr_debug("\tCSR20 (0x%x): 0x%08x, CSR21 (0x%x): 0x%08x\n", -- DMA_CUR_TX_BUF_ADDR, readl(ioaddr + DMA_CUR_TX_BUF_ADDR), -- DMA_CUR_RX_BUF_ADDR, readl(ioaddr + DMA_CUR_RX_BUF_ADDR)); -+ reg_space[DMA_BUS_MODE / 4 + i] = -+ readl(ioaddr + DMA_BUS_MODE + i * 4); -+ -+ reg_space[DMA_CUR_TX_BUF_ADDR / 4] = -+ readl(ioaddr + DMA_CUR_TX_BUF_ADDR); -+ reg_space[DMA_CUR_RX_BUF_ADDR / 4] = -+ readl(ioaddr + DMA_CUR_RX_BUF_ADDR); - } - - /* DMA controller has two counters to track the number of the missed frames. */ ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -@@ -22,6 +22,7 @@ - #define GMAC_HASH_TAB_32_63 0x00000014 - #define GMAC_RX_FLOW_CTRL 0x00000090 - #define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4) -+#define GMAC_RXQ_CTRL0 0x000000a0 - #define GMAC_INT_STATUS 0x000000b0 - #define GMAC_INT_EN 0x000000b4 - #define GMAC_PCS_BASE 0x000000e0 -@@ -44,6 +45,11 @@ - - #define GMAC_MAX_PERFECT_ADDRESSES 128 - -+/* MAC RX Queue Enable */ -+#define GMAC_RX_QUEUE_CLEAR(queue) ~(GENMASK(1, 0) << ((queue) * 2)) -+#define GMAC_RX_AV_QUEUE_ENABLE(queue) BIT((queue) * 2) -+#define GMAC_RX_DCB_QUEUE_ENABLE(queue) BIT(((queue) * 2) + 1) -+ - /* MAC Flow Control RX */ - #define GMAC_RX_FLOW_CTRL_RFE BIT(0) - -@@ -84,6 +90,19 @@ enum power_event { - power_down = 0x00000001, - }; - -+/* Energy Efficient Ethernet (EEE) for GMAC4 -+ * -+ * LPI status, timer and control register offset -+ */ -+#define GMAC4_LPI_CTRL_STATUS 0xd0 -+#define GMAC4_LPI_TIMER_CTRL 0xd4 -+ -+/* LPI control and status defines */ -+#define GMAC4_LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable */ -+#define GMAC4_LPI_CTRL_STATUS_LPITXA BIT(19) /* Enable LPI TX Automate */ -+#define GMAC4_LPI_CTRL_STATUS_PLS BIT(17) /* PHY Link Status */ -+#define GMAC4_LPI_CTRL_STATUS_LPIEN BIT(16) /* LPI Enable */ -+ - /* MAC Debug bitmap */ - #define GMAC_DEBUG_TFCSTS_MASK GENMASK(18, 17) - #define GMAC_DEBUG_TFCSTS_SHIFT 17 -@@ -133,6 +152,8 @@ enum power_event { - /* MAC HW features2 bitmap */ - #define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18) - #define GMAC_HW_FEAT_RXCHCNT GENMASK(15, 12) -+#define GMAC_HW_FEAT_TXQCNT GENMASK(9, 6) -+#define GMAC_HW_FEAT_RXQCNT GENMASK(3, 0) - - /* MAC HW ADDR regs */ - #define GMAC_HI_DCS GENMASK(18, 16) ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -59,19 +59,24 @@ static void dwmac4_core_init(struct mac_ - writel(value, ioaddr + GMAC_INT_EN); - } - --static void dwmac4_dump_regs(struct mac_device_info *hw) -+static void dwmac4_rx_queue_enable(struct mac_device_info *hw, u32 queue) - { - void __iomem *ioaddr = hw->pcsr; -- int i; -+ u32 value = readl(ioaddr + GMAC_RXQ_CTRL0); - -- pr_debug("\tDWMAC4 regs (base addr = 0x%p)\n", ioaddr); -+ value &= GMAC_RX_QUEUE_CLEAR(queue); -+ value |= GMAC_RX_AV_QUEUE_ENABLE(queue); - -- for (i = 0; i < GMAC_REG_NUM; i++) { -- int offset = i * 4; -+ writel(value, ioaddr + GMAC_RXQ_CTRL0); -+} - -- pr_debug("\tReg No. %d (offset 0x%x): 0x%08x\n", i, -- offset, readl(ioaddr + offset)); -- } -+static void dwmac4_dump_regs(struct mac_device_info *hw, u32 *reg_space) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ int i; -+ -+ for (i = 0; i < GMAC_REG_NUM; i++) -+ reg_space[i] = readl(ioaddr + i * 4); - } - - static int dwmac4_rx_ipc_enable(struct mac_device_info *hw) -@@ -126,6 +131,65 @@ static void dwmac4_get_umac_addr(struct - GMAC_ADDR_LOW(reg_n)); - } - -+static void dwmac4_set_eee_mode(struct mac_device_info *hw, -+ bool en_tx_lpi_clockgating) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ /* Enable the link status receive on RGMII, SGMII ore SMII -+ * receive path and instruct the transmit to enter in LPI -+ * state. -+ */ -+ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS); -+ value |= GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA; -+ -+ if (en_tx_lpi_clockgating) -+ value |= GMAC4_LPI_CTRL_STATUS_LPITCSE; -+ -+ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS); -+} -+ -+static void dwmac4_reset_eee_mode(struct mac_device_info *hw) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS); -+ value &= ~(GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA); -+ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS); -+} -+ -+static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS); -+ -+ if (link) -+ value |= GMAC4_LPI_CTRL_STATUS_PLS; -+ else -+ value &= ~GMAC4_LPI_CTRL_STATUS_PLS; -+ -+ writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS); -+} -+ -+static void dwmac4_set_eee_timer(struct mac_device_info *hw, int ls, int tw) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ int value = ((tw & 0xffff)) | ((ls & 0x3ff) << 16); -+ -+ /* Program the timers in the LPI timer control register: -+ * LS: minimum time (ms) for which the link -+ * status from PHY should be ok before transmitting -+ * the LPI pattern. -+ * TW: minimum time (us) for which the core waits -+ * after it has stopped transmitting the LPI pattern. -+ */ -+ writel(value, ioaddr + GMAC4_LPI_TIMER_CTRL); -+} -+ - static void dwmac4_set_filter(struct mac_device_info *hw, - struct net_device *dev) - { -@@ -392,12 +456,17 @@ static void dwmac4_debug(void __iomem *i - static const struct stmmac_ops dwmac4_ops = { - .core_init = dwmac4_core_init, - .rx_ipc = dwmac4_rx_ipc_enable, -+ .rx_queue_enable = dwmac4_rx_queue_enable, - .dump_regs = dwmac4_dump_regs, - .host_irq_status = dwmac4_irq_status, - .flow_ctrl = dwmac4_flow_ctrl, - .pmt = dwmac4_pmt, - .set_umac_addr = dwmac4_set_umac_addr, - .get_umac_addr = dwmac4_get_umac_addr, -+ .set_eee_mode = dwmac4_set_eee_mode, -+ .reset_eee_mode = dwmac4_reset_eee_mode, -+ .set_eee_timer = dwmac4_set_eee_timer, -+ .set_eee_pls = dwmac4_set_eee_pls, - .pcs_ctrl_ane = dwmac4_ctrl_ane, - .pcs_rane = dwmac4_rane, - .pcs_get_adv_lp = dwmac4_get_adv_lp, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -@@ -103,7 +103,7 @@ static int dwmac4_wrback_get_rx_status(v - x->rx_mii++; - - if (unlikely(rdes3 & RDES3_CRC_ERROR)) { -- x->rx_crc++; -+ x->rx_crc_errors++; - stats->rx_crc_errors++; - } - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -@@ -127,53 +127,51 @@ static void dwmac4_dma_init(void __iomem - dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i); - } - --static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel) -+static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel, -+ u32 *reg_space) - { -- pr_debug(" Channel %d\n", channel); -- pr_debug("\tDMA_CHAN_CONTROL, offset: 0x%x, val: 0x%x\n", 0, -- readl(ioaddr + DMA_CHAN_CONTROL(channel))); -- pr_debug("\tDMA_CHAN_TX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x4, -- readl(ioaddr + DMA_CHAN_TX_CONTROL(channel))); -- pr_debug("\tDMA_CHAN_RX_CONTROL, offset: 0x%x, val: 0x%x\n", 0x8, -- readl(ioaddr + DMA_CHAN_RX_CONTROL(channel))); -- pr_debug("\tDMA_CHAN_TX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x14, -- readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel))); -- pr_debug("\tDMA_CHAN_RX_BASE_ADDR, offset: 0x%x, val: 0x%x\n", 0x1c, -- readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel))); -- pr_debug("\tDMA_CHAN_TX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x20, -- readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel))); -- pr_debug("\tDMA_CHAN_RX_END_ADDR, offset: 0x%x, val: 0x%x\n", 0x28, -- readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel))); -- pr_debug("\tDMA_CHAN_TX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x2c, -- readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel))); -- pr_debug("\tDMA_CHAN_RX_RING_LEN, offset: 0x%x, val: 0x%x\n", 0x30, -- readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel))); -- pr_debug("\tDMA_CHAN_INTR_ENA, offset: 0x%x, val: 0x%x\n", 0x34, -- readl(ioaddr + DMA_CHAN_INTR_ENA(channel))); -- pr_debug("\tDMA_CHAN_RX_WATCHDOG, offset: 0x%x, val: 0x%x\n", 0x38, -- readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel))); -- pr_debug("\tDMA_CHAN_SLOT_CTRL_STATUS, offset: 0x%x, val: 0x%x\n", 0x3c, -- readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel))); -- pr_debug("\tDMA_CHAN_CUR_TX_DESC, offset: 0x%x, val: 0x%x\n", 0x44, -- readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel))); -- pr_debug("\tDMA_CHAN_CUR_RX_DESC, offset: 0x%x, val: 0x%x\n", 0x4c, -- readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel))); -- pr_debug("\tDMA_CHAN_CUR_TX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x54, -- readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel))); -- pr_debug("\tDMA_CHAN_CUR_RX_BUF_ADDR, offset: 0x%x, val: 0x%x\n", 0x5c, -- readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel))); -- pr_debug("\tDMA_CHAN_STATUS, offset: 0x%x, val: 0x%x\n", 0x60, -- readl(ioaddr + DMA_CHAN_STATUS(channel))); -+ reg_space[DMA_CHAN_CONTROL(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_CONTROL(channel)); -+ reg_space[DMA_CHAN_TX_CONTROL(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)); -+ reg_space[DMA_CHAN_RX_CONTROL(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)); -+ reg_space[DMA_CHAN_TX_BASE_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)); -+ reg_space[DMA_CHAN_RX_BASE_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)); -+ reg_space[DMA_CHAN_TX_END_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_TX_END_ADDR(channel)); -+ reg_space[DMA_CHAN_RX_END_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_RX_END_ADDR(channel)); -+ reg_space[DMA_CHAN_TX_RING_LEN(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_TX_RING_LEN(channel)); -+ reg_space[DMA_CHAN_RX_RING_LEN(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_RX_RING_LEN(channel)); -+ reg_space[DMA_CHAN_INTR_ENA(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_INTR_ENA(channel)); -+ reg_space[DMA_CHAN_RX_WATCHDOG(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_RX_WATCHDOG(channel)); -+ reg_space[DMA_CHAN_SLOT_CTRL_STATUS(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_SLOT_CTRL_STATUS(channel)); -+ reg_space[DMA_CHAN_CUR_TX_DESC(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_CUR_TX_DESC(channel)); -+ reg_space[DMA_CHAN_CUR_RX_DESC(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_CUR_RX_DESC(channel)); -+ reg_space[DMA_CHAN_CUR_TX_BUF_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_CUR_TX_BUF_ADDR(channel)); -+ reg_space[DMA_CHAN_CUR_RX_BUF_ADDR(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_CUR_RX_BUF_ADDR(channel)); -+ reg_space[DMA_CHAN_STATUS(channel) / 4] = -+ readl(ioaddr + DMA_CHAN_STATUS(channel)); - } - --static void dwmac4_dump_dma_regs(void __iomem *ioaddr) -+static void dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 *reg_space) - { - int i; - -- pr_debug(" GMAC4 DMA registers\n"); -- - for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) -- _dwmac4_dump_dma_regs(ioaddr, i); -+ _dwmac4_dump_dma_regs(ioaddr, i, reg_space); - } - - static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) -@@ -303,6 +301,11 @@ static void dwmac4_get_hw_feature(void _ - ((hw_cap & GMAC_HW_FEAT_RXCHCNT) >> 12) + 1; - dma_cap->number_tx_channel = - ((hw_cap & GMAC_HW_FEAT_TXCHCNT) >> 18) + 1; -+ /* TX and RX number of queues */ -+ dma_cap->number_rx_queues = -+ ((hw_cap & GMAC_HW_FEAT_RXQCNT) >> 0) + 1; -+ dma_cap->number_tx_queues = -+ ((hw_cap & GMAC_HW_FEAT_TXQCNT) >> 6) + 1; - - /* IEEE 1588-2002 */ - dma_cap->time_stamp = 0; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -@@ -10,10 +10,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -21,6 +17,7 @@ - *******************************************************************************/ - - #include -+#include - #include "common.h" - #include "dwmac_dma.h" - -@@ -29,19 +26,16 @@ - int dwmac_dma_reset(void __iomem *ioaddr) - { - u32 value = readl(ioaddr + DMA_BUS_MODE); -- int limit; -+ int err; - - /* DMA SW reset */ - value |= DMA_BUS_MODE_SFT_RESET; - writel(value, ioaddr + DMA_BUS_MODE); -- limit = 10; -- while (limit--) { -- if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET)) -- break; -- mdelay(10); -- } - -- if (limit < 0) -+ err = readl_poll_timeout(ioaddr + DMA_BUS_MODE, value, -+ !(value & DMA_BUS_MODE_SFT_RESET), -+ 100000, 10000); -+ if (err) - return -EBUSY; - - return 0; -@@ -102,7 +96,7 @@ static void show_tx_process_state(unsign - pr_debug("- TX (Stopped): Reset or Stop command\n"); - break; - case 1: -- pr_debug("- TX (Running):Fetching the Tx desc\n"); -+ pr_debug("- TX (Running): Fetching the Tx desc\n"); - break; - case 2: - pr_debug("- TX (Running): Waiting for end of tx\n"); -@@ -136,7 +130,7 @@ static void show_rx_process_state(unsign - pr_debug("- RX (Running): Fetching the Rx desc\n"); - break; - case 2: -- pr_debug("- RX (Running):Checking for end of pkt\n"); -+ pr_debug("- RX (Running): Checking for end of pkt\n"); - break; - case 3: - pr_debug("- RX (Running): Waiting for Rx pkt\n"); -@@ -246,7 +240,7 @@ void stmmac_set_mac_addr(void __iomem *i - unsigned long data; - - data = (addr[5] << 8) | addr[4]; -- /* For MAC Addr registers se have to set the Address Enable (AE) -+ /* For MAC Addr registers we have to set the Address Enable (AE) - * bit that has no effect on the High Reg 0 where the bit 31 (MO) - * is RO. - */ -@@ -261,9 +255,9 @@ void stmmac_set_mac(void __iomem *ioaddr - u32 value = readl(ioaddr + MAC_CTRL_REG); - - if (enable) -- value |= MAC_RNABLE_RX | MAC_ENABLE_TX; -+ value |= MAC_ENABLE_RX | MAC_ENABLE_TX; - else -- value &= ~(MAC_ENABLE_TX | MAC_RNABLE_RX); -+ value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX); - - writel(value, ioaddr + MAC_CTRL_REG); - } ---- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -225,7 +221,7 @@ static int enh_desc_get_rx_status(void * - x->rx_mii++; - - if (unlikely(rdes0 & RDES0_CRC_ERROR)) { -- x->rx_crc++; -+ x->rx_crc_errors++; - stats->rx_crc_errors++; - } - ret = discard_frame; ---- a/drivers/net/ethernet/stmicro/stmmac/mmc.h -+++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -115,7 +111,7 @@ static int ndesc_get_rx_status(void *dat - stats->collisions++; - } - if (unlikely(rdes0 & RDES0_CRC_ERROR)) { -- x->rx_crc++; -+ x->rx_crc_errors++; - stats->rx_crc_errors++; - } - ret = discard_frame; ---- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -@@ -16,10 +16,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -10,10 +10,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -106,9 +102,6 @@ struct stmmac_priv { - u32 msg_enable; - int wolopts; - int wol_irq; -- struct clk *stmmac_clk; -- struct clk *pclk; -- struct reset_control *stmmac_rst; - int clk_csr; - struct timer_list eee_ctrl_timer; - int lpi_irq; -@@ -120,8 +113,6 @@ struct stmmac_priv { - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_clock_ops; - unsigned int default_addend; -- struct clk *clk_ptp_ref; -- unsigned int clk_ptp_rate; - u32 adv_ts; - int use_riwt; - int irq_wake; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -65,7 +61,7 @@ static const struct stmmac_stats stmmac_ - STMMAC_STAT(overflow_error), - STMMAC_STAT(ipc_csum_error), - STMMAC_STAT(rx_collision), -- STMMAC_STAT(rx_crc), -+ STMMAC_STAT(rx_crc_errors), - STMMAC_STAT(dribbling_bit), - STMMAC_STAT(rx_length), - STMMAC_STAT(rx_mii), -@@ -439,32 +435,14 @@ static int stmmac_ethtool_get_regs_len(s - static void stmmac_ethtool_gregs(struct net_device *dev, - struct ethtool_regs *regs, void *space) - { -- int i; - u32 *reg_space = (u32 *) space; - - struct stmmac_priv *priv = netdev_priv(dev); - - memset(reg_space, 0x0, REG_SPACE_SIZE); - -- if (!(priv->plat->has_gmac || priv->plat->has_gmac4)) { -- /* MAC registers */ -- for (i = 0; i < 12; i++) -- reg_space[i] = readl(priv->ioaddr + (i * 4)); -- /* DMA registers */ -- for (i = 0; i < 9; i++) -- reg_space[i + 12] = -- readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4))); -- reg_space[22] = readl(priv->ioaddr + DMA_CUR_TX_BUF_ADDR); -- reg_space[23] = readl(priv->ioaddr + DMA_CUR_RX_BUF_ADDR); -- } else { -- /* MAC registers */ -- for (i = 0; i < 55; i++) -- reg_space[i] = readl(priv->ioaddr + (i * 4)); -- /* DMA registers */ -- for (i = 0; i < 22; i++) -- reg_space[i + 55] = -- readl(priv->ioaddr + (DMA_BUS_MODE + (i * 4))); -- } -+ priv->hw->mac->dump_regs(priv->hw, reg_space); -+ priv->hw->dma->dump_regs(priv->ioaddr, reg_space); - } - - static void -@@ -712,7 +690,7 @@ static int stmmac_ethtool_op_set_eee(str - - static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv) - { -- unsigned long clk = clk_get_rate(priv->stmmac_clk); -+ unsigned long clk = clk_get_rate(priv->plat->stmmac_clk); - - if (!clk) - return 0; -@@ -722,7 +700,7 @@ static u32 stmmac_usec2riwt(u32 usec, st - - static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv) - { -- unsigned long clk = clk_get_rate(priv->stmmac_clk); -+ unsigned long clk = clk_get_rate(priv->plat->stmmac_clk); - - if (!clk) - return 0; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -13,10 +13,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -158,7 +154,7 @@ static void stmmac_clk_csr_set(struct st - { - u32 clk_rate; - -- clk_rate = clk_get_rate(priv->stmmac_clk); -+ clk_rate = clk_get_rate(priv->plat->stmmac_clk); - - /* Platform provided default clk_csr would be assumed valid - * for all other cases except for the below mentioned ones. -@@ -191,7 +187,7 @@ static void print_pkt(unsigned char *buf - - static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) - { -- unsigned avail; -+ u32 avail; - - if (priv->dirty_tx > priv->cur_tx) - avail = priv->dirty_tx - priv->cur_tx - 1; -@@ -203,7 +199,7 @@ static inline u32 stmmac_tx_avail(struct - - static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv) - { -- unsigned dirty; -+ u32 dirty; - - if (priv->dirty_rx <= priv->cur_rx) - dirty = priv->cur_rx - priv->dirty_rx; -@@ -216,7 +212,7 @@ static inline u32 stmmac_rx_dirty(struct - /** - * stmmac_hw_fix_mac_speed - callback for speed selection - * @priv: driver private structure -- * Description: on some platforms (e.g. ST), some HW system configuraton -+ * Description: on some platforms (e.g. ST), some HW system configuration - * registers have to be set according to the link speed negotiated. - */ - static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) -@@ -239,7 +235,8 @@ static void stmmac_enable_eee_mode(struc - /* Check and enter in LPI mode */ - if ((priv->dirty_tx == priv->cur_tx) && - (priv->tx_path_in_lpi_mode == false)) -- priv->hw->mac->set_eee_mode(priv->hw); -+ priv->hw->mac->set_eee_mode(priv->hw, -+ priv->plat->en_tx_lpi_clockgating); - } - - /** -@@ -421,7 +418,7 @@ static void stmmac_get_rx_hwtstamp(struc - /** - * stmmac_hwtstamp_ioctl - control hardware timestamping. - * @dev: device pointer. -- * @ifr: An IOCTL specefic structure, that can contain a pointer to -+ * @ifr: An IOCTL specific structure, that can contain a pointer to - * a proprietary structure used to pass information to the driver. - * Description: - * This function configures the MAC to enable/disable both outgoing(TX) -@@ -621,7 +618,7 @@ static int stmmac_hwtstamp_ioctl(struct - - /* program Sub Second Increment reg */ - sec_inc = priv->hw->ptp->config_sub_second_increment( -- priv->ptpaddr, priv->clk_ptp_rate, -+ priv->ptpaddr, priv->plat->clk_ptp_rate, - priv->plat->has_gmac4); - temp = div_u64(1000000000ULL, sec_inc); - -@@ -631,7 +628,7 @@ static int stmmac_hwtstamp_ioctl(struct - * where, freq_div_ratio = 1e9ns/sec_inc - */ - temp = (u64)(temp << 32); -- priv->default_addend = div_u64(temp, priv->clk_ptp_rate); -+ priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); - priv->hw->ptp->config_addend(priv->ptpaddr, - priv->default_addend); - -@@ -659,18 +656,6 @@ static int stmmac_init_ptp(struct stmmac - if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) - return -EOPNOTSUPP; - -- /* Fall-back to main clock in case of no PTP ref is passed */ -- priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref"); -- if (IS_ERR(priv->clk_ptp_ref)) { -- priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk); -- priv->clk_ptp_ref = NULL; -- netdev_dbg(priv->dev, "PTP uses main clock\n"); -- } else { -- clk_prepare_enable(priv->clk_ptp_ref); -- priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref); -- netdev_dbg(priv->dev, "PTP rate %d\n", priv->clk_ptp_rate); -- } -- - priv->adv_ts = 0; - /* Check if adv_ts can be enabled for dwmac 4.x core */ - if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp) -@@ -697,8 +682,8 @@ static int stmmac_init_ptp(struct stmmac - - static void stmmac_release_ptp(struct stmmac_priv *priv) - { -- if (priv->clk_ptp_ref) -- clk_disable_unprepare(priv->clk_ptp_ref); -+ if (priv->plat->clk_ptp_ref) -+ clk_disable_unprepare(priv->plat->clk_ptp_ref); - stmmac_ptp_unregister(priv); - } - -@@ -719,7 +704,7 @@ static void stmmac_adjust_link(struct ne - int new_state = 0; - unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; - -- if (phydev == NULL) -+ if (!phydev) - return; - - spin_lock_irqsave(&priv->lock, flags); -@@ -746,33 +731,36 @@ static void stmmac_adjust_link(struct ne - new_state = 1; - switch (phydev->speed) { - case 1000: -- if (likely((priv->plat->has_gmac) || -- (priv->plat->has_gmac4))) -+ if (priv->plat->has_gmac || -+ priv->plat->has_gmac4) - ctrl &= ~priv->hw->link.port; -- stmmac_hw_fix_mac_speed(priv); - break; - case 100: -+ if (priv->plat->has_gmac || -+ priv->plat->has_gmac4) { -+ ctrl |= priv->hw->link.port; -+ ctrl |= priv->hw->link.speed; -+ } else { -+ ctrl &= ~priv->hw->link.port; -+ } -+ break; - case 10: -- if (likely((priv->plat->has_gmac) || -- (priv->plat->has_gmac4))) { -+ if (priv->plat->has_gmac || -+ priv->plat->has_gmac4) { - ctrl |= priv->hw->link.port; -- if (phydev->speed == SPEED_100) { -- ctrl |= priv->hw->link.speed; -- } else { -- ctrl &= ~(priv->hw->link.speed); -- } -+ ctrl &= ~(priv->hw->link.speed); - } else { - ctrl &= ~priv->hw->link.port; - } -- stmmac_hw_fix_mac_speed(priv); - break; - default: - netif_warn(priv, link, priv->dev, -- "Speed (%d) not 10/100\n", -- phydev->speed); -+ "broken speed: %d\n", phydev->speed); -+ phydev->speed = SPEED_UNKNOWN; - break; - } -- -+ if (phydev->speed != SPEED_UNKNOWN) -+ stmmac_hw_fix_mac_speed(priv); - priv->speed = phydev->speed; - } - -@@ -785,8 +773,8 @@ static void stmmac_adjust_link(struct ne - } else if (priv->oldlink) { - new_state = 1; - priv->oldlink = 0; -- priv->speed = 0; -- priv->oldduplex = -1; -+ priv->speed = SPEED_UNKNOWN; -+ priv->oldduplex = DUPLEX_UNKNOWN; - } - - if (new_state && netif_msg_link(priv)) -@@ -848,8 +836,8 @@ static int stmmac_init_phy(struct net_de - int interface = priv->plat->interface; - int max_speed = priv->plat->max_speed; - priv->oldlink = 0; -- priv->speed = 0; -- priv->oldduplex = -1; -+ priv->speed = SPEED_UNKNOWN; -+ priv->oldduplex = DUPLEX_UNKNOWN; - - if (priv->plat->phy_node) { - phydev = of_phy_connect(dev, priv->plat->phy_node, -@@ -901,9 +889,7 @@ static int stmmac_init_phy(struct net_de - if (phydev->is_pseudo_fixed_link) - phydev->irq = PHY_POLL; - -- netdev_dbg(priv->dev, "%s: attached to PHY (UID 0x%x) Link = %d\n", -- __func__, phydev->phy_id, phydev->link); -- -+ phy_attached_info(phydev); - return 0; - } - -@@ -1029,7 +1015,7 @@ static void stmmac_free_rx_buffers(struc - * @dev: net device structure - * @flags: gfp flag. - * Description: this function initializes the DMA RX/TX descriptors -- * and allocates the socket buffers. It suppors the chained and ring -+ * and allocates the socket buffers. It supports the chained and ring - * modes. - */ - static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) -@@ -1142,13 +1128,6 @@ static void dma_free_tx_skbufs(struct st - int i; - - for (i = 0; i < DMA_TX_SIZE; i++) { -- struct dma_desc *p; -- -- if (priv->extend_desc) -- p = &((priv->dma_etx + i)->basic); -- else -- p = priv->dma_tx + i; -- - if (priv->tx_skbuff_dma[i].buf) { - if (priv->tx_skbuff_dma[i].map_as_page) - dma_unmap_page(priv->device, -@@ -1162,7 +1141,7 @@ static void dma_free_tx_skbufs(struct st - DMA_TO_DEVICE); - } - -- if (priv->tx_skbuff[i] != NULL) { -+ if (priv->tx_skbuff[i]) { - dev_kfree_skb_any(priv->tx_skbuff[i]); - priv->tx_skbuff[i] = NULL; - priv->tx_skbuff_dma[i].buf = 0; -@@ -1286,6 +1265,28 @@ static void free_dma_desc_resources(stru - } - - /** -+ * stmmac_mac_enable_rx_queues - Enable MAC rx queues -+ * @priv: driver private structure -+ * Description: It is used for enabling the rx queues in the MAC -+ */ -+static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) -+{ -+ int rx_count = priv->dma_cap.number_rx_queues; -+ int queue = 0; -+ -+ /* If GMAC does not have multiple queues, then this is not necessary*/ -+ if (rx_count == 1) -+ return; -+ -+ /** -+ * If the core is synthesized with multiple rx queues / multiple -+ * dma channels, then rx queues will be disabled by default. -+ * For now only rx queue 0 is enabled. -+ */ -+ priv->hw->mac->rx_queue_enable(priv->hw, queue); -+} -+ -+/** - * stmmac_dma_operation_mode - HW DMA operation mode - * @priv: driver private structure - * Description: it is used for configuring the DMA operation mode register in -@@ -1691,10 +1692,6 @@ static int stmmac_hw_setup(struct net_de - /* Copy the MAC addr into the HW */ - priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); - -- /* If required, perform hw setup of the bus. */ -- if (priv->plat->bus_setup) -- priv->plat->bus_setup(priv->ioaddr); -- - /* PS and related bits will be programmed according to the speed */ - if (priv->hw->pcs) { - int speed = priv->plat->mac_port_sel_speed; -@@ -1711,6 +1708,10 @@ static int stmmac_hw_setup(struct net_de - /* Initialize the MAC Core */ - priv->hw->mac->core_init(priv->hw, dev->mtu); - -+ /* Initialize MAC RX Queues */ -+ if (priv->hw->mac->rx_queue_enable) -+ stmmac_mac_enable_rx_queues(priv); -+ - ret = priv->hw->mac->rx_ipc(priv->hw); - if (!ret) { - netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); -@@ -1731,8 +1732,10 @@ static int stmmac_hw_setup(struct net_de - - if (init_ptp) { - ret = stmmac_init_ptp(priv); -- if (ret) -- netdev_warn(priv->dev, "fail to init PTP.\n"); -+ if (ret == -EOPNOTSUPP) -+ netdev_warn(priv->dev, "PTP not supported by HW\n"); -+ else if (ret) -+ netdev_warn(priv->dev, "PTP init failed\n"); - } - - #ifdef CONFIG_DEBUG_FS -@@ -1746,11 +1749,6 @@ static int stmmac_hw_setup(struct net_de - priv->hw->dma->start_tx(priv->ioaddr); - priv->hw->dma->start_rx(priv->ioaddr); - -- /* Dump DMA/MAC registers */ -- if (netif_msg_hw(priv)) { -- priv->hw->mac->dump_regs(priv->hw); -- priv->hw->dma->dump_regs(priv->ioaddr); -- } - priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; - - if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { -@@ -2547,7 +2545,7 @@ static int stmmac_rx(struct stmmac_priv - if (unlikely(status == discard_frame)) { - priv->dev->stats.rx_errors++; - if (priv->hwts_rx_en && !priv->extend_desc) { -- /* DESC2 & DESC3 will be overwitten by device -+ /* DESC2 & DESC3 will be overwritten by device - * with timestamp value, hence reinitialize - * them in stmmac_rx_refill() function so that - * device can reuse it. -@@ -2570,7 +2568,7 @@ static int stmmac_rx(struct stmmac_priv - - frame_len = priv->hw->desc->get_rx_frame_len(p, coe); - -- /* If frame length is greather than skb buffer size -+ /* If frame length is greater than skb buffer size - * (preallocated during init) then the packet is - * ignored - */ -@@ -2790,7 +2788,7 @@ static netdev_features_t stmmac_fix_feat - /* Some GMAC devices have a bugged Jumbo frame support that - * needs to have the Tx COE disabled for oversized frames - * (due to limited buffer sizes). In this case we disable -- * the TX csum insertionin the TDES and not use SF. -+ * the TX csum insertion in the TDES and not use SF. - */ - if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) - features &= ~NETIF_F_CSUM_MASK; -@@ -2936,9 +2934,7 @@ static void sysfs_display_ring(void *hea - struct dma_desc *p = (struct dma_desc *)head; - - for (i = 0; i < size; i++) { -- u64 x; - if (extend_desc) { -- x = *(u64 *) ep; - seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), - le32_to_cpu(ep->basic.des0), -@@ -2947,7 +2943,6 @@ static void sysfs_display_ring(void *hea - le32_to_cpu(ep->basic.des3)); - ep++; - } else { -- x = *(u64 *) p; - seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", - i, (unsigned int)virt_to_phys(ep), - le32_to_cpu(p->des0), le32_to_cpu(p->des1), -@@ -3017,7 +3012,7 @@ static int stmmac_sysfs_dma_cap_read(str - (priv->dma_cap.hash_filter) ? "Y" : "N"); - seq_printf(seq, "\tMultiple MAC address registers: %s\n", - (priv->dma_cap.multi_addr) ? "Y" : "N"); -- seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n", -+ seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n", - (priv->dma_cap.pcs) ? "Y" : "N"); - seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", - (priv->dma_cap.sma_mdio) ? "Y" : "N"); -@@ -3293,44 +3288,8 @@ int stmmac_dvr_probe(struct device *devi - if ((phyaddr >= 0) && (phyaddr <= 31)) - priv->plat->phy_addr = phyaddr; - -- priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); -- if (IS_ERR(priv->stmmac_clk)) { -- netdev_warn(priv->dev, "%s: warning: cannot get CSR clock\n", -- __func__); -- /* If failed to obtain stmmac_clk and specific clk_csr value -- * is NOT passed from the platform, probe fail. -- */ -- if (!priv->plat->clk_csr) { -- ret = PTR_ERR(priv->stmmac_clk); -- goto error_clk_get; -- } else { -- priv->stmmac_clk = NULL; -- } -- } -- clk_prepare_enable(priv->stmmac_clk); -- -- priv->pclk = devm_clk_get(priv->device, "pclk"); -- if (IS_ERR(priv->pclk)) { -- if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) { -- ret = -EPROBE_DEFER; -- goto error_pclk_get; -- } -- priv->pclk = NULL; -- } -- clk_prepare_enable(priv->pclk); -- -- priv->stmmac_rst = devm_reset_control_get(priv->device, -- STMMAC_RESOURCE_NAME); -- if (IS_ERR(priv->stmmac_rst)) { -- if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) { -- ret = -EPROBE_DEFER; -- goto error_hw_init; -- } -- dev_info(priv->device, "no reset control found\n"); -- priv->stmmac_rst = NULL; -- } -- if (priv->stmmac_rst) -- reset_control_deassert(priv->stmmac_rst); -+ if (priv->plat->stmmac_rst) -+ reset_control_deassert(priv->plat->stmmac_rst); - - /* Init MAC and get the capabilities */ - ret = stmmac_hw_init(priv); -@@ -3416,10 +3375,6 @@ error_netdev_register: - error_mdio_register: - netif_napi_del(&priv->napi); - error_hw_init: -- clk_disable_unprepare(priv->pclk); --error_pclk_get: -- clk_disable_unprepare(priv->stmmac_clk); --error_clk_get: - free_netdev(ndev); - - return ret; -@@ -3445,10 +3400,10 @@ int stmmac_dvr_remove(struct device *dev - stmmac_set_mac(priv->ioaddr, false); - netif_carrier_off(ndev); - unregister_netdev(ndev); -- if (priv->stmmac_rst) -- reset_control_assert(priv->stmmac_rst); -- clk_disable_unprepare(priv->pclk); -- clk_disable_unprepare(priv->stmmac_clk); -+ if (priv->plat->stmmac_rst) -+ reset_control_assert(priv->plat->stmmac_rst); -+ clk_disable_unprepare(priv->plat->pclk); -+ clk_disable_unprepare(priv->plat->stmmac_clk); - if (priv->hw->pcs != STMMAC_PCS_RGMII && - priv->hw->pcs != STMMAC_PCS_TBI && - priv->hw->pcs != STMMAC_PCS_RTBI) -@@ -3497,14 +3452,14 @@ int stmmac_suspend(struct device *dev) - stmmac_set_mac(priv->ioaddr, false); - pinctrl_pm_select_sleep_state(priv->device); - /* Disable clock in case of PWM is off */ -- clk_disable(priv->pclk); -- clk_disable(priv->stmmac_clk); -+ clk_disable(priv->plat->pclk); -+ clk_disable(priv->plat->stmmac_clk); - } - spin_unlock_irqrestore(&priv->lock, flags); - - priv->oldlink = 0; -- priv->speed = 0; -- priv->oldduplex = -1; -+ priv->speed = SPEED_UNKNOWN; -+ priv->oldduplex = DUPLEX_UNKNOWN; - return 0; - } - EXPORT_SYMBOL_GPL(stmmac_suspend); -@@ -3537,9 +3492,9 @@ int stmmac_resume(struct device *dev) - priv->irq_wake = 0; - } else { - pinctrl_pm_select_default_state(priv->device); -- /* enable the clk prevously disabled */ -- clk_enable(priv->stmmac_clk); -- clk_enable(priv->pclk); -+ /* enable the clk previously disabled */ -+ clk_enable(priv->plat->stmmac_clk); -+ clk_enable(priv->plat->pclk); - /* reset the phy so that it's ready */ - if (priv->mii) - stmmac_mdio_reset(priv->mii); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -@@ -13,10 +13,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -24,13 +20,14 @@ - Maintainer: Giuseppe Cavallaro - *******************************************************************************/ - -+#include -+#include - #include --#include --#include - #include - #include - #include --#include -+#include -+#include - - #include "stmmac.h" - -@@ -42,22 +39,6 @@ - #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) - #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) - --static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr) --{ -- unsigned long curr; -- unsigned long finish = jiffies + 3 * HZ; -- -- do { -- curr = jiffies; -- if (readl(ioaddr + mii_addr) & MII_BUSY) -- cpu_relax(); -- else -- return 0; -- } while (!time_after_eq(curr, finish)); -- -- return -EBUSY; --} -- - /** - * stmmac_mdio_read - * @bus: points to the mii_bus structure -@@ -74,7 +55,7 @@ static int stmmac_mdio_read(struct mii_b - struct stmmac_priv *priv = netdev_priv(ndev); - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; -- -+ u32 v; - int data; - u32 value = MII_BUSY; - -@@ -86,12 +67,14 @@ static int stmmac_mdio_read(struct mii_b - if (priv->plat->has_gmac4) - value |= MII_GMAC4_READ; - -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), -+ 100, 10000)) - return -EBUSY; - - writel(value, priv->ioaddr + mii_address); - -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), -+ 100, 10000)) - return -EBUSY; - - /* Read the data from the MII data register */ -@@ -115,7 +98,7 @@ static int stmmac_mdio_write(struct mii_ - struct stmmac_priv *priv = netdev_priv(ndev); - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; -- -+ u32 v; - u32 value = MII_BUSY; - - value |= (phyaddr << priv->hw->mii.addr_shift) -@@ -130,7 +113,8 @@ static int stmmac_mdio_write(struct mii_ - value |= MII_WRITE; - - /* Wait until any existing MII operation is complete */ -- if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) -+ if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), -+ 100, 10000)) - return -EBUSY; - - /* Set the MII address register to write */ -@@ -138,7 +122,8 @@ static int stmmac_mdio_write(struct mii_ - writel(value, priv->ioaddr + mii_address); - - /* Wait until any existing MII operation is complete */ -- return stmmac_mdio_busy_wait(priv->ioaddr, mii_address); -+ return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), -+ 100, 10000); - } - - /** -@@ -156,9 +141,9 @@ int stmmac_mdio_reset(struct mii_bus *bu - - #ifdef CONFIG_OF - if (priv->device->of_node) { -- - if (data->reset_gpio < 0) { - struct device_node *np = priv->device->of_node; -+ - if (!np) - return 0; - -@@ -198,7 +183,7 @@ int stmmac_mdio_reset(struct mii_bus *bu - - /* This is a workaround for problems with the STE101P PHY. - * It doesn't complete its reset until at least one clock cycle -- * on MDC, so perform a dummy mdio read. To be upadted for GMAC4 -+ * on MDC, so perform a dummy mdio read. To be updated for GMAC4 - * if needed. - */ - if (!priv->plat->has_gmac4) -@@ -225,7 +210,7 @@ int stmmac_mdio_register(struct net_devi - return 0; - - new_bus = mdiobus_alloc(); -- if (new_bus == NULL) -+ if (!new_bus) - return -ENOMEM; - - if (mdio_bus_data->irqs) -@@ -262,49 +247,48 @@ int stmmac_mdio_register(struct net_devi - found = 0; - for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - struct phy_device *phydev = mdiobus_get_phy(new_bus, addr); -- if (phydev) { -- int act = 0; -- char irq_num[4]; -- char *irq_str; -- -- /* -- * If an IRQ was provided to be assigned after -- * the bus probe, do it here. -- */ -- if ((mdio_bus_data->irqs == NULL) && -- (mdio_bus_data->probed_phy_irq > 0)) { -- new_bus->irq[addr] = -- mdio_bus_data->probed_phy_irq; -- phydev->irq = mdio_bus_data->probed_phy_irq; -- } -- -- /* -- * If we're going to bind the MAC to this PHY bus, -- * and no PHY number was provided to the MAC, -- * use the one probed here. -- */ -- if (priv->plat->phy_addr == -1) -- priv->plat->phy_addr = addr; -- -- act = (priv->plat->phy_addr == addr); -- switch (phydev->irq) { -- case PHY_POLL: -- irq_str = "POLL"; -- break; -- case PHY_IGNORE_INTERRUPT: -- irq_str = "IGNORE"; -- break; -- default: -- sprintf(irq_num, "%d", phydev->irq); -- irq_str = irq_num; -- break; -- } -- netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", -- phydev->phy_id, addr, -- irq_str, phydev_name(phydev), -- act ? " active" : ""); -- found = 1; -+ int act = 0; -+ char irq_num[4]; -+ char *irq_str; -+ -+ if (!phydev) -+ continue; -+ -+ /* -+ * If an IRQ was provided to be assigned after -+ * the bus probe, do it here. -+ */ -+ if (!mdio_bus_data->irqs && -+ (mdio_bus_data->probed_phy_irq > 0)) { -+ new_bus->irq[addr] = mdio_bus_data->probed_phy_irq; -+ phydev->irq = mdio_bus_data->probed_phy_irq; -+ } -+ -+ /* -+ * If we're going to bind the MAC to this PHY bus, -+ * and no PHY number was provided to the MAC, -+ * use the one probed here. -+ */ -+ if (priv->plat->phy_addr == -1) -+ priv->plat->phy_addr = addr; -+ -+ act = (priv->plat->phy_addr == addr); -+ switch (phydev->irq) { -+ case PHY_POLL: -+ irq_str = "POLL"; -+ break; -+ case PHY_IGNORE_INTERRUPT: -+ irq_str = "IGNORE"; -+ break; -+ default: -+ sprintf(irq_num, "%d", phydev->irq); -+ irq_str = irq_num; -+ break; - } -+ netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", -+ phydev->phy_id, addr, irq_str, phydev_name(phydev), -+ act ? " active" : ""); -+ found = 1; - } - - if (!found && !mdio_node) { ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - -@@ -121,7 +117,6 @@ static struct stmmac_axi *stmmac_axi_set - axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en"); - axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm"); - axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe"); -- axi->axi_axi_all = of_property_read_bool(np, "snps,axi_all"); - axi->axi_fb = of_property_read_bool(np, "snps,axi_fb"); - axi->axi_mb = of_property_read_bool(np, "snps,axi_mb"); - axi->axi_rb = of_property_read_bool(np, "snps,axi_rb"); -@@ -181,10 +176,19 @@ static int stmmac_dt_phy(struct plat_stm - mdio = false; - } - -- /* If snps,dwmac-mdio is passed from DT, always register the MDIO */ -- for_each_child_of_node(np, plat->mdio_node) { -- if (of_device_is_compatible(plat->mdio_node, "snps,dwmac-mdio")) -- break; -+ /* exception for dwmac-dwc-qos-eth glue logic */ -+ if (of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) { -+ plat->mdio_node = of_get_child_by_name(np, "mdio"); -+ } else { -+ /** -+ * If snps,dwmac-mdio is passed from DT, always register -+ * the MDIO -+ */ -+ for_each_child_of_node(np, plat->mdio_node) { -+ if (of_device_is_compatible(plat->mdio_node, -+ "snps,dwmac-mdio")) -+ break; -+ } - } - - if (plat->mdio_node) { -@@ -249,6 +253,9 @@ stmmac_probe_config_dt(struct platform_d - plat->force_sf_dma_mode = - of_property_read_bool(np, "snps,force_sf_dma_mode"); - -+ plat->en_tx_lpi_clockgating = -+ of_property_read_bool(np, "snps,en-tx-lpi-clockgating"); -+ - /* Set the maxmtu to a default of JUMBO_LEN in case the - * parameter is not present in the device tree. - */ -@@ -333,7 +340,54 @@ stmmac_probe_config_dt(struct platform_d - - plat->axi = stmmac_axi_setup(pdev); - -+ /* clock setup */ -+ plat->stmmac_clk = devm_clk_get(&pdev->dev, -+ STMMAC_RESOURCE_NAME); -+ if (IS_ERR(plat->stmmac_clk)) { -+ dev_warn(&pdev->dev, "Cannot get CSR clock\n"); -+ plat->stmmac_clk = NULL; -+ } -+ clk_prepare_enable(plat->stmmac_clk); -+ -+ plat->pclk = devm_clk_get(&pdev->dev, "pclk"); -+ if (IS_ERR(plat->pclk)) { -+ if (PTR_ERR(plat->pclk) == -EPROBE_DEFER) -+ goto error_pclk_get; -+ -+ plat->pclk = NULL; -+ } -+ clk_prepare_enable(plat->pclk); -+ -+ /* Fall-back to main clock in case of no PTP ref is passed */ -+ plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "clk_ptp_ref"); -+ if (IS_ERR(plat->clk_ptp_ref)) { -+ plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); -+ plat->clk_ptp_ref = NULL; -+ dev_warn(&pdev->dev, "PTP uses main clock\n"); -+ } else { -+ clk_prepare_enable(plat->clk_ptp_ref); -+ plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); -+ dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); -+ } -+ -+ plat->stmmac_rst = devm_reset_control_get(&pdev->dev, -+ STMMAC_RESOURCE_NAME); -+ if (IS_ERR(plat->stmmac_rst)) { -+ if (PTR_ERR(plat->stmmac_rst) == -EPROBE_DEFER) -+ goto error_hw_init; -+ -+ dev_info(&pdev->dev, "no reset control found\n"); -+ plat->stmmac_rst = NULL; -+ } -+ - return plat; -+ -+error_hw_init: -+ clk_disable_unprepare(plat->pclk); -+error_pclk_get: -+ clk_disable_unprepare(plat->stmmac_clk); -+ -+ return ERR_PTR(-EPROBE_DEFER); - } - - /** -@@ -357,7 +411,7 @@ void stmmac_remove_config_dt(struct plat - struct plat_stmmacenet_data * - stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) - { -- return ERR_PTR(-ENOSYS); -+ return ERR_PTR(-EINVAL); - } - - void stmmac_remove_config_dt(struct platform_device *pdev, ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h -@@ -12,10 +12,6 @@ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - -- 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., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- - The full GNU General Public License is included in this distribution in - the file called "COPYING". - ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -103,7 +103,6 @@ struct stmmac_axi { - u32 axi_wr_osr_lmt; - u32 axi_rd_osr_lmt; - bool axi_kbbe; -- bool axi_axi_all; - u32 axi_blen[AXI_BLEN]; - bool axi_fb; - bool axi_mb; -@@ -135,13 +134,18 @@ struct plat_stmmacenet_data { - int tx_fifo_size; - int rx_fifo_size; - void (*fix_mac_speed)(void *priv, unsigned int speed); -- void (*bus_setup)(void __iomem *ioaddr); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); - void *bsp_priv; -+ struct clk *stmmac_clk; -+ struct clk *pclk; -+ struct clk *clk_ptp_ref; -+ unsigned int clk_ptp_rate; -+ struct reset_control *stmmac_rst; - struct stmmac_axi *axi; - int has_gmac4; - bool tso_en; - int mac_port_sel_speed; -+ bool en_tx_lpi_clockgating; - }; - #endif diff --git a/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch b/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch deleted file mode 100644 index a1b018186f..0000000000 --- a/target/linux/sunxi/patches-4.9/0052-stmmac-form-4-12.patch +++ /dev/null @@ -1,5904 +0,0 @@ ---- a/Documentation/devicetree/bindings/net/stmmac.txt -+++ b/Documentation/devicetree/bindings/net/stmmac.txt -@@ -7,9 +7,12 @@ Required properties: - - interrupt-parent: Should be the phandle for the interrupt controller - that services interrupts for this device - - interrupts: Should contain the STMMAC interrupts --- interrupt-names: Should contain the interrupt names "macirq" -- "eth_wake_irq" if this interrupt is supported in the "interrupts" -- property -+- interrupt-names: Should contain a list of interrupt names corresponding to -+ the interrupts in the interrupts property, if available. -+ Valid interrupt names are: -+ - "macirq" (combined signal for various interrupt events) -+ - "eth_wake_irq" (the interrupt to manage the remote wake-up packet detection) -+ - "eth_lpi" (the interrupt that occurs when Tx or Rx enters/exits LPI state) - - phy-mode: See ethernet.txt file in the same directory. - - snps,reset-gpio gpio number for phy reset. - - snps,reset-active-low boolean flag to indicate if phy reset is active low. -@@ -28,9 +31,9 @@ Optional properties: - clocks may be specified in derived bindings. - - clock-names: One name for each entry in the clocks property, the - first one should be "stmmaceth" and the second one should be "pclk". --- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is -- available this clock is used for programming the Timestamp Addend Register. -- If not passed then the system clock will be used and this is fine on some -+- ptp_ref: this is the PTP reference clock; in case of the PTP is available -+ this clock is used for programming the Timestamp Addend Register. If not -+ passed then the system clock will be used and this is fine on some - platforms. - - tx-fifo-depth: See ethernet.txt file in the same directory - - rx-fifo-depth: See ethernet.txt file in the same directory -@@ -72,7 +75,45 @@ Optional properties: - - snps,mb: mixed-burst - - snps,rb: rebuild INCRx Burst - - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus. -- -+- Multiple RX Queues parameters: below the list of all the parameters to -+ configure the multiple RX queues: -+ - snps,rx-queues-to-use: number of RX queues to be used in the driver -+ - Choose one of these RX scheduling algorithms: -+ - snps,rx-sched-sp: Strict priority -+ - snps,rx-sched-wsp: Weighted Strict priority -+ - For each RX queue -+ - Choose one of these modes: -+ - snps,dcb-algorithm: Queue to be enabled as DCB -+ - snps,avb-algorithm: Queue to be enabled as AVB -+ - snps,map-to-dma-channel: Channel to map -+ - Specifiy specific packet routing: -+ - snps,route-avcp: AV Untagged Control packets -+ - snps,route-ptp: PTP Packets -+ - snps,route-dcbcp: DCB Control Packets -+ - snps,route-up: Untagged Packets -+ - snps,route-multi-broad: Multicast & Broadcast Packets -+ - snps,priority: RX queue priority (Range: 0x0 to 0xF) -+- Multiple TX Queues parameters: below the list of all the parameters to -+ configure the multiple TX queues: -+ - snps,tx-queues-to-use: number of TX queues to be used in the driver -+ - Choose one of these TX scheduling algorithms: -+ - snps,tx-sched-wrr: Weighted Round Robin -+ - snps,tx-sched-wfq: Weighted Fair Queuing -+ - snps,tx-sched-dwrr: Deficit Weighted Round Robin -+ - snps,tx-sched-sp: Strict priority -+ - For each TX queue -+ - snps,weight: TX queue weight (if using a DCB weight algorithm) -+ - Choose one of these modes: -+ - snps,dcb-algorithm: TX queue will be working in DCB -+ - snps,avb-algorithm: TX queue will be working in AVB -+ [Attention] Queue 0 is reserved for legacy traffic -+ and so no AVB is available in this queue. -+ - Configure Credit Base Shaper (if AVB Mode selected): -+ - snps,send_slope: enable Low Power Interface -+ - snps,idle_slope: unlock on WoL -+ - snps,high_credit: max write outstanding req. limit -+ - snps,low_credit: max read outstanding req. limit -+ - snps,priority: TX queue priority (Range: 0x0 to 0xF) - Examples: - - stmmac_axi_setup: stmmac-axi-config { -@@ -81,12 +122,41 @@ Examples: - snps,blen = <256 128 64 32 0 0 0>; - }; - -+ mtl_rx_setup: rx-queues-config { -+ snps,rx-queues-to-use = <1>; -+ snps,rx-sched-sp; -+ queue0 { -+ snps,dcb-algorithm; -+ snps,map-to-dma-channel = <0x0>; -+ snps,priority = <0x0>; -+ }; -+ }; -+ -+ mtl_tx_setup: tx-queues-config { -+ snps,tx-queues-to-use = <2>; -+ snps,tx-sched-wrr; -+ queue0 { -+ snps,weight = <0x10>; -+ snps,dcb-algorithm; -+ snps,priority = <0x0>; -+ }; -+ -+ queue1 { -+ snps,avb-algorithm; -+ snps,send_slope = <0x1000>; -+ snps,idle_slope = <0x1000>; -+ snps,high_credit = <0x3E800>; -+ snps,low_credit = <0xFFC18000>; -+ snps,priority = <0x1>; -+ }; -+ }; -+ - gmac0: ethernet@e0800000 { - compatible = "st,spear600-gmac"; - reg = <0xe0800000 0x8000>; - interrupt-parent = <&vic1>; -- interrupts = <24 23>; -- interrupt-names = "macirq", "eth_wake_irq"; -+ interrupts = <24 23 22>; -+ interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; - mac-address = [000000000000]; /* Filled in by U-Boot */ - max-frame-size = <3800>; - phy-mode = "gmii"; -@@ -104,4 +174,6 @@ Examples: - phy1: ethernet-phy@0 { - }; - }; -+ snps,mtl-rx-config = <&mtl_rx_setup>; -+ snps,mtl-tx-config = <&mtl_tx_setup>; - }; ---- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c -+++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c -@@ -37,6 +37,7 @@ - #define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) - #define TSE_PCS_CONTROL_REG 0x00 - #define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) -+#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140 - #define TSE_PCS_IF_MODE_REG 0x28 - #define TSE_PCS_LINK_TIMER_0_REG 0x24 - #define TSE_PCS_LINK_TIMER_1_REG 0x26 -@@ -65,6 +66,7 @@ - #define TSE_PCS_SW_RESET_TIMEOUT 100 - #define TSE_PCS_USE_SGMII_AN_MASK BIT(1) - #define TSE_PCS_USE_SGMII_ENA BIT(0) -+#define TSE_PCS_IF_USE_SGMII 0x03 - - #define SGMII_ADAPTER_CTRL_REG 0x00 - #define SGMII_ADAPTER_DISABLE 0x0001 -@@ -101,7 +103,9 @@ int tse_pcs_init(void __iomem *base, str - { - int ret = 0; - -- writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG); -+ writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); -+ -+ writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG); - - writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); - writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); ---- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c -@@ -26,12 +26,15 @@ - - static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) - { -- struct stmmac_priv *priv = (struct stmmac_priv *)p; -- unsigned int entry = priv->cur_tx; -- struct dma_desc *desc = priv->dma_tx + entry; -+ struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p; - unsigned int nopaged_len = skb_headlen(skb); -+ struct stmmac_priv *priv = tx_q->priv_data; -+ unsigned int entry = tx_q->cur_tx; - unsigned int bmax, des2; - unsigned int i = 1, len; -+ struct dma_desc *desc; -+ -+ desc = tx_q->dma_tx + entry; - - if (priv->plat->enh_desc) - bmax = BUF_SIZE_8KiB; -@@ -45,16 +48,16 @@ static int stmmac_jumbo_frm(void *p, str - desc->des2 = cpu_to_le32(des2); - if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = bmax; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = bmax; - /* do not close the descriptor and do not set own bit */ - priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE, -- 0, false); -+ 0, false, skb->len); - - while (len != 0) { -- priv->tx_skbuff[entry] = NULL; -+ tx_q->tx_skbuff[entry] = NULL; - entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); -- desc = priv->dma_tx + entry; -+ desc = tx_q->dma_tx + entry; - - if (len > bmax) { - des2 = dma_map_single(priv->device, -@@ -63,11 +66,11 @@ static int stmmac_jumbo_frm(void *p, str - desc->des2 = cpu_to_le32(des2); - if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = bmax; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = bmax; - priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum, - STMMAC_CHAIN_MODE, 1, -- false); -+ false, skb->len); - len -= bmax; - i++; - } else { -@@ -77,17 +80,17 @@ static int stmmac_jumbo_frm(void *p, str - desc->des2 = cpu_to_le32(des2); - if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = len; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = len; - /* last descriptor can be set now */ - priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, - STMMAC_CHAIN_MODE, 1, -- true); -+ true, skb->len); - len = 0; - } - } - -- priv->cur_tx = entry; -+ tx_q->cur_tx = entry; - - return entry; - } -@@ -136,32 +139,34 @@ static void stmmac_init_dma_chain(void * - - static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p) - { -- struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; -+ struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr; -+ struct stmmac_priv *priv = rx_q->priv_data; - - if (priv->hwts_rx_en && !priv->extend_desc) - /* NOTE: Device will overwrite des3 with timestamp value if - * 1588-2002 time stamping is enabled, hence reinitialize it - * to keep explicit chaining in the descriptor. - */ -- p->des3 = cpu_to_le32((unsigned int)(priv->dma_rx_phy + -- (((priv->dirty_rx) + 1) % -+ p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy + -+ (((rx_q->dirty_rx) + 1) % - DMA_RX_SIZE) * - sizeof(struct dma_desc))); - } - - static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) - { -- struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; -- unsigned int entry = priv->dirty_tx; -+ struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr; -+ struct stmmac_priv *priv = tx_q->priv_data; -+ unsigned int entry = tx_q->dirty_tx; - -- if (priv->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && -+ if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc && - priv->hwts_tx_en) - /* NOTE: Device will overwrite des3 with timestamp value if - * 1588-2002 time stamping is enabled, hence reinitialize it - * to keep explicit chaining in the descriptor. - */ -- p->des3 = cpu_to_le32((unsigned int)((priv->dma_tx_phy + -- ((priv->dirty_tx + 1) % DMA_TX_SIZE)) -+ p->des3 = cpu_to_le32((unsigned int)((tx_q->dma_tx_phy + -+ ((tx_q->dirty_tx + 1) % DMA_TX_SIZE)) - * sizeof(struct dma_desc))); - } - ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -246,6 +246,15 @@ struct stmmac_extra_stats { - #define STMMAC_TX_MAX_FRAMES 256 - #define STMMAC_TX_FRAMES 64 - -+/* Packets types */ -+enum packets_types { -+ PACKET_AVCPQ = 0x1, /* AV Untagged Control packets */ -+ PACKET_PTPQ = 0x2, /* PTP Packets */ -+ PACKET_DCBCPQ = 0x3, /* DCB Control Packets */ -+ PACKET_UPQ = 0x4, /* Untagged Packets */ -+ PACKET_MCBCQ = 0x5, /* Multicast & Broadcast Packets */ -+}; -+ - /* Rx IPC status */ - enum rx_frame_status { - good_frame = 0x0, -@@ -324,6 +333,9 @@ struct dma_features { - unsigned int number_tx_queues; - /* Alternate (enhanced) DESC mode */ - unsigned int enh_desc; -+ /* TX and RX FIFO sizes */ -+ unsigned int tx_fifo_size; -+ unsigned int rx_fifo_size; - }; - - /* GMAC TX FIFO is 8K, Rx FIFO is 16K */ -@@ -361,7 +373,7 @@ struct stmmac_desc_ops { - /* Invoked by the xmit function to prepare the tx descriptor */ - void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len, - bool csum_flag, int mode, bool tx_own, -- bool ls); -+ bool ls, unsigned int tot_pkt_len); - void (*prepare_tso_tx_desc)(struct dma_desc *p, int is_fs, int len1, - int len2, bool tx_own, bool ls, - unsigned int tcphdrlen, -@@ -413,6 +425,14 @@ struct stmmac_dma_ops { - int (*reset)(void __iomem *ioaddr); - void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, - u32 dma_tx, u32 dma_rx, int atds); -+ void (*init_chan)(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, u32 chan); -+ void (*init_rx_chan)(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_rx_phy, u32 chan); -+ void (*init_tx_chan)(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx_phy, u32 chan); - /* Configure the AXI Bus Mode Register */ - void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi); - /* Dump DMA registers */ -@@ -421,25 +441,28 @@ struct stmmac_dma_ops { - * An invalid value enables the store-and-forward mode */ - void (*dma_mode)(void __iomem *ioaddr, int txmode, int rxmode, - int rxfifosz); -+ void (*dma_rx_mode)(void __iomem *ioaddr, int mode, u32 channel, -+ int fifosz); -+ void (*dma_tx_mode)(void __iomem *ioaddr, int mode, u32 channel); - /* To track extra statistic (if supported) */ - void (*dma_diagnostic_fr) (void *data, struct stmmac_extra_stats *x, - void __iomem *ioaddr); - void (*enable_dma_transmission) (void __iomem *ioaddr); -- void (*enable_dma_irq) (void __iomem *ioaddr); -- void (*disable_dma_irq) (void __iomem *ioaddr); -- void (*start_tx) (void __iomem *ioaddr); -- void (*stop_tx) (void __iomem *ioaddr); -- void (*start_rx) (void __iomem *ioaddr); -- void (*stop_rx) (void __iomem *ioaddr); -+ void (*enable_dma_irq)(void __iomem *ioaddr, u32 chan); -+ void (*disable_dma_irq)(void __iomem *ioaddr, u32 chan); -+ void (*start_tx)(void __iomem *ioaddr, u32 chan); -+ void (*stop_tx)(void __iomem *ioaddr, u32 chan); -+ void (*start_rx)(void __iomem *ioaddr, u32 chan); -+ void (*stop_rx)(void __iomem *ioaddr, u32 chan); - int (*dma_interrupt) (void __iomem *ioaddr, -- struct stmmac_extra_stats *x); -+ struct stmmac_extra_stats *x, u32 chan); - /* If supported then get the optional core features */ - void (*get_hw_feature)(void __iomem *ioaddr, - struct dma_features *dma_cap); - /* Program the HW RX Watchdog */ -- void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt); -- void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len); -- void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len); -+ void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan); -+ void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan); -+ void (*set_rx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan); - void (*set_rx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); - void (*set_tx_tail_ptr)(void __iomem *ioaddr, u32 tail_ptr, u32 chan); - void (*enable_tso)(void __iomem *ioaddr, bool en, u32 chan); -@@ -451,20 +474,44 @@ struct mac_device_info; - struct stmmac_ops { - /* MAC core initialization */ - void (*core_init)(struct mac_device_info *hw, int mtu); -+ /* Enable the MAC RX/TX */ -+ void (*set_mac)(void __iomem *ioaddr, bool enable); - /* Enable and verify that the IPC module is supported */ - int (*rx_ipc)(struct mac_device_info *hw); - /* Enable RX Queues */ -- void (*rx_queue_enable)(struct mac_device_info *hw, u32 queue); -+ void (*rx_queue_enable)(struct mac_device_info *hw, u8 mode, u32 queue); -+ /* RX Queues Priority */ -+ void (*rx_queue_prio)(struct mac_device_info *hw, u32 prio, u32 queue); -+ /* TX Queues Priority */ -+ void (*tx_queue_prio)(struct mac_device_info *hw, u32 prio, u32 queue); -+ /* RX Queues Routing */ -+ void (*rx_queue_routing)(struct mac_device_info *hw, u8 packet, -+ u32 queue); -+ /* Program RX Algorithms */ -+ void (*prog_mtl_rx_algorithms)(struct mac_device_info *hw, u32 rx_alg); -+ /* Program TX Algorithms */ -+ void (*prog_mtl_tx_algorithms)(struct mac_device_info *hw, u32 tx_alg); -+ /* Set MTL TX queues weight */ -+ void (*set_mtl_tx_queue_weight)(struct mac_device_info *hw, -+ u32 weight, u32 queue); -+ /* RX MTL queue to RX dma mapping */ -+ void (*map_mtl_to_dma)(struct mac_device_info *hw, u32 queue, u32 chan); -+ /* Configure AV Algorithm */ -+ void (*config_cbs)(struct mac_device_info *hw, u32 send_slope, -+ u32 idle_slope, u32 high_credit, u32 low_credit, -+ u32 queue); - /* Dump MAC registers */ - void (*dump_regs)(struct mac_device_info *hw, u32 *reg_space); - /* Handle extra events on specific interrupts hw dependent */ - int (*host_irq_status)(struct mac_device_info *hw, - struct stmmac_extra_stats *x); -+ /* Handle MTL interrupts */ -+ int (*host_mtl_irq_status)(struct mac_device_info *hw, u32 chan); - /* Multicast filter setting */ - void (*set_filter)(struct mac_device_info *hw, struct net_device *dev); - /* Flow control setting */ - void (*flow_ctrl)(struct mac_device_info *hw, unsigned int duplex, -- unsigned int fc, unsigned int pause_time); -+ unsigned int fc, unsigned int pause_time, u32 tx_cnt); - /* Set power management mode (e.g. magic frame) */ - void (*pmt)(struct mac_device_info *hw, unsigned long mode); - /* Set/Get Unicast MAC addresses */ -@@ -477,7 +524,8 @@ struct stmmac_ops { - void (*reset_eee_mode)(struct mac_device_info *hw); - void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw); - void (*set_eee_pls)(struct mac_device_info *hw, int link); -- void (*debug)(void __iomem *ioaddr, struct stmmac_extra_stats *x); -+ void (*debug)(void __iomem *ioaddr, struct stmmac_extra_stats *x, -+ u32 rx_queues, u32 tx_queues); - /* PCS calls */ - void (*pcs_ctrl_ane)(void __iomem *ioaddr, bool ane, bool srgmi_ral, - bool loopback); -@@ -547,6 +595,11 @@ struct mac_device_info { - unsigned int ps; - }; - -+struct stmmac_rx_routing { -+ u32 reg_mask; -+ u32 reg_shift; -+}; -+ - struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins, - int perfect_uc_entries, - int *synopsys_id); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c -@@ -14,16 +14,34 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include -+#include - #include - - #include "stmmac_platform.h" -+#include "dwmac4.h" -+ -+struct tegra_eqos { -+ struct device *dev; -+ void __iomem *regs; -+ -+ struct reset_control *rst; -+ struct clk *clk_master; -+ struct clk *clk_slave; -+ struct clk *clk_tx; -+ struct clk *clk_rx; -+ -+ struct gpio_desc *reset; -+}; - - static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, - struct plat_stmmacenet_data *plat_dat) -@@ -106,13 +124,309 @@ static int dwc_eth_dwmac_config_dt(struc - return 0; - } - -+static void *dwc_qos_probe(struct platform_device *pdev, -+ struct plat_stmmacenet_data *plat_dat, -+ struct stmmac_resources *stmmac_res) -+{ -+ int err; -+ -+ plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); -+ if (IS_ERR(plat_dat->stmmac_clk)) { -+ dev_err(&pdev->dev, "apb_pclk clock not found.\n"); -+ return ERR_CAST(plat_dat->stmmac_clk); -+ } -+ -+ err = clk_prepare_enable(plat_dat->stmmac_clk); -+ if (err < 0) { -+ dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n", -+ err); -+ return ERR_PTR(err); -+ } -+ -+ plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk"); -+ if (IS_ERR(plat_dat->pclk)) { -+ dev_err(&pdev->dev, "phy_ref_clk clock not found.\n"); -+ err = PTR_ERR(plat_dat->pclk); -+ goto disable; -+ } -+ -+ err = clk_prepare_enable(plat_dat->pclk); -+ if (err < 0) { -+ dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n", -+ err); -+ goto disable; -+ } -+ -+ return NULL; -+ -+disable: -+ clk_disable_unprepare(plat_dat->stmmac_clk); -+ return ERR_PTR(err); -+} -+ -+static int dwc_qos_remove(struct platform_device *pdev) -+{ -+ struct net_device *ndev = platform_get_drvdata(pdev); -+ struct stmmac_priv *priv = netdev_priv(ndev); -+ -+ clk_disable_unprepare(priv->plat->pclk); -+ clk_disable_unprepare(priv->plat->stmmac_clk); -+ -+ return 0; -+} -+ -+#define SDMEMCOMPPADCTRL 0x8800 -+#define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) -+ -+#define AUTO_CAL_CONFIG 0x8804 -+#define AUTO_CAL_CONFIG_START BIT(31) -+#define AUTO_CAL_CONFIG_ENABLE BIT(29) -+ -+#define AUTO_CAL_STATUS 0x880c -+#define AUTO_CAL_STATUS_ACTIVE BIT(31) -+ -+static void tegra_eqos_fix_speed(void *priv, unsigned int speed) -+{ -+ struct tegra_eqos *eqos = priv; -+ unsigned long rate = 125000000; -+ bool needs_calibration = false; -+ u32 value; -+ int err; -+ -+ switch (speed) { -+ case SPEED_1000: -+ needs_calibration = true; -+ rate = 125000000; -+ break; -+ -+ case SPEED_100: -+ needs_calibration = true; -+ rate = 25000000; -+ break; -+ -+ case SPEED_10: -+ rate = 2500000; -+ break; -+ -+ default: -+ dev_err(eqos->dev, "invalid speed %u\n", speed); -+ break; -+ } -+ -+ if (needs_calibration) { -+ /* calibrate */ -+ value = readl(eqos->regs + SDMEMCOMPPADCTRL); -+ value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; -+ writel(value, eqos->regs + SDMEMCOMPPADCTRL); -+ -+ udelay(1); -+ -+ value = readl(eqos->regs + AUTO_CAL_CONFIG); -+ value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE; -+ writel(value, eqos->regs + AUTO_CAL_CONFIG); -+ -+ err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, -+ value, -+ value & AUTO_CAL_STATUS_ACTIVE, -+ 1, 10); -+ if (err < 0) { -+ dev_err(eqos->dev, "calibration did not start\n"); -+ goto failed; -+ } -+ -+ err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, -+ value, -+ (value & AUTO_CAL_STATUS_ACTIVE) == 0, -+ 20, 200); -+ if (err < 0) { -+ dev_err(eqos->dev, "calibration didn't finish\n"); -+ goto failed; -+ } -+ -+ failed: -+ value = readl(eqos->regs + SDMEMCOMPPADCTRL); -+ value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; -+ writel(value, eqos->regs + SDMEMCOMPPADCTRL); -+ } else { -+ value = readl(eqos->regs + AUTO_CAL_CONFIG); -+ value &= ~AUTO_CAL_CONFIG_ENABLE; -+ writel(value, eqos->regs + AUTO_CAL_CONFIG); -+ } -+ -+ err = clk_set_rate(eqos->clk_tx, rate); -+ if (err < 0) -+ dev_err(eqos->dev, "failed to set TX rate: %d\n", err); -+} -+ -+static int tegra_eqos_init(struct platform_device *pdev, void *priv) -+{ -+ struct tegra_eqos *eqos = priv; -+ unsigned long rate; -+ u32 value; -+ -+ rate = clk_get_rate(eqos->clk_slave); -+ -+ value = (rate / 1000000) - 1; -+ writel(value, eqos->regs + GMAC_1US_TIC_COUNTER); -+ -+ return 0; -+} -+ -+static void *tegra_eqos_probe(struct platform_device *pdev, -+ struct plat_stmmacenet_data *data, -+ struct stmmac_resources *res) -+{ -+ struct tegra_eqos *eqos; -+ int err; -+ -+ eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL); -+ if (!eqos) { -+ err = -ENOMEM; -+ goto error; -+ } -+ -+ eqos->dev = &pdev->dev; -+ eqos->regs = res->addr; -+ -+ eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus"); -+ if (IS_ERR(eqos->clk_master)) { -+ err = PTR_ERR(eqos->clk_master); -+ goto error; -+ } -+ -+ err = clk_prepare_enable(eqos->clk_master); -+ if (err < 0) -+ goto error; -+ -+ eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus"); -+ if (IS_ERR(eqos->clk_slave)) { -+ err = PTR_ERR(eqos->clk_slave); -+ goto disable_master; -+ } -+ -+ data->stmmac_clk = eqos->clk_slave; -+ -+ err = clk_prepare_enable(eqos->clk_slave); -+ if (err < 0) -+ goto disable_master; -+ -+ eqos->clk_rx = devm_clk_get(&pdev->dev, "rx"); -+ if (IS_ERR(eqos->clk_rx)) { -+ err = PTR_ERR(eqos->clk_rx); -+ goto disable_slave; -+ } -+ -+ err = clk_prepare_enable(eqos->clk_rx); -+ if (err < 0) -+ goto disable_slave; -+ -+ eqos->clk_tx = devm_clk_get(&pdev->dev, "tx"); -+ if (IS_ERR(eqos->clk_tx)) { -+ err = PTR_ERR(eqos->clk_tx); -+ goto disable_rx; -+ } -+ -+ err = clk_prepare_enable(eqos->clk_tx); -+ if (err < 0) -+ goto disable_rx; -+ -+ eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH); -+ if (IS_ERR(eqos->reset)) { -+ err = PTR_ERR(eqos->reset); -+ goto disable_tx; -+ } -+ -+ usleep_range(2000, 4000); -+ gpiod_set_value(eqos->reset, 0); -+ -+ eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); -+ if (IS_ERR(eqos->rst)) { -+ err = PTR_ERR(eqos->rst); -+ goto reset_phy; -+ } -+ -+ err = reset_control_assert(eqos->rst); -+ if (err < 0) -+ goto reset_phy; -+ -+ usleep_range(2000, 4000); -+ -+ err = reset_control_deassert(eqos->rst); -+ if (err < 0) -+ goto reset_phy; -+ -+ usleep_range(2000, 4000); -+ -+ data->fix_mac_speed = tegra_eqos_fix_speed; -+ data->init = tegra_eqos_init; -+ data->bsp_priv = eqos; -+ -+ err = tegra_eqos_init(pdev, eqos); -+ if (err < 0) -+ goto reset; -+ -+out: -+ return eqos; -+ -+reset: -+ reset_control_assert(eqos->rst); -+reset_phy: -+ gpiod_set_value(eqos->reset, 1); -+disable_tx: -+ clk_disable_unprepare(eqos->clk_tx); -+disable_rx: -+ clk_disable_unprepare(eqos->clk_rx); -+disable_slave: -+ clk_disable_unprepare(eqos->clk_slave); -+disable_master: -+ clk_disable_unprepare(eqos->clk_master); -+error: -+ eqos = ERR_PTR(err); -+ goto out; -+} -+ -+static int tegra_eqos_remove(struct platform_device *pdev) -+{ -+ struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev); -+ -+ reset_control_assert(eqos->rst); -+ gpiod_set_value(eqos->reset, 1); -+ clk_disable_unprepare(eqos->clk_tx); -+ clk_disable_unprepare(eqos->clk_rx); -+ clk_disable_unprepare(eqos->clk_slave); -+ clk_disable_unprepare(eqos->clk_master); -+ -+ return 0; -+} -+ -+struct dwc_eth_dwmac_data { -+ void *(*probe)(struct platform_device *pdev, -+ struct plat_stmmacenet_data *data, -+ struct stmmac_resources *res); -+ int (*remove)(struct platform_device *pdev); -+}; -+ -+static const struct dwc_eth_dwmac_data dwc_qos_data = { -+ .probe = dwc_qos_probe, -+ .remove = dwc_qos_remove, -+}; -+ -+static const struct dwc_eth_dwmac_data tegra_eqos_data = { -+ .probe = tegra_eqos_probe, -+ .remove = tegra_eqos_remove, -+}; -+ - static int dwc_eth_dwmac_probe(struct platform_device *pdev) - { -+ const struct dwc_eth_dwmac_data *data; - struct plat_stmmacenet_data *plat_dat; - struct stmmac_resources stmmac_res; - struct resource *res; -+ void *priv; - int ret; - -+ data = of_device_get_match_data(&pdev->dev); -+ - memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); - - /** -@@ -138,39 +452,26 @@ static int dwc_eth_dwmac_probe(struct pl - if (IS_ERR(plat_dat)) - return PTR_ERR(plat_dat); - -- plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); -- if (IS_ERR(plat_dat->stmmac_clk)) { -- dev_err(&pdev->dev, "apb_pclk clock not found.\n"); -- ret = PTR_ERR(plat_dat->stmmac_clk); -- plat_dat->stmmac_clk = NULL; -- goto err_remove_config_dt; -+ priv = data->probe(pdev, plat_dat, &stmmac_res); -+ if (IS_ERR(priv)) { -+ ret = PTR_ERR(priv); -+ dev_err(&pdev->dev, "failed to probe subdriver: %d\n", ret); -+ goto remove_config; - } -- clk_prepare_enable(plat_dat->stmmac_clk); -- -- plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk"); -- if (IS_ERR(plat_dat->pclk)) { -- dev_err(&pdev->dev, "phy_ref_clk clock not found.\n"); -- ret = PTR_ERR(plat_dat->pclk); -- plat_dat->pclk = NULL; -- goto err_out_clk_dis_phy; -- } -- clk_prepare_enable(plat_dat->pclk); - - ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); - if (ret) -- goto err_out_clk_dis_aper; -+ goto remove; - - ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); - if (ret) -- goto err_out_clk_dis_aper; -+ goto remove; - -- return 0; -+ return ret; - --err_out_clk_dis_aper: -- clk_disable_unprepare(plat_dat->pclk); --err_out_clk_dis_phy: -- clk_disable_unprepare(plat_dat->stmmac_clk); --err_remove_config_dt: -+remove: -+ data->remove(pdev); -+remove_config: - stmmac_remove_config_dt(pdev, plat_dat); - - return ret; -@@ -178,11 +479,29 @@ err_remove_config_dt: - - static int dwc_eth_dwmac_remove(struct platform_device *pdev) - { -- return stmmac_pltfr_remove(pdev); -+ struct net_device *ndev = platform_get_drvdata(pdev); -+ struct stmmac_priv *priv = netdev_priv(ndev); -+ const struct dwc_eth_dwmac_data *data; -+ int err; -+ -+ data = of_device_get_match_data(&pdev->dev); -+ -+ err = stmmac_dvr_remove(&pdev->dev); -+ if (err < 0) -+ dev_err(&pdev->dev, "failed to remove platform: %d\n", err); -+ -+ err = data->remove(pdev); -+ if (err < 0) -+ dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err); -+ -+ stmmac_remove_config_dt(pdev, priv->plat); -+ -+ return err; - } - - static const struct of_device_id dwc_eth_dwmac_match[] = { -- { .compatible = "snps,dwc-qos-ethernet-4.10", }, -+ { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data }, -+ { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data }, - { } - }; - MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c -@@ -74,6 +74,10 @@ struct rk_priv_data { - #define GRF_BIT(nr) (BIT(nr) | BIT(nr+16)) - #define GRF_CLR_BIT(nr) (BIT(nr+16)) - -+#define DELAY_ENABLE(soc, tx, rx) \ -+ (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ -+ ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) -+ - #define RK3228_GRF_MAC_CON0 0x0900 - #define RK3228_GRF_MAC_CON1 0x0904 - -@@ -115,8 +119,7 @@ static void rk3228_set_to_rgmii(struct r - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON1, - RK3228_GMAC_PHY_INTF_SEL_RGMII | - RK3228_GMAC_RMII_MODE_CLR | -- RK3228_GMAC_RXCLK_DLY_ENABLE | -- RK3228_GMAC_TXCLK_DLY_ENABLE); -+ DELAY_ENABLE(RK3228, tx_delay, rx_delay)); - - regmap_write(bsp_priv->grf, RK3228_GRF_MAC_CON0, - RK3228_GMAC_CLK_RX_DL_CFG(rx_delay) | -@@ -232,8 +235,7 @@ static void rk3288_set_to_rgmii(struct r - RK3288_GMAC_PHY_INTF_SEL_RGMII | - RK3288_GMAC_RMII_MODE_CLR); - regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3, -- RK3288_GMAC_RXCLK_DLY_ENABLE | -- RK3288_GMAC_TXCLK_DLY_ENABLE | -+ DELAY_ENABLE(RK3288, tx_delay, rx_delay) | - RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) | - RK3288_GMAC_CLK_TX_DL_CFG(tx_delay)); - } -@@ -460,8 +462,7 @@ static void rk3366_set_to_rgmii(struct r - RK3366_GMAC_PHY_INTF_SEL_RGMII | - RK3366_GMAC_RMII_MODE_CLR); - regmap_write(bsp_priv->grf, RK3366_GRF_SOC_CON7, -- RK3366_GMAC_RXCLK_DLY_ENABLE | -- RK3366_GMAC_TXCLK_DLY_ENABLE | -+ DELAY_ENABLE(RK3366, tx_delay, rx_delay) | - RK3366_GMAC_CLK_RX_DL_CFG(rx_delay) | - RK3366_GMAC_CLK_TX_DL_CFG(tx_delay)); - } -@@ -572,8 +573,7 @@ static void rk3368_set_to_rgmii(struct r - RK3368_GMAC_PHY_INTF_SEL_RGMII | - RK3368_GMAC_RMII_MODE_CLR); - regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16, -- RK3368_GMAC_RXCLK_DLY_ENABLE | -- RK3368_GMAC_TXCLK_DLY_ENABLE | -+ DELAY_ENABLE(RK3368, tx_delay, rx_delay) | - RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) | - RK3368_GMAC_CLK_TX_DL_CFG(tx_delay)); - } -@@ -684,8 +684,7 @@ static void rk3399_set_to_rgmii(struct r - RK3399_GMAC_PHY_INTF_SEL_RGMII | - RK3399_GMAC_RMII_MODE_CLR); - regmap_write(bsp_priv->grf, RK3399_GRF_SOC_CON6, -- RK3399_GMAC_RXCLK_DLY_ENABLE | -- RK3399_GMAC_TXCLK_DLY_ENABLE | -+ DELAY_ENABLE(RK3399, tx_delay, rx_delay) | - RK3399_GMAC_CLK_RX_DL_CFG(rx_delay) | - RK3399_GMAC_CLK_TX_DL_CFG(tx_delay)); - } -@@ -985,14 +984,29 @@ static int rk_gmac_powerup(struct rk_pri - return ret; - - /*rmii or rgmii*/ -- if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) { -+ switch (bsp_priv->phy_iface) { -+ case PHY_INTERFACE_MODE_RGMII: - dev_info(dev, "init for RGMII\n"); - bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, - bsp_priv->rx_delay); -- } else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) { -+ break; -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ dev_info(dev, "init for RGMII_ID\n"); -+ bsp_priv->ops->set_to_rgmii(bsp_priv, 0, 0); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ dev_info(dev, "init for RGMII_RXID\n"); -+ bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay, 0); -+ break; -+ case PHY_INTERFACE_MODE_RGMII_TXID: -+ dev_info(dev, "init for RGMII_TXID\n"); -+ bsp_priv->ops->set_to_rgmii(bsp_priv, 0, bsp_priv->rx_delay); -+ break; -+ case PHY_INTERFACE_MODE_RMII: - dev_info(dev, "init for RMII\n"); - bsp_priv->ops->set_to_rmii(bsp_priv); -- } else { -+ break; -+ default: - dev_err(dev, "NO interface defined!\n"); - } - -@@ -1022,12 +1036,19 @@ static void rk_fix_speed(void *priv, uns - struct rk_priv_data *bsp_priv = priv; - struct device *dev = &bsp_priv->pdev->dev; - -- if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) -+ switch (bsp_priv->phy_iface) { -+ case PHY_INTERFACE_MODE_RGMII: -+ case PHY_INTERFACE_MODE_RGMII_ID: -+ case PHY_INTERFACE_MODE_RGMII_RXID: -+ case PHY_INTERFACE_MODE_RGMII_TXID: - bsp_priv->ops->set_rgmii_speed(bsp_priv, speed); -- else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) -+ break; -+ case PHY_INTERFACE_MODE_RMII: - bsp_priv->ops->set_rmii_speed(bsp_priv, speed); -- else -+ break; -+ default: - dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); -+ } - } - - static int rk_gmac_probe(struct platform_device *pdev) ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -@@ -216,7 +216,8 @@ static void dwmac1000_set_filter(struct - - - static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, -- unsigned int fc, unsigned int pause_time) -+ unsigned int fc, unsigned int pause_time, -+ u32 tx_cnt) - { - void __iomem *ioaddr = hw->pcsr; - /* Set flow such that DZPQ in Mac Register 6 is 0, -@@ -412,7 +413,8 @@ static void dwmac1000_get_adv_lp(void __ - dwmac_get_adv_lp(ioaddr, GMAC_PCS_BASE, adv); - } - --static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x) -+static void dwmac1000_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x, -+ u32 rx_queues, u32 tx_queues) - { - u32 value = readl(ioaddr + GMAC_DEBUG); - -@@ -488,6 +490,7 @@ static void dwmac1000_debug(void __iomem - - static const struct stmmac_ops dwmac1000_ops = { - .core_init = dwmac1000_core_init, -+ .set_mac = stmmac_set_mac, - .rx_ipc = dwmac1000_rx_ipc_enable, - .dump_regs = dwmac1000_dump_regs, - .host_irq_status = dwmac1000_irq_status, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -247,7 +247,8 @@ static void dwmac1000_get_hw_feature(voi - dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; - } - --static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt) -+static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt, -+ u32 number_chan) - { - writel(riwt, ioaddr + DMA_RX_WATCHDOG); - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -@@ -131,7 +131,8 @@ static void dwmac100_set_filter(struct m - } - - static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, -- unsigned int fc, unsigned int pause_time) -+ unsigned int fc, unsigned int pause_time, -+ u32 tx_cnt) - { - void __iomem *ioaddr = hw->pcsr; - unsigned int flow = MAC_FLOW_CTRL_ENABLE; -@@ -149,6 +150,7 @@ static void dwmac100_pmt(struct mac_devi - - static const struct stmmac_ops dwmac100_ops = { - .core_init = dwmac100_core_init, -+ .set_mac = stmmac_set_mac, - .rx_ipc = dwmac100_rx_ipc_enable, - .dump_regs = dwmac100_dump_mac_regs, - .host_irq_status = dwmac100_irq_status, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h -@@ -22,9 +22,15 @@ - #define GMAC_HASH_TAB_32_63 0x00000014 - #define GMAC_RX_FLOW_CTRL 0x00000090 - #define GMAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4) -+#define GMAC_TXQ_PRTY_MAP0 0x98 -+#define GMAC_TXQ_PRTY_MAP1 0x9C - #define GMAC_RXQ_CTRL0 0x000000a0 -+#define GMAC_RXQ_CTRL1 0x000000a4 -+#define GMAC_RXQ_CTRL2 0x000000a8 -+#define GMAC_RXQ_CTRL3 0x000000ac - #define GMAC_INT_STATUS 0x000000b0 - #define GMAC_INT_EN 0x000000b4 -+#define GMAC_1US_TIC_COUNTER 0x000000dc - #define GMAC_PCS_BASE 0x000000e0 - #define GMAC_PHYIF_CONTROL_STATUS 0x000000f8 - #define GMAC_PMT 0x000000c0 -@@ -38,6 +44,22 @@ - #define GMAC_ADDR_HIGH(reg) (0x300 + reg * 8) - #define GMAC_ADDR_LOW(reg) (0x304 + reg * 8) - -+/* RX Queues Routing */ -+#define GMAC_RXQCTRL_AVCPQ_MASK GENMASK(2, 0) -+#define GMAC_RXQCTRL_AVCPQ_SHIFT 0 -+#define GMAC_RXQCTRL_PTPQ_MASK GENMASK(6, 4) -+#define GMAC_RXQCTRL_PTPQ_SHIFT 4 -+#define GMAC_RXQCTRL_DCBCPQ_MASK GENMASK(10, 8) -+#define GMAC_RXQCTRL_DCBCPQ_SHIFT 8 -+#define GMAC_RXQCTRL_UPQ_MASK GENMASK(14, 12) -+#define GMAC_RXQCTRL_UPQ_SHIFT 12 -+#define GMAC_RXQCTRL_MCBCQ_MASK GENMASK(18, 16) -+#define GMAC_RXQCTRL_MCBCQ_SHIFT 16 -+#define GMAC_RXQCTRL_MCBCQEN BIT(20) -+#define GMAC_RXQCTRL_MCBCQEN_SHIFT 20 -+#define GMAC_RXQCTRL_TACPQE BIT(21) -+#define GMAC_RXQCTRL_TACPQE_SHIFT 21 -+ - /* MAC Packet Filtering */ - #define GMAC_PACKET_FILTER_PR BIT(0) - #define GMAC_PACKET_FILTER_HMC BIT(2) -@@ -53,6 +75,14 @@ - /* MAC Flow Control RX */ - #define GMAC_RX_FLOW_CTRL_RFE BIT(0) - -+/* RX Queues Priorities */ -+#define GMAC_RXQCTRL_PSRQX_MASK(x) GENMASK(7 + ((x) * 8), 0 + ((x) * 8)) -+#define GMAC_RXQCTRL_PSRQX_SHIFT(x) ((x) * 8) -+ -+/* TX Queues Priorities */ -+#define GMAC_TXQCTRL_PSTQX_MASK(x) GENMASK(7 + ((x) * 8), 0 + ((x) * 8)) -+#define GMAC_TXQCTRL_PSTQX_SHIFT(x) ((x) * 8) -+ - /* MAC Flow Control TX */ - #define GMAC_TX_FLOW_CTRL_TFE BIT(1) - #define GMAC_TX_FLOW_CTRL_PT_SHIFT 16 -@@ -148,6 +178,8 @@ enum power_event { - /* MAC HW features1 bitmap */ - #define GMAC_HW_FEAT_AVSEL BIT(20) - #define GMAC_HW_TSOEN BIT(18) -+#define GMAC_HW_TXFIFOSIZE GENMASK(10, 6) -+#define GMAC_HW_RXFIFOSIZE GENMASK(4, 0) - - /* MAC HW features2 bitmap */ - #define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18) -@@ -161,8 +193,25 @@ enum power_event { - #define GMAC_HI_REG_AE BIT(31) - - /* MTL registers */ -+#define MTL_OPERATION_MODE 0x00000c00 -+#define MTL_OPERATION_SCHALG_MASK GENMASK(6, 5) -+#define MTL_OPERATION_SCHALG_WRR (0x0 << 5) -+#define MTL_OPERATION_SCHALG_WFQ (0x1 << 5) -+#define MTL_OPERATION_SCHALG_DWRR (0x2 << 5) -+#define MTL_OPERATION_SCHALG_SP (0x3 << 5) -+#define MTL_OPERATION_RAA BIT(2) -+#define MTL_OPERATION_RAA_SP (0x0 << 2) -+#define MTL_OPERATION_RAA_WSP (0x1 << 2) -+ - #define MTL_INT_STATUS 0x00000c20 --#define MTL_INT_Q0 BIT(0) -+#define MTL_INT_QX(x) BIT(x) -+ -+#define MTL_RXQ_DMA_MAP0 0x00000c30 /* queue 0 to 3 */ -+#define MTL_RXQ_DMA_MAP1 0x00000c34 /* queue 4 to 7 */ -+#define MTL_RXQ_DMA_Q04MDMACH_MASK GENMASK(3, 0) -+#define MTL_RXQ_DMA_Q04MDMACH(x) ((x) << 0) -+#define MTL_RXQ_DMA_QXMDMACH_MASK(x) GENMASK(11 + (8 * ((x) - 1)), 8 * (x)) -+#define MTL_RXQ_DMA_QXMDMACH(chan, q) ((chan) << (8 * (q))) - - #define MTL_CHAN_BASE_ADDR 0x00000d00 - #define MTL_CHAN_BASE_OFFSET 0x40 -@@ -180,6 +229,7 @@ enum power_event { - #define MTL_OP_MODE_TSF BIT(1) - - #define MTL_OP_MODE_TQS_MASK GENMASK(24, 16) -+#define MTL_OP_MODE_TQS_SHIFT 16 - - #define MTL_OP_MODE_TTC_MASK 0x70 - #define MTL_OP_MODE_TTC_SHIFT 4 -@@ -193,6 +243,17 @@ enum power_event { - #define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT) - #define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT) - -+#define MTL_OP_MODE_RQS_MASK GENMASK(29, 20) -+#define MTL_OP_MODE_RQS_SHIFT 20 -+ -+#define MTL_OP_MODE_RFD_MASK GENMASK(19, 14) -+#define MTL_OP_MODE_RFD_SHIFT 14 -+ -+#define MTL_OP_MODE_RFA_MASK GENMASK(13, 8) -+#define MTL_OP_MODE_RFA_SHIFT 8 -+ -+#define MTL_OP_MODE_EHFC BIT(7) -+ - #define MTL_OP_MODE_RTC_MASK 0x18 - #define MTL_OP_MODE_RTC_SHIFT 3 - -@@ -201,6 +262,46 @@ enum power_event { - #define MTL_OP_MODE_RTC_96 (2 << MTL_OP_MODE_RTC_SHIFT) - #define MTL_OP_MODE_RTC_128 (3 << MTL_OP_MODE_RTC_SHIFT) - -+/* MTL ETS Control register */ -+#define MTL_ETS_CTRL_BASE_ADDR 0x00000d10 -+#define MTL_ETS_CTRL_BASE_OFFSET 0x40 -+#define MTL_ETSX_CTRL_BASE_ADDR(x) (MTL_ETS_CTRL_BASE_ADDR + \ -+ ((x) * MTL_ETS_CTRL_BASE_OFFSET)) -+ -+#define MTL_ETS_CTRL_CC BIT(3) -+#define MTL_ETS_CTRL_AVALG BIT(2) -+ -+/* MTL Queue Quantum Weight */ -+#define MTL_TXQ_WEIGHT_BASE_ADDR 0x00000d18 -+#define MTL_TXQ_WEIGHT_BASE_OFFSET 0x40 -+#define MTL_TXQX_WEIGHT_BASE_ADDR(x) (MTL_TXQ_WEIGHT_BASE_ADDR + \ -+ ((x) * MTL_TXQ_WEIGHT_BASE_OFFSET)) -+#define MTL_TXQ_WEIGHT_ISCQW_MASK GENMASK(20, 0) -+ -+/* MTL sendSlopeCredit register */ -+#define MTL_SEND_SLP_CRED_BASE_ADDR 0x00000d1c -+#define MTL_SEND_SLP_CRED_OFFSET 0x40 -+#define MTL_SEND_SLP_CREDX_BASE_ADDR(x) (MTL_SEND_SLP_CRED_BASE_ADDR + \ -+ ((x) * MTL_SEND_SLP_CRED_OFFSET)) -+ -+#define MTL_SEND_SLP_CRED_SSC_MASK GENMASK(13, 0) -+ -+/* MTL hiCredit register */ -+#define MTL_HIGH_CRED_BASE_ADDR 0x00000d20 -+#define MTL_HIGH_CRED_OFFSET 0x40 -+#define MTL_HIGH_CREDX_BASE_ADDR(x) (MTL_HIGH_CRED_BASE_ADDR + \ -+ ((x) * MTL_HIGH_CRED_OFFSET)) -+ -+#define MTL_HIGH_CRED_HC_MASK GENMASK(28, 0) -+ -+/* MTL loCredit register */ -+#define MTL_LOW_CRED_BASE_ADDR 0x00000d24 -+#define MTL_LOW_CRED_OFFSET 0x40 -+#define MTL_LOW_CREDX_BASE_ADDR(x) (MTL_LOW_CRED_BASE_ADDR + \ -+ ((x) * MTL_LOW_CRED_OFFSET)) -+ -+#define MTL_HIGH_CRED_LC_MASK GENMASK(28, 0) -+ - /* MTL debug */ - #define MTL_DEBUG_TXSTSFSTS BIT(5) - #define MTL_DEBUG_TXFSTS BIT(4) ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -59,17 +59,211 @@ static void dwmac4_core_init(struct mac_ - writel(value, ioaddr + GMAC_INT_EN); - } - --static void dwmac4_rx_queue_enable(struct mac_device_info *hw, u32 queue) -+static void dwmac4_rx_queue_enable(struct mac_device_info *hw, -+ u8 mode, u32 queue) - { - void __iomem *ioaddr = hw->pcsr; - u32 value = readl(ioaddr + GMAC_RXQ_CTRL0); - - value &= GMAC_RX_QUEUE_CLEAR(queue); -- value |= GMAC_RX_AV_QUEUE_ENABLE(queue); -+ if (mode == MTL_QUEUE_AVB) -+ value |= GMAC_RX_AV_QUEUE_ENABLE(queue); -+ else if (mode == MTL_QUEUE_DCB) -+ value |= GMAC_RX_DCB_QUEUE_ENABLE(queue); - - writel(value, ioaddr + GMAC_RXQ_CTRL0); - } - -+static void dwmac4_rx_queue_priority(struct mac_device_info *hw, -+ u32 prio, u32 queue) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 base_register; -+ u32 value; -+ -+ base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3; -+ -+ value = readl(ioaddr + base_register); -+ -+ value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue); -+ value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) & -+ GMAC_RXQCTRL_PSRQX_MASK(queue); -+ writel(value, ioaddr + base_register); -+} -+ -+static void dwmac4_tx_queue_priority(struct mac_device_info *hw, -+ u32 prio, u32 queue) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 base_register; -+ u32 value; -+ -+ base_register = (queue < 4) ? GMAC_TXQ_PRTY_MAP0 : GMAC_TXQ_PRTY_MAP1; -+ -+ value = readl(ioaddr + base_register); -+ -+ value &= ~GMAC_TXQCTRL_PSTQX_MASK(queue); -+ value |= (prio << GMAC_TXQCTRL_PSTQX_SHIFT(queue)) & -+ GMAC_TXQCTRL_PSTQX_MASK(queue); -+ -+ writel(value, ioaddr + base_register); -+} -+ -+static void dwmac4_tx_queue_routing(struct mac_device_info *hw, -+ u8 packet, u32 queue) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ const struct stmmac_rx_routing route_possibilities[] = { -+ { GMAC_RXQCTRL_AVCPQ_MASK, GMAC_RXQCTRL_AVCPQ_SHIFT }, -+ { GMAC_RXQCTRL_PTPQ_MASK, GMAC_RXQCTRL_PTPQ_SHIFT }, -+ { GMAC_RXQCTRL_DCBCPQ_MASK, GMAC_RXQCTRL_DCBCPQ_SHIFT }, -+ { GMAC_RXQCTRL_UPQ_MASK, GMAC_RXQCTRL_UPQ_SHIFT }, -+ { GMAC_RXQCTRL_MCBCQ_MASK, GMAC_RXQCTRL_MCBCQ_SHIFT }, -+ }; -+ -+ value = readl(ioaddr + GMAC_RXQ_CTRL1); -+ -+ /* routing configuration */ -+ value &= ~route_possibilities[packet - 1].reg_mask; -+ value |= (queue << route_possibilities[packet-1].reg_shift) & -+ route_possibilities[packet - 1].reg_mask; -+ -+ /* some packets require extra ops */ -+ if (packet == PACKET_AVCPQ) { -+ value &= ~GMAC_RXQCTRL_TACPQE; -+ value |= 0x1 << GMAC_RXQCTRL_TACPQE_SHIFT; -+ } else if (packet == PACKET_MCBCQ) { -+ value &= ~GMAC_RXQCTRL_MCBCQEN; -+ value |= 0x1 << GMAC_RXQCTRL_MCBCQEN_SHIFT; -+ } -+ -+ writel(value, ioaddr + GMAC_RXQ_CTRL1); -+} -+ -+static void dwmac4_prog_mtl_rx_algorithms(struct mac_device_info *hw, -+ u32 rx_alg) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value = readl(ioaddr + MTL_OPERATION_MODE); -+ -+ value &= ~MTL_OPERATION_RAA; -+ switch (rx_alg) { -+ case MTL_RX_ALGORITHM_SP: -+ value |= MTL_OPERATION_RAA_SP; -+ break; -+ case MTL_RX_ALGORITHM_WSP: -+ value |= MTL_OPERATION_RAA_WSP; -+ break; -+ default: -+ break; -+ } -+ -+ writel(value, ioaddr + MTL_OPERATION_MODE); -+} -+ -+static void dwmac4_prog_mtl_tx_algorithms(struct mac_device_info *hw, -+ u32 tx_alg) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value = readl(ioaddr + MTL_OPERATION_MODE); -+ -+ value &= ~MTL_OPERATION_SCHALG_MASK; -+ switch (tx_alg) { -+ case MTL_TX_ALGORITHM_WRR: -+ value |= MTL_OPERATION_SCHALG_WRR; -+ break; -+ case MTL_TX_ALGORITHM_WFQ: -+ value |= MTL_OPERATION_SCHALG_WFQ; -+ break; -+ case MTL_TX_ALGORITHM_DWRR: -+ value |= MTL_OPERATION_SCHALG_DWRR; -+ break; -+ case MTL_TX_ALGORITHM_SP: -+ value |= MTL_OPERATION_SCHALG_SP; -+ break; -+ default: -+ break; -+ } -+} -+ -+static void dwmac4_set_mtl_tx_queue_weight(struct mac_device_info *hw, -+ u32 weight, u32 queue) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value = readl(ioaddr + MTL_TXQX_WEIGHT_BASE_ADDR(queue)); -+ -+ value &= ~MTL_TXQ_WEIGHT_ISCQW_MASK; -+ value |= weight & MTL_TXQ_WEIGHT_ISCQW_MASK; -+ writel(value, ioaddr + MTL_TXQX_WEIGHT_BASE_ADDR(queue)); -+} -+ -+static void dwmac4_map_mtl_dma(struct mac_device_info *hw, u32 queue, u32 chan) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ if (queue < 4) -+ value = readl(ioaddr + MTL_RXQ_DMA_MAP0); -+ else -+ value = readl(ioaddr + MTL_RXQ_DMA_MAP1); -+ -+ if (queue == 0 || queue == 4) { -+ value &= ~MTL_RXQ_DMA_Q04MDMACH_MASK; -+ value |= MTL_RXQ_DMA_Q04MDMACH(chan); -+ } else { -+ value &= ~MTL_RXQ_DMA_QXMDMACH_MASK(queue); -+ value |= MTL_RXQ_DMA_QXMDMACH(chan, queue); -+ } -+ -+ if (queue < 4) -+ writel(value, ioaddr + MTL_RXQ_DMA_MAP0); -+ else -+ writel(value, ioaddr + MTL_RXQ_DMA_MAP1); -+} -+ -+static void dwmac4_config_cbs(struct mac_device_info *hw, -+ u32 send_slope, u32 idle_slope, -+ u32 high_credit, u32 low_credit, u32 queue) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 value; -+ -+ pr_debug("Queue %d configured as AVB. Parameters:\n", queue); -+ pr_debug("\tsend_slope: 0x%08x\n", send_slope); -+ pr_debug("\tidle_slope: 0x%08x\n", idle_slope); -+ pr_debug("\thigh_credit: 0x%08x\n", high_credit); -+ pr_debug("\tlow_credit: 0x%08x\n", low_credit); -+ -+ /* enable AV algorithm */ -+ value = readl(ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue)); -+ value |= MTL_ETS_CTRL_AVALG; -+ value |= MTL_ETS_CTRL_CC; -+ writel(value, ioaddr + MTL_ETSX_CTRL_BASE_ADDR(queue)); -+ -+ /* configure send slope */ -+ value = readl(ioaddr + MTL_SEND_SLP_CREDX_BASE_ADDR(queue)); -+ value &= ~MTL_SEND_SLP_CRED_SSC_MASK; -+ value |= send_slope & MTL_SEND_SLP_CRED_SSC_MASK; -+ writel(value, ioaddr + MTL_SEND_SLP_CREDX_BASE_ADDR(queue)); -+ -+ /* configure idle slope (same register as tx weight) */ -+ dwmac4_set_mtl_tx_queue_weight(hw, idle_slope, queue); -+ -+ /* configure high credit */ -+ value = readl(ioaddr + MTL_HIGH_CREDX_BASE_ADDR(queue)); -+ value &= ~MTL_HIGH_CRED_HC_MASK; -+ value |= high_credit & MTL_HIGH_CRED_HC_MASK; -+ writel(value, ioaddr + MTL_HIGH_CREDX_BASE_ADDR(queue)); -+ -+ /* configure high credit */ -+ value = readl(ioaddr + MTL_LOW_CREDX_BASE_ADDR(queue)); -+ value &= ~MTL_HIGH_CRED_LC_MASK; -+ value |= low_credit & MTL_HIGH_CRED_LC_MASK; -+ writel(value, ioaddr + MTL_LOW_CREDX_BASE_ADDR(queue)); -+} -+ - static void dwmac4_dump_regs(struct mac_device_info *hw, u32 *reg_space) - { - void __iomem *ioaddr = hw->pcsr; -@@ -251,11 +445,12 @@ static void dwmac4_set_filter(struct mac - } - - static void dwmac4_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, -- unsigned int fc, unsigned int pause_time) -+ unsigned int fc, unsigned int pause_time, -+ u32 tx_cnt) - { - void __iomem *ioaddr = hw->pcsr; -- u32 channel = STMMAC_CHAN0; /* FIXME */ - unsigned int flow = 0; -+ u32 queue = 0; - - pr_debug("GMAC Flow-Control:\n"); - if (fc & FLOW_RX) { -@@ -265,13 +460,18 @@ static void dwmac4_flow_ctrl(struct mac_ - } - if (fc & FLOW_TX) { - pr_debug("\tTransmit Flow-Control ON\n"); -- flow |= GMAC_TX_FLOW_CTRL_TFE; -- writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(channel)); - -- if (duplex) { -+ if (duplex) - pr_debug("\tduplex mode: PAUSE %d\n", pause_time); -- flow |= (pause_time << GMAC_TX_FLOW_CTRL_PT_SHIFT); -- writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(channel)); -+ -+ for (queue = 0; queue < tx_cnt; queue++) { -+ flow |= GMAC_TX_FLOW_CTRL_TFE; -+ -+ if (duplex) -+ flow |= -+ (pause_time << GMAC_TX_FLOW_CTRL_PT_SHIFT); -+ -+ writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(queue)); - } - } - } -@@ -325,11 +525,34 @@ static void dwmac4_phystatus(void __iome - } - } - -+static int dwmac4_irq_mtl_status(struct mac_device_info *hw, u32 chan) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 mtl_int_qx_status; -+ int ret = 0; -+ -+ mtl_int_qx_status = readl(ioaddr + MTL_INT_STATUS); -+ -+ /* Check MTL Interrupt */ -+ if (mtl_int_qx_status & MTL_INT_QX(chan)) { -+ /* read Queue x Interrupt status */ -+ u32 status = readl(ioaddr + MTL_CHAN_INT_CTRL(chan)); -+ -+ if (status & MTL_RX_OVERFLOW_INT) { -+ /* clear Interrupt */ -+ writel(status | MTL_RX_OVERFLOW_INT, -+ ioaddr + MTL_CHAN_INT_CTRL(chan)); -+ ret = CORE_IRQ_MTL_RX_OVERFLOW; -+ } -+ } -+ -+ return ret; -+} -+ - static int dwmac4_irq_status(struct mac_device_info *hw, - struct stmmac_extra_stats *x) - { - void __iomem *ioaddr = hw->pcsr; -- u32 mtl_int_qx_status; - u32 intr_status; - int ret = 0; - -@@ -348,20 +571,6 @@ static int dwmac4_irq_status(struct mac_ - x->irq_receive_pmt_irq_n++; - } - -- mtl_int_qx_status = readl(ioaddr + MTL_INT_STATUS); -- /* Check MTL Interrupt: Currently only one queue is used: Q0. */ -- if (mtl_int_qx_status & MTL_INT_Q0) { -- /* read Queue 0 Interrupt status */ -- u32 status = readl(ioaddr + MTL_CHAN_INT_CTRL(STMMAC_CHAN0)); -- -- if (status & MTL_RX_OVERFLOW_INT) { -- /* clear Interrupt */ -- writel(status | MTL_RX_OVERFLOW_INT, -- ioaddr + MTL_CHAN_INT_CTRL(STMMAC_CHAN0)); -- ret = CORE_IRQ_MTL_RX_OVERFLOW; -- } -- } -- - dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x); - if (intr_status & PCS_RGSMIIIS_IRQ) - dwmac4_phystatus(ioaddr, x); -@@ -369,64 +578,69 @@ static int dwmac4_irq_status(struct mac_ - return ret; - } - --static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x) -+static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x, -+ u32 rx_queues, u32 tx_queues) - { - u32 value; -+ u32 queue; - -- /* Currently only channel 0 is supported */ -- value = readl(ioaddr + MTL_CHAN_TX_DEBUG(STMMAC_CHAN0)); -+ for (queue = 0; queue < tx_queues; queue++) { -+ value = readl(ioaddr + MTL_CHAN_TX_DEBUG(queue)); - -- if (value & MTL_DEBUG_TXSTSFSTS) -- x->mtl_tx_status_fifo_full++; -- if (value & MTL_DEBUG_TXFSTS) -- x->mtl_tx_fifo_not_empty++; -- if (value & MTL_DEBUG_TWCSTS) -- x->mmtl_fifo_ctrl++; -- if (value & MTL_DEBUG_TRCSTS_MASK) { -- u32 trcsts = (value & MTL_DEBUG_TRCSTS_MASK) -- >> MTL_DEBUG_TRCSTS_SHIFT; -- if (trcsts == MTL_DEBUG_TRCSTS_WRITE) -- x->mtl_tx_fifo_read_ctrl_write++; -- else if (trcsts == MTL_DEBUG_TRCSTS_TXW) -- x->mtl_tx_fifo_read_ctrl_wait++; -- else if (trcsts == MTL_DEBUG_TRCSTS_READ) -- x->mtl_tx_fifo_read_ctrl_read++; -- else -- x->mtl_tx_fifo_read_ctrl_idle++; -+ if (value & MTL_DEBUG_TXSTSFSTS) -+ x->mtl_tx_status_fifo_full++; -+ if (value & MTL_DEBUG_TXFSTS) -+ x->mtl_tx_fifo_not_empty++; -+ if (value & MTL_DEBUG_TWCSTS) -+ x->mmtl_fifo_ctrl++; -+ if (value & MTL_DEBUG_TRCSTS_MASK) { -+ u32 trcsts = (value & MTL_DEBUG_TRCSTS_MASK) -+ >> MTL_DEBUG_TRCSTS_SHIFT; -+ if (trcsts == MTL_DEBUG_TRCSTS_WRITE) -+ x->mtl_tx_fifo_read_ctrl_write++; -+ else if (trcsts == MTL_DEBUG_TRCSTS_TXW) -+ x->mtl_tx_fifo_read_ctrl_wait++; -+ else if (trcsts == MTL_DEBUG_TRCSTS_READ) -+ x->mtl_tx_fifo_read_ctrl_read++; -+ else -+ x->mtl_tx_fifo_read_ctrl_idle++; -+ } -+ if (value & MTL_DEBUG_TXPAUSED) -+ x->mac_tx_in_pause++; - } -- if (value & MTL_DEBUG_TXPAUSED) -- x->mac_tx_in_pause++; - -- value = readl(ioaddr + MTL_CHAN_RX_DEBUG(STMMAC_CHAN0)); -+ for (queue = 0; queue < rx_queues; queue++) { -+ value = readl(ioaddr + MTL_CHAN_RX_DEBUG(queue)); - -- if (value & MTL_DEBUG_RXFSTS_MASK) { -- u32 rxfsts = (value & MTL_DEBUG_RXFSTS_MASK) -- >> MTL_DEBUG_RRCSTS_SHIFT; -- -- if (rxfsts == MTL_DEBUG_RXFSTS_FULL) -- x->mtl_rx_fifo_fill_level_full++; -- else if (rxfsts == MTL_DEBUG_RXFSTS_AT) -- x->mtl_rx_fifo_fill_above_thresh++; -- else if (rxfsts == MTL_DEBUG_RXFSTS_BT) -- x->mtl_rx_fifo_fill_below_thresh++; -- else -- x->mtl_rx_fifo_fill_level_empty++; -- } -- if (value & MTL_DEBUG_RRCSTS_MASK) { -- u32 rrcsts = (value & MTL_DEBUG_RRCSTS_MASK) >> -- MTL_DEBUG_RRCSTS_SHIFT; -- -- if (rrcsts == MTL_DEBUG_RRCSTS_FLUSH) -- x->mtl_rx_fifo_read_ctrl_flush++; -- else if (rrcsts == MTL_DEBUG_RRCSTS_RSTAT) -- x->mtl_rx_fifo_read_ctrl_read_data++; -- else if (rrcsts == MTL_DEBUG_RRCSTS_RDATA) -- x->mtl_rx_fifo_read_ctrl_status++; -- else -- x->mtl_rx_fifo_read_ctrl_idle++; -+ if (value & MTL_DEBUG_RXFSTS_MASK) { -+ u32 rxfsts = (value & MTL_DEBUG_RXFSTS_MASK) -+ >> MTL_DEBUG_RRCSTS_SHIFT; -+ -+ if (rxfsts == MTL_DEBUG_RXFSTS_FULL) -+ x->mtl_rx_fifo_fill_level_full++; -+ else if (rxfsts == MTL_DEBUG_RXFSTS_AT) -+ x->mtl_rx_fifo_fill_above_thresh++; -+ else if (rxfsts == MTL_DEBUG_RXFSTS_BT) -+ x->mtl_rx_fifo_fill_below_thresh++; -+ else -+ x->mtl_rx_fifo_fill_level_empty++; -+ } -+ if (value & MTL_DEBUG_RRCSTS_MASK) { -+ u32 rrcsts = (value & MTL_DEBUG_RRCSTS_MASK) >> -+ MTL_DEBUG_RRCSTS_SHIFT; -+ -+ if (rrcsts == MTL_DEBUG_RRCSTS_FLUSH) -+ x->mtl_rx_fifo_read_ctrl_flush++; -+ else if (rrcsts == MTL_DEBUG_RRCSTS_RSTAT) -+ x->mtl_rx_fifo_read_ctrl_read_data++; -+ else if (rrcsts == MTL_DEBUG_RRCSTS_RDATA) -+ x->mtl_rx_fifo_read_ctrl_status++; -+ else -+ x->mtl_rx_fifo_read_ctrl_idle++; -+ } -+ if (value & MTL_DEBUG_RWCSTS) -+ x->mtl_rx_fifo_ctrl_active++; - } -- if (value & MTL_DEBUG_RWCSTS) -- x->mtl_rx_fifo_ctrl_active++; - - /* GMAC debug */ - value = readl(ioaddr + GMAC_DEBUG); -@@ -455,10 +669,51 @@ static void dwmac4_debug(void __iomem *i - - static const struct stmmac_ops dwmac4_ops = { - .core_init = dwmac4_core_init, -+ .set_mac = stmmac_set_mac, - .rx_ipc = dwmac4_rx_ipc_enable, - .rx_queue_enable = dwmac4_rx_queue_enable, -+ .rx_queue_prio = dwmac4_rx_queue_priority, -+ .tx_queue_prio = dwmac4_tx_queue_priority, -+ .rx_queue_routing = dwmac4_tx_queue_routing, -+ .prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms, -+ .prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms, -+ .set_mtl_tx_queue_weight = dwmac4_set_mtl_tx_queue_weight, -+ .map_mtl_to_dma = dwmac4_map_mtl_dma, -+ .config_cbs = dwmac4_config_cbs, - .dump_regs = dwmac4_dump_regs, - .host_irq_status = dwmac4_irq_status, -+ .host_mtl_irq_status = dwmac4_irq_mtl_status, -+ .flow_ctrl = dwmac4_flow_ctrl, -+ .pmt = dwmac4_pmt, -+ .set_umac_addr = dwmac4_set_umac_addr, -+ .get_umac_addr = dwmac4_get_umac_addr, -+ .set_eee_mode = dwmac4_set_eee_mode, -+ .reset_eee_mode = dwmac4_reset_eee_mode, -+ .set_eee_timer = dwmac4_set_eee_timer, -+ .set_eee_pls = dwmac4_set_eee_pls, -+ .pcs_ctrl_ane = dwmac4_ctrl_ane, -+ .pcs_rane = dwmac4_rane, -+ .pcs_get_adv_lp = dwmac4_get_adv_lp, -+ .debug = dwmac4_debug, -+ .set_filter = dwmac4_set_filter, -+}; -+ -+static const struct stmmac_ops dwmac410_ops = { -+ .core_init = dwmac4_core_init, -+ .set_mac = stmmac_dwmac4_set_mac, -+ .rx_ipc = dwmac4_rx_ipc_enable, -+ .rx_queue_enable = dwmac4_rx_queue_enable, -+ .rx_queue_prio = dwmac4_rx_queue_priority, -+ .tx_queue_prio = dwmac4_tx_queue_priority, -+ .rx_queue_routing = dwmac4_tx_queue_routing, -+ .prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms, -+ .prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms, -+ .set_mtl_tx_queue_weight = dwmac4_set_mtl_tx_queue_weight, -+ .map_mtl_to_dma = dwmac4_map_mtl_dma, -+ .config_cbs = dwmac4_config_cbs, -+ .dump_regs = dwmac4_dump_regs, -+ .host_irq_status = dwmac4_irq_status, -+ .host_mtl_irq_status = dwmac4_irq_mtl_status, - .flow_ctrl = dwmac4_flow_ctrl, - .pmt = dwmac4_pmt, - .set_umac_addr = dwmac4_set_umac_addr, -@@ -492,8 +747,6 @@ struct mac_device_info *dwmac4_setup(voi - if (mac->multicast_filter_bins) - mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); - -- mac->mac = &dwmac4_ops; -- - mac->link.port = GMAC_CONFIG_PS; - mac->link.duplex = GMAC_CONFIG_DM; - mac->link.speed = GMAC_CONFIG_FES; -@@ -514,5 +767,10 @@ struct mac_device_info *dwmac4_setup(voi - else - mac->dma = &dwmac4_dma_ops; - -+ if (*synopsys_id >= DWMAC_CORE_4_00) -+ mac->mac = &dwmac410_ops; -+ else -+ mac->mac = &dwmac4_ops; -+ - return mac; - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c -@@ -214,13 +214,13 @@ static int dwmac4_wrback_get_tx_timestam - { - /* Context type from W/B descriptor must be zero */ - if (le32_to_cpu(p->des3) & TDES3_CONTEXT_TYPE) -- return -EINVAL; -+ return 0; - - /* Tx Timestamp Status is 1 so des0 and des1'll have valid values */ - if (le32_to_cpu(p->des3) & TDES3_TIMESTAMP_STATUS) -- return 0; -+ return 1; - -- return 1; -+ return 0; - } - - static inline u64 dwmac4_get_timestamp(void *desc, u32 ats) -@@ -282,7 +282,10 @@ static int dwmac4_wrback_get_rx_timestam - } - } - exit: -- return ret; -+ if (likely(ret == 0)) -+ return 1; -+ -+ return 0; - } - - static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic, -@@ -304,12 +307,13 @@ static void dwmac4_rd_init_tx_desc(struc - - static void dwmac4_rd_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, - bool csum_flag, int mode, bool tx_own, -- bool ls) -+ bool ls, unsigned int tot_pkt_len) - { - unsigned int tdes3 = le32_to_cpu(p->des3); - - p->des2 |= cpu_to_le32(len & TDES2_BUFFER1_SIZE_MASK); - -+ tdes3 |= tot_pkt_len & TDES3_PACKET_SIZE_MASK; - if (is_fs) - tdes3 |= TDES3_FIRST_DESCRIPTOR; - else ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -@@ -71,36 +71,48 @@ static void dwmac4_dma_axi(void __iomem - writel(value, ioaddr + DMA_SYS_BUS_MODE); - } - --static void dwmac4_dma_init_channel(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, -- u32 dma_tx_phy, u32 dma_rx_phy, -- u32 channel) -+void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_rx_phy, u32 chan) - { - u32 value; -- int txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -- int rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; -+ u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; - -- /* set PBL for each channels. Currently we affect same configuration -- * on each channel -- */ -- value = readl(ioaddr + DMA_CHAN_CONTROL(channel)); -- if (dma_cfg->pblx8) -- value = value | DMA_BUS_MODE_PBL; -- writel(value, ioaddr + DMA_CHAN_CONTROL(channel)); -+ value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); -+ value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); -+ writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); -+ -+ writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(chan)); -+} - -- value = readl(ioaddr + DMA_CHAN_TX_CONTROL(channel)); -+void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx_phy, u32 chan) -+{ -+ u32 value; -+ u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -+ -+ value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); - value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT); -- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(channel)); -+ writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); - -- value = readl(ioaddr + DMA_CHAN_RX_CONTROL(channel)); -- value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); -- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(channel)); -+ writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); -+} - -- /* Mask interrupts by writing to CSR7 */ -- writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + DMA_CHAN_INTR_ENA(channel)); -+void dwmac4_dma_init_channel(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, u32 chan) -+{ -+ u32 value; -+ -+ /* common channel control register config */ -+ value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); -+ if (dma_cfg->pblx8) -+ value = value | DMA_BUS_MODE_PBL; -+ writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); - -- writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(channel)); -- writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(channel)); -+ /* Mask interrupts by writing to CSR7 */ -+ writel(DMA_CHAN_INTR_DEFAULT_MASK, -+ ioaddr + DMA_CHAN_INTR_ENA(chan)); - } - - static void dwmac4_dma_init(void __iomem *ioaddr, -@@ -108,7 +120,6 @@ static void dwmac4_dma_init(void __iomem - u32 dma_tx, u32 dma_rx, int atds) - { - u32 value = readl(ioaddr + DMA_SYS_BUS_MODE); -- int i; - - /* Set the Fixed burst mode */ - if (dma_cfg->fixed_burst) -@@ -122,9 +133,6 @@ static void dwmac4_dma_init(void __iomem - value |= DMA_SYS_BUS_AAL; - - writel(value, ioaddr + DMA_SYS_BUS_MODE); -- -- for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) -- dwmac4_dma_init_channel(ioaddr, dma_cfg, dma_tx, dma_rx, i); - } - - static void _dwmac4_dump_dma_regs(void __iomem *ioaddr, u32 channel, -@@ -174,46 +182,121 @@ static void dwmac4_dump_dma_regs(void __ - _dwmac4_dump_dma_regs(ioaddr, i, reg_space); - } - --static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt) -+static void dwmac4_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 number_chan) - { -- int i; -+ u32 chan; - -- for (i = 0; i < DMA_CHANNEL_NB_MAX; i++) -- writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(i)); -+ for (chan = 0; chan < number_chan; chan++) -+ writel(riwt, ioaddr + DMA_CHAN_RX_WATCHDOG(chan)); - } - --static void dwmac4_dma_chan_op_mode(void __iomem *ioaddr, int txmode, -- int rxmode, u32 channel) -+static void dwmac4_dma_rx_chan_op_mode(void __iomem *ioaddr, int mode, -+ u32 channel, int fifosz) - { -- u32 mtl_tx_op, mtl_rx_op, mtl_rx_int; -+ unsigned int rqs = fifosz / 256 - 1; -+ u32 mtl_rx_op, mtl_rx_int; - -- /* Following code only done for channel 0, other channels not yet -- * supported. -- */ -- mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel)); -+ mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel)); -+ -+ if (mode == SF_DMA_MODE) { -+ pr_debug("GMAC: enable RX store and forward mode\n"); -+ mtl_rx_op |= MTL_OP_MODE_RSF; -+ } else { -+ pr_debug("GMAC: disable RX SF mode (threshold %d)\n", mode); -+ mtl_rx_op &= ~MTL_OP_MODE_RSF; -+ mtl_rx_op &= MTL_OP_MODE_RTC_MASK; -+ if (mode <= 32) -+ mtl_rx_op |= MTL_OP_MODE_RTC_32; -+ else if (mode <= 64) -+ mtl_rx_op |= MTL_OP_MODE_RTC_64; -+ else if (mode <= 96) -+ mtl_rx_op |= MTL_OP_MODE_RTC_96; -+ else -+ mtl_rx_op |= MTL_OP_MODE_RTC_128; -+ } -+ -+ mtl_rx_op &= ~MTL_OP_MODE_RQS_MASK; -+ mtl_rx_op |= rqs << MTL_OP_MODE_RQS_SHIFT; -+ -+ /* enable flow control only if each channel gets 4 KiB or more FIFO */ -+ if (fifosz >= 4096) { -+ unsigned int rfd, rfa; -+ -+ mtl_rx_op |= MTL_OP_MODE_EHFC; -+ -+ /* Set Threshold for Activating Flow Control to min 2 frames, -+ * i.e. 1500 * 2 = 3000 bytes. -+ * -+ * Set Threshold for Deactivating Flow Control to min 1 frame, -+ * i.e. 1500 bytes. -+ */ -+ switch (fifosz) { -+ case 4096: -+ /* This violates the above formula because of FIFO size -+ * limit therefore overflow may occur in spite of this. -+ */ -+ rfd = 0x03; /* Full-2.5K */ -+ rfa = 0x01; /* Full-1.5K */ -+ break; -+ -+ case 8192: -+ rfd = 0x06; /* Full-4K */ -+ rfa = 0x0a; /* Full-6K */ -+ break; -+ -+ case 16384: -+ rfd = 0x06; /* Full-4K */ -+ rfa = 0x12; /* Full-10K */ -+ break; -+ -+ default: -+ rfd = 0x06; /* Full-4K */ -+ rfa = 0x1e; /* Full-16K */ -+ break; -+ } - -- if (txmode == SF_DMA_MODE) { -+ mtl_rx_op &= ~MTL_OP_MODE_RFD_MASK; -+ mtl_rx_op |= rfd << MTL_OP_MODE_RFD_SHIFT; -+ -+ mtl_rx_op &= ~MTL_OP_MODE_RFA_MASK; -+ mtl_rx_op |= rfa << MTL_OP_MODE_RFA_SHIFT; -+ } -+ -+ writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel)); -+ -+ /* Enable MTL RX overflow */ -+ mtl_rx_int = readl(ioaddr + MTL_CHAN_INT_CTRL(channel)); -+ writel(mtl_rx_int | MTL_RX_OVERFLOW_INT_EN, -+ ioaddr + MTL_CHAN_INT_CTRL(channel)); -+} -+ -+static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode, -+ u32 channel) -+{ -+ u32 mtl_tx_op = readl(ioaddr + MTL_CHAN_TX_OP_MODE(channel)); -+ -+ if (mode == SF_DMA_MODE) { - pr_debug("GMAC: enable TX store and forward mode\n"); - /* Transmit COE type 2 cannot be done in cut-through mode. */ - mtl_tx_op |= MTL_OP_MODE_TSF; - } else { -- pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode); -+ pr_debug("GMAC: disabling TX SF (threshold %d)\n", mode); - mtl_tx_op &= ~MTL_OP_MODE_TSF; - mtl_tx_op &= MTL_OP_MODE_TTC_MASK; - /* Set the transmit threshold */ -- if (txmode <= 32) -+ if (mode <= 32) - mtl_tx_op |= MTL_OP_MODE_TTC_32; -- else if (txmode <= 64) -+ else if (mode <= 64) - mtl_tx_op |= MTL_OP_MODE_TTC_64; -- else if (txmode <= 96) -+ else if (mode <= 96) - mtl_tx_op |= MTL_OP_MODE_TTC_96; -- else if (txmode <= 128) -+ else if (mode <= 128) - mtl_tx_op |= MTL_OP_MODE_TTC_128; -- else if (txmode <= 192) -+ else if (mode <= 192) - mtl_tx_op |= MTL_OP_MODE_TTC_192; -- else if (txmode <= 256) -+ else if (mode <= 256) - mtl_tx_op |= MTL_OP_MODE_TTC_256; -- else if (txmode <= 384) -+ else if (mode <= 384) - mtl_tx_op |= MTL_OP_MODE_TTC_384; - else - mtl_tx_op |= MTL_OP_MODE_TTC_512; -@@ -230,39 +313,6 @@ static void dwmac4_dma_chan_op_mode(void - */ - mtl_tx_op |= MTL_OP_MODE_TXQEN | MTL_OP_MODE_TQS_MASK; - writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(channel)); -- -- mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel)); -- -- if (rxmode == SF_DMA_MODE) { -- pr_debug("GMAC: enable RX store and forward mode\n"); -- mtl_rx_op |= MTL_OP_MODE_RSF; -- } else { -- pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode); -- mtl_rx_op &= ~MTL_OP_MODE_RSF; -- mtl_rx_op &= MTL_OP_MODE_RTC_MASK; -- if (rxmode <= 32) -- mtl_rx_op |= MTL_OP_MODE_RTC_32; -- else if (rxmode <= 64) -- mtl_rx_op |= MTL_OP_MODE_RTC_64; -- else if (rxmode <= 96) -- mtl_rx_op |= MTL_OP_MODE_RTC_96; -- else -- mtl_rx_op |= MTL_OP_MODE_RTC_128; -- } -- -- writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel)); -- -- /* Enable MTL RX overflow */ -- mtl_rx_int = readl(ioaddr + MTL_CHAN_INT_CTRL(channel)); -- writel(mtl_rx_int | MTL_RX_OVERFLOW_INT_EN, -- ioaddr + MTL_CHAN_INT_CTRL(channel)); --} -- --static void dwmac4_dma_operation_mode(void __iomem *ioaddr, int txmode, -- int rxmode, int rxfifosz) --{ -- /* Only Channel 0 is actually configured and used */ -- dwmac4_dma_chan_op_mode(ioaddr, txmode, rxmode, 0); - } - - static void dwmac4_get_hw_feature(void __iomem *ioaddr, -@@ -294,6 +344,11 @@ static void dwmac4_get_hw_feature(void _ - hw_cap = readl(ioaddr + GMAC_HW_FEATURE1); - dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20; - dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18; -+ /* RX and TX FIFO sizes are encoded as log2(n / 128). Undo that by -+ * shifting and store the sizes in bytes. -+ */ -+ dma_cap->tx_fifo_size = 128 << ((hw_cap & GMAC_HW_TXFIFOSIZE) >> 6); -+ dma_cap->rx_fifo_size = 128 << ((hw_cap & GMAC_HW_RXFIFOSIZE) >> 0); - /* MAC HW feature2 */ - hw_cap = readl(ioaddr + GMAC_HW_FEATURE2); - /* TX and RX number of channels */ -@@ -332,9 +387,13 @@ static void dwmac4_enable_tso(void __iom - const struct stmmac_dma_ops dwmac4_dma_ops = { - .reset = dwmac4_dma_reset, - .init = dwmac4_dma_init, -+ .init_chan = dwmac4_dma_init_channel, -+ .init_rx_chan = dwmac4_dma_init_rx_chan, -+ .init_tx_chan = dwmac4_dma_init_tx_chan, - .axi = dwmac4_dma_axi, - .dump_regs = dwmac4_dump_dma_regs, -- .dma_mode = dwmac4_dma_operation_mode, -+ .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, -+ .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, - .enable_dma_irq = dwmac4_enable_dma_irq, - .disable_dma_irq = dwmac4_disable_dma_irq, - .start_tx = dwmac4_dma_start_tx, -@@ -354,9 +413,13 @@ const struct stmmac_dma_ops dwmac4_dma_o - const struct stmmac_dma_ops dwmac410_dma_ops = { - .reset = dwmac4_dma_reset, - .init = dwmac4_dma_init, -+ .init_chan = dwmac4_dma_init_channel, -+ .init_rx_chan = dwmac4_dma_init_rx_chan, -+ .init_tx_chan = dwmac4_dma_init_tx_chan, - .axi = dwmac4_dma_axi, - .dump_regs = dwmac4_dump_dma_regs, -- .dma_mode = dwmac4_dma_operation_mode, -+ .dma_rx_mode = dwmac4_dma_rx_chan_op_mode, -+ .dma_tx_mode = dwmac4_dma_tx_chan_op_mode, - .enable_dma_irq = dwmac410_enable_dma_irq, - .disable_dma_irq = dwmac4_disable_dma_irq, - .start_tx = dwmac4_dma_start_tx, ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h -@@ -185,17 +185,17 @@ - - int dwmac4_dma_reset(void __iomem *ioaddr); - void dwmac4_enable_dma_transmission(void __iomem *ioaddr, u32 tail_ptr); --void dwmac4_enable_dma_irq(void __iomem *ioaddr); --void dwmac410_enable_dma_irq(void __iomem *ioaddr); --void dwmac4_disable_dma_irq(void __iomem *ioaddr); --void dwmac4_dma_start_tx(void __iomem *ioaddr); --void dwmac4_dma_stop_tx(void __iomem *ioaddr); --void dwmac4_dma_start_rx(void __iomem *ioaddr); --void dwmac4_dma_stop_rx(void __iomem *ioaddr); -+void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan); -+void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan); -+void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan); -+void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan); -+void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan); -+void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan); -+void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan); - int dwmac4_dma_interrupt(void __iomem *ioaddr, -- struct stmmac_extra_stats *x); --void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len); --void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len); -+ struct stmmac_extra_stats *x, u32 chan); -+void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan); -+void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan); - void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); - void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c -@@ -37,96 +37,96 @@ int dwmac4_dma_reset(void __iomem *ioadd - - void dwmac4_set_rx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) - { -- writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(0)); -+ writel(tail_ptr, ioaddr + DMA_CHAN_RX_END_ADDR(chan)); - } - - void dwmac4_set_tx_tail_ptr(void __iomem *ioaddr, u32 tail_ptr, u32 chan) - { -- writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(0)); -+ writel(tail_ptr, ioaddr + DMA_CHAN_TX_END_ADDR(chan)); - } - --void dwmac4_dma_start_tx(void __iomem *ioaddr) -+void dwmac4_dma_start_tx(void __iomem *ioaddr, u32 chan) - { -- u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); -+ u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); - - value |= DMA_CONTROL_ST; -- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); -+ writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); - - value = readl(ioaddr + GMAC_CONFIG); - value |= GMAC_CONFIG_TE; - writel(value, ioaddr + GMAC_CONFIG); - } - --void dwmac4_dma_stop_tx(void __iomem *ioaddr) -+void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan) - { -- u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); -+ u32 value = readl(ioaddr + DMA_CHAN_TX_CONTROL(chan)); - - value &= ~DMA_CONTROL_ST; -- writel(value, ioaddr + DMA_CHAN_TX_CONTROL(STMMAC_CHAN0)); -+ writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); - - value = readl(ioaddr + GMAC_CONFIG); - value &= ~GMAC_CONFIG_TE; - writel(value, ioaddr + GMAC_CONFIG); - } - --void dwmac4_dma_start_rx(void __iomem *ioaddr) -+void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan) - { -- u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); -+ u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); - - value |= DMA_CONTROL_SR; - -- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); -+ writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); - - value = readl(ioaddr + GMAC_CONFIG); - value |= GMAC_CONFIG_RE; - writel(value, ioaddr + GMAC_CONFIG); - } - --void dwmac4_dma_stop_rx(void __iomem *ioaddr) -+void dwmac4_dma_stop_rx(void __iomem *ioaddr, u32 chan) - { -- u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); -+ u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(chan)); - - value &= ~DMA_CONTROL_SR; -- writel(value, ioaddr + DMA_CHAN_RX_CONTROL(STMMAC_CHAN0)); -+ writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan)); - - value = readl(ioaddr + GMAC_CONFIG); - value &= ~GMAC_CONFIG_RE; - writel(value, ioaddr + GMAC_CONFIG); - } - --void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len) -+void dwmac4_set_tx_ring_len(void __iomem *ioaddr, u32 len, u32 chan) - { -- writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(STMMAC_CHAN0)); -+ writel(len, ioaddr + DMA_CHAN_TX_RING_LEN(chan)); - } - --void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len) -+void dwmac4_set_rx_ring_len(void __iomem *ioaddr, u32 len, u32 chan) - { -- writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(STMMAC_CHAN0)); -+ writel(len, ioaddr + DMA_CHAN_RX_RING_LEN(chan)); - } - --void dwmac4_enable_dma_irq(void __iomem *ioaddr) -+void dwmac4_enable_dma_irq(void __iomem *ioaddr, u32 chan) - { - writel(DMA_CHAN_INTR_DEFAULT_MASK, ioaddr + -- DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); -+ DMA_CHAN_INTR_ENA(chan)); - } - --void dwmac410_enable_dma_irq(void __iomem *ioaddr) -+void dwmac410_enable_dma_irq(void __iomem *ioaddr, u32 chan) - { - writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10, -- ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); -+ ioaddr + DMA_CHAN_INTR_ENA(chan)); - } - --void dwmac4_disable_dma_irq(void __iomem *ioaddr) -+void dwmac4_disable_dma_irq(void __iomem *ioaddr, u32 chan) - { -- writel(0, ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); -+ writel(0, ioaddr + DMA_CHAN_INTR_ENA(chan)); - } - - int dwmac4_dma_interrupt(void __iomem *ioaddr, -- struct stmmac_extra_stats *x) -+ struct stmmac_extra_stats *x, u32 chan) - { - int ret = 0; - -- u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(0)); -+ u32 intr_status = readl(ioaddr + DMA_CHAN_STATUS(chan)); - - /* ABNORMAL interrupts */ - if (unlikely(intr_status & DMA_CHAN_STATUS_AIS)) { -@@ -153,7 +153,7 @@ int dwmac4_dma_interrupt(void __iomem *i - if (likely(intr_status & DMA_CHAN_STATUS_RI)) { - u32 value; - -- value = readl(ioaddr + DMA_CHAN_INTR_ENA(STMMAC_CHAN0)); -+ value = readl(ioaddr + DMA_CHAN_INTR_ENA(chan)); - /* to schedule NAPI on real RIE event. */ - if (likely(value & DMA_CHAN_INTR_ENA_RIE)) { - x->rx_normal_irq_n++; -@@ -172,7 +172,7 @@ int dwmac4_dma_interrupt(void __iomem *i - * status [21-0] expect reserved bits [5-3] - */ - writel((intr_status & 0x3fffc7), -- ioaddr + DMA_CHAN_STATUS(STMMAC_CHAN0)); -+ ioaddr + DMA_CHAN_STATUS(chan)); - - return ret; - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -@@ -137,13 +137,14 @@ - #define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ - - void dwmac_enable_dma_transmission(void __iomem *ioaddr); --void dwmac_enable_dma_irq(void __iomem *ioaddr); --void dwmac_disable_dma_irq(void __iomem *ioaddr); --void dwmac_dma_start_tx(void __iomem *ioaddr); --void dwmac_dma_stop_tx(void __iomem *ioaddr); --void dwmac_dma_start_rx(void __iomem *ioaddr); --void dwmac_dma_stop_rx(void __iomem *ioaddr); --int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x); -+void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan); -+void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan); -+void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan); -+void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan); -+void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan); -+void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan); -+int dwmac_dma_interrupt(void __iomem *ioaddr, struct stmmac_extra_stats *x, -+ u32 chan); - int dwmac_dma_reset(void __iomem *ioaddr); - - #endif /* __DWMAC_DMA_H__ */ ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -@@ -47,38 +47,38 @@ void dwmac_enable_dma_transmission(void - writel(1, ioaddr + DMA_XMT_POLL_DEMAND); - } - --void dwmac_enable_dma_irq(void __iomem *ioaddr) -+void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan) - { - writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); - } - --void dwmac_disable_dma_irq(void __iomem *ioaddr) -+void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan) - { - writel(0, ioaddr + DMA_INTR_ENA); - } - --void dwmac_dma_start_tx(void __iomem *ioaddr) -+void dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan) - { - u32 value = readl(ioaddr + DMA_CONTROL); - value |= DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); - } - --void dwmac_dma_stop_tx(void __iomem *ioaddr) -+void dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan) - { - u32 value = readl(ioaddr + DMA_CONTROL); - value &= ~DMA_CONTROL_ST; - writel(value, ioaddr + DMA_CONTROL); - } - --void dwmac_dma_start_rx(void __iomem *ioaddr) -+void dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan) - { - u32 value = readl(ioaddr + DMA_CONTROL); - value |= DMA_CONTROL_SR; - writel(value, ioaddr + DMA_CONTROL); - } - --void dwmac_dma_stop_rx(void __iomem *ioaddr) -+void dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan) - { - u32 value = readl(ioaddr + DMA_CONTROL); - value &= ~DMA_CONTROL_SR; -@@ -156,7 +156,7 @@ static void show_rx_process_state(unsign - #endif - - int dwmac_dma_interrupt(void __iomem *ioaddr, -- struct stmmac_extra_stats *x) -+ struct stmmac_extra_stats *x, u32 chan) - { - int ret = 0; - /* read the status register (CSR5) */ ---- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c -@@ -315,7 +315,7 @@ static void enh_desc_release_tx_desc(str - - static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, - bool csum_flag, int mode, bool tx_own, -- bool ls) -+ bool ls, unsigned int tot_pkt_len) - { - unsigned int tdes0 = le32_to_cpu(p->des0); - ---- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -+++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c -@@ -191,7 +191,7 @@ static void ndesc_release_tx_desc(struct - - static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, - bool csum_flag, int mode, bool tx_own, -- bool ls) -+ bool ls, unsigned int tot_pkt_len) - { - unsigned int tdes1 = le32_to_cpu(p->des1); - ---- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -+++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c -@@ -26,16 +26,17 @@ - - static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum) - { -- struct stmmac_priv *priv = (struct stmmac_priv *)p; -- unsigned int entry = priv->cur_tx; -- struct dma_desc *desc; -+ struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p; - unsigned int nopaged_len = skb_headlen(skb); -+ struct stmmac_priv *priv = tx_q->priv_data; -+ unsigned int entry = tx_q->cur_tx; - unsigned int bmax, len, des2; -+ struct dma_desc *desc; - - if (priv->extend_desc) -- desc = (struct dma_desc *)(priv->dma_etx + entry); -+ desc = (struct dma_desc *)(tx_q->dma_etx + entry); - else -- desc = priv->dma_tx + entry; -+ desc = tx_q->dma_tx + entry; - - if (priv->plat->enh_desc) - bmax = BUF_SIZE_8KiB; -@@ -52,48 +53,51 @@ static int stmmac_jumbo_frm(void *p, str - if (dma_mapping_error(priv->device, des2)) - return -1; - -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = bmax; -- priv->tx_skbuff_dma[entry].is_jumbo = true; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = bmax; -+ tx_q->tx_skbuff_dma[entry].is_jumbo = true; - - desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, -- STMMAC_RING_MODE, 0, false); -- priv->tx_skbuff[entry] = NULL; -+ STMMAC_RING_MODE, 0, -+ false, skb->len); -+ tx_q->tx_skbuff[entry] = NULL; - entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); - - if (priv->extend_desc) -- desc = (struct dma_desc *)(priv->dma_etx + entry); -+ desc = (struct dma_desc *)(tx_q->dma_etx + entry); - else -- desc = priv->dma_tx + entry; -+ desc = tx_q->dma_tx + entry; - - des2 = dma_map_single(priv->device, skb->data + bmax, len, - DMA_TO_DEVICE); - desc->des2 = cpu_to_le32(des2); - if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = len; -- priv->tx_skbuff_dma[entry].is_jumbo = true; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = len; -+ tx_q->tx_skbuff_dma[entry].is_jumbo = true; - - desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 0, len, csum, -- STMMAC_RING_MODE, 1, true); -+ STMMAC_RING_MODE, 1, -+ true, skb->len); - } else { - des2 = dma_map_single(priv->device, skb->data, - nopaged_len, DMA_TO_DEVICE); - desc->des2 = cpu_to_le32(des2); - if (dma_mapping_error(priv->device, des2)) - return -1; -- priv->tx_skbuff_dma[entry].buf = des2; -- priv->tx_skbuff_dma[entry].len = nopaged_len; -- priv->tx_skbuff_dma[entry].is_jumbo = true; -+ tx_q->tx_skbuff_dma[entry].buf = des2; -+ tx_q->tx_skbuff_dma[entry].len = nopaged_len; -+ tx_q->tx_skbuff_dma[entry].is_jumbo = true; - desc->des3 = cpu_to_le32(des2 + BUF_SIZE_4KiB); - priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum, -- STMMAC_RING_MODE, 0, true); -+ STMMAC_RING_MODE, 0, -+ true, skb->len); - } - -- priv->cur_tx = entry; -+ tx_q->cur_tx = entry; - - return entry; - } -@@ -125,12 +129,13 @@ static void stmmac_init_desc3(struct dma - - static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p) - { -- struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr; -- unsigned int entry = priv->dirty_tx; -+ struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr; -+ struct stmmac_priv *priv = tx_q->priv_data; -+ unsigned int entry = tx_q->dirty_tx; - - /* des3 is only used for jumbo frames tx or time stamping */ -- if (unlikely(priv->tx_skbuff_dma[entry].is_jumbo || -- (priv->tx_skbuff_dma[entry].last_segment && -+ if (unlikely(tx_q->tx_skbuff_dma[entry].is_jumbo || -+ (tx_q->tx_skbuff_dma[entry].last_segment && - !priv->extend_desc && priv->hwts_tx_en))) - p->des3 = 0; - } ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -46,38 +46,51 @@ struct stmmac_tx_info { - bool is_jumbo; - }; - --struct stmmac_priv { -- /* Frequently used values are kept adjacent for cache effect */ -+/* Frequently used values are kept adjacent for cache effect */ -+struct stmmac_tx_queue { -+ u32 queue_index; -+ struct stmmac_priv *priv_data; - struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp; - struct dma_desc *dma_tx; - struct sk_buff **tx_skbuff; -+ struct stmmac_tx_info *tx_skbuff_dma; - unsigned int cur_tx; - unsigned int dirty_tx; -+ dma_addr_t dma_tx_phy; -+ u32 tx_tail_addr; -+}; -+ -+struct stmmac_rx_queue { -+ u32 queue_index; -+ struct stmmac_priv *priv_data; -+ struct dma_extended_desc *dma_erx; -+ struct dma_desc *dma_rx ____cacheline_aligned_in_smp; -+ struct sk_buff **rx_skbuff; -+ dma_addr_t *rx_skbuff_dma; -+ unsigned int cur_rx; -+ unsigned int dirty_rx; -+ u32 rx_zeroc_thresh; -+ dma_addr_t dma_rx_phy; -+ u32 rx_tail_addr; -+ struct napi_struct napi ____cacheline_aligned_in_smp; -+}; -+ -+struct stmmac_priv { -+ /* Frequently used values are kept adjacent for cache effect */ - u32 tx_count_frames; - u32 tx_coal_frames; - u32 tx_coal_timer; -- struct stmmac_tx_info *tx_skbuff_dma; -- dma_addr_t dma_tx_phy; -+ - int tx_coalesce; - int hwts_tx_en; - bool tx_path_in_lpi_mode; - struct timer_list txtimer; - bool tso; - -- struct dma_desc *dma_rx ____cacheline_aligned_in_smp; -- struct dma_extended_desc *dma_erx; -- struct sk_buff **rx_skbuff; -- unsigned int cur_rx; -- unsigned int dirty_rx; - unsigned int dma_buf_sz; - unsigned int rx_copybreak; -- unsigned int rx_zeroc_thresh; - u32 rx_riwt; - int hwts_rx_en; -- dma_addr_t *rx_skbuff_dma; -- dma_addr_t dma_rx_phy; -- -- struct napi_struct napi ____cacheline_aligned_in_smp; - - void __iomem *ioaddr; - struct net_device *dev; -@@ -85,6 +98,12 @@ struct stmmac_priv { - struct mac_device_info *hw; - spinlock_t lock; - -+ /* RX Queue */ -+ struct stmmac_rx_queue rx_queue[MTL_MAX_RX_QUEUES]; -+ -+ /* TX Queue */ -+ struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES]; -+ - int oldlink; - int speed; - int oldduplex; -@@ -119,8 +138,6 @@ struct stmmac_priv { - spinlock_t ptp_lock; - void __iomem *mmcaddr; - void __iomem *ptpaddr; -- u32 rx_tail_addr; -- u32 tx_tail_addr; - u32 mss; - - #ifdef CONFIG_DEBUG_FS ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -481,6 +481,7 @@ stmmac_set_pauseparam(struct net_device - struct ethtool_pauseparam *pause) - { - struct stmmac_priv *priv = netdev_priv(netdev); -+ u32 tx_cnt = priv->plat->tx_queues_to_use; - struct phy_device *phy = netdev->phydev; - int new_pause = FLOW_OFF; - -@@ -511,7 +512,7 @@ stmmac_set_pauseparam(struct net_device - } - - priv->hw->mac->flow_ctrl(priv->hw, phy->duplex, priv->flow_ctrl, -- priv->pause); -+ priv->pause, tx_cnt); - return 0; - } - -@@ -519,6 +520,8 @@ static void stmmac_get_ethtool_stats(str - struct ethtool_stats *dummy, u64 *data) - { - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; - int i, j = 0; - - /* Update the DMA HW counters for dwmac10/100 */ -@@ -549,7 +552,8 @@ static void stmmac_get_ethtool_stats(str - if ((priv->hw->mac->debug) && - (priv->synopsys_id >= DWMAC_CORE_3_50)) - priv->hw->mac->debug(priv->ioaddr, -- (void *)&priv->xstats); -+ (void *)&priv->xstats, -+ rx_queues_count, tx_queues_count); - } - for (i = 0; i < STMMAC_STATS_LEN; i++) { - char *p = (char *)priv + stmmac_gstrings_stats[i].stat_offset; -@@ -726,6 +730,7 @@ static int stmmac_set_coalesce(struct ne - struct ethtool_coalesce *ec) - { - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_cnt = priv->plat->rx_queues_to_use; - unsigned int rx_riwt; - - /* Check not supported parameters */ -@@ -764,7 +769,7 @@ static int stmmac_set_coalesce(struct ne - priv->tx_coal_frames = ec->tx_max_coalesced_frames; - priv->tx_coal_timer = ec->tx_coalesce_usecs; - priv->rx_riwt = rx_riwt; -- priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt); -+ priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt, rx_cnt); - - return 0; - } ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -139,6 +139,64 @@ static void stmmac_verify_args(void) - } - - /** -+ * stmmac_disable_all_queues - Disable all queues -+ * @priv: driver private structure -+ */ -+static void stmmac_disable_all_queues(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_cnt = priv->plat->rx_queues_to_use; -+ u32 queue; -+ -+ for (queue = 0; queue < rx_queues_cnt; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ napi_disable(&rx_q->napi); -+ } -+} -+ -+/** -+ * stmmac_enable_all_queues - Enable all queues -+ * @priv: driver private structure -+ */ -+static void stmmac_enable_all_queues(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_cnt = priv->plat->rx_queues_to_use; -+ u32 queue; -+ -+ for (queue = 0; queue < rx_queues_cnt; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ napi_enable(&rx_q->napi); -+ } -+} -+ -+/** -+ * stmmac_stop_all_queues - Stop all queues -+ * @priv: driver private structure -+ */ -+static void stmmac_stop_all_queues(struct stmmac_priv *priv) -+{ -+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ -+ for (queue = 0; queue < tx_queues_cnt; queue++) -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); -+} -+ -+/** -+ * stmmac_start_all_queues - Start all queues -+ * @priv: driver private structure -+ */ -+static void stmmac_start_all_queues(struct stmmac_priv *priv) -+{ -+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ -+ for (queue = 0; queue < tx_queues_cnt; queue++) -+ netif_tx_start_queue(netdev_get_tx_queue(priv->dev, queue)); -+} -+ -+/** - * stmmac_clk_csr_set - dynamically set the MDC clock - * @priv: driver private structure - * Description: this is to dynamically set the MDC clock according to the csr -@@ -185,26 +243,33 @@ static void print_pkt(unsigned char *buf - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); - } - --static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) -+static inline u32 stmmac_tx_avail(struct stmmac_priv *priv, u32 queue) - { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; - u32 avail; - -- if (priv->dirty_tx > priv->cur_tx) -- avail = priv->dirty_tx - priv->cur_tx - 1; -+ if (tx_q->dirty_tx > tx_q->cur_tx) -+ avail = tx_q->dirty_tx - tx_q->cur_tx - 1; - else -- avail = DMA_TX_SIZE - priv->cur_tx + priv->dirty_tx - 1; -+ avail = DMA_TX_SIZE - tx_q->cur_tx + tx_q->dirty_tx - 1; - - return avail; - } - --static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv) -+/** -+ * stmmac_rx_dirty - Get RX queue dirty -+ * @priv: driver private structure -+ * @queue: RX queue index -+ */ -+static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue) - { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - u32 dirty; - -- if (priv->dirty_rx <= priv->cur_rx) -- dirty = priv->cur_rx - priv->dirty_rx; -+ if (rx_q->dirty_rx <= rx_q->cur_rx) -+ dirty = rx_q->cur_rx - rx_q->dirty_rx; - else -- dirty = DMA_RX_SIZE - priv->dirty_rx + priv->cur_rx; -+ dirty = DMA_RX_SIZE - rx_q->dirty_rx + rx_q->cur_rx; - - return dirty; - } -@@ -232,9 +297,19 @@ static inline void stmmac_hw_fix_mac_spe - */ - static void stmmac_enable_eee_mode(struct stmmac_priv *priv) - { -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ -+ /* check if all TX queues have the work finished */ -+ for (queue = 0; queue < tx_cnt; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ if (tx_q->dirty_tx != tx_q->cur_tx) -+ return; /* still unfinished work */ -+ } -+ - /* Check and enter in LPI mode */ -- if ((priv->dirty_tx == priv->cur_tx) && -- (priv->tx_path_in_lpi_mode == false)) -+ if (!priv->tx_path_in_lpi_mode) - priv->hw->mac->set_eee_mode(priv->hw, - priv->plat->en_tx_lpi_clockgating); - } -@@ -365,14 +440,14 @@ static void stmmac_get_tx_hwtstamp(struc - return; - - /* check tx tstamp status */ -- if (!priv->hw->desc->get_tx_timestamp_status(p)) { -+ if (priv->hw->desc->get_tx_timestamp_status(p)) { - /* get the valid tstamp */ - ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); - - memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); - shhwtstamp.hwtstamp = ns_to_ktime(ns); - -- netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns); -+ netdev_dbg(priv->dev, "get valid TX hw timestamp %llu\n", ns); - /* pass tstamp to stack */ - skb_tstamp_tx(skb, &shhwtstamp); - } -@@ -399,19 +474,19 @@ static void stmmac_get_rx_hwtstamp(struc - return; - - /* Check if timestamp is available */ -- if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { -+ if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { - /* For GMAC4, the valid timestamp is from CTX next desc. */ - if (priv->plat->has_gmac4) - ns = priv->hw->desc->get_timestamp(np, priv->adv_ts); - else - ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); - -- netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns); -+ netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); - shhwtstamp = skb_hwtstamps(skb); - memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); - shhwtstamp->hwtstamp = ns_to_ktime(ns); - } else { -- netdev_err(priv->dev, "cannot get RX hw timestamp\n"); -+ netdev_dbg(priv->dev, "cannot get RX hw timestamp\n"); - } - } - -@@ -688,6 +763,19 @@ static void stmmac_release_ptp(struct st - } - - /** -+ * stmmac_mac_flow_ctrl - Configure flow control in all queues -+ * @priv: driver private structure -+ * Description: It is used for configuring the flow control in all queues -+ */ -+static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex) -+{ -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ -+ priv->hw->mac->flow_ctrl(priv->hw, duplex, priv->flow_ctrl, -+ priv->pause, tx_cnt); -+} -+ -+/** - * stmmac_adjust_link - adjusts the link parameters - * @dev: net device structure - * Description: this is the helper called by the physical abstraction layer -@@ -702,7 +790,6 @@ static void stmmac_adjust_link(struct ne - struct phy_device *phydev = dev->phydev; - unsigned long flags; - int new_state = 0; -- unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; - - if (!phydev) - return; -@@ -724,8 +811,7 @@ static void stmmac_adjust_link(struct ne - } - /* Flow Control operation */ - if (phydev->pause) -- priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex, -- fc, pause_time); -+ stmmac_mac_flow_ctrl(priv, phydev->duplex); - - if (phydev->speed != priv->speed) { - new_state = 1; -@@ -893,22 +979,56 @@ static int stmmac_init_phy(struct net_de - return 0; - } - --static void stmmac_display_rings(struct stmmac_priv *priv) -+static void stmmac_display_rx_rings(struct stmmac_priv *priv) - { -- void *head_rx, *head_tx; -+ u32 rx_cnt = priv->plat->rx_queues_to_use; -+ void *head_rx; -+ u32 queue; - -- if (priv->extend_desc) { -- head_rx = (void *)priv->dma_erx; -- head_tx = (void *)priv->dma_etx; -- } else { -- head_rx = (void *)priv->dma_rx; -- head_tx = (void *)priv->dma_tx; -+ /* Display RX rings */ -+ for (queue = 0; queue < rx_cnt; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ pr_info("\tRX Queue %u rings\n", queue); -+ -+ if (priv->extend_desc) -+ head_rx = (void *)rx_q->dma_erx; -+ else -+ head_rx = (void *)rx_q->dma_rx; -+ -+ /* Display RX ring */ -+ priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true); -+ } -+} -+ -+static void stmmac_display_tx_rings(struct stmmac_priv *priv) -+{ -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ void *head_tx; -+ u32 queue; -+ -+ /* Display TX rings */ -+ for (queue = 0; queue < tx_cnt; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ pr_info("\tTX Queue %d rings\n", queue); -+ -+ if (priv->extend_desc) -+ head_tx = (void *)tx_q->dma_etx; -+ else -+ head_tx = (void *)tx_q->dma_tx; -+ -+ priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false); - } -+} -+ -+static void stmmac_display_rings(struct stmmac_priv *priv) -+{ -+ /* Display RX ring */ -+ stmmac_display_rx_rings(priv); - -- /* Display Rx ring */ -- priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true); -- /* Display Tx ring */ -- priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false); -+ /* Display TX ring */ -+ stmmac_display_tx_rings(priv); - } - - static int stmmac_set_bfsize(int mtu, int bufsize) -@@ -928,48 +1048,88 @@ static int stmmac_set_bfsize(int mtu, in - } - - /** -- * stmmac_clear_descriptors - clear descriptors -+ * stmmac_clear_rx_descriptors - clear RX descriptors - * @priv: driver private structure -- * Description: this function is called to clear the tx and rx descriptors -+ * @queue: RX queue index -+ * Description: this function is called to clear the RX descriptors - * in case of both basic and extended descriptors are used. - */ --static void stmmac_clear_descriptors(struct stmmac_priv *priv) -+static void stmmac_clear_rx_descriptors(struct stmmac_priv *priv, u32 queue) - { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - int i; - -- /* Clear the Rx/Tx descriptors */ -+ /* Clear the RX descriptors */ - for (i = 0; i < DMA_RX_SIZE; i++) - if (priv->extend_desc) -- priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, -+ priv->hw->desc->init_rx_desc(&rx_q->dma_erx[i].basic, - priv->use_riwt, priv->mode, - (i == DMA_RX_SIZE - 1)); - else -- priv->hw->desc->init_rx_desc(&priv->dma_rx[i], -+ priv->hw->desc->init_rx_desc(&rx_q->dma_rx[i], - priv->use_riwt, priv->mode, - (i == DMA_RX_SIZE - 1)); -+} -+ -+/** -+ * stmmac_clear_tx_descriptors - clear tx descriptors -+ * @priv: driver private structure -+ * @queue: TX queue index. -+ * Description: this function is called to clear the TX descriptors -+ * in case of both basic and extended descriptors are used. -+ */ -+static void stmmac_clear_tx_descriptors(struct stmmac_priv *priv, u32 queue) -+{ -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ int i; -+ -+ /* Clear the TX descriptors */ - for (i = 0; i < DMA_TX_SIZE; i++) - if (priv->extend_desc) -- priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, -+ priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic, - priv->mode, - (i == DMA_TX_SIZE - 1)); - else -- priv->hw->desc->init_tx_desc(&priv->dma_tx[i], -+ priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i], - priv->mode, - (i == DMA_TX_SIZE - 1)); - } - - /** -+ * stmmac_clear_descriptors - clear descriptors -+ * @priv: driver private structure -+ * Description: this function is called to clear the TX and RX descriptors -+ * in case of both basic and extended descriptors are used. -+ */ -+static void stmmac_clear_descriptors(struct stmmac_priv *priv) -+{ -+ u32 rx_queue_cnt = priv->plat->rx_queues_to_use; -+ u32 tx_queue_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ -+ /* Clear the RX descriptors */ -+ for (queue = 0; queue < rx_queue_cnt; queue++) -+ stmmac_clear_rx_descriptors(priv, queue); -+ -+ /* Clear the TX descriptors */ -+ for (queue = 0; queue < tx_queue_cnt; queue++) -+ stmmac_clear_tx_descriptors(priv, queue); -+} -+ -+/** - * stmmac_init_rx_buffers - init the RX descriptor buffer. - * @priv: driver private structure - * @p: descriptor pointer - * @i: descriptor index -- * @flags: gfp flag. -+ * @flags: gfp flag -+ * @queue: RX queue index - * Description: this function is called to allocate a receive buffer, perform - * the DMA mapping and init the descriptor. - */ - static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, -- int i, gfp_t flags) -+ int i, gfp_t flags, u32 queue) - { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - struct sk_buff *skb; - - skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); -@@ -978,20 +1138,20 @@ static int stmmac_init_rx_buffers(struct - "%s: Rx init fails; skb is NULL\n", __func__); - return -ENOMEM; - } -- priv->rx_skbuff[i] = skb; -- priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, -+ rx_q->rx_skbuff[i] = skb; -+ rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, - priv->dma_buf_sz, - DMA_FROM_DEVICE); -- if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { -+ if (dma_mapping_error(priv->device, rx_q->rx_skbuff_dma[i])) { - netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (priv->synopsys_id >= DWMAC_CORE_4_00) -- p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]); -+ p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[i]); - else -- p->des2 = cpu_to_le32(priv->rx_skbuff_dma[i]); -+ p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[i]); - - if ((priv->hw->mode->init_desc3) && - (priv->dma_buf_sz == BUF_SIZE_16KiB)) -@@ -1000,30 +1160,71 @@ static int stmmac_init_rx_buffers(struct - return 0; - } - --static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) -+/** -+ * stmmac_free_rx_buffer - free RX dma buffers -+ * @priv: private structure -+ * @queue: RX queue index -+ * @i: buffer index. -+ */ -+static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) - { -- if (priv->rx_skbuff[i]) { -- dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ if (rx_q->rx_skbuff[i]) { -+ dma_unmap_single(priv->device, rx_q->rx_skbuff_dma[i], - priv->dma_buf_sz, DMA_FROM_DEVICE); -- dev_kfree_skb_any(priv->rx_skbuff[i]); -+ dev_kfree_skb_any(rx_q->rx_skbuff[i]); - } -- priv->rx_skbuff[i] = NULL; -+ rx_q->rx_skbuff[i] = NULL; - } - - /** -- * init_dma_desc_rings - init the RX/TX descriptor rings -+ * stmmac_free_tx_buffer - free RX dma buffers -+ * @priv: private structure -+ * @queue: RX queue index -+ * @i: buffer index. -+ */ -+static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i) -+{ -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ if (tx_q->tx_skbuff_dma[i].buf) { -+ if (tx_q->tx_skbuff_dma[i].map_as_page) -+ dma_unmap_page(priv->device, -+ tx_q->tx_skbuff_dma[i].buf, -+ tx_q->tx_skbuff_dma[i].len, -+ DMA_TO_DEVICE); -+ else -+ dma_unmap_single(priv->device, -+ tx_q->tx_skbuff_dma[i].buf, -+ tx_q->tx_skbuff_dma[i].len, -+ DMA_TO_DEVICE); -+ } -+ -+ if (tx_q->tx_skbuff[i]) { -+ dev_kfree_skb_any(tx_q->tx_skbuff[i]); -+ tx_q->tx_skbuff[i] = NULL; -+ tx_q->tx_skbuff_dma[i].buf = 0; -+ tx_q->tx_skbuff_dma[i].map_as_page = false; -+ } -+} -+ -+/** -+ * init_dma_rx_desc_rings - init the RX descriptor rings - * @dev: net device structure - * @flags: gfp flag. -- * Description: this function initializes the DMA RX/TX descriptors -+ * Description: this function initializes the DMA RX descriptors - * and allocates the socket buffers. It supports the chained and ring - * modes. - */ --static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) -+static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags) - { -- int i; - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_count = priv->plat->rx_queues_to_use; - unsigned int bfsize = 0; - int ret = -ENOMEM; -+ int queue; -+ int i; - - if (priv->hw->mode->set_16kib_bfsize) - bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); -@@ -1033,235 +1234,409 @@ static int init_dma_desc_rings(struct ne - - priv->dma_buf_sz = bfsize; - -- netif_dbg(priv, probe, priv->dev, -- "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", -- __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy); -- - /* RX INITIALIZATION */ - netif_dbg(priv, probe, priv->dev, - "SKB addresses:\nskb\t\tskb data\tdma data\n"); - -- for (i = 0; i < DMA_RX_SIZE; i++) { -- struct dma_desc *p; -- if (priv->extend_desc) -- p = &((priv->dma_erx + i)->basic); -- else -- p = priv->dma_rx + i; -+ for (queue = 0; queue < rx_count; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - -- ret = stmmac_init_rx_buffers(priv, p, i, flags); -- if (ret) -- goto err_init_rx_buffers; -+ netif_dbg(priv, probe, priv->dev, -+ "(%s) dma_rx_phy=0x%08x\n", __func__, -+ (u32)rx_q->dma_rx_phy); - -- netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n", -- priv->rx_skbuff[i], priv->rx_skbuff[i]->data, -- (unsigned int)priv->rx_skbuff_dma[i]); -+ for (i = 0; i < DMA_RX_SIZE; i++) { -+ struct dma_desc *p; -+ -+ if (priv->extend_desc) -+ p = &((rx_q->dma_erx + i)->basic); -+ else -+ p = rx_q->dma_rx + i; -+ -+ ret = stmmac_init_rx_buffers(priv, p, i, flags, -+ queue); -+ if (ret) -+ goto err_init_rx_buffers; -+ -+ netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n", -+ rx_q->rx_skbuff[i], rx_q->rx_skbuff[i]->data, -+ (unsigned int)rx_q->rx_skbuff_dma[i]); -+ } -+ -+ rx_q->cur_rx = 0; -+ rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); -+ -+ stmmac_clear_rx_descriptors(priv, queue); -+ -+ /* Setup the chained descriptor addresses */ -+ if (priv->mode == STMMAC_CHAIN_MODE) { -+ if (priv->extend_desc) -+ priv->hw->mode->init(rx_q->dma_erx, -+ rx_q->dma_rx_phy, -+ DMA_RX_SIZE, 1); -+ else -+ priv->hw->mode->init(rx_q->dma_rx, -+ rx_q->dma_rx_phy, -+ DMA_RX_SIZE, 0); -+ } - } -- priv->cur_rx = 0; -- priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); -+ - buf_sz = bfsize; - -- /* Setup the chained descriptor addresses */ -- if (priv->mode == STMMAC_CHAIN_MODE) { -- if (priv->extend_desc) { -- priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy, -- DMA_RX_SIZE, 1); -- priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy, -- DMA_TX_SIZE, 1); -- } else { -- priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy, -- DMA_RX_SIZE, 0); -- priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy, -- DMA_TX_SIZE, 0); -- } -+ return 0; -+ -+err_init_rx_buffers: -+ while (queue >= 0) { -+ while (--i >= 0) -+ stmmac_free_rx_buffer(priv, queue, i); -+ -+ if (queue == 0) -+ break; -+ -+ i = DMA_RX_SIZE; -+ queue--; - } - -- /* TX INITIALIZATION */ -- for (i = 0; i < DMA_TX_SIZE; i++) { -- struct dma_desc *p; -- if (priv->extend_desc) -- p = &((priv->dma_etx + i)->basic); -- else -- p = priv->dma_tx + i; -+ return ret; -+} - -- if (priv->synopsys_id >= DWMAC_CORE_4_00) { -- p->des0 = 0; -- p->des1 = 0; -- p->des2 = 0; -- p->des3 = 0; -- } else { -- p->des2 = 0; -+/** -+ * init_dma_tx_desc_rings - init the TX descriptor rings -+ * @dev: net device structure. -+ * Description: this function initializes the DMA TX descriptors -+ * and allocates the socket buffers. It supports the chained and ring -+ * modes. -+ */ -+static int init_dma_tx_desc_rings(struct net_device *dev) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ u32 tx_queue_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ int i; -+ -+ for (queue = 0; queue < tx_queue_cnt; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ netif_dbg(priv, probe, priv->dev, -+ "(%s) dma_tx_phy=0x%08x\n", __func__, -+ (u32)tx_q->dma_tx_phy); -+ -+ /* Setup the chained descriptor addresses */ -+ if (priv->mode == STMMAC_CHAIN_MODE) { -+ if (priv->extend_desc) -+ priv->hw->mode->init(tx_q->dma_etx, -+ tx_q->dma_tx_phy, -+ DMA_TX_SIZE, 1); -+ else -+ priv->hw->mode->init(tx_q->dma_tx, -+ tx_q->dma_tx_phy, -+ DMA_TX_SIZE, 0); -+ } -+ -+ for (i = 0; i < DMA_TX_SIZE; i++) { -+ struct dma_desc *p; -+ if (priv->extend_desc) -+ p = &((tx_q->dma_etx + i)->basic); -+ else -+ p = tx_q->dma_tx + i; -+ -+ if (priv->synopsys_id >= DWMAC_CORE_4_00) { -+ p->des0 = 0; -+ p->des1 = 0; -+ p->des2 = 0; -+ p->des3 = 0; -+ } else { -+ p->des2 = 0; -+ } -+ -+ tx_q->tx_skbuff_dma[i].buf = 0; -+ tx_q->tx_skbuff_dma[i].map_as_page = false; -+ tx_q->tx_skbuff_dma[i].len = 0; -+ tx_q->tx_skbuff_dma[i].last_segment = false; -+ tx_q->tx_skbuff[i] = NULL; - } - -- priv->tx_skbuff_dma[i].buf = 0; -- priv->tx_skbuff_dma[i].map_as_page = false; -- priv->tx_skbuff_dma[i].len = 0; -- priv->tx_skbuff_dma[i].last_segment = false; -- priv->tx_skbuff[i] = NULL; -+ tx_q->dirty_tx = 0; -+ tx_q->cur_tx = 0; -+ -+ netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue)); - } - -- priv->dirty_tx = 0; -- priv->cur_tx = 0; -- netdev_reset_queue(priv->dev); -+ return 0; -+} -+ -+/** -+ * init_dma_desc_rings - init the RX/TX descriptor rings -+ * @dev: net device structure -+ * @flags: gfp flag. -+ * Description: this function initializes the DMA RX/TX descriptors -+ * and allocates the socket buffers. It supports the chained and ring -+ * modes. -+ */ -+static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ int ret; -+ -+ ret = init_dma_rx_desc_rings(dev, flags); -+ if (ret) -+ return ret; -+ -+ ret = init_dma_tx_desc_rings(dev); - - stmmac_clear_descriptors(priv); - - if (netif_msg_hw(priv)) - stmmac_display_rings(priv); - -- return 0; --err_init_rx_buffers: -- while (--i >= 0) -- stmmac_free_rx_buffers(priv, i); - return ret; - } - --static void dma_free_rx_skbufs(struct stmmac_priv *priv) -+/** -+ * dma_free_rx_skbufs - free RX dma buffers -+ * @priv: private structure -+ * @queue: RX queue index -+ */ -+static void dma_free_rx_skbufs(struct stmmac_priv *priv, u32 queue) - { - int i; - - for (i = 0; i < DMA_RX_SIZE; i++) -- stmmac_free_rx_buffers(priv, i); -+ stmmac_free_rx_buffer(priv, queue, i); - } - --static void dma_free_tx_skbufs(struct stmmac_priv *priv) -+/** -+ * dma_free_tx_skbufs - free TX dma buffers -+ * @priv: private structure -+ * @queue: TX queue index -+ */ -+static void dma_free_tx_skbufs(struct stmmac_priv *priv, u32 queue) - { - int i; - -- for (i = 0; i < DMA_TX_SIZE; i++) { -- if (priv->tx_skbuff_dma[i].buf) { -- if (priv->tx_skbuff_dma[i].map_as_page) -- dma_unmap_page(priv->device, -- priv->tx_skbuff_dma[i].buf, -- priv->tx_skbuff_dma[i].len, -- DMA_TO_DEVICE); -- else -- dma_unmap_single(priv->device, -- priv->tx_skbuff_dma[i].buf, -- priv->tx_skbuff_dma[i].len, -- DMA_TO_DEVICE); -- } -+ for (i = 0; i < DMA_TX_SIZE; i++) -+ stmmac_free_tx_buffer(priv, queue, i); -+} - -- if (priv->tx_skbuff[i]) { -- dev_kfree_skb_any(priv->tx_skbuff[i]); -- priv->tx_skbuff[i] = NULL; -- priv->tx_skbuff_dma[i].buf = 0; -- priv->tx_skbuff_dma[i].map_as_page = false; -- } -+/** -+ * free_dma_rx_desc_resources - free RX dma desc resources -+ * @priv: private structure -+ */ -+static void free_dma_rx_desc_resources(struct stmmac_priv *priv) -+{ -+ u32 rx_count = priv->plat->rx_queues_to_use; -+ u32 queue; -+ -+ /* Free RX queue resources */ -+ for (queue = 0; queue < rx_count; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ /* Release the DMA RX socket buffers */ -+ dma_free_rx_skbufs(priv, queue); -+ -+ /* Free DMA regions of consistent memory previously allocated */ -+ if (!priv->extend_desc) -+ dma_free_coherent(priv->device, -+ DMA_RX_SIZE * sizeof(struct dma_desc), -+ rx_q->dma_rx, rx_q->dma_rx_phy); -+ else -+ dma_free_coherent(priv->device, DMA_RX_SIZE * -+ sizeof(struct dma_extended_desc), -+ rx_q->dma_erx, rx_q->dma_rx_phy); -+ -+ kfree(rx_q->rx_skbuff_dma); -+ kfree(rx_q->rx_skbuff); - } - } - - /** -- * alloc_dma_desc_resources - alloc TX/RX resources. -+ * free_dma_tx_desc_resources - free TX dma desc resources -+ * @priv: private structure -+ */ -+static void free_dma_tx_desc_resources(struct stmmac_priv *priv) -+{ -+ u32 tx_count = priv->plat->tx_queues_to_use; -+ u32 queue = 0; -+ -+ /* Free TX queue resources */ -+ for (queue = 0; queue < tx_count; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ /* Release the DMA TX socket buffers */ -+ dma_free_tx_skbufs(priv, queue); -+ -+ /* Free DMA regions of consistent memory previously allocated */ -+ if (!priv->extend_desc) -+ dma_free_coherent(priv->device, -+ DMA_TX_SIZE * sizeof(struct dma_desc), -+ tx_q->dma_tx, tx_q->dma_tx_phy); -+ else -+ dma_free_coherent(priv->device, DMA_TX_SIZE * -+ sizeof(struct dma_extended_desc), -+ tx_q->dma_etx, tx_q->dma_tx_phy); -+ -+ kfree(tx_q->tx_skbuff_dma); -+ kfree(tx_q->tx_skbuff); -+ } -+} -+ -+/** -+ * alloc_dma_rx_desc_resources - alloc RX resources. - * @priv: private structure - * Description: according to which descriptor can be used (extend or basic) - * this function allocates the resources for TX and RX paths. In case of - * reception, for example, it pre-allocated the RX socket buffer in order to - * allow zero-copy mechanism. - */ --static int alloc_dma_desc_resources(struct stmmac_priv *priv) -+static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv) - { -+ u32 rx_count = priv->plat->rx_queues_to_use; - int ret = -ENOMEM; -+ u32 queue; - -- priv->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, sizeof(dma_addr_t), -- GFP_KERNEL); -- if (!priv->rx_skbuff_dma) -- return -ENOMEM; -+ /* RX queues buffers and DMA */ -+ for (queue = 0; queue < rx_count; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - -- priv->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *), -- GFP_KERNEL); -- if (!priv->rx_skbuff) -- goto err_rx_skbuff; -- -- priv->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE, -- sizeof(*priv->tx_skbuff_dma), -- GFP_KERNEL); -- if (!priv->tx_skbuff_dma) -- goto err_tx_skbuff_dma; -- -- priv->tx_skbuff = kmalloc_array(DMA_TX_SIZE, sizeof(struct sk_buff *), -- GFP_KERNEL); -- if (!priv->tx_skbuff) -- goto err_tx_skbuff; -- -- if (priv->extend_desc) { -- priv->dma_erx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * -- sizeof(struct -- dma_extended_desc), -- &priv->dma_rx_phy, -- GFP_KERNEL); -- if (!priv->dma_erx) -- goto err_dma; -+ rx_q->queue_index = queue; -+ rx_q->priv_data = priv; - -- priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * -- sizeof(struct -- dma_extended_desc), -- &priv->dma_tx_phy, -+ rx_q->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, -+ sizeof(dma_addr_t), - GFP_KERNEL); -- if (!priv->dma_etx) { -- dma_free_coherent(priv->device, DMA_RX_SIZE * -- sizeof(struct dma_extended_desc), -- priv->dma_erx, priv->dma_rx_phy); -- goto err_dma; -- } -- } else { -- priv->dma_rx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * -- sizeof(struct dma_desc), -- &priv->dma_rx_phy, -- GFP_KERNEL); -- if (!priv->dma_rx) -- goto err_dma; -+ if (!rx_q->rx_skbuff_dma) -+ return -ENOMEM; - -- priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * -- sizeof(struct dma_desc), -- &priv->dma_tx_phy, -- GFP_KERNEL); -- if (!priv->dma_tx) { -- dma_free_coherent(priv->device, DMA_RX_SIZE * -- sizeof(struct dma_desc), -- priv->dma_rx, priv->dma_rx_phy); -+ rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE, -+ sizeof(struct sk_buff *), -+ GFP_KERNEL); -+ if (!rx_q->rx_skbuff) - goto err_dma; -+ -+ if (priv->extend_desc) { -+ rx_q->dma_erx = dma_zalloc_coherent(priv->device, -+ DMA_RX_SIZE * -+ sizeof(struct -+ dma_extended_desc), -+ &rx_q->dma_rx_phy, -+ GFP_KERNEL); -+ if (!rx_q->dma_erx) -+ goto err_dma; -+ -+ } else { -+ rx_q->dma_rx = dma_zalloc_coherent(priv->device, -+ DMA_RX_SIZE * -+ sizeof(struct -+ dma_desc), -+ &rx_q->dma_rx_phy, -+ GFP_KERNEL); -+ if (!rx_q->dma_rx) -+ goto err_dma; - } - } - - return 0; - - err_dma: -- kfree(priv->tx_skbuff); --err_tx_skbuff: -- kfree(priv->tx_skbuff_dma); --err_tx_skbuff_dma: -- kfree(priv->rx_skbuff); --err_rx_skbuff: -- kfree(priv->rx_skbuff_dma); -+ free_dma_rx_desc_resources(priv); -+ -+ return ret; -+} -+ -+/** -+ * alloc_dma_tx_desc_resources - alloc TX resources. -+ * @priv: private structure -+ * Description: according to which descriptor can be used (extend or basic) -+ * this function allocates the resources for TX and RX paths. In case of -+ * reception, for example, it pre-allocated the RX socket buffer in order to -+ * allow zero-copy mechanism. -+ */ -+static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv) -+{ -+ u32 tx_count = priv->plat->tx_queues_to_use; -+ int ret = -ENOMEM; -+ u32 queue; -+ -+ /* TX queues buffers and DMA */ -+ for (queue = 0; queue < tx_count; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ tx_q->queue_index = queue; -+ tx_q->priv_data = priv; -+ -+ tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE, -+ sizeof(*tx_q->tx_skbuff_dma), -+ GFP_KERNEL); -+ if (!tx_q->tx_skbuff_dma) -+ return -ENOMEM; -+ -+ tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE, -+ sizeof(struct sk_buff *), -+ GFP_KERNEL); -+ if (!tx_q->tx_skbuff) -+ goto err_dma_buffers; -+ -+ if (priv->extend_desc) { -+ tx_q->dma_etx = dma_zalloc_coherent(priv->device, -+ DMA_TX_SIZE * -+ sizeof(struct -+ dma_extended_desc), -+ &tx_q->dma_tx_phy, -+ GFP_KERNEL); -+ if (!tx_q->dma_etx) -+ goto err_dma_buffers; -+ } else { -+ tx_q->dma_tx = dma_zalloc_coherent(priv->device, -+ DMA_TX_SIZE * -+ sizeof(struct -+ dma_desc), -+ &tx_q->dma_tx_phy, -+ GFP_KERNEL); -+ if (!tx_q->dma_tx) -+ goto err_dma_buffers; -+ } -+ } -+ -+ return 0; -+ -+err_dma_buffers: -+ free_dma_tx_desc_resources(priv); -+ -+ return ret; -+} -+ -+/** -+ * alloc_dma_desc_resources - alloc TX/RX resources. -+ * @priv: private structure -+ * Description: according to which descriptor can be used (extend or basic) -+ * this function allocates the resources for TX and RX paths. In case of -+ * reception, for example, it pre-allocated the RX socket buffer in order to -+ * allow zero-copy mechanism. -+ */ -+static int alloc_dma_desc_resources(struct stmmac_priv *priv) -+{ -+ /* RX Allocation */ -+ int ret = alloc_dma_rx_desc_resources(priv); -+ -+ if (ret) -+ return ret; -+ -+ ret = alloc_dma_tx_desc_resources(priv); -+ - return ret; - } - -+/** -+ * free_dma_desc_resources - free dma desc resources -+ * @priv: private structure -+ */ - static void free_dma_desc_resources(struct stmmac_priv *priv) - { -- /* Release the DMA TX/RX socket buffers */ -- dma_free_rx_skbufs(priv); -- dma_free_tx_skbufs(priv); -- -- /* Free DMA regions of consistent memory previously allocated */ -- if (!priv->extend_desc) { -- dma_free_coherent(priv->device, -- DMA_TX_SIZE * sizeof(struct dma_desc), -- priv->dma_tx, priv->dma_tx_phy); -- dma_free_coherent(priv->device, -- DMA_RX_SIZE * sizeof(struct dma_desc), -- priv->dma_rx, priv->dma_rx_phy); -- } else { -- dma_free_coherent(priv->device, DMA_TX_SIZE * -- sizeof(struct dma_extended_desc), -- priv->dma_etx, priv->dma_tx_phy); -- dma_free_coherent(priv->device, DMA_RX_SIZE * -- sizeof(struct dma_extended_desc), -- priv->dma_erx, priv->dma_rx_phy); -- } -- kfree(priv->rx_skbuff_dma); -- kfree(priv->rx_skbuff); -- kfree(priv->tx_skbuff_dma); -- kfree(priv->tx_skbuff); -+ /* Release the DMA RX socket buffers */ -+ free_dma_rx_desc_resources(priv); -+ -+ /* Release the DMA TX socket buffers */ -+ free_dma_tx_desc_resources(priv); - } - - /** -@@ -1271,19 +1646,104 @@ static void free_dma_desc_resources(stru - */ - static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) - { -- int rx_count = priv->dma_cap.number_rx_queues; -- int queue = 0; -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ int queue; -+ u8 mode; - -- /* If GMAC does not have multiple queues, then this is not necessary*/ -- if (rx_count == 1) -- return; -+ for (queue = 0; queue < rx_queues_count; queue++) { -+ mode = priv->plat->rx_queues_cfg[queue].mode_to_use; -+ priv->hw->mac->rx_queue_enable(priv->hw, mode, queue); -+ } -+} - -- /** -- * If the core is synthesized with multiple rx queues / multiple -- * dma channels, then rx queues will be disabled by default. -- * For now only rx queue 0 is enabled. -- */ -- priv->hw->mac->rx_queue_enable(priv->hw, queue); -+/** -+ * stmmac_start_rx_dma - start RX DMA channel -+ * @priv: driver private structure -+ * @chan: RX channel index -+ * Description: -+ * This starts a RX DMA channel -+ */ -+static void stmmac_start_rx_dma(struct stmmac_priv *priv, u32 chan) -+{ -+ netdev_dbg(priv->dev, "DMA RX processes started in channel %d\n", chan); -+ priv->hw->dma->start_rx(priv->ioaddr, chan); -+} -+ -+/** -+ * stmmac_start_tx_dma - start TX DMA channel -+ * @priv: driver private structure -+ * @chan: TX channel index -+ * Description: -+ * This starts a TX DMA channel -+ */ -+static void stmmac_start_tx_dma(struct stmmac_priv *priv, u32 chan) -+{ -+ netdev_dbg(priv->dev, "DMA TX processes started in channel %d\n", chan); -+ priv->hw->dma->start_tx(priv->ioaddr, chan); -+} -+ -+/** -+ * stmmac_stop_rx_dma - stop RX DMA channel -+ * @priv: driver private structure -+ * @chan: RX channel index -+ * Description: -+ * This stops a RX DMA channel -+ */ -+static void stmmac_stop_rx_dma(struct stmmac_priv *priv, u32 chan) -+{ -+ netdev_dbg(priv->dev, "DMA RX processes stopped in channel %d\n", chan); -+ priv->hw->dma->stop_rx(priv->ioaddr, chan); -+} -+ -+/** -+ * stmmac_stop_tx_dma - stop TX DMA channel -+ * @priv: driver private structure -+ * @chan: TX channel index -+ * Description: -+ * This stops a TX DMA channel -+ */ -+static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan) -+{ -+ netdev_dbg(priv->dev, "DMA TX processes stopped in channel %d\n", chan); -+ priv->hw->dma->stop_tx(priv->ioaddr, chan); -+} -+ -+/** -+ * stmmac_start_all_dma - start all RX and TX DMA channels -+ * @priv: driver private structure -+ * Description: -+ * This starts all the RX and TX DMA channels -+ */ -+static void stmmac_start_all_dma(struct stmmac_priv *priv) -+{ -+ u32 rx_channels_count = priv->plat->rx_queues_to_use; -+ u32 tx_channels_count = priv->plat->tx_queues_to_use; -+ u32 chan = 0; -+ -+ for (chan = 0; chan < rx_channels_count; chan++) -+ stmmac_start_rx_dma(priv, chan); -+ -+ for (chan = 0; chan < tx_channels_count; chan++) -+ stmmac_start_tx_dma(priv, chan); -+} -+ -+/** -+ * stmmac_stop_all_dma - stop all RX and TX DMA channels -+ * @priv: driver private structure -+ * Description: -+ * This stops the RX and TX DMA channels -+ */ -+static void stmmac_stop_all_dma(struct stmmac_priv *priv) -+{ -+ u32 rx_channels_count = priv->plat->rx_queues_to_use; -+ u32 tx_channels_count = priv->plat->tx_queues_to_use; -+ u32 chan = 0; -+ -+ for (chan = 0; chan < rx_channels_count; chan++) -+ stmmac_stop_rx_dma(priv, chan); -+ -+ for (chan = 0; chan < tx_channels_count; chan++) -+ stmmac_stop_tx_dma(priv, chan); - } - - /** -@@ -1294,11 +1754,20 @@ static void stmmac_mac_enable_rx_queues( - */ - static void stmmac_dma_operation_mode(struct stmmac_priv *priv) - { -+ u32 rx_channels_count = priv->plat->rx_queues_to_use; -+ u32 tx_channels_count = priv->plat->tx_queues_to_use; - int rxfifosz = priv->plat->rx_fifo_size; -- -- if (priv->plat->force_thresh_dma_mode) -- priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); -- else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { -+ u32 txmode = 0; -+ u32 rxmode = 0; -+ u32 chan = 0; -+ -+ if (rxfifosz == 0) -+ rxfifosz = priv->dma_cap.rx_fifo_size; -+ -+ if (priv->plat->force_thresh_dma_mode) { -+ txmode = tc; -+ rxmode = tc; -+ } else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { - /* - * In case of GMAC, SF mode can be enabled - * to perform the TX COE in HW. This depends on: -@@ -1306,37 +1775,53 @@ static void stmmac_dma_operation_mode(st - * 2) There is no bugged Jumbo frame support - * that needs to not insert csum in the TDES. - */ -- priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, -- rxfifosz); -+ txmode = SF_DMA_MODE; -+ rxmode = SF_DMA_MODE; - priv->xstats.threshold = SF_DMA_MODE; -- } else -- priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, -+ } else { -+ txmode = tc; -+ rxmode = SF_DMA_MODE; -+ } -+ -+ /* configure all channels */ -+ if (priv->synopsys_id >= DWMAC_CORE_4_00) { -+ for (chan = 0; chan < rx_channels_count; chan++) -+ priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, -+ rxfifosz); -+ -+ for (chan = 0; chan < tx_channels_count; chan++) -+ priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); -+ } else { -+ priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, - rxfifosz); -+ } - } - - /** - * stmmac_tx_clean - to manage the transmission completion - * @priv: driver private structure -+ * @queue: TX queue index - * Description: it reclaims the transmit resources after transmission completes. - */ --static void stmmac_tx_clean(struct stmmac_priv *priv) -+static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) - { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; - unsigned int bytes_compl = 0, pkts_compl = 0; -- unsigned int entry = priv->dirty_tx; -+ unsigned int entry = tx_q->dirty_tx; - - netif_tx_lock(priv->dev); - - priv->xstats.tx_clean++; - -- while (entry != priv->cur_tx) { -- struct sk_buff *skb = priv->tx_skbuff[entry]; -+ while (entry != tx_q->cur_tx) { -+ struct sk_buff *skb = tx_q->tx_skbuff[entry]; - struct dma_desc *p; - int status; - - if (priv->extend_desc) -- p = (struct dma_desc *)(priv->dma_etx + entry); -+ p = (struct dma_desc *)(tx_q->dma_etx + entry); - else -- p = priv->dma_tx + entry; -+ p = tx_q->dma_tx + entry; - - status = priv->hw->desc->tx_status(&priv->dev->stats, - &priv->xstats, p, -@@ -1362,48 +1847,51 @@ static void stmmac_tx_clean(struct stmma - stmmac_get_tx_hwtstamp(priv, p, skb); - } - -- if (likely(priv->tx_skbuff_dma[entry].buf)) { -- if (priv->tx_skbuff_dma[entry].map_as_page) -+ if (likely(tx_q->tx_skbuff_dma[entry].buf)) { -+ if (tx_q->tx_skbuff_dma[entry].map_as_page) - dma_unmap_page(priv->device, -- priv->tx_skbuff_dma[entry].buf, -- priv->tx_skbuff_dma[entry].len, -+ tx_q->tx_skbuff_dma[entry].buf, -+ tx_q->tx_skbuff_dma[entry].len, - DMA_TO_DEVICE); - else - dma_unmap_single(priv->device, -- priv->tx_skbuff_dma[entry].buf, -- priv->tx_skbuff_dma[entry].len, -+ tx_q->tx_skbuff_dma[entry].buf, -+ tx_q->tx_skbuff_dma[entry].len, - DMA_TO_DEVICE); -- priv->tx_skbuff_dma[entry].buf = 0; -- priv->tx_skbuff_dma[entry].len = 0; -- priv->tx_skbuff_dma[entry].map_as_page = false; -+ tx_q->tx_skbuff_dma[entry].buf = 0; -+ tx_q->tx_skbuff_dma[entry].len = 0; -+ tx_q->tx_skbuff_dma[entry].map_as_page = false; - } - - if (priv->hw->mode->clean_desc3) -- priv->hw->mode->clean_desc3(priv, p); -+ priv->hw->mode->clean_desc3(tx_q, p); - -- priv->tx_skbuff_dma[entry].last_segment = false; -- priv->tx_skbuff_dma[entry].is_jumbo = false; -+ tx_q->tx_skbuff_dma[entry].last_segment = false; -+ tx_q->tx_skbuff_dma[entry].is_jumbo = false; - - if (likely(skb != NULL)) { - pkts_compl++; - bytes_compl += skb->len; - dev_consume_skb_any(skb); -- priv->tx_skbuff[entry] = NULL; -+ tx_q->tx_skbuff[entry] = NULL; - } - - priv->hw->desc->release_tx_desc(p, priv->mode); - - entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); - } -- priv->dirty_tx = entry; -+ tx_q->dirty_tx = entry; -+ -+ netdev_tx_completed_queue(netdev_get_tx_queue(priv->dev, queue), -+ pkts_compl, bytes_compl); - -- netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); -+ if (unlikely(netif_tx_queue_stopped(netdev_get_tx_queue(priv->dev, -+ queue))) && -+ stmmac_tx_avail(priv, queue) > STMMAC_TX_THRESH) { - -- if (unlikely(netif_queue_stopped(priv->dev) && -- stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) { - netif_dbg(priv, tx_done, priv->dev, - "%s: restart transmit\n", __func__); -- netif_wake_queue(priv->dev); -+ netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, queue)); - } - - if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { -@@ -1413,45 +1901,76 @@ static void stmmac_tx_clean(struct stmma - netif_tx_unlock(priv->dev); - } - --static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) -+static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan) - { -- priv->hw->dma->enable_dma_irq(priv->ioaddr); -+ priv->hw->dma->enable_dma_irq(priv->ioaddr, chan); - } - --static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) -+static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan) - { -- priv->hw->dma->disable_dma_irq(priv->ioaddr); -+ priv->hw->dma->disable_dma_irq(priv->ioaddr, chan); - } - - /** - * stmmac_tx_err - to manage the tx error - * @priv: driver private structure -+ * @chan: channel index - * Description: it cleans the descriptors and restarts the transmission - * in case of transmission errors. - */ --static void stmmac_tx_err(struct stmmac_priv *priv) -+static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan) - { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan]; - int i; -- netif_stop_queue(priv->dev); - -- priv->hw->dma->stop_tx(priv->ioaddr); -- dma_free_tx_skbufs(priv); -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, chan)); -+ -+ stmmac_stop_tx_dma(priv, chan); -+ dma_free_tx_skbufs(priv, chan); - for (i = 0; i < DMA_TX_SIZE; i++) - if (priv->extend_desc) -- priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, -+ priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic, - priv->mode, - (i == DMA_TX_SIZE - 1)); - else -- priv->hw->desc->init_tx_desc(&priv->dma_tx[i], -+ priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i], - priv->mode, - (i == DMA_TX_SIZE - 1)); -- priv->dirty_tx = 0; -- priv->cur_tx = 0; -- netdev_reset_queue(priv->dev); -- priv->hw->dma->start_tx(priv->ioaddr); -+ tx_q->dirty_tx = 0; -+ tx_q->cur_tx = 0; -+ netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, chan)); -+ stmmac_start_tx_dma(priv, chan); - - priv->dev->stats.tx_errors++; -- netif_wake_queue(priv->dev); -+ netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, chan)); -+} -+ -+/** -+ * stmmac_set_dma_operation_mode - Set DMA operation mode by channel -+ * @priv: driver private structure -+ * @txmode: TX operating mode -+ * @rxmode: RX operating mode -+ * @chan: channel index -+ * Description: it is used for configuring of the DMA operation mode in -+ * runtime in order to program the tx/rx DMA thresholds or Store-And-Forward -+ * mode. -+ */ -+static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode, -+ u32 rxmode, u32 chan) -+{ -+ int rxfifosz = priv->plat->rx_fifo_size; -+ -+ if (rxfifosz == 0) -+ rxfifosz = priv->dma_cap.rx_fifo_size; -+ -+ if (priv->synopsys_id >= DWMAC_CORE_4_00) { -+ priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, -+ rxfifosz); -+ priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); -+ } else { -+ priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, -+ rxfifosz); -+ } - } - - /** -@@ -1463,31 +1982,43 @@ static void stmmac_tx_err(struct stmmac_ - */ - static void stmmac_dma_interrupt(struct stmmac_priv *priv) - { -+ u32 tx_channel_count = priv->plat->tx_queues_to_use; - int status; -- int rxfifosz = priv->plat->rx_fifo_size; -+ u32 chan; -+ -+ for (chan = 0; chan < tx_channel_count; chan++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan]; - -- status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); -- if (likely((status & handle_rx)) || (status & handle_tx)) { -- if (likely(napi_schedule_prep(&priv->napi))) { -- stmmac_disable_dma_irq(priv); -- __napi_schedule(&priv->napi); -+ status = priv->hw->dma->dma_interrupt(priv->ioaddr, -+ &priv->xstats, chan); -+ if (likely((status & handle_rx)) || (status & handle_tx)) { -+ if (likely(napi_schedule_prep(&rx_q->napi))) { -+ stmmac_disable_dma_irq(priv, chan); -+ __napi_schedule(&rx_q->napi); -+ } - } -- } -- if (unlikely(status & tx_hard_error_bump_tc)) { -- /* Try to bump up the dma threshold on this failure */ -- if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && -- (tc <= 256)) { -- tc += 64; -- if (priv->plat->force_thresh_dma_mode) -- priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, -- rxfifosz); -- else -- priv->hw->dma->dma_mode(priv->ioaddr, tc, -- SF_DMA_MODE, rxfifosz); -- priv->xstats.threshold = tc; -+ -+ if (unlikely(status & tx_hard_error_bump_tc)) { -+ /* Try to bump up the dma threshold on this failure */ -+ if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && -+ (tc <= 256)) { -+ tc += 64; -+ if (priv->plat->force_thresh_dma_mode) -+ stmmac_set_dma_operation_mode(priv, -+ tc, -+ tc, -+ chan); -+ else -+ stmmac_set_dma_operation_mode(priv, -+ tc, -+ SF_DMA_MODE, -+ chan); -+ priv->xstats.threshold = tc; -+ } -+ } else if (unlikely(status == tx_hard_error)) { -+ stmmac_tx_err(priv, chan); - } -- } else if (unlikely(status == tx_hard_error)) -- stmmac_tx_err(priv); -+ } - } - - /** -@@ -1594,6 +2125,13 @@ static void stmmac_check_ether_addr(stru - */ - static int stmmac_init_dma_engine(struct stmmac_priv *priv) - { -+ u32 rx_channels_count = priv->plat->rx_queues_to_use; -+ u32 tx_channels_count = priv->plat->tx_queues_to_use; -+ struct stmmac_rx_queue *rx_q; -+ struct stmmac_tx_queue *tx_q; -+ u32 dummy_dma_rx_phy = 0; -+ u32 dummy_dma_tx_phy = 0; -+ u32 chan = 0; - int atds = 0; - int ret = 0; - -@@ -1611,19 +2149,49 @@ static int stmmac_init_dma_engine(struct - return ret; - } - -- priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, -- priv->dma_tx_phy, priv->dma_rx_phy, atds); -- - if (priv->synopsys_id >= DWMAC_CORE_4_00) { -- priv->rx_tail_addr = priv->dma_rx_phy + -- (DMA_RX_SIZE * sizeof(struct dma_desc)); -- priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, priv->rx_tail_addr, -- STMMAC_CHAN0); -- -- priv->tx_tail_addr = priv->dma_tx_phy + -- (DMA_TX_SIZE * sizeof(struct dma_desc)); -- priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, -- STMMAC_CHAN0); -+ /* DMA Configuration */ -+ priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, -+ dummy_dma_tx_phy, dummy_dma_rx_phy, atds); -+ -+ /* DMA RX Channel Configuration */ -+ for (chan = 0; chan < rx_channels_count; chan++) { -+ rx_q = &priv->rx_queue[chan]; -+ -+ priv->hw->dma->init_rx_chan(priv->ioaddr, -+ priv->plat->dma_cfg, -+ rx_q->dma_rx_phy, chan); -+ -+ rx_q->rx_tail_addr = rx_q->dma_rx_phy + -+ (DMA_RX_SIZE * sizeof(struct dma_desc)); -+ priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, -+ rx_q->rx_tail_addr, -+ chan); -+ } -+ -+ /* DMA TX Channel Configuration */ -+ for (chan = 0; chan < tx_channels_count; chan++) { -+ tx_q = &priv->tx_queue[chan]; -+ -+ priv->hw->dma->init_chan(priv->ioaddr, -+ priv->plat->dma_cfg, -+ chan); -+ -+ priv->hw->dma->init_tx_chan(priv->ioaddr, -+ priv->plat->dma_cfg, -+ tx_q->dma_tx_phy, chan); -+ -+ tx_q->tx_tail_addr = tx_q->dma_tx_phy + -+ (DMA_TX_SIZE * sizeof(struct dma_desc)); -+ priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, -+ tx_q->tx_tail_addr, -+ chan); -+ } -+ } else { -+ rx_q = &priv->rx_queue[chan]; -+ tx_q = &priv->tx_queue[chan]; -+ priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, -+ tx_q->dma_tx_phy, rx_q->dma_rx_phy, atds); - } - - if (priv->plat->axi && priv->hw->dma->axi) -@@ -1641,8 +2209,12 @@ static int stmmac_init_dma_engine(struct - static void stmmac_tx_timer(unsigned long data) - { - struct stmmac_priv *priv = (struct stmmac_priv *)data; -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; -+ u32 queue; - -- stmmac_tx_clean(priv); -+ /* let's scan all the tx queues */ -+ for (queue = 0; queue < tx_queues_count; queue++) -+ stmmac_tx_clean(priv, queue); - } - - /** -@@ -1664,6 +2236,196 @@ static void stmmac_init_tx_coalesce(stru - add_timer(&priv->txtimer); - } - -+static void stmmac_set_rings_length(struct stmmac_priv *priv) -+{ -+ u32 rx_channels_count = priv->plat->rx_queues_to_use; -+ u32 tx_channels_count = priv->plat->tx_queues_to_use; -+ u32 chan; -+ -+ /* set TX ring length */ -+ if (priv->hw->dma->set_tx_ring_len) { -+ for (chan = 0; chan < tx_channels_count; chan++) -+ priv->hw->dma->set_tx_ring_len(priv->ioaddr, -+ (DMA_TX_SIZE - 1), chan); -+ } -+ -+ /* set RX ring length */ -+ if (priv->hw->dma->set_rx_ring_len) { -+ for (chan = 0; chan < rx_channels_count; chan++) -+ priv->hw->dma->set_rx_ring_len(priv->ioaddr, -+ (DMA_RX_SIZE - 1), chan); -+ } -+} -+ -+/** -+ * stmmac_set_tx_queue_weight - Set TX queue weight -+ * @priv: driver private structure -+ * Description: It is used for setting TX queues weight -+ */ -+static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv) -+{ -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; -+ u32 weight; -+ u32 queue; -+ -+ for (queue = 0; queue < tx_queues_count; queue++) { -+ weight = priv->plat->tx_queues_cfg[queue].weight; -+ priv->hw->mac->set_mtl_tx_queue_weight(priv->hw, weight, queue); -+ } -+} -+ -+/** -+ * stmmac_configure_cbs - Configure CBS in TX queue -+ * @priv: driver private structure -+ * Description: It is used for configuring CBS in AVB TX queues -+ */ -+static void stmmac_configure_cbs(struct stmmac_priv *priv) -+{ -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; -+ u32 mode_to_use; -+ u32 queue; -+ -+ /* queue 0 is reserved for legacy traffic */ -+ for (queue = 1; queue < tx_queues_count; queue++) { -+ mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; -+ if (mode_to_use == MTL_QUEUE_DCB) -+ continue; -+ -+ priv->hw->mac->config_cbs(priv->hw, -+ priv->plat->tx_queues_cfg[queue].send_slope, -+ priv->plat->tx_queues_cfg[queue].idle_slope, -+ priv->plat->tx_queues_cfg[queue].high_credit, -+ priv->plat->tx_queues_cfg[queue].low_credit, -+ queue); -+ } -+} -+ -+/** -+ * stmmac_rx_queue_dma_chan_map - Map RX queue to RX dma channel -+ * @priv: driver private structure -+ * Description: It is used for mapping RX queues to RX dma channels -+ */ -+static void stmmac_rx_queue_dma_chan_map(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ u32 queue; -+ u32 chan; -+ -+ for (queue = 0; queue < rx_queues_count; queue++) { -+ chan = priv->plat->rx_queues_cfg[queue].chan; -+ priv->hw->mac->map_mtl_to_dma(priv->hw, queue, chan); -+ } -+} -+ -+/** -+ * stmmac_mac_config_rx_queues_prio - Configure RX Queue priority -+ * @priv: driver private structure -+ * Description: It is used for configuring the RX Queue Priority -+ */ -+static void stmmac_mac_config_rx_queues_prio(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ u32 queue; -+ u32 prio; -+ -+ for (queue = 0; queue < rx_queues_count; queue++) { -+ if (!priv->plat->rx_queues_cfg[queue].use_prio) -+ continue; -+ -+ prio = priv->plat->rx_queues_cfg[queue].prio; -+ priv->hw->mac->rx_queue_prio(priv->hw, prio, queue); -+ } -+} -+ -+/** -+ * stmmac_mac_config_tx_queues_prio - Configure TX Queue priority -+ * @priv: driver private structure -+ * Description: It is used for configuring the TX Queue Priority -+ */ -+static void stmmac_mac_config_tx_queues_prio(struct stmmac_priv *priv) -+{ -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; -+ u32 queue; -+ u32 prio; -+ -+ for (queue = 0; queue < tx_queues_count; queue++) { -+ if (!priv->plat->tx_queues_cfg[queue].use_prio) -+ continue; -+ -+ prio = priv->plat->tx_queues_cfg[queue].prio; -+ priv->hw->mac->tx_queue_prio(priv->hw, prio, queue); -+ } -+} -+ -+/** -+ * stmmac_mac_config_rx_queues_routing - Configure RX Queue Routing -+ * @priv: driver private structure -+ * Description: It is used for configuring the RX queue routing -+ */ -+static void stmmac_mac_config_rx_queues_routing(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ u32 queue; -+ u8 packet; -+ -+ for (queue = 0; queue < rx_queues_count; queue++) { -+ /* no specific packet type routing specified for the queue */ -+ if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0) -+ continue; -+ -+ packet = priv->plat->rx_queues_cfg[queue].pkt_route; -+ priv->hw->mac->rx_queue_prio(priv->hw, packet, queue); -+ } -+} -+ -+/** -+ * stmmac_mtl_configuration - Configure MTL -+ * @priv: driver private structure -+ * Description: It is used for configurring MTL -+ */ -+static void stmmac_mtl_configuration(struct stmmac_priv *priv) -+{ -+ u32 rx_queues_count = priv->plat->rx_queues_to_use; -+ u32 tx_queues_count = priv->plat->tx_queues_to_use; -+ -+ if (tx_queues_count > 1 && priv->hw->mac->set_mtl_tx_queue_weight) -+ stmmac_set_tx_queue_weight(priv); -+ -+ /* Configure MTL RX algorithms */ -+ if (rx_queues_count > 1 && priv->hw->mac->prog_mtl_rx_algorithms) -+ priv->hw->mac->prog_mtl_rx_algorithms(priv->hw, -+ priv->plat->rx_sched_algorithm); -+ -+ /* Configure MTL TX algorithms */ -+ if (tx_queues_count > 1 && priv->hw->mac->prog_mtl_tx_algorithms) -+ priv->hw->mac->prog_mtl_tx_algorithms(priv->hw, -+ priv->plat->tx_sched_algorithm); -+ -+ /* Configure CBS in AVB TX queues */ -+ if (tx_queues_count > 1 && priv->hw->mac->config_cbs) -+ stmmac_configure_cbs(priv); -+ -+ /* Map RX MTL to DMA channels */ -+ if (priv->hw->mac->map_mtl_to_dma) -+ stmmac_rx_queue_dma_chan_map(priv); -+ -+ /* Enable MAC RX Queues */ -+ if (priv->hw->mac->rx_queue_enable) -+ stmmac_mac_enable_rx_queues(priv); -+ -+ /* Set RX priorities */ -+ if (rx_queues_count > 1 && priv->hw->mac->rx_queue_prio) -+ stmmac_mac_config_rx_queues_prio(priv); -+ -+ /* Set TX priorities */ -+ if (tx_queues_count > 1 && priv->hw->mac->tx_queue_prio) -+ stmmac_mac_config_tx_queues_prio(priv); -+ -+ /* Set RX routing */ -+ if (rx_queues_count > 1 && priv->hw->mac->rx_queue_routing) -+ stmmac_mac_config_rx_queues_routing(priv); -+} -+ - /** - * stmmac_hw_setup - setup mac in a usable state. - * @dev : pointer to the device structure. -@@ -1679,6 +2441,9 @@ static void stmmac_init_tx_coalesce(stru - static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) - { - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_cnt = priv->plat->rx_queues_to_use; -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ u32 chan; - int ret; - - /* DMA initialization and SW reset */ -@@ -1708,9 +2473,9 @@ static int stmmac_hw_setup(struct net_de - /* Initialize the MAC Core */ - priv->hw->mac->core_init(priv->hw, dev->mtu); - -- /* Initialize MAC RX Queues */ -- if (priv->hw->mac->rx_queue_enable) -- stmmac_mac_enable_rx_queues(priv); -+ /* Initialize MTL*/ -+ if (priv->synopsys_id >= DWMAC_CORE_4_00) -+ stmmac_mtl_configuration(priv); - - ret = priv->hw->mac->rx_ipc(priv->hw); - if (!ret) { -@@ -1720,10 +2485,7 @@ static int stmmac_hw_setup(struct net_de - } - - /* Enable the MAC Rx/Tx */ -- if (priv->synopsys_id >= DWMAC_CORE_4_00) -- stmmac_dwmac4_set_mac(priv->ioaddr, true); -- else -- stmmac_set_mac(priv->ioaddr, true); -+ priv->hw->mac->set_mac(priv->ioaddr, true); - - /* Set the HW DMA mode and the COE */ - stmmac_dma_operation_mode(priv); -@@ -1731,6 +2493,10 @@ static int stmmac_hw_setup(struct net_de - stmmac_mmc_setup(priv); - - if (init_ptp) { -+ ret = clk_prepare_enable(priv->plat->clk_ptp_ref); -+ if (ret < 0) -+ netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret); -+ - ret = stmmac_init_ptp(priv); - if (ret == -EOPNOTSUPP) - netdev_warn(priv->dev, "PTP not supported by HW\n"); -@@ -1745,35 +2511,37 @@ static int stmmac_hw_setup(struct net_de - __func__); - #endif - /* Start the ball rolling... */ -- netdev_dbg(priv->dev, "DMA RX/TX processes started...\n"); -- priv->hw->dma->start_tx(priv->ioaddr); -- priv->hw->dma->start_rx(priv->ioaddr); -+ stmmac_start_all_dma(priv); - - priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; - - if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { - priv->rx_riwt = MAX_DMA_RIWT; -- priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); -+ priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT, rx_cnt); - } - - if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) - priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0); - -- /* set TX ring length */ -- if (priv->hw->dma->set_tx_ring_len) -- priv->hw->dma->set_tx_ring_len(priv->ioaddr, -- (DMA_TX_SIZE - 1)); -- /* set RX ring length */ -- if (priv->hw->dma->set_rx_ring_len) -- priv->hw->dma->set_rx_ring_len(priv->ioaddr, -- (DMA_RX_SIZE - 1)); -+ /* set TX and RX rings length */ -+ stmmac_set_rings_length(priv); -+ - /* Enable TSO */ -- if (priv->tso) -- priv->hw->dma->enable_tso(priv->ioaddr, 1, STMMAC_CHAN0); -+ if (priv->tso) { -+ for (chan = 0; chan < tx_cnt; chan++) -+ priv->hw->dma->enable_tso(priv->ioaddr, 1, chan); -+ } - - return 0; - } - -+static void stmmac_hw_teardown(struct net_device *dev) -+{ -+ struct stmmac_priv *priv = netdev_priv(dev); -+ -+ clk_disable_unprepare(priv->plat->clk_ptp_ref); -+} -+ - /** - * stmmac_open - open entry point of the driver - * @dev : pointer to the device structure. -@@ -1842,7 +2610,7 @@ static int stmmac_open(struct net_device - netdev_err(priv->dev, - "%s: ERROR: allocating the IRQ %d (error: %d)\n", - __func__, dev->irq, ret); -- goto init_error; -+ goto irq_error; - } - - /* Request the Wake IRQ in case of another line is used for WoL */ -@@ -1869,8 +2637,8 @@ static int stmmac_open(struct net_device - } - } - -- napi_enable(&priv->napi); -- netif_start_queue(dev); -+ stmmac_enable_all_queues(priv); -+ stmmac_start_all_queues(priv); - - return 0; - -@@ -1879,7 +2647,12 @@ lpiirq_error: - free_irq(priv->wol_irq, dev); - wolirq_error: - free_irq(dev->irq, dev); -+irq_error: -+ if (dev->phydev) -+ phy_stop(dev->phydev); - -+ del_timer_sync(&priv->txtimer); -+ stmmac_hw_teardown(dev); - init_error: - free_dma_desc_resources(priv); - dma_desc_error: -@@ -1908,9 +2681,9 @@ static int stmmac_release(struct net_dev - phy_disconnect(dev->phydev); - } - -- netif_stop_queue(dev); -+ stmmac_stop_all_queues(priv); - -- napi_disable(&priv->napi); -+ stmmac_disable_all_queues(priv); - - del_timer_sync(&priv->txtimer); - -@@ -1922,14 +2695,13 @@ static int stmmac_release(struct net_dev - free_irq(priv->lpi_irq, dev); - - /* Stop TX/RX DMA and clear the descriptors */ -- priv->hw->dma->stop_tx(priv->ioaddr); -- priv->hw->dma->stop_rx(priv->ioaddr); -+ stmmac_stop_all_dma(priv); - - /* Release and free the Rx/Tx resources */ - free_dma_desc_resources(priv); - - /* Disable the MAC Rx/Tx */ -- stmmac_set_mac(priv->ioaddr, false); -+ priv->hw->mac->set_mac(priv->ioaddr, false); - - netif_carrier_off(dev); - -@@ -1948,22 +2720,24 @@ static int stmmac_release(struct net_dev - * @des: buffer start address - * @total_len: total length to fill in descriptors - * @last_segmant: condition for the last descriptor -+ * @queue: TX queue index - * Description: - * This function fills descriptor and request new descriptors according to - * buffer length to fill - */ - static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, -- int total_len, bool last_segment) -+ int total_len, bool last_segment, u32 queue) - { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; - struct dma_desc *desc; -- int tmp_len; - u32 buff_size; -+ int tmp_len; - - tmp_len = total_len; - - while (tmp_len > 0) { -- priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); -- desc = priv->dma_tx + priv->cur_tx; -+ tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); -+ desc = tx_q->dma_tx + tx_q->cur_tx; - - desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); - buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? -@@ -1971,7 +2745,7 @@ static void stmmac_tso_allocator(struct - - priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, - 0, 1, -- (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), -+ (last_segment) && (tmp_len <= TSO_MAX_BUFF_SIZE), - 0, 0); - - tmp_len -= TSO_MAX_BUFF_SIZE; -@@ -2007,23 +2781,28 @@ static void stmmac_tso_allocator(struct - */ - static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) - { -- u32 pay_len, mss; -- int tmp_pay_len = 0; -+ struct dma_desc *desc, *first, *mss_desc = NULL; - struct stmmac_priv *priv = netdev_priv(dev); - int nfrags = skb_shinfo(skb)->nr_frags; -+ u32 queue = skb_get_queue_mapping(skb); - unsigned int first_entry, des; -- struct dma_desc *desc, *first, *mss_desc = NULL; -+ struct stmmac_tx_queue *tx_q; -+ int tmp_pay_len = 0; -+ u32 pay_len, mss; - u8 proto_hdr_len; - int i; - -+ tx_q = &priv->tx_queue[queue]; -+ - /* Compute header lengths */ - proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - - /* Desc availability based on threshold should be enough safe */ -- if (unlikely(stmmac_tx_avail(priv) < -+ if (unlikely(stmmac_tx_avail(priv, queue) < - (((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) { -- if (!netif_queue_stopped(dev)) { -- netif_stop_queue(dev); -+ if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) { -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, -+ queue)); - /* This is a hard error, log it. */ - netdev_err(priv->dev, - "%s: Tx Ring full when queue awake\n", -@@ -2038,10 +2817,10 @@ static netdev_tx_t stmmac_tso_xmit(struc - - /* set new MSS value if needed */ - if (mss != priv->mss) { -- mss_desc = priv->dma_tx + priv->cur_tx; -+ mss_desc = tx_q->dma_tx + tx_q->cur_tx; - priv->hw->desc->set_mss(mss_desc, mss); - priv->mss = mss; -- priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); -+ tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); - } - - if (netif_msg_tx_queued(priv)) { -@@ -2051,9 +2830,9 @@ static netdev_tx_t stmmac_tso_xmit(struc - skb->data_len); - } - -- first_entry = priv->cur_tx; -+ first_entry = tx_q->cur_tx; - -- desc = priv->dma_tx + first_entry; -+ desc = tx_q->dma_tx + first_entry; - first = desc; - - /* first descriptor: fill Headers on Buf1 */ -@@ -2062,9 +2841,8 @@ static netdev_tx_t stmmac_tso_xmit(struc - if (dma_mapping_error(priv->device, des)) - goto dma_map_err; - -- priv->tx_skbuff_dma[first_entry].buf = des; -- priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb); -- priv->tx_skbuff[first_entry] = skb; -+ tx_q->tx_skbuff_dma[first_entry].buf = des; -+ tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); - - first->des0 = cpu_to_le32(des); - -@@ -2075,7 +2853,7 @@ static netdev_tx_t stmmac_tso_xmit(struc - /* If needed take extra descriptors to fill the remaining payload */ - tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; - -- stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0)); -+ stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue); - - /* Prepare fragments */ - for (i = 0; i < nfrags; i++) { -@@ -2084,24 +2862,34 @@ static netdev_tx_t stmmac_tso_xmit(struc - des = skb_frag_dma_map(priv->device, frag, 0, - skb_frag_size(frag), - DMA_TO_DEVICE); -+ if (dma_mapping_error(priv->device, des)) -+ goto dma_map_err; - - stmmac_tso_allocator(priv, des, skb_frag_size(frag), -- (i == nfrags - 1)); -+ (i == nfrags - 1), queue); - -- priv->tx_skbuff_dma[priv->cur_tx].buf = des; -- priv->tx_skbuff_dma[priv->cur_tx].len = skb_frag_size(frag); -- priv->tx_skbuff[priv->cur_tx] = NULL; -- priv->tx_skbuff_dma[priv->cur_tx].map_as_page = true; -+ tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des; -+ tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_frag_size(frag); -+ tx_q->tx_skbuff[tx_q->cur_tx] = NULL; -+ tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = true; - } - -- priv->tx_skbuff_dma[priv->cur_tx].last_segment = true; -+ tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true; -+ -+ /* Only the last descriptor gets to point to the skb. */ -+ tx_q->tx_skbuff[tx_q->cur_tx] = skb; - -- priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); -+ /* We've used all descriptors we need for this skb, however, -+ * advance cur_tx so that it references a fresh descriptor. -+ * ndo_start_xmit will fill this descriptor the next time it's -+ * called and stmmac_tx_clean may clean up to this descriptor. -+ */ -+ tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); - -- if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { -+ if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) { - netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", - __func__); -- netif_stop_queue(dev); -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); - } - - dev->stats.tx_bytes += skb->len; -@@ -2133,7 +2921,7 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->hw->desc->prepare_tso_tx_desc(first, 1, - proto_hdr_len, - pay_len, -- 1, priv->tx_skbuff_dma[first_entry].last_segment, -+ 1, tx_q->tx_skbuff_dma[first_entry].last_segment, - tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len)); - - /* If context desc is used to change MSS */ -@@ -2155,20 +2943,20 @@ static netdev_tx_t stmmac_tso_xmit(struc - - if (netif_msg_pktdata(priv)) { - pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", -- __func__, priv->cur_tx, priv->dirty_tx, first_entry, -- priv->cur_tx, first, nfrags); -+ __func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry, -+ tx_q->cur_tx, first, nfrags); - -- priv->hw->desc->display_ring((void *)priv->dma_tx, DMA_TX_SIZE, -+ priv->hw->desc->display_ring((void *)tx_q->dma_tx, DMA_TX_SIZE, - 0); - - pr_info(">>> frame to be transmitted: "); - print_pkt(skb->data, skb_headlen(skb)); - } - -- netdev_sent_queue(dev, skb->len); -+ netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); - -- priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, -- STMMAC_CHAN0); -+ priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr, -+ queue); - - return NETDEV_TX_OK; - -@@ -2192,21 +2980,27 @@ static netdev_tx_t stmmac_xmit(struct sk - struct stmmac_priv *priv = netdev_priv(dev); - unsigned int nopaged_len = skb_headlen(skb); - int i, csum_insertion = 0, is_jumbo = 0; -+ u32 queue = skb_get_queue_mapping(skb); - int nfrags = skb_shinfo(skb)->nr_frags; -- unsigned int entry, first_entry; -+ int entry; -+ unsigned int first_entry; - struct dma_desc *desc, *first; -+ struct stmmac_tx_queue *tx_q; - unsigned int enh_desc; - unsigned int des; - -+ tx_q = &priv->tx_queue[queue]; -+ - /* Manage oversized TCP frames for GMAC4 device */ - if (skb_is_gso(skb) && priv->tso) { - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - return stmmac_tso_xmit(skb, dev); - } - -- if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { -- if (!netif_queue_stopped(dev)) { -- netif_stop_queue(dev); -+ if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) { -+ if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) { -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, -+ queue)); - /* This is a hard error, log it. */ - netdev_err(priv->dev, - "%s: Tx Ring full when queue awake\n", -@@ -2218,20 +3012,18 @@ static netdev_tx_t stmmac_xmit(struct sk - if (priv->tx_path_in_lpi_mode) - stmmac_disable_eee_mode(priv); - -- entry = priv->cur_tx; -+ entry = tx_q->cur_tx; - first_entry = entry; - - csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); - - if (likely(priv->extend_desc)) -- desc = (struct dma_desc *)(priv->dma_etx + entry); -+ desc = (struct dma_desc *)(tx_q->dma_etx + entry); - else -- desc = priv->dma_tx + entry; -+ desc = tx_q->dma_tx + entry; - - first = desc; - -- priv->tx_skbuff[first_entry] = skb; -- - enh_desc = priv->plat->enh_desc; - /* To program the descriptors according to the size of the frame */ - if (enh_desc) -@@ -2239,7 +3031,7 @@ static netdev_tx_t stmmac_xmit(struct sk - - if (unlikely(is_jumbo) && likely(priv->synopsys_id < - DWMAC_CORE_4_00)) { -- entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); -+ entry = priv->hw->mode->jumbo_frm(tx_q, skb, csum_insertion); - if (unlikely(entry < 0)) - goto dma_map_err; - } -@@ -2252,48 +3044,56 @@ static netdev_tx_t stmmac_xmit(struct sk - entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); - - if (likely(priv->extend_desc)) -- desc = (struct dma_desc *)(priv->dma_etx + entry); -+ desc = (struct dma_desc *)(tx_q->dma_etx + entry); - else -- desc = priv->dma_tx + entry; -+ desc = tx_q->dma_tx + entry; - - des = skb_frag_dma_map(priv->device, frag, 0, len, - DMA_TO_DEVICE); - if (dma_mapping_error(priv->device, des)) - goto dma_map_err; /* should reuse desc w/o issues */ - -- priv->tx_skbuff[entry] = NULL; -+ tx_q->tx_skbuff[entry] = NULL; - -- priv->tx_skbuff_dma[entry].buf = des; -+ tx_q->tx_skbuff_dma[entry].buf = des; - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) - desc->des0 = cpu_to_le32(des); - else - desc->des2 = cpu_to_le32(des); - -- priv->tx_skbuff_dma[entry].map_as_page = true; -- priv->tx_skbuff_dma[entry].len = len; -- priv->tx_skbuff_dma[entry].last_segment = last_segment; -+ tx_q->tx_skbuff_dma[entry].map_as_page = true; -+ tx_q->tx_skbuff_dma[entry].len = len; -+ tx_q->tx_skbuff_dma[entry].last_segment = last_segment; - - /* Prepare the descriptor and set the own bit too */ - priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, -- priv->mode, 1, last_segment); -+ priv->mode, 1, last_segment, -+ skb->len); - } - -- entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); -+ /* Only the last descriptor gets to point to the skb. */ -+ tx_q->tx_skbuff[entry] = skb; - -- priv->cur_tx = entry; -+ /* We've used all descriptors we need for this skb, however, -+ * advance cur_tx so that it references a fresh descriptor. -+ * ndo_start_xmit will fill this descriptor the next time it's -+ * called and stmmac_tx_clean may clean up to this descriptor. -+ */ -+ entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); -+ tx_q->cur_tx = entry; - - if (netif_msg_pktdata(priv)) { - void *tx_head; - - netdev_dbg(priv->dev, - "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", -- __func__, priv->cur_tx, priv->dirty_tx, first_entry, -+ __func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry, - entry, first, nfrags); - - if (priv->extend_desc) -- tx_head = (void *)priv->dma_etx; -+ tx_head = (void *)tx_q->dma_etx; - else -- tx_head = (void *)priv->dma_tx; -+ tx_head = (void *)tx_q->dma_tx; - - priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); - -@@ -2301,10 +3101,10 @@ static netdev_tx_t stmmac_xmit(struct sk - print_pkt(skb->data, skb->len); - } - -- if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { -+ if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) { - netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", - __func__); -- netif_stop_queue(dev); -+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue)); - } - - dev->stats.tx_bytes += skb->len; -@@ -2339,14 +3139,14 @@ static netdev_tx_t stmmac_xmit(struct sk - if (dma_mapping_error(priv->device, des)) - goto dma_map_err; - -- priv->tx_skbuff_dma[first_entry].buf = des; -+ tx_q->tx_skbuff_dma[first_entry].buf = des; - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) - first->des0 = cpu_to_le32(des); - else - first->des2 = cpu_to_le32(des); - -- priv->tx_skbuff_dma[first_entry].len = nopaged_len; -- priv->tx_skbuff_dma[first_entry].last_segment = last_segment; -+ tx_q->tx_skbuff_dma[first_entry].len = nopaged_len; -+ tx_q->tx_skbuff_dma[first_entry].last_segment = last_segment; - - if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - priv->hwts_tx_en)) { -@@ -2358,7 +3158,7 @@ static netdev_tx_t stmmac_xmit(struct sk - /* Prepare the first descriptor setting the OWN bit too */ - priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len, - csum_insertion, priv->mode, 1, -- last_segment); -+ last_segment, skb->len); - - /* The own bit must be the latest setting done when prepare the - * descriptor and then barrier is needed to make sure that -@@ -2367,13 +3167,13 @@ static netdev_tx_t stmmac_xmit(struct sk - dma_wmb(); - } - -- netdev_sent_queue(dev, skb->len); -+ netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len); - - if (priv->synopsys_id < DWMAC_CORE_4_00) - priv->hw->dma->enable_dma_transmission(priv->ioaddr); - else -- priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, -- STMMAC_CHAN0); -+ priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr, -+ queue); - - return NETDEV_TX_OK; - -@@ -2401,9 +3201,9 @@ static void stmmac_rx_vlan(struct net_de - } - - --static inline int stmmac_rx_threshold_count(struct stmmac_priv *priv) -+static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q) - { -- if (priv->rx_zeroc_thresh < STMMAC_RX_THRESH) -+ if (rx_q->rx_zeroc_thresh < STMMAC_RX_THRESH) - return 0; - - return 1; -@@ -2412,30 +3212,33 @@ static inline int stmmac_rx_threshold_co - /** - * stmmac_rx_refill - refill used skb preallocated buffers - * @priv: driver private structure -+ * @queue: RX queue index - * Description : this is to reallocate the skb for the reception process - * that is based on zero-copy. - */ --static inline void stmmac_rx_refill(struct stmmac_priv *priv) -+static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) - { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ int dirty = stmmac_rx_dirty(priv, queue); -+ unsigned int entry = rx_q->dirty_rx; -+ - int bfsize = priv->dma_buf_sz; -- unsigned int entry = priv->dirty_rx; -- int dirty = stmmac_rx_dirty(priv); - - while (dirty-- > 0) { - struct dma_desc *p; - - if (priv->extend_desc) -- p = (struct dma_desc *)(priv->dma_erx + entry); -+ p = (struct dma_desc *)(rx_q->dma_erx + entry); - else -- p = priv->dma_rx + entry; -+ p = rx_q->dma_rx + entry; - -- if (likely(priv->rx_skbuff[entry] == NULL)) { -+ if (likely(!rx_q->rx_skbuff[entry])) { - struct sk_buff *skb; - - skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); - if (unlikely(!skb)) { - /* so for a while no zero-copy! */ -- priv->rx_zeroc_thresh = STMMAC_RX_THRESH; -+ rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH; - if (unlikely(net_ratelimit())) - dev_err(priv->device, - "fail to alloc skb entry %d\n", -@@ -2443,28 +3246,28 @@ static inline void stmmac_rx_refill(stru - break; - } - -- priv->rx_skbuff[entry] = skb; -- priv->rx_skbuff_dma[entry] = -+ rx_q->rx_skbuff[entry] = skb; -+ rx_q->rx_skbuff_dma[entry] = - dma_map_single(priv->device, skb->data, bfsize, - DMA_FROM_DEVICE); - if (dma_mapping_error(priv->device, -- priv->rx_skbuff_dma[entry])) { -+ rx_q->rx_skbuff_dma[entry])) { - netdev_err(priv->dev, "Rx DMA map failed\n"); - dev_kfree_skb(skb); - break; - } - - if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { -- p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]); -+ p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]); - p->des1 = 0; - } else { -- p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]); -+ p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]); - } - if (priv->hw->mode->refill_desc3) -- priv->hw->mode->refill_desc3(priv, p); -+ priv->hw->mode->refill_desc3(rx_q, p); - -- if (priv->rx_zeroc_thresh > 0) -- priv->rx_zeroc_thresh--; -+ if (rx_q->rx_zeroc_thresh > 0) -+ rx_q->rx_zeroc_thresh--; - - netif_dbg(priv, rx_status, priv->dev, - "refill entry #%d\n", entry); -@@ -2480,31 +3283,33 @@ static inline void stmmac_rx_refill(stru - - entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); - } -- priv->dirty_rx = entry; -+ rx_q->dirty_rx = entry; - } - - /** - * stmmac_rx - manage the receive process - * @priv: driver private structure -- * @limit: napi bugget. -+ * @limit: napi bugget -+ * @queue: RX queue index. - * Description : this the function called by the napi poll method. - * It gets all the frames inside the ring. - */ --static int stmmac_rx(struct stmmac_priv *priv, int limit) -+static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) - { -- unsigned int entry = priv->cur_rx; -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ unsigned int entry = rx_q->cur_rx; -+ int coe = priv->hw->rx_csum; - unsigned int next_entry; - unsigned int count = 0; -- int coe = priv->hw->rx_csum; - - if (netif_msg_rx_status(priv)) { - void *rx_head; - - netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__); - if (priv->extend_desc) -- rx_head = (void *)priv->dma_erx; -+ rx_head = (void *)rx_q->dma_erx; - else -- rx_head = (void *)priv->dma_rx; -+ rx_head = (void *)rx_q->dma_rx; - - priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); - } -@@ -2514,9 +3319,9 @@ static int stmmac_rx(struct stmmac_priv - struct dma_desc *np; - - if (priv->extend_desc) -- p = (struct dma_desc *)(priv->dma_erx + entry); -+ p = (struct dma_desc *)(rx_q->dma_erx + entry); - else -- p = priv->dma_rx + entry; -+ p = rx_q->dma_rx + entry; - - /* read the status of the incoming frame */ - status = priv->hw->desc->rx_status(&priv->dev->stats, -@@ -2527,20 +3332,20 @@ static int stmmac_rx(struct stmmac_priv - - count++; - -- priv->cur_rx = STMMAC_GET_ENTRY(priv->cur_rx, DMA_RX_SIZE); -- next_entry = priv->cur_rx; -+ rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx, DMA_RX_SIZE); -+ next_entry = rx_q->cur_rx; - - if (priv->extend_desc) -- np = (struct dma_desc *)(priv->dma_erx + next_entry); -+ np = (struct dma_desc *)(rx_q->dma_erx + next_entry); - else -- np = priv->dma_rx + next_entry; -+ np = rx_q->dma_rx + next_entry; - - prefetch(np); - - if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) - priv->hw->desc->rx_extended_status(&priv->dev->stats, - &priv->xstats, -- priv->dma_erx + -+ rx_q->dma_erx + - entry); - if (unlikely(status == discard_frame)) { - priv->dev->stats.rx_errors++; -@@ -2550,9 +3355,9 @@ static int stmmac_rx(struct stmmac_priv - * them in stmmac_rx_refill() function so that - * device can reuse it. - */ -- priv->rx_skbuff[entry] = NULL; -+ rx_q->rx_skbuff[entry] = NULL; - dma_unmap_single(priv->device, -- priv->rx_skbuff_dma[entry], -+ rx_q->rx_skbuff_dma[entry], - priv->dma_buf_sz, - DMA_FROM_DEVICE); - } -@@ -2600,7 +3405,7 @@ static int stmmac_rx(struct stmmac_priv - */ - if (unlikely(!priv->plat->has_gmac4 && - ((frame_len < priv->rx_copybreak) || -- stmmac_rx_threshold_count(priv)))) { -+ stmmac_rx_threshold_count(rx_q)))) { - skb = netdev_alloc_skb_ip_align(priv->dev, - frame_len); - if (unlikely(!skb)) { -@@ -2612,21 +3417,21 @@ static int stmmac_rx(struct stmmac_priv - } - - dma_sync_single_for_cpu(priv->device, -- priv->rx_skbuff_dma -+ rx_q->rx_skbuff_dma - [entry], frame_len, - DMA_FROM_DEVICE); - skb_copy_to_linear_data(skb, -- priv-> -+ rx_q-> - rx_skbuff[entry]->data, - frame_len); - - skb_put(skb, frame_len); - dma_sync_single_for_device(priv->device, -- priv->rx_skbuff_dma -+ rx_q->rx_skbuff_dma - [entry], frame_len, - DMA_FROM_DEVICE); - } else { -- skb = priv->rx_skbuff[entry]; -+ skb = rx_q->rx_skbuff[entry]; - if (unlikely(!skb)) { - netdev_err(priv->dev, - "%s: Inconsistent Rx chain\n", -@@ -2635,12 +3440,12 @@ static int stmmac_rx(struct stmmac_priv - break; - } - prefetch(skb->data - NET_IP_ALIGN); -- priv->rx_skbuff[entry] = NULL; -- priv->rx_zeroc_thresh++; -+ rx_q->rx_skbuff[entry] = NULL; -+ rx_q->rx_zeroc_thresh++; - - skb_put(skb, frame_len); - dma_unmap_single(priv->device, -- priv->rx_skbuff_dma[entry], -+ rx_q->rx_skbuff_dma[entry], - priv->dma_buf_sz, - DMA_FROM_DEVICE); - } -@@ -2662,7 +3467,7 @@ static int stmmac_rx(struct stmmac_priv - else - skb->ip_summed = CHECKSUM_UNNECESSARY; - -- napi_gro_receive(&priv->napi, skb); -+ napi_gro_receive(&rx_q->napi, skb); - - priv->dev->stats.rx_packets++; - priv->dev->stats.rx_bytes += frame_len; -@@ -2670,7 +3475,7 @@ static int stmmac_rx(struct stmmac_priv - entry = next_entry; - } - -- stmmac_rx_refill(priv); -+ stmmac_rx_refill(priv, queue); - - priv->xstats.rx_pkt_n += count; - -@@ -2687,16 +3492,24 @@ static int stmmac_rx(struct stmmac_priv - */ - static int stmmac_poll(struct napi_struct *napi, int budget) - { -- struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); -+ struct stmmac_rx_queue *rx_q = -+ container_of(napi, struct stmmac_rx_queue, napi); -+ struct stmmac_priv *priv = rx_q->priv_data; -+ u32 tx_count = priv->plat->tx_queues_to_use; -+ u32 chan = rx_q->queue_index; - int work_done = 0; -+ u32 queue; - - priv->xstats.napi_poll++; -- stmmac_tx_clean(priv); - -- work_done = stmmac_rx(priv, budget); -+ /* check all the queues */ -+ for (queue = 0; queue < tx_count; queue++) -+ stmmac_tx_clean(priv, queue); -+ -+ work_done = stmmac_rx(priv, budget, rx_q->queue_index); - if (work_done < budget) { - napi_complete_done(napi, work_done); -- stmmac_enable_dma_irq(priv); -+ stmmac_enable_dma_irq(priv, chan); - } - return work_done; - } -@@ -2712,9 +3525,12 @@ static int stmmac_poll(struct napi_struc - static void stmmac_tx_timeout(struct net_device *dev) - { - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 tx_count = priv->plat->tx_queues_to_use; -+ u32 chan; - - /* Clear Tx resources and restart transmitting again */ -- stmmac_tx_err(priv); -+ for (chan = 0; chan < tx_count; chan++) -+ stmmac_tx_err(priv, chan); - } - - /** -@@ -2837,6 +3653,12 @@ static irqreturn_t stmmac_interrupt(int - { - struct net_device *dev = (struct net_device *)dev_id; - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_cnt = priv->plat->rx_queues_to_use; -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ u32 queues_count; -+ u32 queue; -+ -+ queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt; - - if (priv->irq_wake) - pm_wakeup_event(priv->device, 0); -@@ -2850,16 +3672,30 @@ static irqreturn_t stmmac_interrupt(int - if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { - int status = priv->hw->mac->host_irq_status(priv->hw, - &priv->xstats); -+ - if (unlikely(status)) { - /* For LPI we need to save the tx status */ - if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) - priv->tx_path_in_lpi_mode = true; - if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) - priv->tx_path_in_lpi_mode = false; -- if (status & CORE_IRQ_MTL_RX_OVERFLOW && priv->hw->dma->set_rx_tail_ptr) -- priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, -- priv->rx_tail_addr, -- STMMAC_CHAN0); -+ } -+ -+ if (priv->synopsys_id >= DWMAC_CORE_4_00) { -+ for (queue = 0; queue < queues_count; queue++) { -+ struct stmmac_rx_queue *rx_q = -+ &priv->rx_queue[queue]; -+ -+ status |= -+ priv->hw->mac->host_mtl_irq_status(priv->hw, -+ queue); -+ -+ if (status & CORE_IRQ_MTL_RX_OVERFLOW && -+ priv->hw->dma->set_rx_tail_ptr) -+ priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, -+ rx_q->rx_tail_addr, -+ queue); -+ } - } - - /* PCS link status */ -@@ -2944,7 +3780,7 @@ static void sysfs_display_ring(void *hea - ep++; - } else { - seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", -- i, (unsigned int)virt_to_phys(ep), -+ i, (unsigned int)virt_to_phys(p), - le32_to_cpu(p->des0), le32_to_cpu(p->des1), - le32_to_cpu(p->des2), le32_to_cpu(p->des3)); - p++; -@@ -2957,17 +3793,40 @@ static int stmmac_sysfs_ring_read(struct - { - struct net_device *dev = seq->private; - struct stmmac_priv *priv = netdev_priv(dev); -+ u32 rx_count = priv->plat->rx_queues_to_use; -+ u32 tx_count = priv->plat->tx_queues_to_use; -+ u32 queue; - -- if (priv->extend_desc) { -- seq_printf(seq, "Extended RX descriptor ring:\n"); -- sysfs_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1, seq); -- seq_printf(seq, "Extended TX descriptor ring:\n"); -- sysfs_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1, seq); -- } else { -- seq_printf(seq, "RX descriptor ring:\n"); -- sysfs_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0, seq); -- seq_printf(seq, "TX descriptor ring:\n"); -- sysfs_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0, seq); -+ for (queue = 0; queue < rx_count; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ seq_printf(seq, "RX Queue %d:\n", queue); -+ -+ if (priv->extend_desc) { -+ seq_printf(seq, "Extended descriptor ring:\n"); -+ sysfs_display_ring((void *)rx_q->dma_erx, -+ DMA_RX_SIZE, 1, seq); -+ } else { -+ seq_printf(seq, "Descriptor ring:\n"); -+ sysfs_display_ring((void *)rx_q->dma_rx, -+ DMA_RX_SIZE, 0, seq); -+ } -+ } -+ -+ for (queue = 0; queue < tx_count; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ seq_printf(seq, "TX Queue %d:\n", queue); -+ -+ if (priv->extend_desc) { -+ seq_printf(seq, "Extended descriptor ring:\n"); -+ sysfs_display_ring((void *)tx_q->dma_etx, -+ DMA_TX_SIZE, 1, seq); -+ } else { -+ seq_printf(seq, "Descriptor ring:\n"); -+ sysfs_display_ring((void *)tx_q->dma_tx, -+ DMA_TX_SIZE, 0, seq); -+ } - } - - return 0; -@@ -3250,11 +4109,14 @@ int stmmac_dvr_probe(struct device *devi - struct plat_stmmacenet_data *plat_dat, - struct stmmac_resources *res) - { -- int ret = 0; - struct net_device *ndev = NULL; - struct stmmac_priv *priv; -+ int ret = 0; -+ u32 queue; - -- ndev = alloc_etherdev(sizeof(struct stmmac_priv)); -+ ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv), -+ MTL_MAX_TX_QUEUES, -+ MTL_MAX_RX_QUEUES); - if (!ndev) - return -ENOMEM; - -@@ -3296,6 +4158,10 @@ int stmmac_dvr_probe(struct device *devi - if (ret) - goto error_hw_init; - -+ /* Configure real RX and TX queues */ -+ netif_set_real_num_rx_queues(ndev, priv->plat->rx_queues_to_use); -+ netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use); -+ - ndev->netdev_ops = &stmmac_netdev_ops; - - ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -@@ -3328,7 +4194,12 @@ int stmmac_dvr_probe(struct device *devi - "Enable RX Mitigation via HW Watchdog Timer\n"); - } - -- netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); -+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ netif_napi_add(ndev, &rx_q->napi, stmmac_poll, -+ (8 * priv->plat->rx_queues_to_use)); -+ } - - spin_lock_init(&priv->lock); - -@@ -3373,7 +4244,11 @@ error_netdev_register: - priv->hw->pcs != STMMAC_PCS_RTBI) - stmmac_mdio_unregister(ndev); - error_mdio_register: -- netif_napi_del(&priv->napi); -+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ netif_napi_del(&rx_q->napi); -+ } - error_hw_init: - free_netdev(ndev); - -@@ -3394,10 +4269,9 @@ int stmmac_dvr_remove(struct device *dev - - netdev_info(priv->dev, "%s: removing driver", __func__); - -- priv->hw->dma->stop_rx(priv->ioaddr); -- priv->hw->dma->stop_tx(priv->ioaddr); -+ stmmac_stop_all_dma(priv); - -- stmmac_set_mac(priv->ioaddr, false); -+ priv->hw->mac->set_mac(priv->ioaddr, false); - netif_carrier_off(ndev); - unregister_netdev(ndev); - if (priv->plat->stmmac_rst) -@@ -3436,20 +4310,19 @@ int stmmac_suspend(struct device *dev) - spin_lock_irqsave(&priv->lock, flags); - - netif_device_detach(ndev); -- netif_stop_queue(ndev); -+ stmmac_stop_all_queues(priv); - -- napi_disable(&priv->napi); -+ stmmac_disable_all_queues(priv); - - /* Stop TX/RX DMA */ -- priv->hw->dma->stop_tx(priv->ioaddr); -- priv->hw->dma->stop_rx(priv->ioaddr); -+ stmmac_stop_all_dma(priv); - - /* Enable Power down mode by programming the PMT regs */ - if (device_may_wakeup(priv->device)) { - priv->hw->mac->pmt(priv->hw, priv->wolopts); - priv->irq_wake = 1; - } else { -- stmmac_set_mac(priv->ioaddr, false); -+ priv->hw->mac->set_mac(priv->ioaddr, false); - pinctrl_pm_select_sleep_state(priv->device); - /* Disable clock in case of PWM is off */ - clk_disable(priv->plat->pclk); -@@ -3465,6 +4338,31 @@ int stmmac_suspend(struct device *dev) - EXPORT_SYMBOL_GPL(stmmac_suspend); - - /** -+ * stmmac_reset_queues_param - reset queue parameters -+ * @dev: device pointer -+ */ -+static void stmmac_reset_queues_param(struct stmmac_priv *priv) -+{ -+ u32 rx_cnt = priv->plat->rx_queues_to_use; -+ u32 tx_cnt = priv->plat->tx_queues_to_use; -+ u32 queue; -+ -+ for (queue = 0; queue < rx_cnt; queue++) { -+ struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; -+ -+ rx_q->cur_rx = 0; -+ rx_q->dirty_rx = 0; -+ } -+ -+ for (queue = 0; queue < tx_cnt; queue++) { -+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; -+ -+ tx_q->cur_tx = 0; -+ tx_q->dirty_tx = 0; -+ } -+} -+ -+/** - * stmmac_resume - resume callback - * @dev: device pointer - * Description: when resume this function is invoked to setup the DMA and CORE -@@ -3504,10 +4402,8 @@ int stmmac_resume(struct device *dev) - - spin_lock_irqsave(&priv->lock, flags); - -- priv->cur_rx = 0; -- priv->dirty_rx = 0; -- priv->dirty_tx = 0; -- priv->cur_tx = 0; -+ stmmac_reset_queues_param(priv); -+ - /* reset private mss value to force mss context settings at - * next tso xmit (only used for gmac4). - */ -@@ -3519,9 +4415,9 @@ int stmmac_resume(struct device *dev) - stmmac_init_tx_coalesce(priv); - stmmac_set_rx_mode(ndev); - -- napi_enable(&priv->napi); -+ stmmac_enable_all_queues(priv); - -- netif_start_queue(ndev); -+ stmmac_start_all_queues(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -32,6 +32,7 @@ - */ - struct stmmac_pci_dmi_data { - const char *name; -+ const char *asset_tag; - unsigned int func; - int phy_addr; - }; -@@ -46,6 +47,7 @@ struct stmmac_pci_info { - static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info) - { - const char *name = dmi_get_system_info(DMI_BOARD_NAME); -+ const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG); - unsigned int func = PCI_FUNC(info->pdev->devfn); - struct stmmac_pci_dmi_data *dmi; - -@@ -57,18 +59,19 @@ static int stmmac_pci_find_phy_addr(stru - return 1; - - for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) { -- if (!strcmp(dmi->name, name) && dmi->func == func) -+ if (!strcmp(dmi->name, name) && dmi->func == func) { -+ /* If asset tag is provided, match on it as well. */ -+ if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag)) -+ continue; - return dmi->phy_addr; -+ } - } - - return -ENODEV; - } - --static void stmmac_default_data(struct plat_stmmacenet_data *plat) -+static void common_default_data(struct plat_stmmacenet_data *plat) - { -- plat->bus_id = 1; -- plat->phy_addr = 0; -- plat->interface = PHY_INTERFACE_MODE_GMII; - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ - plat->has_gmac = 1; - plat->force_sf_dma_mode = 1; -@@ -76,10 +79,6 @@ static void stmmac_default_data(struct p - plat->mdio_bus_data->phy_reset = NULL; - plat->mdio_bus_data->phy_mask = 0; - -- plat->dma_cfg->pbl = 32; -- plat->dma_cfg->pblx8 = true; -- /* TODO: AXI */ -- - /* Set default value for multicast hash bins */ - plat->multicast_filter_bins = HASH_TABLE_SIZE; - -@@ -88,6 +87,31 @@ static void stmmac_default_data(struct p - - /* Set the maxmtu to a default of JUMBO_LEN */ - plat->maxmtu = JUMBO_LEN; -+ -+ /* Set default number of RX and TX queues to use */ -+ plat->tx_queues_to_use = 1; -+ plat->rx_queues_to_use = 1; -+ -+ /* Disable Priority config by default */ -+ plat->tx_queues_cfg[0].use_prio = false; -+ plat->rx_queues_cfg[0].use_prio = false; -+ -+ /* Disable RX queues routing by default */ -+ plat->rx_queues_cfg[0].pkt_route = 0x0; -+} -+ -+static void stmmac_default_data(struct plat_stmmacenet_data *plat) -+{ -+ /* Set common default data first */ -+ common_default_data(plat); -+ -+ plat->bus_id = 1; -+ plat->phy_addr = 0; -+ plat->interface = PHY_INTERFACE_MODE_GMII; -+ -+ plat->dma_cfg->pbl = 32; -+ plat->dma_cfg->pblx8 = true; -+ /* TODO: AXI */ - } - - static int quark_default_data(struct plat_stmmacenet_data *plat, -@@ -96,6 +120,9 @@ static int quark_default_data(struct pla - struct pci_dev *pdev = info->pdev; - int ret; - -+ /* Set common default data first */ -+ common_default_data(plat); -+ - /* - * Refuse to load the driver and register net device if MAC controller - * does not connect to any PHY interface. -@@ -107,27 +134,12 @@ static int quark_default_data(struct pla - plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn); - plat->phy_addr = ret; - plat->interface = PHY_INTERFACE_MODE_RMII; -- plat->clk_csr = 2; -- plat->has_gmac = 1; -- plat->force_sf_dma_mode = 1; -- -- plat->mdio_bus_data->phy_reset = NULL; -- plat->mdio_bus_data->phy_mask = 0; - - plat->dma_cfg->pbl = 16; - plat->dma_cfg->pblx8 = true; - plat->dma_cfg->fixed_burst = 1; - /* AXI (TODO) */ - -- /* Set default value for multicast hash bins */ -- plat->multicast_filter_bins = HASH_TABLE_SIZE; -- -- /* Set default value for unicast filter entries */ -- plat->unicast_filter_entries = 1; -- -- /* Set the maxmtu to a default of JUMBO_LEN */ -- plat->maxmtu = JUMBO_LEN; -- - return 0; - } - -@@ -142,6 +154,24 @@ static struct stmmac_pci_dmi_data quark_ - .func = 6, - .phy_addr = 1, - }, -+ { -+ .name = "SIMATIC IOT2000", -+ .asset_tag = "6ES7647-0AA00-0YA2", -+ .func = 6, -+ .phy_addr = 1, -+ }, -+ { -+ .name = "SIMATIC IOT2000", -+ .asset_tag = "6ES7647-0AA00-1YA2", -+ .func = 6, -+ .phy_addr = 1, -+ }, -+ { -+ .name = "SIMATIC IOT2000", -+ .asset_tag = "6ES7647-0AA00-1YA2", -+ .func = 7, -+ .phy_addr = 1, -+ }, - {} - }; - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -108,7 +108,7 @@ static struct stmmac_axi *stmmac_axi_set - if (!np) - return NULL; - -- axi = kzalloc(sizeof(*axi), GFP_KERNEL); -+ axi = devm_kzalloc(&pdev->dev, sizeof(*axi), GFP_KERNEL); - if (!axi) { - of_node_put(np); - return ERR_PTR(-ENOMEM); -@@ -132,6 +132,155 @@ static struct stmmac_axi *stmmac_axi_set - } - - /** -+ * stmmac_mtl_setup - parse DT parameters for multiple queues configuration -+ * @pdev: platform device -+ */ -+static void stmmac_mtl_setup(struct platform_device *pdev, -+ struct plat_stmmacenet_data *plat) -+{ -+ struct device_node *q_node; -+ struct device_node *rx_node; -+ struct device_node *tx_node; -+ u8 queue = 0; -+ -+ /* For backwards-compatibility with device trees that don't have any -+ * snps,mtl-rx-config or snps,mtl-tx-config properties, we fall back -+ * to one RX and TX queues each. -+ */ -+ plat->rx_queues_to_use = 1; -+ plat->tx_queues_to_use = 1; -+ -+ rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0); -+ if (!rx_node) -+ return; -+ -+ tx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-tx-config", 0); -+ if (!tx_node) { -+ of_node_put(rx_node); -+ return; -+ } -+ -+ /* Processing RX queues common config */ -+ if (of_property_read_u8(rx_node, "snps,rx-queues-to-use", -+ &plat->rx_queues_to_use)) -+ plat->rx_queues_to_use = 1; -+ -+ if (of_property_read_bool(rx_node, "snps,rx-sched-sp")) -+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; -+ else if (of_property_read_bool(rx_node, "snps,rx-sched-wsp")) -+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_WSP; -+ else -+ plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP; -+ -+ /* Processing individual RX queue config */ -+ for_each_child_of_node(rx_node, q_node) { -+ if (queue >= plat->rx_queues_to_use) -+ break; -+ -+ if (of_property_read_bool(q_node, "snps,dcb-algorithm")) -+ plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; -+ else if (of_property_read_bool(q_node, "snps,avb-algorithm")) -+ plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB; -+ else -+ plat->rx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; -+ -+ if (of_property_read_u8(q_node, "snps,map-to-dma-channel", -+ &plat->rx_queues_cfg[queue].chan)) -+ plat->rx_queues_cfg[queue].chan = queue; -+ /* TODO: Dynamic mapping to be included in the future */ -+ -+ if (of_property_read_u32(q_node, "snps,priority", -+ &plat->rx_queues_cfg[queue].prio)) { -+ plat->rx_queues_cfg[queue].prio = 0; -+ plat->rx_queues_cfg[queue].use_prio = false; -+ } else { -+ plat->rx_queues_cfg[queue].use_prio = true; -+ } -+ -+ /* RX queue specific packet type routing */ -+ if (of_property_read_bool(q_node, "snps,route-avcp")) -+ plat->rx_queues_cfg[queue].pkt_route = PACKET_AVCPQ; -+ else if (of_property_read_bool(q_node, "snps,route-ptp")) -+ plat->rx_queues_cfg[queue].pkt_route = PACKET_PTPQ; -+ else if (of_property_read_bool(q_node, "snps,route-dcbcp")) -+ plat->rx_queues_cfg[queue].pkt_route = PACKET_DCBCPQ; -+ else if (of_property_read_bool(q_node, "snps,route-up")) -+ plat->rx_queues_cfg[queue].pkt_route = PACKET_UPQ; -+ else if (of_property_read_bool(q_node, "snps,route-multi-broad")) -+ plat->rx_queues_cfg[queue].pkt_route = PACKET_MCBCQ; -+ else -+ plat->rx_queues_cfg[queue].pkt_route = 0x0; -+ -+ queue++; -+ } -+ -+ /* Processing TX queues common config */ -+ if (of_property_read_u8(tx_node, "snps,tx-queues-to-use", -+ &plat->tx_queues_to_use)) -+ plat->tx_queues_to_use = 1; -+ -+ if (of_property_read_bool(tx_node, "snps,tx-sched-wrr")) -+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WRR; -+ else if (of_property_read_bool(tx_node, "snps,tx-sched-wfq")) -+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_WFQ; -+ else if (of_property_read_bool(tx_node, "snps,tx-sched-dwrr")) -+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_DWRR; -+ else if (of_property_read_bool(tx_node, "snps,tx-sched-sp")) -+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP; -+ else -+ plat->tx_sched_algorithm = MTL_TX_ALGORITHM_SP; -+ -+ queue = 0; -+ -+ /* Processing individual TX queue config */ -+ for_each_child_of_node(tx_node, q_node) { -+ if (queue >= plat->tx_queues_to_use) -+ break; -+ -+ if (of_property_read_u8(q_node, "snps,weight", -+ &plat->tx_queues_cfg[queue].weight)) -+ plat->tx_queues_cfg[queue].weight = 0x10 + queue; -+ -+ if (of_property_read_bool(q_node, "snps,dcb-algorithm")) { -+ plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; -+ } else if (of_property_read_bool(q_node, -+ "snps,avb-algorithm")) { -+ plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB; -+ -+ /* Credit Base Shaper parameters used by AVB */ -+ if (of_property_read_u32(q_node, "snps,send_slope", -+ &plat->tx_queues_cfg[queue].send_slope)) -+ plat->tx_queues_cfg[queue].send_slope = 0x0; -+ if (of_property_read_u32(q_node, "snps,idle_slope", -+ &plat->tx_queues_cfg[queue].idle_slope)) -+ plat->tx_queues_cfg[queue].idle_slope = 0x0; -+ if (of_property_read_u32(q_node, "snps,high_credit", -+ &plat->tx_queues_cfg[queue].high_credit)) -+ plat->tx_queues_cfg[queue].high_credit = 0x0; -+ if (of_property_read_u32(q_node, "snps,low_credit", -+ &plat->tx_queues_cfg[queue].low_credit)) -+ plat->tx_queues_cfg[queue].low_credit = 0x0; -+ } else { -+ plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; -+ } -+ -+ if (of_property_read_u32(q_node, "snps,priority", -+ &plat->tx_queues_cfg[queue].prio)) { -+ plat->tx_queues_cfg[queue].prio = 0; -+ plat->tx_queues_cfg[queue].use_prio = false; -+ } else { -+ plat->tx_queues_cfg[queue].use_prio = true; -+ } -+ -+ queue++; -+ } -+ -+ of_node_put(rx_node); -+ of_node_put(tx_node); -+ of_node_put(q_node); -+} -+ -+/** - * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources - * @plat: driver data platform structure - * @np: device tree node -@@ -340,6 +489,8 @@ stmmac_probe_config_dt(struct platform_d - - plat->axi = stmmac_axi_setup(pdev); - -+ stmmac_mtl_setup(pdev, plat); -+ - /* clock setup */ - plat->stmmac_clk = devm_clk_get(&pdev->dev, - STMMAC_RESOURCE_NAME); -@@ -359,13 +510,12 @@ stmmac_probe_config_dt(struct platform_d - clk_prepare_enable(plat->pclk); - - /* Fall-back to main clock in case of no PTP ref is passed */ -- plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "clk_ptp_ref"); -+ plat->clk_ptp_ref = devm_clk_get(&pdev->dev, "ptp_ref"); - if (IS_ERR(plat->clk_ptp_ref)) { - plat->clk_ptp_rate = clk_get_rate(plat->stmmac_clk); - plat->clk_ptp_ref = NULL; - dev_warn(&pdev->dev, "PTP uses main clock\n"); - } else { -- clk_prepare_enable(plat->clk_ptp_ref); - plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref); - dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate); - } ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -28,6 +28,9 @@ - - #include - -+#define MTL_MAX_RX_QUEUES 8 -+#define MTL_MAX_TX_QUEUES 8 -+ - #define STMMAC_RX_COE_NONE 0 - #define STMMAC_RX_COE_TYPE1 1 - #define STMMAC_RX_COE_TYPE2 2 -@@ -44,6 +47,18 @@ - #define STMMAC_CSR_150_250M 0x4 /* MDC = clk_scr_i/102 */ - #define STMMAC_CSR_250_300M 0x5 /* MDC = clk_scr_i/122 */ - -+/* MTL algorithms identifiers */ -+#define MTL_TX_ALGORITHM_WRR 0x0 -+#define MTL_TX_ALGORITHM_WFQ 0x1 -+#define MTL_TX_ALGORITHM_DWRR 0x2 -+#define MTL_TX_ALGORITHM_SP 0x3 -+#define MTL_RX_ALGORITHM_SP 0x4 -+#define MTL_RX_ALGORITHM_WSP 0x5 -+ -+/* RX/TX Queue Mode */ -+#define MTL_QUEUE_AVB 0x0 -+#define MTL_QUEUE_DCB 0x1 -+ - /* The MDC clock could be set higher than the IEEE 802.3 - * specified frequency limit 0f 2.5 MHz, by programming a clock divider - * of value different than the above defined values. The resultant MDIO -@@ -109,6 +124,26 @@ struct stmmac_axi { - bool axi_rb; - }; - -+struct stmmac_rxq_cfg { -+ u8 mode_to_use; -+ u8 chan; -+ u8 pkt_route; -+ bool use_prio; -+ u32 prio; -+}; -+ -+struct stmmac_txq_cfg { -+ u8 weight; -+ u8 mode_to_use; -+ /* Credit Base Shaper parameters */ -+ u32 send_slope; -+ u32 idle_slope; -+ u32 high_credit; -+ u32 low_credit; -+ bool use_prio; -+ u32 prio; -+}; -+ - struct plat_stmmacenet_data { - int bus_id; - int phy_addr; -@@ -133,6 +168,12 @@ struct plat_stmmacenet_data { - int unicast_filter_entries; - int tx_fifo_size; - int rx_fifo_size; -+ u8 rx_queues_to_use; -+ u8 tx_queues_to_use; -+ u8 rx_sched_algorithm; -+ u8 tx_sched_algorithm; -+ struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES]; -+ struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES]; - void (*fix_mac_speed)(void *priv, unsigned int speed); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); diff --git a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch b/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch deleted file mode 100644 index abdc618e6b..0000000000 --- a/target/linux/sunxi/patches-4.9/0053-stmmac-form-4-13.patch +++ /dev/null @@ -1,1923 +0,0 @@ ---- a/drivers/net/ethernet/stmicro/stmmac/Kconfig -+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig -@@ -145,6 +145,17 @@ config DWMAC_SUNXI - This selects Allwinner SoC glue layer support for the - stmmac device driver. This driver is used for A20/A31 - GMAC ethernet controller. -+ -+config DWMAC_SUN8I -+ tristate "Allwinner sun8i GMAC support" -+ default ARCH_SUNXI -+ depends on OF && (ARCH_SUNXI || COMPILE_TEST) -+ ---help--- -+ Support for Allwinner H3 A83T A64 EMAC ethernet controllers. -+ -+ This selects Allwinner SoC glue layer support for the -+ stmmac device driver. This driver is used for H3/A83T/A64 -+ EMAC ethernet controller. - endif - - config STMMAC_PCI ---- a/drivers/net/ethernet/stmicro/stmmac/Makefile -+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-alt - obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o - obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o - obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o -+obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o - obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o - obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o - stmmac-platform-objs:= stmmac_platform.o ---- a/drivers/net/ethernet/stmicro/stmmac/common.h -+++ b/drivers/net/ethernet/stmicro/stmmac/common.h -@@ -549,9 +549,11 @@ extern const struct stmmac_hwtimestamp s - extern const struct stmmac_mode_ops dwmac4_ring_mode_ops; - - struct mac_link { -- int port; -- int duplex; -- int speed; -+ u32 speed_mask; -+ u32 speed10; -+ u32 speed100; -+ u32 speed1000; -+ u32 duplex; - }; - - struct mii_regs { ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c -@@ -270,7 +270,10 @@ static int socfpga_dwmac_set_phy_mode(st - ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); - ctrl |= val << reg_shift; - -- if (dwmac->f2h_ptp_ref_clk) { -+ if (dwmac->f2h_ptp_ref_clk || -+ phymode == PHY_INTERFACE_MODE_MII || -+ phymode == PHY_INTERFACE_MODE_GMII || -+ phymode == PHY_INTERFACE_MODE_SGMII) { - ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2); - regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG, - &module); ---- /dev/null -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c -@@ -0,0 +1,1007 @@ -+/* -+ * dwmac-sun8i.c - Allwinner sun8i DWMAC specific glue layer -+ * -+ * Copyright (C) 2017 Corentin Labbe -+ * -+ * 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 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 "stmmac.h" -+#include "stmmac_platform.h" -+ -+/* General notes on dwmac-sun8i: -+ * Locking: no locking is necessary in this file because all necessary locking -+ * is done in the "stmmac files" -+ */ -+ -+/* struct emac_variant - Descrive dwmac-sun8i hardware variant -+ * @default_syscon_value: The default value of the EMAC register in syscon -+ * This value is used for disabling properly EMAC -+ * and used as a good starting value in case of the -+ * boot process(uboot) leave some stuff. -+ * @internal_phy: Does the MAC embed an internal PHY -+ * @support_mii: Does the MAC handle MII -+ * @support_rmii: Does the MAC handle RMII -+ * @support_rgmii: Does the MAC handle RGMII -+ */ -+struct emac_variant { -+ u32 default_syscon_value; -+ int internal_phy; -+ bool support_mii; -+ bool support_rmii; -+ bool support_rgmii; -+}; -+ -+/* struct sunxi_priv_data - hold all sunxi private data -+ * @tx_clk: reference to MAC TX clock -+ * @ephy_clk: reference to the optional EPHY clock for the internal PHY -+ * @regulator: reference to the optional regulator -+ * @rst_ephy: reference to the optional EPHY reset for the internal PHY -+ * @variant: reference to the current board variant -+ * @regmap: regmap for using the syscon -+ * @use_internal_phy: Does the current PHY choice imply using the internal PHY -+ */ -+struct sunxi_priv_data { -+ struct clk *tx_clk; -+ struct clk *ephy_clk; -+ struct regulator *regulator; -+ struct reset_control *rst_ephy; -+ const struct emac_variant *variant; -+ struct regmap *regmap; -+ bool use_internal_phy; -+}; -+ -+static const struct emac_variant emac_variant_h3 = { -+ .default_syscon_value = 0x58000, -+ .internal_phy = PHY_INTERFACE_MODE_MII, -+ .support_mii = true, -+ .support_rmii = true, -+ .support_rgmii = true -+}; -+ -+static const struct emac_variant emac_variant_v3s = { -+ .default_syscon_value = 0x38000, -+ .internal_phy = PHY_INTERFACE_MODE_MII, -+ .support_mii = true -+}; -+ -+static const struct emac_variant emac_variant_a83t = { -+ .default_syscon_value = 0, -+ .internal_phy = 0, -+ .support_mii = true, -+ .support_rgmii = true -+}; -+ -+static const struct emac_variant emac_variant_a64 = { -+ .default_syscon_value = 0, -+ .internal_phy = 0, -+ .support_mii = true, -+ .support_rmii = true, -+ .support_rgmii = true -+}; -+ -+#define EMAC_BASIC_CTL0 0x00 -+#define EMAC_BASIC_CTL1 0x04 -+#define EMAC_INT_STA 0x08 -+#define EMAC_INT_EN 0x0C -+#define EMAC_TX_CTL0 0x10 -+#define EMAC_TX_CTL1 0x14 -+#define EMAC_TX_FLOW_CTL 0x1C -+#define EMAC_TX_DESC_LIST 0x20 -+#define EMAC_RX_CTL0 0x24 -+#define EMAC_RX_CTL1 0x28 -+#define EMAC_RX_DESC_LIST 0x34 -+#define EMAC_RX_FRM_FLT 0x38 -+#define EMAC_MDIO_CMD 0x48 -+#define EMAC_MDIO_DATA 0x4C -+#define EMAC_MACADDR_HI(reg) (0x50 + (reg) * 8) -+#define EMAC_MACADDR_LO(reg) (0x54 + (reg) * 8) -+#define EMAC_TX_DMA_STA 0xB0 -+#define EMAC_TX_CUR_DESC 0xB4 -+#define EMAC_TX_CUR_BUF 0xB8 -+#define EMAC_RX_DMA_STA 0xC0 -+#define EMAC_RX_CUR_DESC 0xC4 -+#define EMAC_RX_CUR_BUF 0xC8 -+ -+/* Use in EMAC_BASIC_CTL0 */ -+#define EMAC_DUPLEX_FULL BIT(0) -+#define EMAC_LOOPBACK BIT(1) -+#define EMAC_SPEED_1000 0 -+#define EMAC_SPEED_100 (0x03 << 2) -+#define EMAC_SPEED_10 (0x02 << 2) -+ -+/* Use in EMAC_BASIC_CTL1 */ -+#define EMAC_BURSTLEN_SHIFT 24 -+ -+/* Used in EMAC_RX_FRM_FLT */ -+#define EMAC_FRM_FLT_RXALL BIT(0) -+#define EMAC_FRM_FLT_CTL BIT(13) -+#define EMAC_FRM_FLT_MULTICAST BIT(16) -+ -+/* Used in RX_CTL1*/ -+#define EMAC_RX_MD BIT(1) -+#define EMAC_RX_TH_MASK GENMASK(4, 5) -+#define EMAC_RX_TH_32 0 -+#define EMAC_RX_TH_64 (0x1 << 4) -+#define EMAC_RX_TH_96 (0x2 << 4) -+#define EMAC_RX_TH_128 (0x3 << 4) -+#define EMAC_RX_DMA_EN BIT(30) -+#define EMAC_RX_DMA_START BIT(31) -+ -+/* Used in TX_CTL1*/ -+#define EMAC_TX_MD BIT(1) -+#define EMAC_TX_NEXT_FRM BIT(2) -+#define EMAC_TX_TH_MASK GENMASK(8, 10) -+#define EMAC_TX_TH_64 0 -+#define EMAC_TX_TH_128 (0x1 << 8) -+#define EMAC_TX_TH_192 (0x2 << 8) -+#define EMAC_TX_TH_256 (0x3 << 8) -+#define EMAC_TX_DMA_EN BIT(30) -+#define EMAC_TX_DMA_START BIT(31) -+ -+/* Used in RX_CTL0 */ -+#define EMAC_RX_RECEIVER_EN BIT(31) -+#define EMAC_RX_DO_CRC BIT(27) -+#define EMAC_RX_FLOW_CTL_EN BIT(16) -+ -+/* Used in TX_CTL0 */ -+#define EMAC_TX_TRANSMITTER_EN BIT(31) -+ -+/* Used in EMAC_TX_FLOW_CTL */ -+#define EMAC_TX_FLOW_CTL_EN BIT(0) -+ -+/* Used in EMAC_INT_STA */ -+#define EMAC_TX_INT BIT(0) -+#define EMAC_TX_DMA_STOP_INT BIT(1) -+#define EMAC_TX_BUF_UA_INT BIT(2) -+#define EMAC_TX_TIMEOUT_INT BIT(3) -+#define EMAC_TX_UNDERFLOW_INT BIT(4) -+#define EMAC_TX_EARLY_INT BIT(5) -+#define EMAC_RX_INT BIT(8) -+#define EMAC_RX_BUF_UA_INT BIT(9) -+#define EMAC_RX_DMA_STOP_INT BIT(10) -+#define EMAC_RX_TIMEOUT_INT BIT(11) -+#define EMAC_RX_OVERFLOW_INT BIT(12) -+#define EMAC_RX_EARLY_INT BIT(13) -+#define EMAC_RGMII_STA_INT BIT(16) -+ -+#define MAC_ADDR_TYPE_DST BIT(31) -+ -+/* H3 specific bits for EPHY */ -+#define H3_EPHY_ADDR_SHIFT 20 -+#define H3_EPHY_CLK_SEL BIT(18) /* 1: 24MHz, 0: 25MHz */ -+#define H3_EPHY_LED_POL BIT(17) /* 1: active low, 0: active high */ -+#define H3_EPHY_SHUTDOWN BIT(16) /* 1: shutdown, 0: power up */ -+#define H3_EPHY_SELECT BIT(15) /* 1: internal PHY, 0: external PHY */ -+ -+/* H3/A64 specific bits */ -+#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */ -+ -+/* Generic system control EMAC_CLK bits */ -+#define SYSCON_ETXDC_MASK GENMASK(2, 0) -+#define SYSCON_ETXDC_SHIFT 10 -+#define SYSCON_ERXDC_MASK GENMASK(4, 0) -+#define SYSCON_ERXDC_SHIFT 5 -+/* EMAC PHY Interface Type */ -+#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */ -+#define SYSCON_ETCS_MASK GENMASK(1, 0) -+#define SYSCON_ETCS_MII 0x0 -+#define SYSCON_ETCS_EXT_GMII 0x1 -+#define SYSCON_ETCS_INT_GMII 0x2 -+#define SYSCON_EMAC_REG 0x30 -+ -+/* sun8i_dwmac_dma_reset() - reset the EMAC -+ * Called from stmmac via stmmac_dma_ops->reset -+ */ -+static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) -+{ -+ writel(0, ioaddr + EMAC_RX_CTL1); -+ writel(0, ioaddr + EMAC_TX_CTL1); -+ writel(0, ioaddr + EMAC_RX_FRM_FLT); -+ writel(0, ioaddr + EMAC_RX_DESC_LIST); -+ writel(0, ioaddr + EMAC_TX_DESC_LIST); -+ writel(0, ioaddr + EMAC_INT_EN); -+ writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); -+ return 0; -+} -+ -+/* sun8i_dwmac_dma_init() - initialize the EMAC -+ * Called from stmmac via stmmac_dma_ops->init -+ */ -+static void sun8i_dwmac_dma_init(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx, u32 dma_rx, int atds) -+{ -+ /* Write TX and RX descriptors address */ -+ writel(dma_rx, ioaddr + EMAC_RX_DESC_LIST); -+ writel(dma_tx, ioaddr + EMAC_TX_DESC_LIST); -+ -+ writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN); -+ writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); -+} -+ -+/* sun8i_dwmac_dump_regs() - Dump EMAC address space -+ * Called from stmmac_dma_ops->dump_regs -+ * Used for ethtool -+ */ -+static void sun8i_dwmac_dump_regs(void __iomem *ioaddr, u32 *reg_space) -+{ -+ int i; -+ -+ for (i = 0; i < 0xC8; i += 4) { -+ if (i == 0x32 || i == 0x3C) -+ continue; -+ reg_space[i / 4] = readl(ioaddr + i); -+ } -+} -+ -+/* sun8i_dwmac_dump_mac_regs() - Dump EMAC address space -+ * Called from stmmac_ops->dump_regs -+ * Used for ethtool -+ */ -+static void sun8i_dwmac_dump_mac_regs(struct mac_device_info *hw, -+ u32 *reg_space) -+{ -+ int i; -+ void __iomem *ioaddr = hw->pcsr; -+ -+ for (i = 0; i < 0xC8; i += 4) { -+ if (i == 0x32 || i == 0x3C) -+ continue; -+ reg_space[i / 4] = readl(ioaddr + i); -+ } -+} -+ -+static void sun8i_dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan) -+{ -+ writel(EMAC_RX_INT | EMAC_TX_INT, ioaddr + EMAC_INT_EN); -+} -+ -+static void sun8i_dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan) -+{ -+ writel(0, ioaddr + EMAC_INT_EN); -+} -+ -+static void sun8i_dwmac_dma_start_tx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v |= EMAC_TX_DMA_START; -+ v |= EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_enable_dma_transmission(void __iomem *ioaddr) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v |= EMAC_TX_DMA_START; -+ v |= EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_stop_tx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ v &= ~EMAC_TX_DMA_EN; -+ writel(v, ioaddr + EMAC_TX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_start_rx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ v |= EMAC_RX_DMA_START; -+ v |= EMAC_RX_DMA_EN; -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static void sun8i_dwmac_dma_stop_rx(void __iomem *ioaddr, u32 chan) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ v &= ~EMAC_RX_DMA_EN; -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static int sun8i_dwmac_dma_interrupt(void __iomem *ioaddr, -+ struct stmmac_extra_stats *x, u32 chan) -+{ -+ u32 v; -+ int ret = 0; -+ -+ v = readl(ioaddr + EMAC_INT_STA); -+ -+ if (v & EMAC_TX_INT) { -+ ret |= handle_tx; -+ x->tx_normal_irq_n++; -+ } -+ -+ if (v & EMAC_TX_DMA_STOP_INT) -+ x->tx_process_stopped_irq++; -+ -+ if (v & EMAC_TX_BUF_UA_INT) -+ x->tx_process_stopped_irq++; -+ -+ if (v & EMAC_TX_TIMEOUT_INT) -+ ret |= tx_hard_error; -+ -+ if (v & EMAC_TX_UNDERFLOW_INT) { -+ ret |= tx_hard_error; -+ x->tx_undeflow_irq++; -+ } -+ -+ if (v & EMAC_TX_EARLY_INT) -+ x->tx_early_irq++; -+ -+ if (v & EMAC_RX_INT) { -+ ret |= handle_rx; -+ x->rx_normal_irq_n++; -+ } -+ -+ if (v & EMAC_RX_BUF_UA_INT) -+ x->rx_buf_unav_irq++; -+ -+ if (v & EMAC_RX_DMA_STOP_INT) -+ x->rx_process_stopped_irq++; -+ -+ if (v & EMAC_RX_TIMEOUT_INT) -+ ret |= tx_hard_error; -+ -+ if (v & EMAC_RX_OVERFLOW_INT) { -+ ret |= tx_hard_error; -+ x->rx_overflow_irq++; -+ } -+ -+ if (v & EMAC_RX_EARLY_INT) -+ x->rx_early_irq++; -+ -+ if (v & EMAC_RGMII_STA_INT) -+ x->irq_rgmii_n++; -+ -+ writel(v, ioaddr + EMAC_INT_STA); -+ -+ return ret; -+} -+ -+static void sun8i_dwmac_dma_operation_mode(void __iomem *ioaddr, int txmode, -+ int rxmode, int rxfifosz) -+{ -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_TX_CTL1); -+ if (txmode == SF_DMA_MODE) { -+ v |= EMAC_TX_MD; -+ /* Undocumented bit (called TX_NEXT_FRM in BSP), the original -+ * comment is -+ * "Operating on second frame increase the performance -+ * especially when transmit store-and-forward is used." -+ */ -+ v |= EMAC_TX_NEXT_FRM; -+ } else { -+ v &= ~EMAC_TX_MD; -+ v &= ~EMAC_TX_TH_MASK; -+ if (txmode < 64) -+ v |= EMAC_TX_TH_64; -+ else if (txmode < 128) -+ v |= EMAC_TX_TH_128; -+ else if (txmode < 192) -+ v |= EMAC_TX_TH_192; -+ else if (txmode < 256) -+ v |= EMAC_TX_TH_256; -+ } -+ writel(v, ioaddr + EMAC_TX_CTL1); -+ -+ v = readl(ioaddr + EMAC_RX_CTL1); -+ if (rxmode == SF_DMA_MODE) { -+ v |= EMAC_RX_MD; -+ } else { -+ v &= ~EMAC_RX_MD; -+ v &= ~EMAC_RX_TH_MASK; -+ if (rxmode < 32) -+ v |= EMAC_RX_TH_32; -+ else if (rxmode < 64) -+ v |= EMAC_RX_TH_64; -+ else if (rxmode < 96) -+ v |= EMAC_RX_TH_96; -+ else if (rxmode < 128) -+ v |= EMAC_RX_TH_128; -+ } -+ writel(v, ioaddr + EMAC_RX_CTL1); -+} -+ -+static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = { -+ .reset = sun8i_dwmac_dma_reset, -+ .init = sun8i_dwmac_dma_init, -+ .dump_regs = sun8i_dwmac_dump_regs, -+ .dma_mode = sun8i_dwmac_dma_operation_mode, -+ .enable_dma_transmission = sun8i_dwmac_enable_dma_transmission, -+ .enable_dma_irq = sun8i_dwmac_enable_dma_irq, -+ .disable_dma_irq = sun8i_dwmac_disable_dma_irq, -+ .start_tx = sun8i_dwmac_dma_start_tx, -+ .stop_tx = sun8i_dwmac_dma_stop_tx, -+ .start_rx = sun8i_dwmac_dma_start_rx, -+ .stop_rx = sun8i_dwmac_dma_stop_rx, -+ .dma_interrupt = sun8i_dwmac_dma_interrupt, -+}; -+ -+static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) -+{ -+ struct sunxi_priv_data *gmac = priv; -+ int ret; -+ -+ if (gmac->regulator) { -+ ret = regulator_enable(gmac->regulator); -+ if (ret) { -+ dev_err(&pdev->dev, "Fail to enable regulator\n"); -+ return ret; -+ } -+ } -+ -+ ret = clk_prepare_enable(gmac->tx_clk); -+ if (ret) { -+ if (gmac->regulator) -+ regulator_disable(gmac->regulator); -+ dev_err(&pdev->dev, "Could not enable AHB clock\n"); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static void sun8i_dwmac_core_init(struct mac_device_info *hw, int mtu) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = (8 << EMAC_BURSTLEN_SHIFT); /* burst len */ -+ writel(v, ioaddr + EMAC_BASIC_CTL1); -+} -+ -+static void sun8i_dwmac_set_mac(void __iomem *ioaddr, bool enable) -+{ -+ u32 t, r; -+ -+ t = readl(ioaddr + EMAC_TX_CTL0); -+ r = readl(ioaddr + EMAC_RX_CTL0); -+ if (enable) { -+ t |= EMAC_TX_TRANSMITTER_EN; -+ r |= EMAC_RX_RECEIVER_EN; -+ } else { -+ t &= ~EMAC_TX_TRANSMITTER_EN; -+ r &= ~EMAC_RX_RECEIVER_EN; -+ } -+ writel(t, ioaddr + EMAC_TX_CTL0); -+ writel(r, ioaddr + EMAC_RX_CTL0); -+} -+ -+/* Set MAC address at slot reg_n -+ * All slot > 0 need to be enabled with MAC_ADDR_TYPE_DST -+ * If addr is NULL, clear the slot -+ */ -+static void sun8i_dwmac_set_umac_addr(struct mac_device_info *hw, -+ unsigned char *addr, -+ unsigned int reg_n) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ if (!addr) { -+ writel(0, ioaddr + EMAC_MACADDR_HI(reg_n)); -+ return; -+ } -+ -+ stmmac_set_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n), -+ EMAC_MACADDR_LO(reg_n)); -+ if (reg_n > 0) { -+ v = readl(ioaddr + EMAC_MACADDR_HI(reg_n)); -+ v |= MAC_ADDR_TYPE_DST; -+ writel(v, ioaddr + EMAC_MACADDR_HI(reg_n)); -+ } -+} -+ -+static void sun8i_dwmac_get_umac_addr(struct mac_device_info *hw, -+ unsigned char *addr, -+ unsigned int reg_n) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ -+ stmmac_get_mac_addr(ioaddr, addr, EMAC_MACADDR_HI(reg_n), -+ EMAC_MACADDR_LO(reg_n)); -+} -+ -+/* caution this function must return non 0 to work */ -+static int sun8i_dwmac_rx_ipc_enable(struct mac_device_info *hw) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL0); -+ v |= EMAC_RX_DO_CRC; -+ writel(v, ioaddr + EMAC_RX_CTL0); -+ -+ return 1; -+} -+ -+static void sun8i_dwmac_set_filter(struct mac_device_info *hw, -+ struct net_device *dev) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ int i = 1; -+ struct netdev_hw_addr *ha; -+ int macaddrs = netdev_uc_count(dev) + netdev_mc_count(dev) + 1; -+ -+ v = EMAC_FRM_FLT_CTL; -+ -+ if (dev->flags & IFF_PROMISC) { -+ v = EMAC_FRM_FLT_RXALL; -+ } else if (dev->flags & IFF_ALLMULTI) { -+ v |= EMAC_FRM_FLT_MULTICAST; -+ } else if (macaddrs <= hw->unicast_filter_entries) { -+ if (!netdev_mc_empty(dev)) { -+ netdev_for_each_mc_addr(ha, dev) { -+ sun8i_dwmac_set_umac_addr(hw, ha->addr, i); -+ i++; -+ } -+ } -+ if (!netdev_uc_empty(dev)) { -+ netdev_for_each_uc_addr(ha, dev) { -+ sun8i_dwmac_set_umac_addr(hw, ha->addr, i); -+ i++; -+ } -+ } -+ } else { -+ netdev_info(dev, "Too many address, switching to promiscuous\n"); -+ v = EMAC_FRM_FLT_RXALL; -+ } -+ -+ /* Disable unused address filter slots */ -+ while (i < hw->unicast_filter_entries) -+ sun8i_dwmac_set_umac_addr(hw, NULL, i++); -+ -+ writel(v, ioaddr + EMAC_RX_FRM_FLT); -+} -+ -+static void sun8i_dwmac_flow_ctrl(struct mac_device_info *hw, -+ unsigned int duplex, unsigned int fc, -+ unsigned int pause_time, u32 tx_cnt) -+{ -+ void __iomem *ioaddr = hw->pcsr; -+ u32 v; -+ -+ v = readl(ioaddr + EMAC_RX_CTL0); -+ if (fc == FLOW_AUTO) -+ v |= EMAC_RX_FLOW_CTL_EN; -+ else -+ v &= ~EMAC_RX_FLOW_CTL_EN; -+ writel(v, ioaddr + EMAC_RX_CTL0); -+ -+ v = readl(ioaddr + EMAC_TX_FLOW_CTL); -+ if (fc == FLOW_AUTO) -+ v |= EMAC_TX_FLOW_CTL_EN; -+ else -+ v &= ~EMAC_TX_FLOW_CTL_EN; -+ writel(v, ioaddr + EMAC_TX_FLOW_CTL); -+} -+ -+static int sun8i_dwmac_reset(struct stmmac_priv *priv) -+{ -+ u32 v; -+ int err; -+ -+ v = readl(priv->ioaddr + EMAC_BASIC_CTL1); -+ writel(v | 0x01, priv->ioaddr + EMAC_BASIC_CTL1); -+ -+ /* The timeout was previoulsy set to 10ms, but some board (OrangePI0) -+ * need more if no cable plugged. 100ms seems OK -+ */ -+ err = readl_poll_timeout(priv->ioaddr + EMAC_BASIC_CTL1, v, -+ !(v & 0x01), 100, 100000); -+ -+ if (err) { -+ dev_err(priv->device, "EMAC reset timeout\n"); -+ return -EFAULT; -+ } -+ return 0; -+} -+ -+static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) -+{ -+ struct sunxi_priv_data *gmac = priv->plat->bsp_priv; -+ struct device_node *node = priv->device->of_node; -+ int ret; -+ u32 reg, val; -+ -+ regmap_read(gmac->regmap, SYSCON_EMAC_REG, &val); -+ reg = gmac->variant->default_syscon_value; -+ if (reg != val) -+ dev_warn(priv->device, -+ "Current syscon value is not the default %x (expect %x)\n", -+ val, reg); -+ -+ if (gmac->variant->internal_phy) { -+ if (!gmac->use_internal_phy) { -+ /* switch to external PHY interface */ -+ reg &= ~H3_EPHY_SELECT; -+ } else { -+ reg |= H3_EPHY_SELECT; -+ reg &= ~H3_EPHY_SHUTDOWN; -+ dev_dbg(priv->device, "Select internal_phy %x\n", reg); -+ -+ if (of_property_read_bool(priv->plat->phy_node, -+ "allwinner,leds-active-low")) -+ reg |= H3_EPHY_LED_POL; -+ else -+ reg &= ~H3_EPHY_LED_POL; -+ -+ /* Force EPHY xtal frequency to 24MHz. */ -+ reg |= H3_EPHY_CLK_SEL; -+ -+ ret = of_mdio_parse_addr(priv->device, -+ priv->plat->phy_node); -+ if (ret < 0) { -+ dev_err(priv->device, "Could not parse MDIO addr\n"); -+ return ret; -+ } -+ /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY -+ * address. No need to mask it again. -+ */ -+ reg |= ret << H3_EPHY_ADDR_SHIFT; -+ } -+ } -+ -+ if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) { -+ if (val % 100) { -+ dev_err(priv->device, "tx-delay must be a multiple of 100\n"); -+ return -EINVAL; -+ } -+ val /= 100; -+ dev_dbg(priv->device, "set tx-delay to %x\n", val); -+ if (val <= SYSCON_ETXDC_MASK) { -+ reg &= ~(SYSCON_ETXDC_MASK << SYSCON_ETXDC_SHIFT); -+ reg |= (val << SYSCON_ETXDC_SHIFT); -+ } else { -+ dev_err(priv->device, "Invalid TX clock delay: %d\n", -+ val); -+ return -EINVAL; -+ } -+ } -+ -+ if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) { -+ if (val % 100) { -+ dev_err(priv->device, "rx-delay must be a multiple of 100\n"); -+ return -EINVAL; -+ } -+ val /= 100; -+ dev_dbg(priv->device, "set rx-delay to %x\n", val); -+ if (val <= SYSCON_ERXDC_MASK) { -+ reg &= ~(SYSCON_ERXDC_MASK << SYSCON_ERXDC_SHIFT); -+ reg |= (val << SYSCON_ERXDC_SHIFT); -+ } else { -+ dev_err(priv->device, "Invalid RX clock delay: %d\n", -+ val); -+ return -EINVAL; -+ } -+ } -+ -+ /* Clear interface mode bits */ -+ reg &= ~(SYSCON_ETCS_MASK | SYSCON_EPIT); -+ if (gmac->variant->support_rmii) -+ reg &= ~SYSCON_RMII_EN; -+ -+ switch (priv->plat->interface) { -+ case PHY_INTERFACE_MODE_MII: -+ /* default */ -+ break; -+ case PHY_INTERFACE_MODE_RGMII: -+ reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII; -+ break; -+ case PHY_INTERFACE_MODE_RMII: -+ reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII; -+ break; -+ default: -+ dev_err(priv->device, "Unsupported interface mode: %s", -+ phy_modes(priv->plat->interface)); -+ return -EINVAL; -+ } -+ -+ regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); -+ -+ return 0; -+} -+ -+static void sun8i_dwmac_unset_syscon(struct sunxi_priv_data *gmac) -+{ -+ u32 reg = gmac->variant->default_syscon_value; -+ -+ regmap_write(gmac->regmap, SYSCON_EMAC_REG, reg); -+} -+ -+static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv) -+{ -+ struct sunxi_priv_data *gmac = priv->plat->bsp_priv; -+ int ret; -+ -+ if (!gmac->use_internal_phy) -+ return 0; -+ -+ ret = clk_prepare_enable(gmac->ephy_clk); -+ if (ret) { -+ dev_err(priv->device, "Cannot enable ephy\n"); -+ return ret; -+ } -+ -+ /* Make sure the EPHY is properly reseted, as U-Boot may leave -+ * it at deasserted state, and thus it may fail to reset EMAC. -+ */ -+ reset_control_assert(gmac->rst_ephy); -+ -+ ret = reset_control_deassert(gmac->rst_ephy); -+ if (ret) { -+ dev_err(priv->device, "Cannot deassert ephy\n"); -+ clk_disable_unprepare(gmac->ephy_clk); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int sun8i_dwmac_unpower_internal_phy(struct sunxi_priv_data *gmac) -+{ -+ if (!gmac->use_internal_phy) -+ return 0; -+ -+ clk_disable_unprepare(gmac->ephy_clk); -+ reset_control_assert(gmac->rst_ephy); -+ return 0; -+} -+ -+/* sun8i_power_phy() - Activate the PHY: -+ * In case of error, no need to call sun8i_unpower_phy(), -+ * it will be called anyway by sun8i_dwmac_exit() -+ */ -+static int sun8i_power_phy(struct stmmac_priv *priv) -+{ -+ int ret; -+ -+ ret = sun8i_dwmac_power_internal_phy(priv); -+ if (ret) -+ return ret; -+ -+ ret = sun8i_dwmac_set_syscon(priv); -+ if (ret) -+ return ret; -+ -+ /* After changing syscon value, the MAC need reset or it will use -+ * the last value (and so the last PHY set. -+ */ -+ ret = sun8i_dwmac_reset(priv); -+ if (ret) -+ return ret; -+ return 0; -+} -+ -+static void sun8i_unpower_phy(struct sunxi_priv_data *gmac) -+{ -+ sun8i_dwmac_unset_syscon(gmac); -+ sun8i_dwmac_unpower_internal_phy(gmac); -+} -+ -+static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) -+{ -+ struct sunxi_priv_data *gmac = priv; -+ -+ sun8i_unpower_phy(gmac); -+ -+ clk_disable_unprepare(gmac->tx_clk); -+ -+ if (gmac->regulator) -+ regulator_disable(gmac->regulator); -+} -+ -+static const struct stmmac_ops sun8i_dwmac_ops = { -+ .core_init = sun8i_dwmac_core_init, -+ .set_mac = sun8i_dwmac_set_mac, -+ .dump_regs = sun8i_dwmac_dump_mac_regs, -+ .rx_ipc = sun8i_dwmac_rx_ipc_enable, -+ .set_filter = sun8i_dwmac_set_filter, -+ .flow_ctrl = sun8i_dwmac_flow_ctrl, -+ .set_umac_addr = sun8i_dwmac_set_umac_addr, -+ .get_umac_addr = sun8i_dwmac_get_umac_addr, -+}; -+ -+static struct mac_device_info *sun8i_dwmac_setup(void *ppriv) -+{ -+ struct mac_device_info *mac; -+ struct stmmac_priv *priv = ppriv; -+ int ret; -+ -+ mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL); -+ if (!mac) -+ return NULL; -+ -+ ret = sun8i_power_phy(priv); -+ if (ret) -+ return NULL; -+ -+ mac->pcsr = priv->ioaddr; -+ mac->mac = &sun8i_dwmac_ops; -+ mac->dma = &sun8i_dwmac_dma_ops; -+ -+ /* The loopback bit seems to be re-set when link change -+ * Simply mask it each time -+ * Speed 10/100/1000 are set in BIT(2)/BIT(3) -+ */ -+ mac->link.speed_mask = GENMASK(3, 2) | EMAC_LOOPBACK; -+ mac->link.speed10 = EMAC_SPEED_10; -+ mac->link.speed100 = EMAC_SPEED_100; -+ mac->link.speed1000 = EMAC_SPEED_1000; -+ mac->link.duplex = EMAC_DUPLEX_FULL; -+ mac->mii.addr = EMAC_MDIO_CMD; -+ mac->mii.data = EMAC_MDIO_DATA; -+ mac->mii.reg_shift = 4; -+ mac->mii.reg_mask = GENMASK(8, 4); -+ mac->mii.addr_shift = 12; -+ mac->mii.addr_mask = GENMASK(16, 12); -+ mac->mii.clk_csr_shift = 20; -+ mac->mii.clk_csr_mask = GENMASK(22, 20); -+ mac->unicast_filter_entries = 8; -+ -+ /* Synopsys Id is not available */ -+ priv->synopsys_id = 0; -+ -+ return mac; -+} -+ -+static int sun8i_dwmac_probe(struct platform_device *pdev) -+{ -+ struct plat_stmmacenet_data *plat_dat; -+ struct stmmac_resources stmmac_res; -+ struct sunxi_priv_data *gmac; -+ struct device *dev = &pdev->dev; -+ int ret; -+ -+ ret = stmmac_get_platform_resources(pdev, &stmmac_res); -+ if (ret) -+ return ret; -+ -+ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); -+ if (IS_ERR(plat_dat)) -+ return PTR_ERR(plat_dat); -+ -+ gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); -+ if (!gmac) -+ return -ENOMEM; -+ -+ gmac->variant = of_device_get_match_data(&pdev->dev); -+ if (!gmac->variant) { -+ dev_err(&pdev->dev, "Missing dwmac-sun8i variant\n"); -+ return -EINVAL; -+ } -+ -+ gmac->tx_clk = devm_clk_get(dev, "stmmaceth"); -+ if (IS_ERR(gmac->tx_clk)) { -+ dev_err(dev, "Could not get TX clock\n"); -+ return PTR_ERR(gmac->tx_clk); -+ } -+ -+ /* Optional regulator for PHY */ -+ gmac->regulator = devm_regulator_get_optional(dev, "phy"); -+ if (IS_ERR(gmac->regulator)) { -+ if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; -+ dev_info(dev, "No regulator found\n"); -+ gmac->regulator = NULL; -+ } -+ -+ gmac->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, -+ "syscon"); -+ if (IS_ERR(gmac->regmap)) { -+ ret = PTR_ERR(gmac->regmap); -+ dev_err(&pdev->dev, "Unable to map syscon: %d\n", ret); -+ return ret; -+ } -+ -+ plat_dat->interface = of_get_phy_mode(dev->of_node); -+ if (plat_dat->interface == gmac->variant->internal_phy) { -+ dev_info(&pdev->dev, "Will use internal PHY\n"); -+ gmac->use_internal_phy = true; -+ gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0); -+ if (IS_ERR(gmac->ephy_clk)) { -+ ret = PTR_ERR(gmac->ephy_clk); -+ dev_err(&pdev->dev, "Cannot get EPHY clock: %d\n", ret); -+ return -EINVAL; -+ } -+ -+ gmac->rst_ephy = of_reset_control_get(plat_dat->phy_node, NULL); -+ if (IS_ERR(gmac->rst_ephy)) { -+ ret = PTR_ERR(gmac->rst_ephy); -+ if (ret == -EPROBE_DEFER) -+ return ret; -+ dev_err(&pdev->dev, "No EPHY reset control found %d\n", -+ ret); -+ return -EINVAL; -+ } -+ } else { -+ dev_info(&pdev->dev, "Will use external PHY\n"); -+ gmac->use_internal_phy = false; -+ } -+ -+ /* platform data specifying hardware features and callbacks. -+ * hardware features were copied from Allwinner drivers. -+ */ -+ plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; -+ plat_dat->tx_coe = 1; -+ plat_dat->has_sun8i = true; -+ plat_dat->bsp_priv = gmac; -+ plat_dat->init = sun8i_dwmac_init; -+ plat_dat->exit = sun8i_dwmac_exit; -+ plat_dat->setup = sun8i_dwmac_setup; -+ -+ ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); -+ if (ret) -+ return ret; -+ -+ ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); -+ if (ret) -+ sun8i_dwmac_exit(pdev, plat_dat->bsp_priv); -+ -+ return ret; -+} -+ -+static const struct of_device_id sun8i_dwmac_match[] = { -+ { .compatible = "allwinner,sun8i-h3-emac", -+ .data = &emac_variant_h3 }, -+ { .compatible = "allwinner,sun8i-v3s-emac", -+ .data = &emac_variant_v3s }, -+ { .compatible = "allwinner,sun8i-a83t-emac", -+ .data = &emac_variant_a83t }, -+ { .compatible = "allwinner,sun50i-a64-emac", -+ .data = &emac_variant_a64 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); -+ -+static struct platform_driver sun8i_dwmac_driver = { -+ .probe = sun8i_dwmac_probe, -+ .remove = stmmac_pltfr_remove, -+ .driver = { -+ .name = "dwmac-sun8i", -+ .pm = &stmmac_pltfr_pm_ops, -+ .of_match_table = sun8i_dwmac_match, -+ }, -+}; -+module_platform_driver(sun8i_dwmac_driver); -+ -+MODULE_AUTHOR("Corentin Labbe "); -+MODULE_DESCRIPTION("Allwinner sun8i DWMAC specific glue layer"); -+MODULE_LICENSE("GPL"); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c -@@ -45,15 +45,17 @@ static void dwmac1000_core_init(struct m - if (hw->ps) { - value |= GMAC_CONTROL_TE; - -- if (hw->ps == SPEED_1000) { -- value &= ~GMAC_CONTROL_PS; -- } else { -- value |= GMAC_CONTROL_PS; -- -- if (hw->ps == SPEED_10) -- value &= ~GMAC_CONTROL_FES; -- else -- value |= GMAC_CONTROL_FES; -+ value &= ~hw->link.speed_mask; -+ switch (hw->ps) { -+ case SPEED_1000: -+ value |= hw->link.speed1000; -+ break; -+ case SPEED_100: -+ value |= hw->link.speed100; -+ break; -+ case SPEED_10: -+ value |= hw->link.speed10; -+ break; - } - } - -@@ -531,9 +533,11 @@ struct mac_device_info *dwmac1000_setup( - mac->mac = &dwmac1000_ops; - mac->dma = &dwmac1000_dma_ops; - -- mac->link.port = GMAC_CONTROL_PS; - mac->link.duplex = GMAC_CONTROL_DM; -- mac->link.speed = GMAC_CONTROL_FES; -+ mac->link.speed10 = GMAC_CONTROL_PS; -+ mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES; -+ mac->link.speed1000 = 0; -+ mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES; - mac->mii.addr = GMAC_MII_ADDR; - mac->mii.data = GMAC_MII_DATA; - mac->mii.addr_shift = 11; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c -@@ -205,8 +205,8 @@ static void dwmac1000_dump_dma_regs(void - { - int i; - -- for (i = 0; i < 22; i++) -- if ((i < 9) || (i > 17)) -+ for (i = 0; i < NUM_DWMAC1000_DMA_REGS; i++) -+ if ((i < 12) || (i > 17)) - reg_space[DMA_BUS_MODE / 4 + i] = - readl(ioaddr + DMA_BUS_MODE + i * 4); - } ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c -@@ -175,9 +175,11 @@ struct mac_device_info *dwmac100_setup(v - mac->mac = &dwmac100_ops; - mac->dma = &dwmac100_dma_ops; - -- mac->link.port = MAC_CONTROL_PS; - mac->link.duplex = MAC_CONTROL_F; -- mac->link.speed = 0; -+ mac->link.speed10 = 0; -+ mac->link.speed100 = 0; -+ mac->link.speed1000 = 0; -+ mac->link.speed_mask = MAC_CONTROL_PS; - mac->mii.addr = MAC_MII_ADDR; - mac->mii.data = MAC_MII_DATA; - mac->mii.addr_shift = 11; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c -@@ -70,7 +70,7 @@ static void dwmac100_dump_dma_regs(void - { - int i; - -- for (i = 0; i < 9; i++) -+ for (i = 0; i < NUM_DWMAC100_DMA_REGS; i++) - reg_space[DMA_BUS_MODE / 4 + i] = - readl(ioaddr + DMA_BUS_MODE + i * 4); - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c -@@ -35,15 +35,17 @@ static void dwmac4_core_init(struct mac_ - if (hw->ps) { - value |= GMAC_CONFIG_TE; - -- if (hw->ps == SPEED_1000) { -- value &= ~GMAC_CONFIG_PS; -- } else { -- value |= GMAC_CONFIG_PS; -- -- if (hw->ps == SPEED_10) -- value &= ~GMAC_CONFIG_FES; -- else -- value |= GMAC_CONFIG_FES; -+ value &= hw->link.speed_mask; -+ switch (hw->ps) { -+ case SPEED_1000: -+ value |= hw->link.speed1000; -+ break; -+ case SPEED_100: -+ value |= hw->link.speed100; -+ break; -+ case SPEED_10: -+ value |= hw->link.speed10; -+ break; - } - } - -@@ -115,7 +117,7 @@ static void dwmac4_tx_queue_routing(stru - void __iomem *ioaddr = hw->pcsr; - u32 value; - -- const struct stmmac_rx_routing route_possibilities[] = { -+ static const struct stmmac_rx_routing route_possibilities[] = { - { GMAC_RXQCTRL_AVCPQ_MASK, GMAC_RXQCTRL_AVCPQ_SHIFT }, - { GMAC_RXQCTRL_PTPQ_MASK, GMAC_RXQCTRL_PTPQ_SHIFT }, - { GMAC_RXQCTRL_DCBCPQ_MASK, GMAC_RXQCTRL_DCBCPQ_SHIFT }, -@@ -747,9 +749,11 @@ struct mac_device_info *dwmac4_setup(voi - if (mac->multicast_filter_bins) - mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); - -- mac->link.port = GMAC_CONFIG_PS; - mac->link.duplex = GMAC_CONFIG_DM; -- mac->link.speed = GMAC_CONFIG_FES; -+ mac->link.speed10 = GMAC_CONFIG_PS; -+ mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS; -+ mac->link.speed1000 = 0; -+ mac->link.speed_mask = GMAC_CONFIG_FES | GMAC_CONFIG_PS; - mac->mii.addr = GMAC_MDIO_ADDR; - mac->mii.data = GMAC_MDIO_DATA; - mac->mii.addr_shift = 21; ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c -@@ -71,9 +71,9 @@ static void dwmac4_dma_axi(void __iomem - writel(value, ioaddr + DMA_SYS_BUS_MODE); - } - --void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, -- u32 dma_rx_phy, u32 chan) -+static void dwmac4_dma_init_rx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_rx_phy, u32 chan) - { - u32 value; - u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; -@@ -85,9 +85,9 @@ void dwmac4_dma_init_rx_chan(void __iome - writel(dma_rx_phy, ioaddr + DMA_CHAN_RX_BASE_ADDR(chan)); - } - --void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, -- u32 dma_tx_phy, u32 chan) -+static void dwmac4_dma_init_tx_chan(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, -+ u32 dma_tx_phy, u32 chan) - { - u32 value; - u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; -@@ -99,8 +99,8 @@ void dwmac4_dma_init_tx_chan(void __iome - writel(dma_tx_phy, ioaddr + DMA_CHAN_TX_BASE_ADDR(chan)); - } - --void dwmac4_dma_init_channel(void __iomem *ioaddr, -- struct stmmac_dma_cfg *dma_cfg, u32 chan) -+static void dwmac4_dma_init_channel(void __iomem *ioaddr, -+ struct stmmac_dma_cfg *dma_cfg, u32 chan) - { - u32 value; - ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h -@@ -136,6 +136,9 @@ - #define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */ - #define DMA_CONTROL_FTF 0x00100000 /* Flush transmit FIFO */ - -+#define NUM_DWMAC100_DMA_REGS 9 -+#define NUM_DWMAC1000_DMA_REGS 23 -+ - void dwmac_enable_dma_transmission(void __iomem *ioaddr); - void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan); - void dwmac_disable_dma_irq(void __iomem *ioaddr, u32 chan); ---- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c -@@ -248,6 +248,7 @@ void stmmac_set_mac_addr(void __iomem *i - data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; - writel(data, ioaddr + low); - } -+EXPORT_SYMBOL_GPL(stmmac_set_mac_addr); - - /* Enable disable MAC RX/TX */ - void stmmac_set_mac(void __iomem *ioaddr, bool enable) -@@ -279,4 +280,4 @@ void stmmac_get_mac_addr(void __iomem *i - addr[4] = hi_addr & 0xff; - addr[5] = (hi_addr >> 8) & 0xff; - } -- -+EXPORT_SYMBOL_GPL(stmmac_get_mac_addr); ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h -@@ -104,7 +104,7 @@ struct stmmac_priv { - /* TX Queue */ - struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES]; - -- int oldlink; -+ bool oldlink; - int speed; - int oldduplex; - unsigned int flow_ctrl; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c -@@ -29,10 +29,12 @@ - #include "stmmac.h" - #include "dwmac_dma.h" - --#define REG_SPACE_SIZE 0x1054 -+#define REG_SPACE_SIZE 0x1060 - #define MAC100_ETHTOOL_NAME "st_mac100" - #define GMAC_ETHTOOL_NAME "st_gmac" - -+#define ETHTOOL_DMA_OFFSET 55 -+ - struct stmmac_stats { - char stat_string[ETH_GSTRING_LEN]; - int sizeof_stat; -@@ -273,7 +275,6 @@ static int stmmac_ethtool_get_link_ksett - { - struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phy = dev->phydev; -- int rc; - - if (priv->hw->pcs & STMMAC_PCS_RGMII || - priv->hw->pcs & STMMAC_PCS_SGMII) { -@@ -364,8 +365,8 @@ static int stmmac_ethtool_get_link_ksett - "link speed / duplex setting\n", dev->name); - return -EBUSY; - } -- rc = phy_ethtool_ksettings_get(phy, cmd); -- return rc; -+ phy_ethtool_ksettings_get(phy, cmd); -+ return 0; - } - - static int -@@ -443,6 +444,9 @@ static void stmmac_ethtool_gregs(struct - - priv->hw->mac->dump_regs(priv->hw, reg_space); - priv->hw->dma->dump_regs(priv->ioaddr, reg_space); -+ /* Copy DMA registers to where ethtool expects them */ -+ memcpy(®_space[ETHTOOL_DMA_OFFSET], ®_space[DMA_BUS_MODE / 4], -+ NUM_DWMAC1000_DMA_REGS * 4); - } - - static void ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c -@@ -235,6 +235,17 @@ static void stmmac_clk_csr_set(struct st - else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) - priv->clk_csr = STMMAC_CSR_250_300M; - } -+ -+ if (priv->plat->has_sun8i) { -+ if (clk_rate > 160000000) -+ priv->clk_csr = 0x03; -+ else if (clk_rate > 80000000) -+ priv->clk_csr = 0x02; -+ else if (clk_rate > 40000000) -+ priv->clk_csr = 0x01; -+ else -+ priv->clk_csr = 0; -+ } - } - - static void print_pkt(unsigned char *buf, int len) -@@ -789,7 +800,7 @@ static void stmmac_adjust_link(struct ne - struct stmmac_priv *priv = netdev_priv(dev); - struct phy_device *phydev = dev->phydev; - unsigned long flags; -- int new_state = 0; -+ bool new_state = false; - - if (!phydev) - return; -@@ -802,8 +813,8 @@ static void stmmac_adjust_link(struct ne - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (phydev->duplex != priv->oldduplex) { -- new_state = 1; -- if (!(phydev->duplex)) -+ new_state = true; -+ if (!phydev->duplex) - ctrl &= ~priv->hw->link.duplex; - else - ctrl |= priv->hw->link.duplex; -@@ -814,30 +825,17 @@ static void stmmac_adjust_link(struct ne - stmmac_mac_flow_ctrl(priv, phydev->duplex); - - if (phydev->speed != priv->speed) { -- new_state = 1; -+ new_state = true; -+ ctrl &= ~priv->hw->link.speed_mask; - switch (phydev->speed) { -- case 1000: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) -- ctrl &= ~priv->hw->link.port; -+ case SPEED_1000: -+ ctrl |= priv->hw->link.speed1000; - break; -- case 100: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) { -- ctrl |= priv->hw->link.port; -- ctrl |= priv->hw->link.speed; -- } else { -- ctrl &= ~priv->hw->link.port; -- } -+ case SPEED_100: -+ ctrl |= priv->hw->link.speed100; - break; -- case 10: -- if (priv->plat->has_gmac || -- priv->plat->has_gmac4) { -- ctrl |= priv->hw->link.port; -- ctrl &= ~(priv->hw->link.speed); -- } else { -- ctrl &= ~priv->hw->link.port; -- } -+ case SPEED_10: -+ ctrl |= priv->hw->link.speed10; - break; - default: - netif_warn(priv, link, priv->dev, -@@ -853,12 +851,12 @@ static void stmmac_adjust_link(struct ne - writel(ctrl, priv->ioaddr + MAC_CTRL_REG); - - if (!priv->oldlink) { -- new_state = 1; -- priv->oldlink = 1; -+ new_state = true; -+ priv->oldlink = true; - } - } else if (priv->oldlink) { -- new_state = 1; -- priv->oldlink = 0; -+ new_state = true; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - } -@@ -921,7 +919,7 @@ static int stmmac_init_phy(struct net_de - char bus_id[MII_BUS_ID_SIZE]; - int interface = priv->plat->interface; - int max_speed = priv->plat->max_speed; -- priv->oldlink = 0; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - -@@ -1456,7 +1454,7 @@ static void free_dma_rx_desc_resources(s - static void free_dma_tx_desc_resources(struct stmmac_priv *priv) - { - u32 tx_count = priv->plat->tx_queues_to_use; -- u32 queue = 0; -+ u32 queue; - - /* Free TX queue resources */ - for (queue = 0; queue < tx_count; queue++) { -@@ -1505,7 +1503,7 @@ static int alloc_dma_rx_desc_resources(s - sizeof(dma_addr_t), - GFP_KERNEL); - if (!rx_q->rx_skbuff_dma) -- return -ENOMEM; -+ goto err_dma; - - rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE, - sizeof(struct sk_buff *), -@@ -1568,13 +1566,13 @@ static int alloc_dma_tx_desc_resources(s - sizeof(*tx_q->tx_skbuff_dma), - GFP_KERNEL); - if (!tx_q->tx_skbuff_dma) -- return -ENOMEM; -+ goto err_dma; - - tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE, - sizeof(struct sk_buff *), - GFP_KERNEL); - if (!tx_q->tx_skbuff) -- goto err_dma_buffers; -+ goto err_dma; - - if (priv->extend_desc) { - tx_q->dma_etx = dma_zalloc_coherent(priv->device, -@@ -1584,7 +1582,7 @@ static int alloc_dma_tx_desc_resources(s - &tx_q->dma_tx_phy, - GFP_KERNEL); - if (!tx_q->dma_etx) -- goto err_dma_buffers; -+ goto err_dma; - } else { - tx_q->dma_tx = dma_zalloc_coherent(priv->device, - DMA_TX_SIZE * -@@ -1593,13 +1591,13 @@ static int alloc_dma_tx_desc_resources(s - &tx_q->dma_tx_phy, - GFP_KERNEL); - if (!tx_q->dma_tx) -- goto err_dma_buffers; -+ goto err_dma; - } - } - - return 0; - --err_dma_buffers: -+err_dma: - free_dma_tx_desc_resources(priv); - - return ret; -@@ -2907,8 +2905,7 @@ static netdev_tx_t stmmac_tso_xmit(struc - priv->xstats.tx_set_ic_bit++; - } - -- if (!priv->hwts_tx_en) -- skb_tx_timestamp(skb); -+ skb_tx_timestamp(skb); - - if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - priv->hwts_tx_en)) { -@@ -2993,7 +2990,7 @@ static netdev_tx_t stmmac_xmit(struct sk - - /* Manage oversized TCP frames for GMAC4 device */ - if (skb_is_gso(skb) && priv->tso) { -- if (ip_hdr(skb)->protocol == IPPROTO_TCP) -+ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) - return stmmac_tso_xmit(skb, dev); - } - -@@ -3124,8 +3121,7 @@ static netdev_tx_t stmmac_xmit(struct sk - priv->xstats.tx_set_ic_bit++; - } - -- if (!priv->hwts_tx_en) -- skb_tx_timestamp(skb); -+ skb_tx_timestamp(skb); - - /* Ready to fill the first descriptor and set the OWN bit w/o any - * problems because all the descriptors are actually ready to be -@@ -4002,7 +3998,9 @@ static int stmmac_hw_init(struct stmmac_ - struct mac_device_info *mac; - - /* Identify the MAC HW device */ -- if (priv->plat->has_gmac) { -+ if (priv->plat->setup) { -+ mac = priv->plat->setup(priv); -+ } else if (priv->plat->has_gmac) { - priv->dev->priv_flags |= IFF_UNICAST_FLT; - mac = dwmac1000_setup(priv->ioaddr, - priv->plat->multicast_filter_bins, -@@ -4022,6 +4020,10 @@ static int stmmac_hw_init(struct stmmac_ - - priv->hw = mac; - -+ /* dwmac-sun8i only work in chain mode */ -+ if (priv->plat->has_sun8i) -+ chain_mode = 1; -+ - /* To use the chained or ring mode */ - if (priv->synopsys_id >= DWMAC_CORE_4_00) { - priv->hw->mode = &dwmac4_ring_mode_ops; -@@ -4150,8 +4152,15 @@ int stmmac_dvr_probe(struct device *devi - if ((phyaddr >= 0) && (phyaddr <= 31)) - priv->plat->phy_addr = phyaddr; - -- if (priv->plat->stmmac_rst) -+ if (priv->plat->stmmac_rst) { -+ ret = reset_control_assert(priv->plat->stmmac_rst); - reset_control_deassert(priv->plat->stmmac_rst); -+ /* Some reset controllers have only reset callback instead of -+ * assert + deassert callbacks pair. -+ */ -+ if (ret == -ENOTSUPP) -+ reset_control_reset(priv->plat->stmmac_rst); -+ } - - /* Init MAC and get the capabilities */ - ret = stmmac_hw_init(priv); -@@ -4168,7 +4177,7 @@ int stmmac_dvr_probe(struct device *devi - NETIF_F_RXCSUM; - - if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { -- ndev->hw_features |= NETIF_F_TSO; -+ ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; - priv->tso = true; - dev_info(priv->device, "TSO feature enabled\n"); - } -@@ -4330,7 +4339,7 @@ int stmmac_suspend(struct device *dev) - } - spin_unlock_irqrestore(&priv->lock, flags); - -- priv->oldlink = 0; -+ priv->oldlink = false; - priv->speed = SPEED_UNKNOWN; - priv->oldduplex = DUPLEX_UNKNOWN; - return 0; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c -@@ -204,6 +204,7 @@ int stmmac_mdio_register(struct net_devi - struct stmmac_priv *priv = netdev_priv(ndev); - struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; - struct device_node *mdio_node = priv->plat->mdio_node; -+ struct device *dev = ndev->dev.parent; - int addr, found; - - if (!mdio_bus_data) -@@ -237,7 +238,7 @@ int stmmac_mdio_register(struct net_devi - else - err = mdiobus_register(new_bus); - if (err != 0) { -- netdev_err(ndev, "Cannot register the MDIO bus\n"); -+ dev_err(dev, "Cannot register the MDIO bus\n"); - goto bus_register_fail; - } - -@@ -292,7 +293,7 @@ int stmmac_mdio_register(struct net_devi - } - - if (!found && !mdio_node) { -- netdev_warn(ndev, "No PHY found\n"); -+ dev_warn(dev, "No PHY found\n"); - mdiobus_unregister(new_bus); - mdiobus_free(new_bus); - return -ENODEV; ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c -@@ -30,42 +30,39 @@ - * negative value of the address means that MAC controller is not connected - * with PHY. - */ --struct stmmac_pci_dmi_data { -- const char *name; -- const char *asset_tag; -+struct stmmac_pci_func_data { - unsigned int func; - int phy_addr; - }; - -+struct stmmac_pci_dmi_data { -+ const struct stmmac_pci_func_data *func; -+ size_t nfuncs; -+}; -+ - struct stmmac_pci_info { -- struct pci_dev *pdev; -- int (*setup)(struct plat_stmmacenet_data *plat, -- struct stmmac_pci_info *info); -- struct stmmac_pci_dmi_data *dmi; -+ int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); - }; - --static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info) -+static int stmmac_pci_find_phy_addr(struct pci_dev *pdev, -+ const struct dmi_system_id *dmi_list) - { -- const char *name = dmi_get_system_info(DMI_BOARD_NAME); -- const char *asset_tag = dmi_get_system_info(DMI_BOARD_ASSET_TAG); -- unsigned int func = PCI_FUNC(info->pdev->devfn); -- struct stmmac_pci_dmi_data *dmi; -- -- /* -- * Galileo boards with old firmware don't support DMI. We always return -- * 1 here, so at least first found MAC controller would be probed. -- */ -- if (!name) -- return 1; -- -- for (dmi = info->dmi; dmi->name && *dmi->name; dmi++) { -- if (!strcmp(dmi->name, name) && dmi->func == func) { -- /* If asset tag is provided, match on it as well. */ -- if (dmi->asset_tag && strcmp(dmi->asset_tag, asset_tag)) -- continue; -- return dmi->phy_addr; -- } -- } -+ const struct stmmac_pci_func_data *func_data; -+ const struct stmmac_pci_dmi_data *dmi_data; -+ const struct dmi_system_id *dmi_id; -+ int func = PCI_FUNC(pdev->devfn); -+ size_t n; -+ -+ dmi_id = dmi_first_match(dmi_list); -+ if (!dmi_id) -+ return -ENODEV; -+ -+ dmi_data = dmi_id->driver_data; -+ func_data = dmi_data->func; -+ -+ for (n = 0; n < dmi_data->nfuncs; n++, func_data++) -+ if (func_data->func == func) -+ return func_data->phy_addr; - - return -ENODEV; - } -@@ -100,7 +97,8 @@ static void common_default_data(struct p - plat->rx_queues_cfg[0].pkt_route = 0x0; - } - --static void stmmac_default_data(struct plat_stmmacenet_data *plat) -+static int stmmac_default_data(struct pci_dev *pdev, -+ struct plat_stmmacenet_data *plat) - { - /* Set common default data first */ - common_default_data(plat); -@@ -112,12 +110,77 @@ static void stmmac_default_data(struct p - plat->dma_cfg->pbl = 32; - plat->dma_cfg->pblx8 = true; - /* TODO: AXI */ -+ -+ return 0; - } - --static int quark_default_data(struct plat_stmmacenet_data *plat, -- struct stmmac_pci_info *info) -+static const struct stmmac_pci_info stmmac_pci_info = { -+ .setup = stmmac_default_data, -+}; -+ -+static const struct stmmac_pci_func_data galileo_stmmac_func_data[] = { -+ { -+ .func = 6, -+ .phy_addr = 1, -+ }, -+}; -+ -+static const struct stmmac_pci_dmi_data galileo_stmmac_dmi_data = { -+ .func = galileo_stmmac_func_data, -+ .nfuncs = ARRAY_SIZE(galileo_stmmac_func_data), -+}; -+ -+static const struct stmmac_pci_func_data iot2040_stmmac_func_data[] = { -+ { -+ .func = 6, -+ .phy_addr = 1, -+ }, -+ { -+ .func = 7, -+ .phy_addr = 1, -+ }, -+}; -+ -+static const struct stmmac_pci_dmi_data iot2040_stmmac_dmi_data = { -+ .func = iot2040_stmmac_func_data, -+ .nfuncs = ARRAY_SIZE(iot2040_stmmac_func_data), -+}; -+ -+static const struct dmi_system_id quark_pci_dmi[] = { -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "Galileo"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), -+ DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, -+ "6ES7647-0AA00-0YA2"), -+ }, -+ .driver_data = (void *)&galileo_stmmac_dmi_data, -+ }, -+ { -+ .matches = { -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"), -+ DMI_EXACT_MATCH(DMI_BOARD_ASSET_TAG, -+ "6ES7647-0AA00-1YA2"), -+ }, -+ .driver_data = (void *)&iot2040_stmmac_dmi_data, -+ }, -+ {} -+}; -+ -+static int quark_default_data(struct pci_dev *pdev, -+ struct plat_stmmacenet_data *plat) - { -- struct pci_dev *pdev = info->pdev; - int ret; - - /* Set common default data first */ -@@ -127,9 +190,19 @@ static int quark_default_data(struct pla - * Refuse to load the driver and register net device if MAC controller - * does not connect to any PHY interface. - */ -- ret = stmmac_pci_find_phy_addr(info); -- if (ret < 0) -- return ret; -+ ret = stmmac_pci_find_phy_addr(pdev, quark_pci_dmi); -+ if (ret < 0) { -+ /* Return error to the caller on DMI enabled boards. */ -+ if (dmi_get_system_info(DMI_BOARD_NAME)) -+ return ret; -+ -+ /* -+ * Galileo boards with old firmware don't support DMI. We always -+ * use 1 here as PHY address, so at least the first found MAC -+ * controller would be probed. -+ */ -+ ret = 1; -+ } - - plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn); - plat->phy_addr = ret; -@@ -143,41 +216,8 @@ static int quark_default_data(struct pla - return 0; - } - --static struct stmmac_pci_dmi_data quark_pci_dmi_data[] = { -- { -- .name = "Galileo", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "GalileoGen2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-0YA2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-1YA2", -- .func = 6, -- .phy_addr = 1, -- }, -- { -- .name = "SIMATIC IOT2000", -- .asset_tag = "6ES7647-0AA00-1YA2", -- .func = 7, -- .phy_addr = 1, -- }, -- {} --}; -- --static struct stmmac_pci_info quark_pci_info = { -+static const struct stmmac_pci_info quark_pci_info = { - .setup = quark_default_data, -- .dmi = quark_pci_dmi_data, - }; - - /** -@@ -236,15 +276,9 @@ static int stmmac_pci_probe(struct pci_d - - pci_set_master(pdev); - -- if (info) { -- info->pdev = pdev; -- if (info->setup) { -- ret = info->setup(plat, info); -- if (ret) -- return ret; -- } -- } else -- stmmac_default_data(plat); -+ ret = info->setup(pdev, plat); -+ if (ret) -+ return ret; - - pci_enable_msi(pdev); - -@@ -306,14 +340,21 @@ static int stmmac_pci_resume(struct devi - - static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); - --#define STMMAC_VENDOR_ID 0x700 -+/* synthetic ID, no official vendor */ -+#define PCI_VENDOR_ID_STMMAC 0x700 -+ - #define STMMAC_QUARK_ID 0x0937 - #define STMMAC_DEVICE_ID 0x1108 - -+#define STMMAC_DEVICE(vendor_id, dev_id, info) { \ -+ PCI_VDEVICE(vendor_id, dev_id), \ -+ .driver_data = (kernel_ulong_t)&info \ -+ } -+ - static const struct pci_device_id stmmac_id_table[] = { -- {PCI_DEVICE(STMMAC_VENDOR_ID, STMMAC_DEVICE_ID)}, -- {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_MAC)}, -- {PCI_VDEVICE(INTEL, STMMAC_QUARK_ID), (kernel_ulong_t)&quark_pci_info}, -+ STMMAC_DEVICE(STMMAC, STMMAC_DEVICE_ID, stmmac_pci_info), -+ STMMAC_DEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_MAC, stmmac_pci_info), -+ STMMAC_DEVICE(INTEL, STMMAC_QUARK_ID, quark_pci_info), - {} - }; - ---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c -@@ -309,6 +309,13 @@ static int stmmac_dt_phy(struct plat_stm - struct device_node *np, struct device *dev) - { - bool mdio = true; -+ static const struct of_device_id need_mdio_ids[] = { -+ { .compatible = "snps,dwc-qos-ethernet-4.10" }, -+ { .compatible = "allwinner,sun8i-a83t-emac" }, -+ { .compatible = "allwinner,sun8i-h3-emac" }, -+ { .compatible = "allwinner,sun8i-v3s-emac" }, -+ { .compatible = "allwinner,sun50i-a64-emac" }, -+ }; - - /* If phy-handle property is passed from DT, use it as the PHY */ - plat->phy_node = of_parse_phandle(np, "phy-handle", 0); -@@ -325,8 +332,7 @@ static int stmmac_dt_phy(struct plat_stm - mdio = false; - } - -- /* exception for dwmac-dwc-qos-eth glue logic */ -- if (of_device_is_compatible(np, "snps,dwc-qos-ethernet-4.10")) { -+ if (of_match_node(need_mdio_ids, np)) { - plat->mdio_node = of_get_child_by_name(np, "mdio"); - } else { - /** ---- a/include/linux/stmmac.h -+++ b/include/linux/stmmac.h -@@ -177,6 +177,7 @@ struct plat_stmmacenet_data { - void (*fix_mac_speed)(void *priv, unsigned int speed); - int (*init)(struct platform_device *pdev, void *priv); - void (*exit)(struct platform_device *pdev, void *priv); -+ struct mac_device_info *(*setup)(void *priv); - void *bsp_priv; - struct clk *stmmac_clk; - struct clk *pclk; -@@ -185,6 +186,7 @@ struct plat_stmmacenet_data { - struct reset_control *stmmac_rst; - struct stmmac_axi *axi; - int has_gmac4; -+ bool has_sun8i; - bool tso_en; - int mac_port_sel_speed; - bool en_tx_lpi_clockgating; diff --git a/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch b/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch deleted file mode 100644 index f2bac1fde0..0000000000 --- a/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch +++ /dev/null @@ -1,206 +0,0 @@ -From b8ae5c7387ad075ee61e8c8774ce2bca46bc9236 Mon Sep 17 00:00:00 2001 -From: Corentin LABBE -Date: Mon, 3 Jul 2017 20:48:48 +0200 -Subject: crypto: sun4i-ss - support the Security System PRNG - -The Security System has a PRNG, this patch adds support for it via -crypto_rng. - -Signed-off-by: Corentin Labbe -Signed-off-by: Herbert Xu ---- - drivers/crypto/Kconfig | 8 +++++ - drivers/crypto/sunxi-ss/Makefile | 1 + - drivers/crypto/sunxi-ss/sun4i-ss-core.c | 30 ++++++++++++++++++ - drivers/crypto/sunxi-ss/sun4i-ss-prng.c | 56 +++++++++++++++++++++++++++++++++ - drivers/crypto/sunxi-ss/sun4i-ss.h | 11 +++++++ - 5 files changed, 106 insertions(+) - create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-prng.c - ---- a/drivers/crypto/Kconfig -+++ b/drivers/crypto/Kconfig -@@ -538,6 +538,14 @@ config CRYPTO_DEV_SUN4I_SS - To compile this driver as a module, choose M here: the module - will be called sun4i-ss. - -+config CRYPTO_DEV_SUN4I_SS_PRNG -+ bool "Support for Allwinner Security System PRNG" -+ depends on CRYPTO_DEV_SUN4I_SS -+ select CRYPTO_RNG -+ help -+ Select this option if you want to provide kernel-side support for -+ the Pseudo-Random Number Generator found in the Security System. -+ - config CRYPTO_DEV_ROCKCHIP - tristate "Rockchip's Cryptographic Engine driver" - depends on OF && ARCH_ROCKCHIP ---- a/drivers/crypto/sunxi-ss/Makefile -+++ b/drivers/crypto/sunxi-ss/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o - sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o -+sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o ---- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c -+++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c -@@ -214,6 +214,23 @@ static struct sun4i_ss_alg_template ss_a - } - } - }, -+#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG -+{ -+ .type = CRYPTO_ALG_TYPE_RNG, -+ .alg.rng = { -+ .base = { -+ .cra_name = "stdrng", -+ .cra_driver_name = "sun4i_ss_rng", -+ .cra_priority = 300, -+ .cra_ctxsize = 0, -+ .cra_module = THIS_MODULE, -+ }, -+ .generate = sun4i_ss_prng_generate, -+ .seed = sun4i_ss_prng_seed, -+ .seedsize = SS_SEED_LEN / BITS_PER_BYTE, -+ } -+}, -+#endif - }; - - static int sun4i_ss_probe(struct platform_device *pdev) -@@ -356,6 +373,13 @@ static int sun4i_ss_probe(struct platfor - goto error_alg; - } - break; -+ case CRYPTO_ALG_TYPE_RNG: -+ err = crypto_register_rng(&ss_algs[i].alg.rng); -+ if (err) { -+ dev_err(ss->dev, "Fail to register %s\n", -+ ss_algs[i].alg.rng.base.cra_name); -+ } -+ break; - } - } - platform_set_drvdata(pdev, ss); -@@ -370,6 +394,9 @@ error_alg: - case CRYPTO_ALG_TYPE_AHASH: - crypto_unregister_ahash(&ss_algs[i].alg.hash); - break; -+ case CRYPTO_ALG_TYPE_RNG: -+ crypto_unregister_rng(&ss_algs[i].alg.rng); -+ break; - } - } - if (ss->reset) -@@ -394,6 +421,9 @@ static int sun4i_ss_remove(struct platfo - case CRYPTO_ALG_TYPE_AHASH: - crypto_unregister_ahash(&ss_algs[i].alg.hash); - break; -+ case CRYPTO_ALG_TYPE_RNG: -+ crypto_unregister_rng(&ss_algs[i].alg.rng); -+ break; - } - } - ---- /dev/null -+++ b/drivers/crypto/sunxi-ss/sun4i-ss-prng.c -@@ -0,0 +1,56 @@ -+#include "sun4i-ss.h" -+ -+int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, -+ unsigned int slen) -+{ -+ struct sun4i_ss_alg_template *algt; -+ struct rng_alg *alg = crypto_rng_alg(tfm); -+ -+ algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); -+ memcpy(algt->ss->seed, seed, slen); -+ -+ return 0; -+} -+ -+int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, -+ unsigned int slen, u8 *dst, unsigned int dlen) -+{ -+ struct sun4i_ss_alg_template *algt; -+ struct rng_alg *alg = crypto_rng_alg(tfm); -+ int i; -+ u32 v; -+ u32 *data = (u32 *)dst; -+ const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED; -+ size_t len; -+ struct sun4i_ss_ctx *ss; -+ unsigned int todo = (dlen / 4) * 4; -+ -+ algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); -+ ss = algt->ss; -+ -+ spin_lock(&ss->slock); -+ -+ writel(mode, ss->base + SS_CTL); -+ -+ while (todo > 0) { -+ /* write the seed */ -+ for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) -+ writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); -+ -+ /* Read the random data */ -+ len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo); -+ readsl(ss->base + SS_TXFIFO, data, len / 4); -+ data += len / 4; -+ todo -= len; -+ -+ /* Update the seed */ -+ for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) { -+ v = readl(ss->base + SS_KEY0 + i * 4); -+ ss->seed[i] = v; -+ } -+ } -+ -+ writel(0, ss->base + SS_CTL); -+ spin_unlock(&ss->slock); -+ return dlen; -+} ---- a/drivers/crypto/sunxi-ss/sun4i-ss.h -+++ b/drivers/crypto/sunxi-ss/sun4i-ss.h -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #define SS_CTL 0x00 - #define SS_KEY0 0x04 -@@ -125,6 +126,9 @@ - #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) - #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) - -+#define SS_SEED_LEN 192 -+#define SS_DATA_LEN 160 -+ - struct sun4i_ss_ctx { - void __iomem *base; - int irq; -@@ -134,6 +138,9 @@ struct sun4i_ss_ctx { - struct device *dev; - struct resource *res; - spinlock_t slock; /* control the use of the device */ -+#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG -+ u32 seed[SS_SEED_LEN / BITS_PER_LONG]; -+#endif - }; - - struct sun4i_ss_alg_template { -@@ -142,6 +149,7 @@ struct sun4i_ss_alg_template { - union { - struct crypto_alg crypto; - struct ahash_alg hash; -+ struct rng_alg rng; - } alg; - struct sun4i_ss_ctx *ss; - }; -@@ -199,3 +207,6 @@ int sun4i_ss_des_setkey(struct crypto_ab - unsigned int keylen); - int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, - unsigned int keylen); -+int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, -+ unsigned int slen, u8 *dst, unsigned int dlen); -+int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen); diff --git a/target/linux/sunxi/patches-4.9/0060-arm64-allwinner-sun50i-a64-Add-dt-node-for-the-sysco.patch b/target/linux/sunxi/patches-4.9/0060-arm64-allwinner-sun50i-a64-Add-dt-node-for-the-sysco.patch deleted file mode 100644 index 911ea49967..0000000000 --- a/target/linux/sunxi/patches-4.9/0060-arm64-allwinner-sun50i-a64-Add-dt-node-for-the-sysco.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 79b953605ded6a9a995040a1c8cc665127a6411a Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:45 +0200 -Subject: arm64: allwinner: sun50i-a64: Add dt node for the syscon control - module - -This patch add the dt node for the syscon register present on the -Allwinner A64. - -Only two register are present in this syscon and the only one useful is -the one dedicated to EMAC clock. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -129,6 +129,12 @@ - #size-cells = <1>; - ranges; - -+ syscon: syscon@1c00000 { -+ compatible = "allwinner,sun50i-a64-system-controller", -+ "syscon"; -+ reg = <0x01c00000 0x1000>; -+ }; -+ - mmc0: mmc@1c0f000 { - compatible = "allwinner,sun50i-a64-mmc"; - reg = <0x01c0f000 0x1000>; diff --git a/target/linux/sunxi/patches-4.9/0061-arm64-allwinner-sun50i-a64-add-dwmac-sun8i-Ethernet-.patch b/target/linux/sunxi/patches-4.9/0061-arm64-allwinner-sun50i-a64-add-dwmac-sun8i-Ethernet-.patch deleted file mode 100644 index e59c3e8735..0000000000 --- a/target/linux/sunxi/patches-4.9/0061-arm64-allwinner-sun50i-a64-add-dwmac-sun8i-Ethernet-.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e53f67e981bcc5547857475241b3a4a066955f8c Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:46 +0200 -Subject: arm64: allwinner: sun50i-a64: add dwmac-sun8i Ethernet driver - -The dwmac-sun8i is an Ethernet MAC that supports 10/100/1000 Mbit -connections. It is very similar to the device found in the Allwinner -H3, but lacks the internal 100 Mbit PHY and its associated control -bits. -This adds the necessary bits to the Allwinner A64 SoC .dtsi, but keeps -it disabled at this level. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 35 +++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -284,6 +284,21 @@ - bias-pull-up; - }; - -+ rmii_pins: rmii_pins { -+ pins = "PD10", "PD11", "PD13", "PD14", "PD17", -+ "PD18", "PD19", "PD20", "PD22", "PD23"; -+ function = "emac"; -+ drive-strength = <40>; -+ }; -+ -+ rgmii_pins: rgmii_pins { -+ pins = "PD8", "PD9", "PD10", "PD11", "PD12", -+ "PD13", "PD15", "PD16", "PD17", "PD18", -+ "PD19", "PD20", "PD21", "PD22", "PD23"; -+ function = "emac"; -+ drive-strength = <40>; -+ }; -+ - uart0_pins_a: uart0@0 { - pins = "PB8", "PB9"; - function = "uart0"; -@@ -388,6 +403,26 @@ - #size-cells = <0>; - }; - -+ emac: ethernet@1c30000 { -+ compatible = "allwinner,sun50i-a64-emac"; -+ syscon = <&syscon>; -+ reg = <0x01c30000 0x100>; -+ interrupts = ; -+ interrupt-names = "macirq"; -+ resets = <&ccu RST_BUS_EMAC>; -+ reset-names = "stmmaceth"; -+ clocks = <&ccu CLK_BUS_EMAC>; -+ clock-names = "stmmaceth"; -+ status = "disabled"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ mdio: mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ }; -+ }; -+ - gic: interrupt-controller@1c81000 { - compatible = "arm,gic-400"; - reg = <0x01c81000 0x1000>, diff --git a/target/linux/sunxi/patches-4.9/0062-arm64-allwinner-pine64-Enable-dwmac-sun8i.patch b/target/linux/sunxi/patches-4.9/0062-arm64-allwinner-pine64-Enable-dwmac-sun8i.patch deleted file mode 100644 index d9a825490d..0000000000 --- a/target/linux/sunxi/patches-4.9/0062-arm64-allwinner-pine64-Enable-dwmac-sun8i.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 97023943749367111b9a88e09d1b9bd157dd3326 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:47 +0200 -Subject: arm64: allwinner: pine64: Enable dwmac-sun8i - -The dwmac-sun8i hardware is present on the pine64 -It uses an external PHY via RMII. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -70,6 +70,15 @@ - status = "okay"; - }; - -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rmii_pins>; -+ phy-mode = "rmii"; -+ phy-handle = <&ext_rmii_phy1>; -+ status = "okay"; -+ -+}; -+ - &i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&i2c1_pins>; -@@ -80,6 +89,13 @@ - bias-pull-up; - }; - -+&mdio { -+ ext_rmii_phy1: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ }; -+}; -+ - &mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins>; diff --git a/target/linux/sunxi/patches-4.9/0063-arm64-allwinner-pine64-plus-Enable-dwmac-sun8i.patch b/target/linux/sunxi/patches-4.9/0063-arm64-allwinner-pine64-plus-Enable-dwmac-sun8i.patch deleted file mode 100644 index f89b842790..0000000000 --- a/target/linux/sunxi/patches-4.9/0063-arm64-allwinner-pine64-plus-Enable-dwmac-sun8i.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 94dcfdc77fc55ed1956011ceea341911c6e760a0 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:48 +0200 -Subject: arm64: allwinner: pine64-plus: Enable dwmac-sun8i - -The dwmac-sun8i hardware is present on the pine64 plus. -It uses an external PHY rtl8211e via RGMII. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - .../arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts -@@ -46,5 +46,20 @@ - model = "Pine64+"; - compatible = "pine64,pine64-plus", "allwinner,sun50i-a64"; - -- /* TODO: Camera, Ethernet PHY, touchscreen, etc. */ -+ /* TODO: Camera, touchscreen, etc. */ -+}; -+ -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&rgmii_pins>; -+ phy-mode = "rgmii"; -+ phy-handle = <&ext_rgmii_phy>; -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rgmii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ }; - }; diff --git a/target/linux/sunxi/patches-4.9/0064-arm64-allwinner-sun50i-a64-Correct-emac-register-siz.patch b/target/linux/sunxi/patches-4.9/0064-arm64-allwinner-sun50i-a64-Correct-emac-register-siz.patch deleted file mode 100644 index 924c875288..0000000000 --- a/target/linux/sunxi/patches-4.9/0064-arm64-allwinner-sun50i-a64-Correct-emac-register-siz.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 3a4bae5fd44aa1cf49780dd25b3a89e6a39e8560 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Mon, 10 Jul 2017 20:44:40 +0200 -Subject: arm64: allwinner: sun50i-a64: Correct emac register size - -The datasheet said that emac register size is 0x10000 not 0x100 - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard -[wens@csie.org: Fixed commit subject prefix] -Signed-off-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi -@@ -406,7 +406,7 @@ - emac: ethernet@1c30000 { - compatible = "allwinner,sun50i-a64-emac"; - syscon = <&syscon>; -- reg = <0x01c30000 0x100>; -+ reg = <0x01c30000 0x10000>; - interrupts = ; - interrupt-names = "macirq"; - resets = <&ccu RST_BUS_EMAC>; diff --git a/target/linux/sunxi/patches-4.9/0065-arm64-allwinner-a64-pine64-add-missing-ethernet0-ali.patch b/target/linux/sunxi/patches-4.9/0065-arm64-allwinner-a64-pine64-add-missing-ethernet0-ali.patch deleted file mode 100644 index f892219fa3..0000000000 --- a/target/linux/sunxi/patches-4.9/0065-arm64-allwinner-a64-pine64-add-missing-ethernet0-ali.patch +++ /dev/null @@ -1,29 +0,0 @@ -From dff751c68904cf587d918cfb6b2f5b0112f73bc9 Mon Sep 17 00:00:00 2001 -From: Icenowy Zheng -Date: Sat, 22 Jul 2017 10:28:51 +0800 -Subject: arm64: allwinner: a64: pine64: add missing ethernet0 alias - -The EMAC Ethernet controller was enabled, but an accompanying alias -was not added. This results in unstable numbering if other Ethernet -devices, such as a USB dongle, are present. Also, the bootloader uses -the alias to assign a generated stable MAC address to the device node. - -Signed-off-by: Icenowy Zheng -Signed-off-by: Maxime Ripard -Fixes: 970239437493 ("arm64: allwinner: pine64: Enable dwmac-sun8i") -[wens@csie.org: Rewrite commit log as fixing a previous patch with Fixes] -Signed-off-by: Chen-Yu Tsai ---- - arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts -@@ -51,6 +51,7 @@ - compatible = "pine64,pine64", "allwinner,sun50i-a64"; - - aliases { -+ ethernet0 = &emac; - serial0 = &uart0; - }; - diff --git a/target/linux/sunxi/patches-4.9/0070-arm-sun8i-sunxi-h3-h5-Add-dt-node-for-the-syscon-con.patch b/target/linux/sunxi/patches-4.9/0070-arm-sun8i-sunxi-h3-h5-Add-dt-node-for-the-syscon-con.patch deleted file mode 100644 index 88d431d319..0000000000 --- a/target/linux/sunxi/patches-4.9/0070-arm-sun8i-sunxi-h3-h5-Add-dt-node-for-the-syscon-con.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d91d3daf5de90e0118227d8ddcb7bb4ff40c1b91 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:37 +0200 -Subject: arm: sun8i: sunxi-h3-h5: Add dt node for the syscon control module - -This patch add the dt node for the syscon register present on the -Allwinner H3/H5 - -Only two register are present in this syscon and the only one useful is -the one dedicated to EMAC clock.. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 6 ++++++ - 1 file changed, 6 insertions(+) - ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -140,6 +140,12 @@ - #size-cells = <1>; - ranges; - -+ syscon: syscon@1c00000 { -+ compatible = "allwinner,sun8i-h3-system-controller", -+ "syscon"; -+ reg = <0x01c00000 0x1000>; -+ }; -+ - dma: dma-controller@01c02000 { - compatible = "allwinner,sun8i-h3-dma"; - reg = <0x01c02000 0x1000>; diff --git a/target/linux/sunxi/patches-4.9/0071-arm-sun8i-sunxi-h3-h5-add-dwmac-sun8i-ethernet-drive.patch b/target/linux/sunxi/patches-4.9/0071-arm-sun8i-sunxi-h3-h5-add-dwmac-sun8i-ethernet-drive.patch deleted file mode 100644 index 7054e3dc0f..0000000000 --- a/target/linux/sunxi/patches-4.9/0071-arm-sun8i-sunxi-h3-h5-add-dwmac-sun8i-ethernet-drive.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0eba511a3cac29d6338b22b5b727f40cf8d163df Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:38 +0200 -Subject: arm: sun8i: sunxi-h3-h5: add dwmac-sun8i ethernet driver - -The dwmac-sun8i is an ethernet MAC hardware that support 10/100/1000 -speed. - -This patch enable the dwmac-sun8i on Allwinner H3/H5 SoC Device-tree. -SoC H3/H5 have an internal PHY, so optionals syscon and ephy are set. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -333,6 +333,14 @@ - interrupt-controller; - #interrupt-cells = <3>; - -+ emac_rgmii_pins: emac0 { -+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", -+ "PD5", "PD7", "PD8", "PD9", "PD10", -+ "PD12", "PD13", "PD15", "PD16", "PD17"; -+ function = "emac"; -+ drive-strength = <40>; -+ }; -+ - i2c0_pins: i2c0 { - allwinner,pins = "PA11", "PA12"; - allwinner,function = "i2c0"; -@@ -431,6 +439,32 @@ - clocks = <&osc24M>; - }; - -+ emac: ethernet@1c30000 { -+ compatible = "allwinner,sun8i-h3-emac"; -+ syscon = <&syscon>; -+ reg = <0x01c30000 0x104>; -+ interrupts = ; -+ interrupt-names = "macirq"; -+ resets = <&ccu RST_BUS_EMAC>; -+ reset-names = "stmmaceth"; -+ clocks = <&ccu CLK_BUS_EMAC>; -+ clock-names = "stmmaceth"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ status = "disabled"; -+ -+ mdio: mdio { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ int_mii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <1>; -+ clocks = <&ccu CLK_BUS_EPHY>; -+ resets = <&ccu RST_BUS_EPHY>; -+ }; -+ }; -+ }; -+ - wdt0: watchdog@01c20ca0 { - compatible = "allwinner,sun6i-a31-wdt"; - reg = <0x01c20ca0 0x20>; diff --git a/target/linux/sunxi/patches-4.9/0072-arm-sun8i-orangepi-2-Enable-dwmac-sun8i.patch b/target/linux/sunxi/patches-4.9/0072-arm-sun8i-orangepi-2-Enable-dwmac-sun8i.patch deleted file mode 100644 index 450d5bc2be..0000000000 --- a/target/linux/sunxi/patches-4.9/0072-arm-sun8i-orangepi-2-Enable-dwmac-sun8i.patch +++ /dev/null @@ -1,40 +0,0 @@ -From a9992f2dd1890112643a93d621ff5a4c97c55d53 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Wed, 31 May 2017 09:18:42 +0200 -Subject: arm: sun8i: orangepi-2: Enable dwmac-sun8i - -The dwmac-sun8i hardware is present on the Orange PI 2. -It uses the internal PHY. - -This patch create the needed emac node. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts -+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-2.dts -@@ -55,6 +55,7 @@ - aliases { - serial0 = &uart0; - /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */ -+ ethernet0 = &emac; - ethernet1 = &rtl8189; - }; - -@@ -109,6 +110,13 @@ - status = "okay"; - }; - -+&emac { -+ phy-handle = <&int_mii_phy>; -+ phy-mode = "mii"; -+ allwinner,leds-active-low; -+ status = "okay"; -+}; -+ - &ir { - pinctrl-names = "default"; - pinctrl-0 = <&ir_pins_a>; diff --git a/target/linux/sunxi/patches-4.9/0073-ARM-sun8i-orangepi-plus-Enable-dwmac-sun8i.patch b/target/linux/sunxi/patches-4.9/0073-ARM-sun8i-orangepi-plus-Enable-dwmac-sun8i.patch deleted file mode 100644 index 375d119d55..0000000000 --- a/target/linux/sunxi/patches-4.9/0073-ARM-sun8i-orangepi-plus-Enable-dwmac-sun8i.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 1dcd0095019aca7533eaeed9475d995a4eb30137 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Mon, 5 Jun 2017 21:21:26 +0200 -Subject: ARM: sun8i: orangepi-plus: Enable dwmac-sun8i - -The dwmac-sun8i hardware is present on the Orange PI plus. -It uses an external PHY rtl8211e via RGMII. - -This patch create the needed regulator, emac and phy nodes. - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard ---- - arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 32 ++++++++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - ---- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts -+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts -@@ -47,6 +47,20 @@ - model = "Xunlong Orange Pi Plus / Plus 2"; - compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3"; - -+ aliases { -+ ethernet0 = &emac; -+ }; -+ -+ reg_gmac_3v3: gmac-3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "gmac-3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <100000>; -+ enable-active-high; -+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; -+ }; -+ - reg_usb3_vbus: usb3-vbus { - compatible = "regulator-fixed"; - pinctrl-names = "default"; -@@ -64,6 +78,24 @@ - status = "okay"; - }; - -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emac_rgmii_pins>; -+ phy-supply = <®_gmac_3v3>; -+ phy-handle = <&ext_rgmii_phy>; -+ phy-mode = "rgmii"; -+ -+ allwinner,leds-active-low; -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rgmii_phy: ethernet-phy@1 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <0>; -+ }; -+}; -+ - &mmc2 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc2_8bit_pins>; diff --git a/target/linux/sunxi/patches-4.9/0074-ARM-dts-sunxi-h3-h5-Correct-emac-register-size.patch b/target/linux/sunxi/patches-4.9/0074-ARM-dts-sunxi-h3-h5-Correct-emac-register-size.patch deleted file mode 100644 index 50877a5301..0000000000 --- a/target/linux/sunxi/patches-4.9/0074-ARM-dts-sunxi-h3-h5-Correct-emac-register-size.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 072b6e3692532b6281bf781ded1c7a986ac17471 Mon Sep 17 00:00:00 2001 -From: Corentin Labbe -Date: Thu, 6 Jul 2017 10:53:34 +0200 -Subject: ARM: dts: sunxi: h3/h5: Correct emac register size - -The datasheet said that emac register size is 0x10000 not 0x104 - -Signed-off-by: Corentin Labbe -Signed-off-by: Maxime Ripard -[wens@csie.org: Fixed commit subject prefix] -Signed-off-by: Chen-Yu Tsai ---- - arch/arm/boot/dts/sunxi-h3-h5.dtsi | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm/boot/dts/sun8i-h3.dtsi -+++ b/arch/arm/boot/dts/sun8i-h3.dtsi -@@ -442,7 +442,7 @@ - emac: ethernet@1c30000 { - compatible = "allwinner,sun8i-h3-emac"; - syscon = <&syscon>; -- reg = <0x01c30000 0x104>; -+ reg = <0x01c30000 0x10000>; - interrupts = ; - interrupt-names = "macirq"; - resets = <&ccu RST_BUS_EMAC>; diff --git a/target/linux/sunxi/patches-4.9/0080-ARM-dts-sunxi-nanopi-neo-Enable-dwmac-sun8i.patch b/target/linux/sunxi/patches-4.9/0080-ARM-dts-sunxi-nanopi-neo-Enable-dwmac-sun8i.patch deleted file mode 100644 index 4de2fd2e85..0000000000 --- a/target/linux/sunxi/patches-4.9/0080-ARM-dts-sunxi-nanopi-neo-Enable-dwmac-sun8i.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts -+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts -@@ -53,6 +53,7 @@ - - aliases { - serial0 = &uart0; -+ ethernet0 = &emac; - }; - - chosen { -@@ -81,6 +82,13 @@ - status = "okay"; - }; - -+&emac { -+ phy-handle = <&int_mii_phy>; -+ phy-mode = "mii"; -+ allwinner,leds-active-low; -+ status = "okay"; -+}; -+ - &mmc0 { - pinctrl-names = "default"; - pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>; diff --git a/target/linux/sunxi/patches-4.9/0081-ARM-dts-sun8i-nanopi-neo-enable-UART-USB-and-I2C-pin.patch b/target/linux/sunxi/patches-4.9/0081-ARM-dts-sun8i-nanopi-neo-enable-UART-USB-and-I2C-pin.patch deleted file mode 100644 index b815f7263b..0000000000 --- a/target/linux/sunxi/patches-4.9/0081-ARM-dts-sun8i-nanopi-neo-enable-UART-USB-and-I2C-pin.patch +++ /dev/null @@ -1,80 +0,0 @@ -From e036def69972b9db9d2695f45cbf4e84c707b3c5 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Fri, 23 Dec 2016 07:28:51 +0100 -Subject: [PATCH] ARM: dts: sun8i: nanopi-neo: enable UART, USB and I2C pins - ---- - arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 43 ++++++++++++++++++++++++++++--- - 1 file changed, 40 insertions(+), 3 deletions(-) - ---- a/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts -+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts -@@ -78,10 +78,30 @@ - }; - }; - -+&ehci1 { -+ status = "okay"; -+}; -+ -+&ohci1 { -+ status = "okay"; -+}; -+ -+&ehci2 { -+ status = "okay"; -+}; -+ -+&ohci2 { -+ status = "okay"; -+}; -+ - &ehci3 { - status = "okay"; - }; - -+&ohci3 { -+ status = "okay"; -+}; -+ - &emac { - phy-handle = <&int_mii_phy>; - phy-mode = "mii"; -@@ -99,9 +119,6 @@ - status = "okay"; - }; - --&ohci3 { -- status = "okay"; --}; - - &pio { - leds_opc: led-pins { -@@ -127,7 +144,27 @@ - status = "okay"; - }; - -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>; -+ status = "okay"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart2_pins>; -+ status = "okay"; -+}; -+ - &usbphy { - /* USB VBUS is always on */ - status = "okay"; - }; -+ -+&i2c0 { -+ status = "okay"; -+}; -+ -+&i2c1 { -+ status = "okay"; -+}; diff --git a/target/linux/sunxi/patches-4.9/090-sunxi-mmc-from-4-13.patch b/target/linux/sunxi/patches-4.9/090-sunxi-mmc-from-4-13.patch deleted file mode 100644 index e64581ff83..0000000000 --- a/target/linux/sunxi/patches-4.9/090-sunxi-mmc-from-4-13.patch +++ /dev/null @@ -1,288 +0,0 @@ ---- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt -+++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt -@@ -13,6 +13,7 @@ Required properties: - * "allwinner,sun5i-a13-mmc" - * "allwinner,sun7i-a20-mmc" - * "allwinner,sun9i-a80-mmc" -+ * "allwinner,sun50i-a64-emmc" - * "allwinner,sun50i-a64-mmc" - - reg : mmc controller base registers - - clocks : a list with 4 phandle + clock specifier pairs ---- a/drivers/mmc/host/sunxi-mmc.c -+++ b/drivers/mmc/host/sunxi-mmc.c -@@ -5,6 +5,7 @@ - * (C) Copyright 2013-2014 O2S GmbH - * (C) Copyright 2013-2014 David Lanzend�rfer - * (C) Copyright 2013-2014 Hans de Goede -+ * (C) Copyright 2017 Sootech SA - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as -@@ -101,6 +102,7 @@ - (SDXC_SOFT_RESET | SDXC_FIFO_RESET | SDXC_DMA_RESET) - - /* clock control bits */ -+#define SDXC_MASK_DATA0 BIT(31) - #define SDXC_CARD_CLOCK_ON BIT(16) - #define SDXC_LOW_POWER_ON BIT(17) - -@@ -253,6 +255,11 @@ struct sunxi_mmc_cfg { - - /* does the IP block support autocalibration? */ - bool can_calibrate; -+ -+ /* Does DATA0 needs to be masked while the clock is updated */ -+ bool mask_data0; -+ -+ bool needs_new_timings; - }; - - struct sunxi_mmc_host { -@@ -482,7 +489,7 @@ static void sunxi_mmc_dump_errinfo(struc - cmd->opcode == SD_IO_RW_DIRECT)) - return; - -- dev_err(mmc_dev(host->mmc), -+ dev_dbg(mmc_dev(host->mmc), - "smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n", - host->mmc->index, cmd->opcode, - data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "", -@@ -654,11 +661,16 @@ static int sunxi_mmc_oclk_onoff(struct s - unsigned long expire = jiffies + msecs_to_jiffies(750); - u32 rval; - -+ dev_dbg(mmc_dev(host->mmc), "%sabling the clock\n", -+ oclk_en ? "en" : "dis"); -+ - rval = mmc_readl(host, REG_CLKCR); -- rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON); -+ rval &= ~(SDXC_CARD_CLOCK_ON | SDXC_LOW_POWER_ON | SDXC_MASK_DATA0); - - if (oclk_en) - rval |= SDXC_CARD_CLOCK_ON; -+ if (host->cfg->mask_data0) -+ rval |= SDXC_MASK_DATA0; - - mmc_writel(host, REG_CLKCR, rval); - -@@ -678,46 +690,29 @@ static int sunxi_mmc_oclk_onoff(struct s - return -EIO; - } - -+ if (host->cfg->mask_data0) { -+ rval = mmc_readl(host, REG_CLKCR); -+ mmc_writel(host, REG_CLKCR, rval & ~SDXC_MASK_DATA0); -+ } -+ - return 0; - } - - static int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off) - { -- u32 reg = readl(host->reg_base + reg_off); -- u32 delay; -- unsigned long timeout; -- - if (!host->cfg->can_calibrate) - return 0; - -- reg &= ~(SDXC_CAL_DL_MASK << SDXC_CAL_DL_SW_SHIFT); -- reg &= ~SDXC_CAL_DL_SW_EN; -- -- writel(reg | SDXC_CAL_START, host->reg_base + reg_off); -- -- dev_dbg(mmc_dev(host->mmc), "calibration started\n"); -- -- timeout = jiffies + HZ * SDXC_CAL_TIMEOUT; -- -- while (!((reg = readl(host->reg_base + reg_off)) & SDXC_CAL_DONE)) { -- if (time_before(jiffies, timeout)) -- cpu_relax(); -- else { -- reg &= ~SDXC_CAL_START; -- writel(reg, host->reg_base + reg_off); -- -- return -ETIMEDOUT; -- } -- } -- -- delay = (reg >> SDXC_CAL_DL_SHIFT) & SDXC_CAL_DL_MASK; -- -- reg &= ~SDXC_CAL_START; -- reg |= (delay << SDXC_CAL_DL_SW_SHIFT) | SDXC_CAL_DL_SW_EN; -- -- writel(reg, host->reg_base + reg_off); -- -- dev_dbg(mmc_dev(host->mmc), "calibration ended, reg is 0x%x\n", reg); -+ /* -+ * FIXME: -+ * This is not clear how the calibration is supposed to work -+ * yet. The best rate have been obtained by simply setting the -+ * delay to 0, as Allwinner does in its BSP. -+ * -+ * The only mode that doesn't have such a delay is HS400, that -+ * is in itself a TODO. -+ */ -+ writel(SDXC_CAL_DL_SW_EN, host->reg_base + reg_off); - - return 0; - } -@@ -745,6 +740,7 @@ static int sunxi_mmc_clk_set_phase(struc - index = SDXC_CLK_50M_DDR; - } - } else { -+ dev_dbg(mmc_dev(host->mmc), "Invalid clock... returning\n"); - return -EINVAL; - } - -@@ -757,10 +753,21 @@ static int sunxi_mmc_clk_set_phase(struc - static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, - struct mmc_ios *ios) - { -+ struct mmc_host *mmc = host->mmc; - long rate; - u32 rval, clock = ios->clock; - int ret; - -+ ret = sunxi_mmc_oclk_onoff(host, 0); -+ if (ret) -+ return ret; -+ -+ /* Our clock is gated now */ -+ mmc->actual_clock = 0; -+ -+ if (!ios->clock) -+ return 0; -+ - /* 8 bit DDR requires a higher module clock */ - if (ios->timing == MMC_TIMING_MMC_DDR52 && - ios->bus_width == MMC_BUS_WIDTH_8) -@@ -768,25 +775,21 @@ static int sunxi_mmc_clk_set_rate(struct - - rate = clk_round_rate(host->clk_mmc, clock); - if (rate < 0) { -- dev_err(mmc_dev(host->mmc), "error rounding clk to %d: %ld\n", -+ dev_err(mmc_dev(mmc), "error rounding clk to %d: %ld\n", - clock, rate); - return rate; - } -- dev_dbg(mmc_dev(host->mmc), "setting clk to %d, rounded %ld\n", -+ dev_dbg(mmc_dev(mmc), "setting clk to %d, rounded %ld\n", - clock, rate); - - /* setting clock rate */ - ret = clk_set_rate(host->clk_mmc, rate); - if (ret) { -- dev_err(mmc_dev(host->mmc), "error setting clk to %ld: %d\n", -+ dev_err(mmc_dev(mmc), "error setting clk to %ld: %d\n", - rate, ret); - return ret; - } - -- ret = sunxi_mmc_oclk_onoff(host, 0); -- if (ret) -- return ret; -- - /* clear internal divider */ - rval = mmc_readl(host, REG_CLKCR); - rval &= ~0xff; -@@ -798,6 +801,13 @@ static int sunxi_mmc_clk_set_rate(struct - } - mmc_writel(host, REG_CLKCR, rval); - -+ if (host->cfg->needs_new_timings) { -+ /* Don't touch the delay bits */ -+ rval = mmc_readl(host, REG_SD_NTSR); -+ rval |= SDXC_2X_TIMING_MODE; -+ mmc_writel(host, REG_SD_NTSR, rval); -+ } -+ - ret = sunxi_mmc_clk_set_phase(host, ios, rate); - if (ret) - return ret; -@@ -806,9 +816,22 @@ static int sunxi_mmc_clk_set_rate(struct - if (ret) - return ret; - -- /* TODO: enable calibrate on sdc2 SDXC_REG_DS_DL_REG of A64 */ -+ /* -+ * FIXME: -+ * -+ * In HS400 we'll also need to calibrate the data strobe -+ * signal. This should only happen on the MMC2 controller (at -+ * least on the A64). -+ */ -+ -+ ret = sunxi_mmc_oclk_onoff(host, 1); -+ if (ret) -+ return ret; - -- return sunxi_mmc_oclk_onoff(host, 1); -+ /* And we just enabled our clock back */ -+ mmc->actual_clock = rate; -+ -+ return 0; - } - - static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -822,10 +845,13 @@ static void sunxi_mmc_set_ios(struct mmc - break; - - case MMC_POWER_UP: -- host->ferror = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, -- ios->vdd); -- if (host->ferror) -- return; -+ if (!IS_ERR(mmc->supply.vmmc)) { -+ host->ferror = mmc_regulator_set_ocr(mmc, -+ mmc->supply.vmmc, -+ ios->vdd); -+ if (host->ferror) -+ return; -+ } - - if (!IS_ERR(mmc->supply.vqmmc)) { - host->ferror = regulator_enable(mmc->supply.vqmmc); -@@ -847,7 +873,9 @@ static void sunxi_mmc_set_ios(struct mmc - case MMC_POWER_OFF: - dev_dbg(mmc_dev(mmc), "power off!\n"); - sunxi_mmc_reset_host(host); -- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); -+ if (!IS_ERR(mmc->supply.vmmc)) -+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); -+ - if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) - regulator_disable(mmc->supply.vqmmc); - host->vqmmc_enabled = false; -@@ -877,7 +905,7 @@ static void sunxi_mmc_set_ios(struct mmc - mmc_writel(host, REG_GCTRL, rval); - - /* set up clock */ -- if (ios->clock && ios->power_mode) { -+ if (ios->power_mode) { - host->ferror = sunxi_mmc_clk_set_rate(host, ios); - /* Android code had a usleep_range(50000, 55000); here */ - } -@@ -1084,6 +1112,14 @@ static const struct sunxi_mmc_cfg sun50i - .idma_des_size_bits = 16, - .clk_delays = NULL, - .can_calibrate = true, -+ .mask_data0 = true, -+ .needs_new_timings = true, -+}; -+ -+static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = { -+ .idma_des_size_bits = 13, -+ .clk_delays = NULL, -+ .can_calibrate = true, - }; - - static const struct of_device_id sunxi_mmc_of_match[] = { -@@ -1092,6 +1128,7 @@ static const struct of_device_id sunxi_m - { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg }, - { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg }, - { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg }, -+ { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg }, - { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); diff --git a/target/linux/sunxi/patches-4.9/115-musb-ignore-vbus-errors.patch b/target/linux/sunxi/patches-4.9/115-musb-ignore-vbus-errors.patch deleted file mode 100644 index 460aec078c..0000000000 --- a/target/linux/sunxi/patches-4.9/115-musb-ignore-vbus-errors.patch +++ /dev/null @@ -1,26 +0,0 @@ -From fce20ac5d8c98f1a8ea5298051d9fa669e455f04 Mon Sep 17 00:00:00 2001 -From: Hans de Goede -Date: Tue, 4 Aug 2015 23:22:45 +0200 -Subject: [PATCH] musb: sunxi: Ignore VBus errors in host-only mode - -For some unclear reason sometimes we get VBus errors in host-only mode, -even though we do not have any vbus-detection then. Ignore these. - -Signed-off-by: Hans de Goede ---- - drivers/usb/musb/sunxi.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/usb/musb/sunxi.c -+++ b/drivers/usb/musb/sunxi.c -@@ -202,6 +202,10 @@ static irqreturn_t sunxi_musb_interrupt( - musb_writeb(musb->mregs, MUSB_FADDR, 0); - } - -+ /* Ignore Vbus errors when in host only mode */ -+ if (musb->port_mode == MUSB_PORT_MODE_HOST) -+ musb->int_usb &= ~MUSB_INTR_VBUSERROR; -+ - musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX); - if (musb->int_tx) - writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX); diff --git a/target/linux/sunxi/patches-4.9/131-reset-add-h3-resets.patch b/target/linux/sunxi/patches-4.9/131-reset-add-h3-resets.patch deleted file mode 100644 index dee01dc020..0000000000 --- a/target/linux/sunxi/patches-4.9/131-reset-add-h3-resets.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 5f0bb9d0bc545ef53a83f7bd176fdc0736eed8e5 Mon Sep 17 00:00:00 2001 -From: Jens Kuske -Date: Tue, 27 Oct 2015 17:50:24 +0100 -Subject: [PATCH] reset: sunxi: Add Allwinner H3 bus resets - -The H3 bus resets have some holes between the registers, so we add -an of_xlate() function to skip them according to the datasheet. - -Signed-off-by: Jens Kuske ---- - .../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 + - drivers/reset/reset-sunxi.c | 30 +++++++++++++++++++--- - 2 files changed, 28 insertions(+), 3 deletions(-) - ---- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt -+++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt -@@ -8,6 +8,7 @@ Required properties: - - compatible: Should be one of the following: - "allwinner,sun6i-a31-ahb1-reset" - "allwinner,sun6i-a31-clock-reset" -+ "allwinner,sun8i-h3-bus-reset" - - reg: should be register base and length as documented in the - datasheet - - #reset-cells: 1, see below ---- a/drivers/reset/reset-sunxi.c -+++ b/drivers/reset/reset-sunxi.c -@@ -75,7 +75,9 @@ static const struct reset_control_ops su - .deassert = sunxi_reset_deassert, - }; - --static int sunxi_reset_init(struct device_node *np) -+static int sunxi_reset_init(struct device_node *np, -+ int (*of_xlate)(struct reset_controller_dev *rcdev, -+ const struct of_phandle_args *reset_spec)) - { - struct sunxi_reset_data *data; - struct resource res; -@@ -108,6 +110,7 @@ static int sunxi_reset_init(struct devic - data->rcdev.nr_resets = size * 32; - data->rcdev.ops = &sunxi_reset_ops; - data->rcdev.of_node = np; -+ data->rcdev.of_xlate = of_xlate; - - return reset_controller_register(&data->rcdev); - -@@ -116,6 +119,21 @@ err_alloc: - return ret; - }; - -+static int sun8i_h3_bus_reset_xlate(struct reset_controller_dev *rcdev, -+ const struct of_phandle_args *reset_spec) -+{ -+ unsigned int index = reset_spec->args[0]; -+ -+ if (index < 96) -+ return index; -+ else if (index < 128) -+ return index + 32; -+ else if (index < 160) -+ return index + 64; -+ else -+ return -EINVAL; -+} -+ - /* - * These are the reset controller we need to initialize early on in - * our system, before we can even think of using a regular device -@@ -123,15 +141,21 @@ err_alloc: - */ - static const struct of_device_id sunxi_early_reset_dt_ids[] __initconst = { - { .compatible = "allwinner,sun6i-a31-ahb1-reset", }, -+ { .compatible = "allwinner,sun8i-h3-bus-reset", .data = sun8i_h3_bus_reset_xlate, }, - { /* sentinel */ }, - }; - - void __init sun6i_reset_init(void) - { - struct device_node *np; -- -- for_each_matching_node(np, sunxi_early_reset_dt_ids) -- sunxi_reset_init(np); -+ const struct of_device_id *match; -+ int (*of_xlate)(struct reset_controller_dev *rcdev, -+ const struct of_phandle_args *reset_spec); -+ -+ for_each_matching_node_and_match(np, sunxi_early_reset_dt_ids, &match) { -+ of_xlate = match->data; -+ sunxi_reset_init(np, of_xlate); -+ } - } - - /* diff --git a/target/linux/sunxi/patches-4.9/200-ARM-dts-sunxi-add-support-for-Orange-Pi-R1-board.patch b/target/linux/sunxi/patches-4.9/200-ARM-dts-sunxi-add-support-for-Orange-Pi-R1-board.patch deleted file mode 100644 index 7e92a565fa..0000000000 --- a/target/linux/sunxi/patches-4.9/200-ARM-dts-sunxi-add-support-for-Orange-Pi-R1-board.patch +++ /dev/null @@ -1,196 +0,0 @@ -From daf75255fb67bf44db178e4c95a803b7972ed670 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens -Date: Tue, 26 Sep 2017 22:29:06 +0200 -Subject: ARM: dts: sunxi: add support for Orange Pi R1 board - -Signed-off-by: Hauke Mehrtens ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts | 171 ++++++++++++++++++++++++ - 2 files changed, 172 insertions(+) - create mode 100644 arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -819,6 +819,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ - sun8i-a33-sinlinx-sina33.dtb \ - sun8i-a83t-allwinner-h8homlet-v2.dtb \ - sun8i-a83t-cubietruck-plus.dtb \ -+ sun8i-h2-plus-orangepi-r1.dtb \ - sun8i-h3-bananapi-m2-plus.dtb \ - sun8i-h3-nanopi-neo.dtb \ - sun8i-h3-orangepi-2.dtb \ ---- /dev/null -+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dts -@@ -0,0 +1,171 @@ -+/* -+ * Copyright (C) 2017 Hauke Mehrtens -+ * -+ * Based on sun8i-h2-plus-orangepi-zero.dts, which is: -+ * Copyright (C) 2016 Icenowy Zheng -+ * -+ * Based on sun8i-h3-orangepi-one.dts, which is: -+ * Copyright (C) 2016 Hans de Goede -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+/dts-v1/; -+#include "sun8i-h3.dtsi" -+#include "sunxi-common-regulators.dtsi" -+ -+#include -+#include -+#include -+ -+/ { -+ model = "Xunlong Orange Pi R1"; -+ compatible = "xunlong,orangepi-r1", "allwinner,sun8i-h2-plus"; -+ -+ aliases { -+ serial0 = &uart0; -+ /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */ -+ ethernet0 = &emac; -+ ethernet1 = &xr819; -+ }; -+ -+ chosen { -+ stdout-path = "serial0:115200n8"; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ pwr_led { -+ label = "orangepi:green:pwr"; -+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; -+ default-state = "on"; -+ }; -+ -+ status_led { -+ label = "orangepi:red:status"; -+ gpios = <&pio 0 17 GPIO_ACTIVE_HIGH>; -+ }; -+ }; -+ -+ reg_vcc_wifi: reg_vcc_wifi { -+ compatible = "regulator-fixed"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ regulator-name = "vcc-wifi"; -+ enable-active-high; -+ gpio = <&pio 0 20 GPIO_ACTIVE_HIGH>; -+ }; -+ -+ wifi_pwrseq: wifi_pwrseq { -+ compatible = "mmc-pwrseq-simple"; -+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; -+ post-power-on-delay-ms = <200>; -+ }; -+}; -+ -+&ehci1 { -+ status = "okay"; -+}; -+ -+&emac { -+ phy-handle = <&int_mii_phy>; -+ phy-mode = "mii"; -+ allwinner,leds-active-low; -+ status = "okay"; -+}; -+ -+&mmc0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc0_pins_a>; -+ vmmc-supply = <®_vcc3v3>; -+ bus-width = <4>; -+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ -+ cd-inverted; -+ status = "okay"; -+}; -+ -+&mmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc1_pins_a>; -+ vmmc-supply = <®_vcc_wifi>; -+ mmc-pwrseq = <&wifi_pwrseq>; -+ bus-width = <4>; -+ non-removable; -+ status = "okay"; -+ -+ /* -+ * Explicitly define the sdio device, so that we can add an ethernet -+ * alias for it (which e.g. makes u-boot set a mac-address). -+ */ -+ xr819: sdio_wifi@1 { -+ reg = <1>; -+ }; -+}; -+ -+&mmc1_pins_a { -+ bias-pull-up; -+}; -+ -+&ohci1 { -+ status = "okay"; -+}; -+ -+&uart0 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart0_pins_a>; -+ status = "okay"; -+}; -+ -+&uart1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart1_pins>; -+ status = "disabled"; -+}; -+ -+&uart2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&uart2_pins>; -+ status = "disabled"; -+}; -+ -+&usbphy { -+ /* USB VBUS is always on */ -+ status = "okay"; -+}; diff --git a/target/linux/sunxi/patches-4.9/205-arm-dts-sun8i-add-support-for-nanopi-m1-plus-board.patch b/target/linux/sunxi/patches-4.9/205-arm-dts-sun8i-add-support-for-nanopi-m1-plus-board.patch deleted file mode 100644 index d0ee8edd14..0000000000 --- a/target/linux/sunxi/patches-4.9/205-arm-dts-sun8i-add-support-for-nanopi-m1-plus-board.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 2ed2388bc0c5b7d04c7b079d673ce61a0333c818 Mon Sep 17 00:00:00 2001 -From: Jagan Teki -Date: Tue, 30 May 2017 17:42:50 +0000 -Subject: ARM: dts: sun8i: h3: Add initial NanoPi M1 Plus support - -Backported support from kernel 4.13 with the following changes: -- Added WiFi node -- Added Ethernet node -- Added eMMC node - -Original commit message: -NanoPi M1 Plus is designed and developed by FriendlyElec -for professionals, enterprise users, makers and hobbyists -using the Allwinner H3 SOC. - -NanoPi M1 Plus key features -- Allwinner H3, Quad-core Cortex-A7@1.2GHz -- 1GB DDR3 RAM -- 8GB eMMC -- microSD slot -- 10/100/1000M Ethernet -- Serial Debug Port -- 5V 2A DC power-supply - -Signed-off-by: Jagan Teki -Signed-off-by: Maxime Ripard ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -821,6 +821,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \ - sun8i-a83t-cubietruck-plus.dtb \ - sun8i-h2-plus-orangepi-r1.dtb \ - sun8i-h3-bananapi-m2-plus.dtb \ -+ sun8i-h3-nanopi-m1-plus.dtb \ - sun8i-h3-nanopi-neo.dtb \ - sun8i-h3-orangepi-2.dtb \ - sun8i-h3-orangepi-lite.dtb \ ---- /dev/null -+++ b/arch/arm/boot/dts/sun8i-h3-nanopi-m1-plus.dts -@@ -0,0 +1,129 @@ -+/* -+ * Copyright (C) 2017 Jagan Teki -+ * -+ * This file is dual-licensed: you can use it either under the terms -+ * of the GPL or the X11 license, at your option. Note that this dual -+ * licensing only applies to this file, and not this project as a -+ * whole. -+ * -+ * a) This file 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 file 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. -+ * -+ * Or, alternatively, -+ * -+ * b) Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation -+ * files (the "Software"), to deal in the Software without -+ * restriction, including without limitation the rights to use, -+ * copy, modify, merge, publish, distribute, sublicense, and/or -+ * sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following -+ * conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include "sun8i-h3-nanopi.dtsi" -+ -+/ { -+ model = "FriendlyArm NanoPi M1 Plus"; -+ compatible = "friendlyarm,nanopi-m1-plus", "allwinner,sun8i-h3"; -+ -+ aliases { -+ ethernet0 = &emac; -+ }; -+ -+ pwrseq_wifi: pwrseq0 { -+ compatible = "mmc-pwrseq-simple"; -+ pinctrl-names = "default"; -+ reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */ -+ }; -+ -+ reg_gmac_3v3: gmac-3v3 { -+ compatible = "regulator-fixed"; -+ regulator-name = "gmac-3v3"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ startup-delay-us = <100000>; -+ enable-active-high; -+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ -+ }; -+}; -+ -+&ehci1 { -+ status = "okay"; -+}; -+ -+&ehci2 { -+ status = "okay"; -+}; -+ -+&emac { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emac_rgmii_pins>; -+ phy-supply = <®_gmac_3v3>; -+ phy-handle = <&ext_rgmii_phy>; -+ phy-mode = "rgmii"; -+ status = "okay"; -+}; -+ -+&mdio { -+ ext_rgmii_phy: ethernet-phy@7 { -+ compatible = "ethernet-phy-ieee802.3-c22"; -+ reg = <7>; -+ }; -+}; -+ -+&mmc1 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc1_pins_a>; -+ vmmc-supply = <®_vcc3v3>; -+ vqmmc-supply = <®_vcc3v3>; -+ mmc-pwrseq = <&pwrseq_wifi>; -+ bus-width = <4>; -+ non-removable; -+ status = "okay"; -+ -+ brcmf: wifi@1 { -+ reg = <1>; -+ compatible = "brcm,bcm4329-fmac"; -+ interrupt-parent = <&pio>; -+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 / EINT10 */ -+ interrupt-names = "host-wake"; -+ }; -+}; -+ -+&mmc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&mmc2_8bit_pins>; -+ vmmc-supply = <®_vcc3v3>; -+ vqmmc-supply = <®_vcc3v3>; -+ bus-width = <8>; -+ non-removable; -+ status = "okay"; -+}; -+ -+&ohci1 { -+ status = "okay"; -+}; -+ -+&ohci2 { -+ status = "okay"; -+};