mvebu: remove linux 4.4 support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -1,437 +0,0 @@ | ||||
| CONFIG_AHCI_MVEBU=y | ||||
| CONFIG_ALIGNMENT_TRAP=y | ||||
| CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=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_MVEBU=y | ||||
| CONFIG_ARCH_NR_GPIO=0 | ||||
| CONFIG_ARCH_REQUIRE_GPIOLIB=y | ||||
| # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set | ||||
| # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set | ||||
| 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_ARCH_WANT_OPTIONAL_GPIOLIB=y | ||||
| CONFIG_ARM=y | ||||
| CONFIG_ARMADA_370_CLK=y | ||||
| CONFIG_ARMADA_370_XP_TIMER=y | ||||
| CONFIG_ARMADA_38X_CLK=y | ||||
| CONFIG_ARMADA_THERMAL=y | ||||
| CONFIG_ARMADA_XP_CLK=y | ||||
| CONFIG_ARM_APPENDED_DTB=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_CRYPTO=y | ||||
| CONFIG_ARM_ERRATA_720789=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 is not set | ||||
| CONFIG_ARM_MVEBU_V7_CPUIDLE=y | ||||
| CONFIG_ARM_PATCH_PHYS_VIRT=y | ||||
| CONFIG_ARM_THUMB=y | ||||
| # CONFIG_ARM_THUMBEE is not set | ||||
| CONFIG_ARM_UNWIND=y | ||||
| CONFIG_ARM_VIRT_EXT=y | ||||
| CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y | ||||
| CONFIG_ATA=y | ||||
| CONFIG_ATAGS=y | ||||
| CONFIG_AUTO_ZRELADDR=y | ||||
| CONFIG_BLK_DEV_LOOP=y | ||||
| CONFIG_BOUNCE=y | ||||
| # CONFIG_CACHE_FEROCEON_L2 is not set | ||||
| CONFIG_CACHE_L2X0=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_CPUFREQ_DT=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_ONDEMAND=y | ||||
| # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set | ||||
| CONFIG_CPU_FREQ_GOV_COMMON=y | ||||
| # CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set | ||||
| CONFIG_CPU_FREQ_GOV_ONDEMAND=y | ||||
| CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||||
| # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set | ||||
| # CONFIG_CPU_FREQ_GOV_USERSPACE is not set | ||||
| CONFIG_CPU_FREQ_STAT=y | ||||
| CONFIG_CPU_HAS_ASID=y | ||||
| # CONFIG_CPU_ICACHE_DISABLE is not set | ||||
| CONFIG_CPU_IDLE=y | ||||
| CONFIG_CPU_IDLE_GOV_LADDER=y | ||||
| CONFIG_CPU_PABRT_V7=y | ||||
| CONFIG_CPU_PJ4B=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_CRYPTO_ABLK_HELPER=y | ||||
| CONFIG_CRYPTO_AEAD=y | ||||
| CONFIG_CRYPTO_AEAD2=y | ||||
| CONFIG_CRYPTO_AES_ARM=y | ||||
| CONFIG_CRYPTO_AES_ARM_BS=y | ||||
| # CONFIG_CRYPTO_AES_ARM_CE is not set | ||||
| CONFIG_CRYPTO_CRC32C=y | ||||
| CONFIG_CRYPTO_CRYPTD=y | ||||
| CONFIG_CRYPTO_DEFLATE=y | ||||
| CONFIG_CRYPTO_DES=y | ||||
| CONFIG_CRYPTO_DEV_MARVELL_CESA=y | ||||
| # CONFIG_CRYPTO_GHASH_ARM_CE is not set | ||||
| CONFIG_CRYPTO_HASH=y | ||||
| CONFIG_CRYPTO_HASH2=y | ||||
| CONFIG_CRYPTO_HW=y | ||||
| CONFIG_CRYPTO_LZO=y | ||||
| CONFIG_CRYPTO_MANAGER=y | ||||
| CONFIG_CRYPTO_MANAGER2=y | ||||
| CONFIG_CRYPTO_NULL2=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_SHA1=y | ||||
| CONFIG_CRYPTO_SHA1_ARM=y | ||||
| # CONFIG_CRYPTO_SHA1_ARM_CE is not set | ||||
| CONFIG_CRYPTO_SHA1_ARM_NEON=y | ||||
| CONFIG_CRYPTO_SHA256_ARM=y | ||||
| # CONFIG_CRYPTO_SHA2_ARM_CE is not set | ||||
| CONFIG_CRYPTO_SHA512_ARM=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_DCACHE_WORD_ACCESS=y | ||||
| CONFIG_DEBUG_INFO=y | ||||
| CONFIG_DEBUG_LL=y | ||||
| CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" | ||||
| CONFIG_DEBUG_MVEBU_UART0=y | ||||
| # CONFIG_DEBUG_MVEBU_UART0_ALTERNATE is not set | ||||
| # CONFIG_DEBUG_MVEBU_UART1_ALTERNATE is not set | ||||
| CONFIG_DEBUG_UART_8250=y | ||||
| # CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set | ||||
| CONFIG_DEBUG_UART_8250_SHIFT=2 | ||||
| # CONFIG_DEBUG_UART_8250_WORD is not set | ||||
| CONFIG_DEBUG_UART_PHYS=0xd0012000 | ||||
| CONFIG_DEBUG_UART_VIRT=0xfec12000 | ||||
| CONFIG_DEBUG_UNCOMPRESS=y | ||||
| CONFIG_DEBUG_USER=y | ||||
| CONFIG_DMADEVICES=y | ||||
| CONFIG_DMA_ENGINE=y | ||||
| CONFIG_DMA_ENGINE_RAID=y | ||||
| CONFIG_DMA_OF=y | ||||
| CONFIG_DTC=y | ||||
| # CONFIG_DW_DMAC_PCI is not set | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_EDAC_ATOMIC_SCRUB=y | ||||
| CONFIG_EDAC_SUPPORT=y | ||||
| CONFIG_EXT4_FS=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_FIXED_PHY=y | ||||
| CONFIG_FIX_EARLYCON_MEM=y | ||||
| CONFIG_FS_MBCACHE=y | ||||
| CONFIG_GENERIC_ALLOCATOR=y | ||||
| CONFIG_GENERIC_BUG=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=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_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_STRNCPY_FROM_USER=y | ||||
| CONFIG_GENERIC_STRNLEN_USER=y | ||||
| CONFIG_GLOB=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_DEVRES=y | ||||
| CONFIG_GPIO_MVEBU=y | ||||
| CONFIG_GPIO_MVEBU_PWM=y | ||||
| CONFIG_GPIO_PCA953X=y | ||||
| # CONFIG_GPIO_PCA953X_IRQ is not set | ||||
| 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_ARM_SCU=y | ||||
| CONFIG_HAVE_ARM_TWD=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_BPF_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_ATTRS=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_IDE=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=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_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 is not set | ||||
| CONFIG_HOTPLUG_CPU=y | ||||
| CONFIG_HWBM=y | ||||
| CONFIG_HWMON=y | ||||
| CONFIG_HZ_FIXED=0 | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_I2C=y | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
| CONFIG_I2C_CHARDEV=y | ||||
| CONFIG_I2C_MV64XXX=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IOMMU_HELPER=y | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_DOMAIN_DEBUG=y | ||||
| CONFIG_IRQ_DOMAIN_HIERARCHY=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| # CONFIG_IWMMXT is not set | ||||
| CONFIG_JBD2=y | ||||
| CONFIG_LEDS_GPIO=y | ||||
| CONFIG_LEDS_PCA963X=y | ||||
| CONFIG_LEDS_TLC591XX=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_LOCK_SPIN_ON_OWNER=y | ||||
| CONFIG_LZO_COMPRESS=y | ||||
| CONFIG_LZO_DECOMPRESS=y | ||||
| CONFIG_MACH_ARMADA_370=y | ||||
| # CONFIG_MACH_ARMADA_375 is not set | ||||
| CONFIG_MACH_ARMADA_38X=y | ||||
| # CONFIG_MACH_ARMADA_39X is not set | ||||
| CONFIG_MACH_ARMADA_XP=y | ||||
| # CONFIG_MACH_DOVE is not set | ||||
| CONFIG_MACH_MVEBU_ANY=y | ||||
| CONFIG_MACH_MVEBU_V7=y | ||||
| CONFIG_MAGIC_SYSRQ=y | ||||
| CONFIG_MANGLE_BOOTARGS=y | ||||
| CONFIG_MARVELL_PHY=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MDIO_I2C=y | ||||
| CONFIG_MEMORY=y | ||||
| CONFIG_MIGHT_HAVE_CACHE_L2X0=y | ||||
| CONFIG_MIGHT_HAVE_PCI=y | ||||
| CONFIG_MMC=y | ||||
| CONFIG_MMC_BLOCK=y | ||||
| CONFIG_MMC_MVSDIO=y | ||||
| CONFIG_MMC_SDHCI=y | ||||
| # CONFIG_MMC_SDHCI_PCI is not set | ||||
| CONFIG_MMC_SDHCI_PLTFM=y | ||||
| CONFIG_MMC_SDHCI_PXAV3=y | ||||
| # CONFIG_MMC_TIFM_SD is not set | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| CONFIG_MTD_CFI_STAA=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_NAND=y | ||||
| CONFIG_MTD_NAND_ECC=y | ||||
| CONFIG_MTD_NAND_PXA3xx=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_UBI=y | ||||
| CONFIG_MTD_UBI_BEB_LIMIT=20 | ||||
| CONFIG_MTD_UBI_BLOCK=y | ||||
| # CONFIG_MTD_UBI_FASTMAP is not set | ||||
| # CONFIG_MTD_UBI_GLUEBI is not set | ||||
| CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||||
| CONFIG_MULTI_IRQ_HANDLER=y | ||||
| CONFIG_MUTEX_SPIN_ON_OWNER=y | ||||
| CONFIG_MVEBU_CLK_COMMON=y | ||||
| CONFIG_MVEBU_CLK_COREDIV=y | ||||
| CONFIG_MVEBU_CLK_CPU=y | ||||
| CONFIG_MVEBU_DEVBUS=y | ||||
| CONFIG_MVEBU_MBUS=y | ||||
| CONFIG_MVMDIO=y | ||||
| CONFIG_MVNETA=y | ||||
| CONFIG_MVNETA_BM=y | ||||
| CONFIG_MVSW61XX_PHY=y | ||||
| CONFIG_MV_XOR=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEON=y | ||||
| CONFIG_NET_FLOW_LIMIT=y | ||||
| CONFIG_NLS=y | ||||
| CONFIG_NOP_USB_XCEIV=y | ||||
| CONFIG_NO_BOOTMEM=y | ||||
| CONFIG_NR_CPUS=4 | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_MTD=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_OF_RESERVED_MEM=y | ||||
| CONFIG_OLD_SIGACTION=y | ||||
| CONFIG_OLD_SIGSUSPEND3=y | ||||
| CONFIG_ORION_WATCHDOG=y | ||||
| CONFIG_OUTER_CACHE=y | ||||
| CONFIG_OUTER_CACHE_SYNC=y | ||||
| CONFIG_PAGE_OFFSET=0xC0000000 | ||||
| CONFIG_PCI=y | ||||
| # CONFIG_PCI_DOMAINS_GENERIC is not set | ||||
| CONFIG_PCI_MVEBU=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHYLINK=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_ARMADA_370=y | ||||
| CONFIG_PINCTRL_ARMADA_38X=y | ||||
| CONFIG_PINCTRL_ARMADA_XP=y | ||||
| CONFIG_PINCTRL_MVEBU=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_PJ4B_ERRATA_4742=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_PLAT_ORION=y | ||||
| CONFIG_PM_OPP=y | ||||
| CONFIG_PWM=y | ||||
| CONFIG_PWM_SYSFS=y | ||||
| CONFIG_RATIONAL=y | ||||
| CONFIG_RCU_STALL_COMMON=y | ||||
| CONFIG_REGMAP=y | ||||
| CONFIG_REGMAP_I2C=y | ||||
| CONFIG_REGULATOR=y | ||||
| CONFIG_REGULATOR_FIXED_VOLTAGE=y | ||||
| CONFIG_RFS_ACCEL=y | ||||
| CONFIG_RPS=y | ||||
| CONFIG_RTC_CLASS=y | ||||
| CONFIG_RTC_DRV_ARMADA38X=y | ||||
| CONFIG_RTC_DRV_MV=y | ||||
| CONFIG_RWSEM_SPIN_ON_OWNER=y | ||||
| CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||||
| CONFIG_SATA_AHCI_PLATFORM=y | ||||
| CONFIG_SATA_MV=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| CONFIG_SCSI=y | ||||
| CONFIG_SENSORS_PWM_FAN=y | ||||
| CONFIG_SENSORS_TMP421=y | ||||
| CONFIG_SERIAL_8250_DW=y | ||||
| CONFIG_SERIAL_8250_FSL=y | ||||
| CONFIG_SFP=y | ||||
| CONFIG_SMP=y | ||||
| CONFIG_SMP_ON_UP=y | ||||
| CONFIG_SOC_BUS=y | ||||
| CONFIG_SPARSE_IRQ=y | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_ORION=y | ||||
| CONFIG_SRAM=y | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWIOTLB=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SWP_EMULATE=y | ||||
| CONFIG_SYS_SUPPORTS_APM_EMULATION=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_TIMER_STATS=y | ||||
| CONFIG_TREE_RCU=y | ||||
| CONFIG_UBIFS_FS=y | ||||
| # CONFIG_UBIFS_FS_ADVANCED_COMPR is not set | ||||
| CONFIG_UBIFS_FS_LZO=y | ||||
| CONFIG_UBIFS_FS_ZLIB=y | ||||
| CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" | ||||
| CONFIG_USB=y | ||||
| CONFIG_USB_COMMON=y | ||||
| CONFIG_USB_EHCI_HCD=y | ||||
| CONFIG_USB_EHCI_HCD_ORION=y | ||||
| CONFIG_USB_EHCI_HCD_PLATFORM=y | ||||
| CONFIG_USB_EHCI_PCI=y | ||||
| CONFIG_USB_LEDS_TRIGGER_USBPORT=y | ||||
| CONFIG_USB_PHY=y | ||||
| CONFIG_USB_STORAGE=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| # CONFIG_USB_UHCI_HCD is not set | ||||
| CONFIG_USB_XHCI_HCD=y | ||||
| CONFIG_USB_XHCI_MVEBU=y | ||||
| CONFIG_USB_XHCI_PCI=y | ||||
| CONFIG_USB_XHCI_PLATFORM=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_VECTORS_BASE=0xffff0000 | ||||
| CONFIG_VFP=y | ||||
| CONFIG_VFPv3=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
| CONFIG_XPS=y | ||||
| CONFIG_XZ_DEC_ARM=y | ||||
| CONFIG_XZ_DEC_BCJ=y | ||||
| CONFIG_ZBOOT_ROM_BSS=0x0 | ||||
| CONFIG_ZBOOT_ROM_TEXT=0x0 | ||||
| CONFIG_ZLIB_DEFLATE=y | ||||
| CONFIG_ZLIB_INFLATE=y | ||||
| CONFIG_ZONE_DMA_FLAG=0 | ||||
| @@ -1,748 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| @@ -86,12 +86,100 @@ | ||||
|  			pcie@2,0 { | ||||
|  				/* Port 0, Lane 1 */ | ||||
|  				status = "okay"; | ||||
| + | ||||
| +				mwlwifi { | ||||
| +					marvell,5ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						FCC = | ||||
| +							<1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| + | ||||
| +						ETSI = | ||||
| +							<1 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
|  			}; | ||||
|   | ||||
|  			/* Second mini-PCIe port */ | ||||
|  			pcie@3,0 { | ||||
|  				/* Port 0, Lane 3 */ | ||||
|  				status = "okay"; | ||||
| + | ||||
| +				mwlwifi { | ||||
| +					marvell,2ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						FCC = | ||||
| +							<36 0 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<40 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<44 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<48 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<52 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, | ||||
| +							<56 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, | ||||
| +							<60 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, | ||||
| +							<64 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, | ||||
| +							<100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>; | ||||
| + | ||||
| +						ETSI = | ||||
| +							<36 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<40 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<44 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<48 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<52 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<56 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<60 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<64 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<100 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<104 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<108 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<112 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<116 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<120 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<124 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<128 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<132 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<136 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<140 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, | ||||
| +							<149 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
|  			}; | ||||
|  		}; | ||||
|   | ||||
| --- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts | ||||
| +++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts | ||||
| @@ -100,6 +100,212 @@ | ||||
|  				}; | ||||
|  			}; | ||||
|  		}; | ||||
| + | ||||
| +		pcie-controller { | ||||
| +			pcie@1,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,2ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; | ||||
| +						CA = | ||||
| +							<36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; | ||||
| +						CN = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; | ||||
| +						FCC = | ||||
| +							<36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			pcie@2,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,5ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						CA = | ||||
| +							<1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						CN = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						FCC = | ||||
| +							<1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	gpio-leds { | ||||
| --- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts | ||||
| +++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts | ||||
| @@ -100,6 +100,212 @@ | ||||
|  				}; | ||||
|  			}; | ||||
|  		}; | ||||
| + | ||||
| +		pcie-controller { | ||||
| +			pcie@1,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,2ghz = <0>; | ||||
| +					marvell,chainmask = <2 2>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<100 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<104 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<108 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<112 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<116 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<120 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<124 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<128 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<132 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<136 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<140 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, | ||||
| +							<149 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, | ||||
| +							<153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, | ||||
| +							<157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, | ||||
| +							<161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, | ||||
| +							<165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>; | ||||
| +						CA = | ||||
| +							<36 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<40 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<44 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<48 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; | ||||
| +						CN = | ||||
| +							<36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<149 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<165 0 0x15 0x15 0x15 0x15 0x16 0x16 0x16 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, | ||||
| +							<149 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>; | ||||
| +						FCC = | ||||
| +							<36 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<40 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<44 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<48 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, | ||||
| +							<165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			pcie@2,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,5ghz = <0>; | ||||
| +					marvell,chainmask = <2 2>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						CA = | ||||
| +							<1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, | ||||
| +							<11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x00 0x00 0x00 0x00 0 0xf>; | ||||
| +						CN = | ||||
| +							<1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<14 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						FCC = | ||||
| +							<1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	gpio-leds { | ||||
| --- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts | ||||
| +++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts | ||||
| @@ -100,6 +100,212 @@ | ||||
|  				}; | ||||
|  			}; | ||||
|  		}; | ||||
| + | ||||
| +		pcie-controller { | ||||
| +			pcie@1,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,2ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, | ||||
| +							<149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, | ||||
| +							<165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; | ||||
| +						CA = | ||||
| +							<36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; | ||||
| +						CN = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, | ||||
| +							<149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; | ||||
| +						FCC = | ||||
| +							<36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, | ||||
| +							<52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, | ||||
| +							<149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, | ||||
| +							<165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			pcie@2,0 { | ||||
| +				mwlwifi { | ||||
| +					marvell,5ghz = <0>; | ||||
| +					marvell,chainmask = <4 4>; | ||||
| +					marvell,powertable { | ||||
| +						AU = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						CA = | ||||
| +							<1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						CN = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						ETSI = | ||||
| +							<1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +						FCC = | ||||
| +							<1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, | ||||
| +							<11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; | ||||
| +					}; | ||||
| +				}; | ||||
| +			}; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	gpio-leds { | ||||
| @@ -1,40 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| @@ -467,6 +467,16 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|  	}; | ||||
| + | ||||
| +	mvsw61xx { | ||||
| +		compatible = "marvell,88e6172"; | ||||
| +		status = "okay"; | ||||
| +		reg = <0x10>; | ||||
| + | ||||
| +		mii-bus = <&mdio>; | ||||
| +		cpu-port-0 = <5>; | ||||
| +		cpu-port-1 = <6>; | ||||
| +	}; | ||||
|  }; | ||||
|   | ||||
|  &pinctrl { | ||||
| --- a/arch/arm/boot/dts/armada-385-linksys.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-385-linksys.dtsi | ||||
| @@ -309,6 +309,18 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|  	}; | ||||
| + | ||||
| +	mvsw61xx { | ||||
| +		#address-cells = <1>; | ||||
| +		#size-cells = <0>; | ||||
| +		compatible = "marvell,88e6176"; | ||||
| +		status = "okay"; | ||||
| +		reg = <0x10>; | ||||
| + | ||||
| +		mii-bus = <&mdio>; | ||||
| +		cpu-port-0 = <5>; | ||||
| +		cpu-port-1 = <6>; | ||||
| +	}; | ||||
|  }; | ||||
|   | ||||
|  &pinctrl { | ||||
| @@ -1,11 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/Makefile | ||||
| +++ b/arch/arm/boot/dts/Makefile | ||||
| @@ -748,6 +748,8 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ | ||||
|  	armada-385-db-ap.dtb \ | ||||
|  	armada-385-linksys-caiman.dtb \ | ||||
|  	armada-385-linksys-cobra.dtb \ | ||||
| +	armada-385-linksys-rango.dtb \ | ||||
| +	armada-385-linksys-shelby.dtb \ | ||||
|  	armada-388-db.dtb \ | ||||
|  	armada-388-gp.dtb \ | ||||
|  	armada-388-rd.dtb | ||||
| @@ -1,428 +0,0 @@ | ||||
| From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||||
| Date: Wed, 10 Feb 2016 14:54:21 +0100 | ||||
| Subject: [PATCH] mtd: nand: pxa3xx_nand: add support for partial chunks | ||||
|  | ||||
| This commit is needed to properly support the 8-bits ECC configuration | ||||
| with 4KB pages. | ||||
|  | ||||
| When pages larger than 2 KB are used on platforms using the PXA3xx | ||||
| NAND controller, the reading/programming operations need to be split | ||||
| in chunks of 2 KBs or less because the controller FIFO is limited to | ||||
| about 2 KB (i.e a bit more than 2 KB to accommodate OOB data). Due to | ||||
| this requirement, the data layout on NAND is a bit strange, with ECC | ||||
| interleaved with data, at the end of each chunk. | ||||
|  | ||||
| When a 4-bits ECC configuration is used with 4 KB pages, the physical | ||||
| data layout on the NAND looks like this: | ||||
|  | ||||
| | 2048 data | 32 spare | 30 ECC | 2048 data | 32 spare | 30 ECC | | ||||
|  | ||||
| So the data chunks have an equal size, 2080 bytes for each chunk, | ||||
| which the driver supports properly. | ||||
|  | ||||
| When a 8-bits ECC configuration is used with 4KB pages, the physical | ||||
| data layout on the NAND looks like this: | ||||
|  | ||||
| | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 1024 data | 30 ECC | 64 spare | 30 ECC | | ||||
|  | ||||
| So, the spare area is stored in its own chunk, which has a different | ||||
| size than the other chunks. Since OOB is not used by UBIFS, the initial | ||||
| implementation of the driver has chosen to not support reading this | ||||
| additional "spare" chunk of data. | ||||
|  | ||||
| Unfortunately, Marvell has chosen to store the BBT signature in the | ||||
| OOB area. Therefore, if the driver doesn't read this spare area, Linux | ||||
| has no way of finding the BBT. It thinks there is no BBT, and rewrites | ||||
| one, which U-Boot does not recognize, causing compatibility problems | ||||
| between the bootloader and the kernel in terms of NAND usage. | ||||
|  | ||||
| To fix this, this commit implements the support for reading a partial | ||||
| last chunk. This support is currently only useful for the case of 8 | ||||
| bits ECC with 4 KB pages, but it will be useful in the future to | ||||
| enable other configurations such as 12 bits and 16 bits ECC with 4 KB | ||||
| pages, or 8 bits ECC with 8 KB pages, etc. All those configurations | ||||
| have a "last" chunk that doesn't have the same size as the other | ||||
| chunks. | ||||
|  | ||||
| In order to implement reading of the last chunk, this commit: | ||||
|  | ||||
|  - Adds a number of new fields to the pxa3xx_nand_info to describe how | ||||
|    many full chunks and how many chunks we have, the size of full | ||||
|    chunks and partial chunks, both in terms of data area and spare | ||||
|    area. | ||||
|  | ||||
|  - Fills in the step_chunk_size and step_spare_size variables to | ||||
|    describe how much data and spare should be read/written for the | ||||
|    current read/program step. | ||||
|  | ||||
|  - Reworks the state machine to accommodate doing the additional read | ||||
|    or program step when a last partial chunk is used. | ||||
|  | ||||
| This commit has been tested on a Marvell Armada 398 DB board, with a | ||||
| 4KB page NAND, tested in both 4 bits ECC and 8 bits ECC | ||||
| configurations. Robert Jarzmik has tested on some PXA platforms. | ||||
|  | ||||
| Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||||
| Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> | ||||
| Acked-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> | ||||
| Signed-off-by: Brian Norris <computersforpeace@gmail.com> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/mtd/nand/pxa3xx_nand.c | ||||
| +++ b/drivers/mtd/nand/pxa3xx_nand.c | ||||
| @@ -228,15 +228,44 @@ struct pxa3xx_nand_info { | ||||
|  	int			use_spare;	/* use spare ? */ | ||||
|  	int			need_wait; | ||||
|   | ||||
| -	unsigned int		data_size;	/* data to be read from FIFO */ | ||||
| -	unsigned int		chunk_size;	/* split commands chunk size */ | ||||
| -	unsigned int		oob_size; | ||||
| +	/* Amount of real data per full chunk */ | ||||
| +	unsigned int		chunk_size; | ||||
| + | ||||
| +	/* Amount of spare data per full chunk */ | ||||
|  	unsigned int		spare_size; | ||||
| + | ||||
| +	/* Number of full chunks (i.e chunk_size + spare_size) */ | ||||
| +	unsigned int            nfullchunks; | ||||
| + | ||||
| +	/* | ||||
| +	 * Total number of chunks. If equal to nfullchunks, then there | ||||
| +	 * are only full chunks. Otherwise, there is one last chunk of | ||||
| +	 * size (last_chunk_size + last_spare_size) | ||||
| +	 */ | ||||
| +	unsigned int            ntotalchunks; | ||||
| + | ||||
| +	/* Amount of real data in the last chunk */ | ||||
| +	unsigned int		last_chunk_size; | ||||
| + | ||||
| +	/* Amount of spare data in the last chunk */ | ||||
| +	unsigned int		last_spare_size; | ||||
| + | ||||
|  	unsigned int		ecc_size; | ||||
|  	unsigned int		ecc_err_cnt; | ||||
|  	unsigned int		max_bitflips; | ||||
|  	int 			retcode; | ||||
|   | ||||
| +	/* | ||||
| +	 * Variables only valid during command | ||||
| +	 * execution. step_chunk_size and step_spare_size is the | ||||
| +	 * amount of real data and spare data in the current | ||||
| +	 * chunk. cur_chunk is the current chunk being | ||||
| +	 * read/programmed. | ||||
| +	 */ | ||||
| +	unsigned int		step_chunk_size; | ||||
| +	unsigned int		step_spare_size; | ||||
| +	unsigned int            cur_chunk; | ||||
| + | ||||
|  	/* cached register value */ | ||||
|  	uint32_t		reg_ndcr; | ||||
|  	uint32_t		ndtr0cs0; | ||||
| @@ -531,25 +560,6 @@ static int pxa3xx_nand_init(struct pxa3x | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| -/* | ||||
| - * Set the data and OOB size, depending on the selected | ||||
| - * spare and ECC configuration. | ||||
| - * Only applicable to READ0, READOOB and PAGEPROG commands. | ||||
| - */ | ||||
| -static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info, | ||||
| -				struct mtd_info *mtd) | ||||
| -{ | ||||
| -	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; | ||||
| - | ||||
| -	info->data_size = mtd->writesize; | ||||
| -	if (!oob_enable) | ||||
| -		return; | ||||
| - | ||||
| -	info->oob_size = info->spare_size; | ||||
| -	if (!info->use_ecc) | ||||
| -		info->oob_size += info->ecc_size; | ||||
| -} | ||||
| - | ||||
|  /** | ||||
|   * NOTE: it is a must to set ND_RUN firstly, then write | ||||
|   * command buffer, otherwise, it does not work. | ||||
| @@ -665,28 +675,28 @@ static void drain_fifo(struct pxa3xx_nan | ||||
|   | ||||
|  static void handle_data_pio(struct pxa3xx_nand_info *info) | ||||
|  { | ||||
| -	unsigned int do_bytes = min(info->data_size, info->chunk_size); | ||||
| - | ||||
|  	switch (info->state) { | ||||
|  	case STATE_PIO_WRITING: | ||||
| -		writesl(info->mmio_base + NDDB, | ||||
| -			info->data_buff + info->data_buff_pos, | ||||
| -			DIV_ROUND_UP(do_bytes, 4)); | ||||
| +		if (info->step_chunk_size) | ||||
| +			writesl(info->mmio_base + NDDB, | ||||
| +				info->data_buff + info->data_buff_pos, | ||||
| +				DIV_ROUND_UP(info->step_chunk_size, 4)); | ||||
|   | ||||
| -		if (info->oob_size > 0) | ||||
| +		if (info->step_spare_size) | ||||
|  			writesl(info->mmio_base + NDDB, | ||||
|  				info->oob_buff + info->oob_buff_pos, | ||||
| -				DIV_ROUND_UP(info->oob_size, 4)); | ||||
| +				DIV_ROUND_UP(info->step_spare_size, 4)); | ||||
|  		break; | ||||
|  	case STATE_PIO_READING: | ||||
| -		drain_fifo(info, | ||||
| -			   info->data_buff + info->data_buff_pos, | ||||
| -			   DIV_ROUND_UP(do_bytes, 4)); | ||||
| +		if (info->step_chunk_size) | ||||
| +			drain_fifo(info, | ||||
| +				   info->data_buff + info->data_buff_pos, | ||||
| +				   DIV_ROUND_UP(info->step_chunk_size, 4)); | ||||
|   | ||||
| -		if (info->oob_size > 0) | ||||
| +		if (info->step_spare_size) | ||||
|  			drain_fifo(info, | ||||
|  				   info->oob_buff + info->oob_buff_pos, | ||||
| -				   DIV_ROUND_UP(info->oob_size, 4)); | ||||
| +				   DIV_ROUND_UP(info->step_spare_size, 4)); | ||||
|  		break; | ||||
|  	default: | ||||
|  		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, | ||||
| @@ -695,9 +705,8 @@ static void handle_data_pio(struct pxa3x | ||||
|  	} | ||||
|   | ||||
|  	/* Update buffer pointers for multi-page read/write */ | ||||
| -	info->data_buff_pos += do_bytes; | ||||
| -	info->oob_buff_pos += info->oob_size; | ||||
| -	info->data_size -= do_bytes; | ||||
| +	info->data_buff_pos += info->step_chunk_size; | ||||
| +	info->oob_buff_pos += info->step_spare_size; | ||||
|  } | ||||
|   | ||||
|  static void pxa3xx_nand_data_dma_irq(void *data) | ||||
| @@ -738,8 +747,9 @@ static void start_data_dma(struct pxa3xx | ||||
|  				info->state); | ||||
|  		BUG(); | ||||
|  	} | ||||
| -	info->sg.length = info->data_size + | ||||
| -		(info->oob_size ? info->spare_size + info->ecc_size : 0); | ||||
| +	info->sg.length = info->chunk_size; | ||||
| +	if (info->use_spare) | ||||
| +		info->sg.length += info->spare_size + info->ecc_size; | ||||
|  	dma_map_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir); | ||||
|   | ||||
|  	tx = dmaengine_prep_slave_sg(info->dma_chan, &info->sg, 1, direction, | ||||
| @@ -900,9 +910,11 @@ static void prepare_start_command(struct | ||||
|  	/* reset data and oob column point to handle data */ | ||||
|  	info->buf_start		= 0; | ||||
|  	info->buf_count		= 0; | ||||
| -	info->oob_size		= 0; | ||||
|  	info->data_buff_pos	= 0; | ||||
|  	info->oob_buff_pos	= 0; | ||||
| +	info->step_chunk_size   = 0; | ||||
| +	info->step_spare_size   = 0; | ||||
| +	info->cur_chunk         = 0; | ||||
|  	info->use_ecc		= 0; | ||||
|  	info->use_spare		= 1; | ||||
|  	info->retcode		= ERR_NONE; | ||||
| @@ -914,8 +926,6 @@ static void prepare_start_command(struct | ||||
|  	case NAND_CMD_READ0: | ||||
|  	case NAND_CMD_PAGEPROG: | ||||
|  		info->use_ecc = 1; | ||||
| -	case NAND_CMD_READOOB: | ||||
| -		pxa3xx_set_datasize(info, mtd); | ||||
|  		break; | ||||
|  	case NAND_CMD_PARAM: | ||||
|  		info->use_spare = 0; | ||||
| @@ -974,6 +984,14 @@ static int prepare_set_command(struct px | ||||
|  		if (command == NAND_CMD_READOOB) | ||||
|  			info->buf_start += mtd->writesize; | ||||
|   | ||||
| +		if (info->cur_chunk < info->nfullchunks) { | ||||
| +			info->step_chunk_size = info->chunk_size; | ||||
| +			info->step_spare_size = info->spare_size; | ||||
| +		} else { | ||||
| +			info->step_chunk_size = info->last_chunk_size; | ||||
| +			info->step_spare_size = info->last_spare_size; | ||||
| +		} | ||||
| + | ||||
|  		/* | ||||
|  		 * Multiple page read needs an 'extended command type' field, | ||||
|  		 * which is either naked-read or last-read according to the | ||||
| @@ -985,8 +1003,8 @@ static int prepare_set_command(struct px | ||||
|  			info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) | ||||
|  					| NDCB0_LEN_OVRD | ||||
|  					| NDCB0_EXT_CMD_TYPE(ext_cmd_type); | ||||
| -			info->ndcb3 = info->chunk_size + | ||||
| -				      info->oob_size; | ||||
| +			info->ndcb3 = info->step_chunk_size + | ||||
| +				info->step_spare_size; | ||||
|  		} | ||||
|   | ||||
|  		set_command_address(info, mtd->writesize, column, page_addr); | ||||
| @@ -1006,8 +1024,6 @@ static int prepare_set_command(struct px | ||||
|  				| NDCB0_EXT_CMD_TYPE(ext_cmd_type) | ||||
|  				| addr_cycle | ||||
|  				| command; | ||||
| -			/* No data transfer in this case */ | ||||
| -			info->data_size = 0; | ||||
|  			exec_cmd = 1; | ||||
|  		} | ||||
|  		break; | ||||
| @@ -1019,6 +1035,14 @@ static int prepare_set_command(struct px | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
| +		if (info->cur_chunk < info->nfullchunks) { | ||||
| +			info->step_chunk_size = info->chunk_size; | ||||
| +			info->step_spare_size = info->spare_size; | ||||
| +		} else { | ||||
| +			info->step_chunk_size = info->last_chunk_size; | ||||
| +			info->step_spare_size = info->last_spare_size; | ||||
| +		} | ||||
| + | ||||
|  		/* Second command setting for large pages */ | ||||
|  		if (mtd->writesize > PAGE_CHUNK_SIZE) { | ||||
|  			/* | ||||
| @@ -1029,14 +1053,14 @@ static int prepare_set_command(struct px | ||||
|  			info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | ||||
|  					| NDCB0_LEN_OVRD | ||||
|  					| NDCB0_EXT_CMD_TYPE(ext_cmd_type); | ||||
| -			info->ndcb3 = info->chunk_size + | ||||
| -				      info->oob_size; | ||||
| +			info->ndcb3 = info->step_chunk_size + | ||||
| +				      info->step_spare_size; | ||||
|   | ||||
|  			/* | ||||
|  			 * This is the command dispatch that completes a chunked | ||||
|  			 * page program operation. | ||||
|  			 */ | ||||
| -			if (info->data_size == 0) { | ||||
| +			if (info->cur_chunk == info->ntotalchunks) { | ||||
|  				info->ndcb0 = NDCB0_CMD_TYPE(0x1) | ||||
|  					| NDCB0_EXT_CMD_TYPE(ext_cmd_type) | ||||
|  					| command; | ||||
| @@ -1063,7 +1087,7 @@ static int prepare_set_command(struct px | ||||
|  				| command; | ||||
|  		info->ndcb1 = (column & 0xFF); | ||||
|  		info->ndcb3 = INIT_BUFFER_SIZE; | ||||
| -		info->data_size = INIT_BUFFER_SIZE; | ||||
| +		info->step_chunk_size = INIT_BUFFER_SIZE; | ||||
|  		break; | ||||
|   | ||||
|  	case NAND_CMD_READID: | ||||
| @@ -1073,7 +1097,7 @@ static int prepare_set_command(struct px | ||||
|  				| command; | ||||
|  		info->ndcb1 = (column & 0xFF); | ||||
|   | ||||
| -		info->data_size = 8; | ||||
| +		info->step_chunk_size = 8; | ||||
|  		break; | ||||
|  	case NAND_CMD_STATUS: | ||||
|  		info->buf_count = 1; | ||||
| @@ -1081,7 +1105,7 @@ static int prepare_set_command(struct px | ||||
|  				| NDCB0_ADDR_CYC(1) | ||||
|  				| command; | ||||
|   | ||||
| -		info->data_size = 8; | ||||
| +		info->step_chunk_size = 8; | ||||
|  		break; | ||||
|   | ||||
|  	case NAND_CMD_ERASE1: | ||||
| @@ -1220,6 +1244,7 @@ static void nand_cmdfunc_extended(struct | ||||
|  	init_completion(&info->dev_ready); | ||||
|  	do { | ||||
|  		info->state = STATE_PREPARED; | ||||
| + | ||||
|  		exec_cmd = prepare_set_command(info, command, ext_cmd_type, | ||||
|  					       column, page_addr); | ||||
|  		if (!exec_cmd) { | ||||
| @@ -1239,22 +1264,30 @@ static void nand_cmdfunc_extended(struct | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
| +		/* Only a few commands need several steps */ | ||||
| +		if (command != NAND_CMD_PAGEPROG && | ||||
| +		    command != NAND_CMD_READ0    && | ||||
| +		    command != NAND_CMD_READOOB) | ||||
| +			break; | ||||
| + | ||||
| +		info->cur_chunk++; | ||||
| + | ||||
|  		/* Check if the sequence is complete */ | ||||
| -		if (info->data_size == 0 && command != NAND_CMD_PAGEPROG) | ||||
| +		if (info->cur_chunk == info->ntotalchunks && command != NAND_CMD_PAGEPROG) | ||||
|  			break; | ||||
|   | ||||
|  		/* | ||||
|  		 * After a splitted program command sequence has issued | ||||
|  		 * the command dispatch, the command sequence is complete. | ||||
|  		 */ | ||||
| -		if (info->data_size == 0 && | ||||
| +		if (info->cur_chunk == (info->ntotalchunks + 1) && | ||||
|  		    command == NAND_CMD_PAGEPROG && | ||||
|  		    ext_cmd_type == EXT_CMD_TYPE_DISPATCH) | ||||
|  			break; | ||||
|   | ||||
|  		if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) { | ||||
|  			/* Last read: issue a 'last naked read' */ | ||||
| -			if (info->data_size == info->chunk_size) | ||||
| +			if (info->cur_chunk == info->ntotalchunks - 1) | ||||
|  				ext_cmd_type = EXT_CMD_TYPE_LAST_RW; | ||||
|  			else | ||||
|  				ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; | ||||
| @@ -1264,7 +1297,7 @@ static void nand_cmdfunc_extended(struct | ||||
|  		 * the command dispatch must be issued to complete. | ||||
|  		 */ | ||||
|  		} else if (command == NAND_CMD_PAGEPROG && | ||||
| -			   info->data_size == 0) { | ||||
| +			   info->cur_chunk == info->ntotalchunks) { | ||||
|  				ext_cmd_type = EXT_CMD_TYPE_DISPATCH; | ||||
|  		} | ||||
|  	} while (1); | ||||
| @@ -1514,6 +1547,8 @@ static int pxa_ecc_init(struct pxa3xx_na | ||||
|  			int strength, int ecc_stepsize, int page_size) | ||||
|  { | ||||
|  	if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { | ||||
| +		info->nfullchunks = 1; | ||||
| +		info->ntotalchunks = 1; | ||||
|  		info->chunk_size = 2048; | ||||
|  		info->spare_size = 40; | ||||
|  		info->ecc_size = 24; | ||||
| @@ -1522,6 +1557,8 @@ static int pxa_ecc_init(struct pxa3xx_na | ||||
|  		ecc->strength = 1; | ||||
|   | ||||
|  	} else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) { | ||||
| +		info->nfullchunks = 1; | ||||
| +		info->ntotalchunks = 1; | ||||
|  		info->chunk_size = 512; | ||||
|  		info->spare_size = 8; | ||||
|  		info->ecc_size = 8; | ||||
| @@ -1535,6 +1572,8 @@ static int pxa_ecc_init(struct pxa3xx_na | ||||
|  	 */ | ||||
|  	} else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) { | ||||
|  		info->ecc_bch = 1; | ||||
| +		info->nfullchunks = 1; | ||||
| +		info->ntotalchunks = 1; | ||||
|  		info->chunk_size = 2048; | ||||
|  		info->spare_size = 32; | ||||
|  		info->ecc_size = 32; | ||||
| @@ -1545,6 +1584,8 @@ static int pxa_ecc_init(struct pxa3xx_na | ||||
|   | ||||
|  	} else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { | ||||
|  		info->ecc_bch = 1; | ||||
| +		info->nfullchunks = 2; | ||||
| +		info->ntotalchunks = 2; | ||||
|  		info->chunk_size = 2048; | ||||
|  		info->spare_size = 32; | ||||
|  		info->ecc_size = 32; | ||||
| @@ -1559,8 +1600,12 @@ static int pxa_ecc_init(struct pxa3xx_na | ||||
|  	 */ | ||||
|  	} else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { | ||||
|  		info->ecc_bch = 1; | ||||
| +		info->nfullchunks = 4; | ||||
| +		info->ntotalchunks = 5; | ||||
|  		info->chunk_size = 1024; | ||||
|  		info->spare_size = 0; | ||||
| +		info->last_chunk_size = 0; | ||||
| +		info->last_spare_size = 64; | ||||
|  		info->ecc_size = 32; | ||||
|  		ecc->mode = NAND_ECC_HW; | ||||
|  		ecc->size = info->chunk_size; | ||||
| @@ -1,42 +0,0 @@ | ||||
| From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= <ezequiel@vanguardiasur.com.ar> | ||||
| Date: Wed, 4 Nov 2015 13:13:41 -0300 | ||||
| Subject: [PATCH] mtd: pxa3xx_nand: Increase the initial chunk size | ||||
|  | ||||
| The chunk size represents the size of the data chunks, which | ||||
| is used by the controllers that allow to split transfered data. | ||||
|  | ||||
| However, the initial chunk size is used in a non-splitted way, | ||||
| during device identification. Therefore, it must be large enough | ||||
| for all the NAND commands issued during device identification. | ||||
| This includes NAND_CMD_PARAM which was recently changed to | ||||
| transfer up to 2048 bytes (for the redundant parameter pages). | ||||
|  | ||||
| Thus, the initial chunk size should be 2048 as well. | ||||
|  | ||||
| On Armada 370/XP platforms (NFCv2) booted without the keep-config | ||||
| devicetree property, this commit fixes a timeout on the NAND_CMD_PARAM | ||||
| command: | ||||
|  | ||||
|   [..] | ||||
|   pxa3xx-nand f10d0000.nand: This platform can't do DMA on this device | ||||
|   pxa3xx-nand f10d0000.nand: Wait time out!!! | ||||
|   nand: device found, Manufacturer ID: 0x2c, Chip ID: 0x38 | ||||
|   nand: Micron MT29F8G08ABABAWP | ||||
|   nand: 1024 MiB, SLC, erase size: 512 KiB, page size: 4096, OOB size: 224 | ||||
|  | ||||
| Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> | ||||
| Acked-by: Robert Jarzmik <robert.jarzmik@free.fr> | ||||
| Signed-off-by: Brian Norris <computersforpeace@gmail.com> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/mtd/nand/pxa3xx_nand.c | ||||
| +++ b/drivers/mtd/nand/pxa3xx_nand.c | ||||
| @@ -1637,7 +1637,7 @@ static int pxa3xx_nand_scan(struct mtd_i | ||||
|  		goto KEEP_CONFIG; | ||||
|   | ||||
|  	/* Set a default chunk size */ | ||||
| -	info->chunk_size = 512; | ||||
| +	info->chunk_size = PAGE_CHUNK_SIZE; | ||||
|   | ||||
|  	ret = pxa3xx_nand_config_flash(info); | ||||
|  	if (ret) | ||||
| @@ -1,104 +0,0 @@ | ||||
| From: =?UTF-8?q?Ezequiel=20Garc=C3=ADa?= <ezequiel@vanguardiasur.com.ar> | ||||
| Date: Wed, 4 Nov 2015 13:13:42 -0300 | ||||
| Subject: [PATCH] mtd: pxa3xx_nand: Fix initial controller configuration | ||||
|  | ||||
| The Data Flash Control Register (NDCR) contains two types | ||||
| of parameters: those that are needed for device identification, | ||||
| and those that can only be set after device identification. | ||||
|  | ||||
| Therefore, the driver can't set them all at once and instead | ||||
| needs to configure the first group before nand_scan_ident() | ||||
| and the second group later. | ||||
|  | ||||
| Let's split pxa3xx_nand_config in two halves, and set the | ||||
| parameters that depend on the device geometry once this is known. | ||||
|  | ||||
| Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> | ||||
| Signed-off-by: Brian Norris <computersforpeace@gmail.com> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/mtd/nand/pxa3xx_nand.c | ||||
| +++ b/drivers/mtd/nand/pxa3xx_nand.c | ||||
| @@ -1420,34 +1420,43 @@ static int pxa3xx_nand_waitfunc(struct m | ||||
|  	return NAND_STATUS_READY; | ||||
|  } | ||||
|   | ||||
| -static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info) | ||||
| +static int pxa3xx_nand_config_ident(struct pxa3xx_nand_info *info) | ||||
|  { | ||||
|  	struct platform_device *pdev = info->pdev; | ||||
|  	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||||
| -	struct pxa3xx_nand_host *host = info->host[info->cs]; | ||||
| -	struct mtd_info *mtd = host->mtd; | ||||
| -	struct nand_chip *chip = mtd->priv; | ||||
|   | ||||
| -	/* configure default flash values */ | ||||
| +	/* Configure default flash values */ | ||||
| +	info->chunk_size = PAGE_CHUNK_SIZE; | ||||
|  	info->reg_ndcr = 0x0; /* enable all interrupts */ | ||||
|  	info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | ||||
|  	info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES); | ||||
| -	info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | ||||
| +	info->reg_ndcr |= NDCR_SPARE_EN; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void pxa3xx_nand_config_tail(struct pxa3xx_nand_info *info) | ||||
| +{ | ||||
| +	struct pxa3xx_nand_host *host = info->host[info->cs]; | ||||
| +	struct mtd_info *mtd = host->mtd; | ||||
| +	struct nand_chip *chip = mtd->priv; | ||||
| + | ||||
|  	info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0; | ||||
|  	info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0; | ||||
|  	info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0; | ||||
| - | ||||
| -	return 0; | ||||
|  } | ||||
|   | ||||
|  static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) | ||||
|  { | ||||
| +	struct platform_device *pdev = info->pdev; | ||||
| +	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||||
|  	uint32_t ndcr = nand_readl(info, NDCR); | ||||
|   | ||||
|  	/* Set an initial chunk size */ | ||||
|  	info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512; | ||||
|  	info->reg_ndcr = ndcr & | ||||
|  		~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL); | ||||
| +	info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | ||||
|  	info->ndtr0cs0 = nand_readl(info, NDTR0CS0); | ||||
|  	info->ndtr1cs0 = nand_readl(info, NDTR1CS0); | ||||
|  	return 0; | ||||
| @@ -1636,10 +1645,7 @@ static int pxa3xx_nand_scan(struct mtd_i | ||||
|  	if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) | ||||
|  		goto KEEP_CONFIG; | ||||
|   | ||||
| -	/* Set a default chunk size */ | ||||
| -	info->chunk_size = PAGE_CHUNK_SIZE; | ||||
| - | ||||
| -	ret = pxa3xx_nand_config_flash(info); | ||||
| +	ret = pxa3xx_nand_config_ident(info); | ||||
|  	if (ret) | ||||
|  		return ret; | ||||
|   | ||||
| @@ -1652,7 +1658,6 @@ static int pxa3xx_nand_scan(struct mtd_i | ||||
|  	} | ||||
|   | ||||
|  KEEP_CONFIG: | ||||
| -	info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | ||||
|  	if (info->reg_ndcr & NDCR_DWIDTH_M) | ||||
|  		chip->options |= NAND_BUSWIDTH_16; | ||||
|   | ||||
| @@ -1737,6 +1742,10 @@ KEEP_CONFIG: | ||||
|  		host->row_addr_cycles = 3; | ||||
|  	else | ||||
|  		host->row_addr_cycles = 2; | ||||
| + | ||||
| +	if (!pdata->keep_config) | ||||
| +		pxa3xx_nand_config_tail(info); | ||||
| + | ||||
|  	return nand_scan_tail(mtd); | ||||
|  } | ||||
|   | ||||
| @@ -1,94 +0,0 @@ | ||||
| From: Marcin Wojtas <mw@semihalf.com> | ||||
| Date: Mon, 14 Mar 2016 09:39:02 +0100 | ||||
| Subject: [PATCH] bus: mvebu-mbus: provide api for obtaining IO and DRAM window | ||||
|  information | ||||
|  | ||||
| This commit enables finding appropriate mbus window and obtaining its | ||||
| target id and attribute for given physical address in two separate | ||||
| routines, both for IO and DRAM windows. This functionality | ||||
| is needed for Armada XP/38x Network Controller's Buffer Manager and | ||||
| PnC configuration. | ||||
|  | ||||
| [gregory.clement@free-electrons.com: Fix size test for | ||||
| mvebu_mbus_get_dram_win_info] | ||||
|  | ||||
| Signed-off-by: Marcin Wojtas <mw@semihalf.com> | ||||
| [DRAM window information reference in LKv3.10] | ||||
| Signed-off-by: Evan Wang <xswang@marvell.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/bus/mvebu-mbus.c | ||||
| +++ b/drivers/bus/mvebu-mbus.c | ||||
| @@ -948,6 +948,58 @@ void mvebu_mbus_get_pcie_io_aperture(str | ||||
|  	*res = mbus_state.pcie_io_aperture; | ||||
|  } | ||||
|   | ||||
| +int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr) | ||||
| +{ | ||||
| +	const struct mbus_dram_target_info *dram; | ||||
| +	int i; | ||||
| + | ||||
| +	/* Get dram info */ | ||||
| +	dram = mv_mbus_dram_info(); | ||||
| +	if (!dram) { | ||||
| +		pr_err("missing DRAM information\n"); | ||||
| +		return -ENODEV; | ||||
| +	} | ||||
| + | ||||
| +	/* Try to find matching DRAM window for phyaddr */ | ||||
| +	for (i = 0; i < dram->num_cs; i++) { | ||||
| +		const struct mbus_dram_window *cs = dram->cs + i; | ||||
| + | ||||
| +		if (cs->base <= phyaddr && | ||||
| +			phyaddr <= (cs->base + cs->size - 1)) { | ||||
| +			*target = dram->mbus_dram_target_id; | ||||
| +			*attr = cs->mbus_attr; | ||||
| +			return 0; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	pr_err("invalid dram address 0x%x\n", phyaddr); | ||||
| +	return -EINVAL; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(mvebu_mbus_get_dram_win_info); | ||||
| + | ||||
| +int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target, | ||||
| +			       u8 *attr) | ||||
| +{ | ||||
| +	int win; | ||||
| + | ||||
| +	for (win = 0; win < mbus_state.soc->num_wins; win++) { | ||||
| +		u64 wbase; | ||||
| +		int enabled; | ||||
| + | ||||
| +		mvebu_mbus_read_window(&mbus_state, win, &enabled, &wbase, | ||||
| +				       size, target, attr, NULL); | ||||
| + | ||||
| +		if (!enabled) | ||||
| +			continue; | ||||
| + | ||||
| +		if (wbase <= phyaddr && phyaddr <= wbase + *size) | ||||
| +			return win; | ||||
| +	} | ||||
| + | ||||
| +	return -EINVAL; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(mvebu_mbus_get_io_win_info); | ||||
| + | ||||
|  static __init int mvebu_mbus_debugfs_init(void) | ||||
|  { | ||||
|  	struct mvebu_mbus_state *s = &mbus_state; | ||||
| --- a/include/linux/mbus.h | ||||
| +++ b/include/linux/mbus.h | ||||
| @@ -69,6 +69,9 @@ static inline const struct mbus_dram_tar | ||||
|  int mvebu_mbus_save_cpu_target(u32 *store_addr); | ||||
|  void mvebu_mbus_get_pcie_mem_aperture(struct resource *res); | ||||
|  void mvebu_mbus_get_pcie_io_aperture(struct resource *res); | ||||
| +int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr); | ||||
| +int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target, | ||||
| +			       u8 *attr); | ||||
|  int mvebu_mbus_add_window_remap_by_id(unsigned int target, | ||||
|  				      unsigned int attribute, | ||||
|  				      phys_addr_t base, size_t size, | ||||
| @@ -1,55 +0,0 @@ | ||||
| From: Stas Sergeev <stsp@list.ru> | ||||
| Date: Wed, 2 Dec 2015 20:33:56 +0300 | ||||
| Subject: [PATCH] mvneta: consolidate autoneg enabling | ||||
|  | ||||
| This moves autoneg-related bit manipulations to the single place. | ||||
|  | ||||
| CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||||
| CC: netdev@vger.kernel.org | ||||
| CC: linux-kernel@vger.kernel.org | ||||
|  | ||||
| Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -1067,15 +1067,28 @@ static void mvneta_defaults_set(struct m | ||||
|  		       MVNETA_GMAC_AN_SPEED_EN | | ||||
|  		       MVNETA_GMAC_AN_DUPLEX_EN; | ||||
|  		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| + | ||||
|  		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
|  		val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
|  		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| +		val |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
|  	} else { | ||||
|  		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
|  		val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
|  		       MVNETA_GMAC_AN_SPEED_EN | | ||||
|  		       MVNETA_GMAC_AN_DUPLEX_EN); | ||||
|  		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| +		val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| +		val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
|  	} | ||||
|   | ||||
|  	mvneta_set_ucast_table(pp, -1); | ||||
| @@ -3230,9 +3243,6 @@ static int mvneta_port_power_up(struct m | ||||
|  		return -EINVAL; | ||||
|  	} | ||||
|   | ||||
| -	if (pp->use_inband_status) | ||||
| -		ctrl |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| - | ||||
|  	/* Cancel Port Reset */ | ||||
|  	ctrl &= ~MVNETA_GMAC2_PORT_RESET; | ||||
|  	mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl); | ||||
| @@ -1,165 +0,0 @@ | ||||
| From: Stas Sergeev <stsp@list.ru> | ||||
| Date: Wed, 2 Dec 2015 20:35:11 +0300 | ||||
| Subject: [PATCH] mvneta: implement ethtool autonegotiation control | ||||
|  | ||||
| This patch allows to do | ||||
| ethtool -s eth0 autoneg off | ||||
| ethtool -s eth0 autoneg on | ||||
| to disable or enable autonegotiation at run-time. | ||||
| Without that functionality, the only way to control the autonegotiation | ||||
| is to modify the device tree. | ||||
|  | ||||
| This is needed if you plan to use the same kernel with | ||||
| different ethernet switches, the ones that support the in-band | ||||
| status and the ones that not. | ||||
|  | ||||
| CC: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||||
| CC: netdev@vger.kernel.org | ||||
| CC: linux-kernel@vger.kernel.org | ||||
|  | ||||
| Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -371,7 +371,7 @@ struct mvneta_port { | ||||
|  	unsigned int duplex; | ||||
|  	unsigned int speed; | ||||
|  	unsigned int tx_csum_limit; | ||||
| -	int use_inband_status:1; | ||||
| +	unsigned int use_inband_status:1; | ||||
|   | ||||
|  	u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; | ||||
|  }; | ||||
| @@ -973,6 +973,44 @@ static void mvneta_set_other_mcast_table | ||||
|  		mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val); | ||||
|  } | ||||
|   | ||||
| +static void mvneta_set_autoneg(struct mvneta_port *pp, int enable) | ||||
| +{ | ||||
| +	u32 val; | ||||
| + | ||||
| +	if (enable) { | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| +		val &= ~(MVNETA_GMAC_FORCE_LINK_PASS | | ||||
| +			 MVNETA_GMAC_FORCE_LINK_DOWN | | ||||
| +			 MVNETA_GMAC_AN_FLOW_CTRL_EN); | ||||
| +		val |= MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| +		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| +		       MVNETA_GMAC_AN_DUPLEX_EN; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| +		val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| +		val |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| +	} else { | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| +		val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| +		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| +		       MVNETA_GMAC_AN_DUPLEX_EN); | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| +		val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| + | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| +		val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
|  /* This method sets defaults to the NETA port: | ||||
|   *	Clears interrupt Cause and Mask registers. | ||||
|   *	Clears all MAC tables. | ||||
| @@ -1058,39 +1096,7 @@ static void mvneta_defaults_set(struct m | ||||
|  	val &= ~MVNETA_PHY_POLLING_ENABLE; | ||||
|  	mvreg_write(pp, MVNETA_UNIT_CONTROL, val); | ||||
|   | ||||
| -	if (pp->use_inband_status) { | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -		val &= ~(MVNETA_GMAC_FORCE_LINK_PASS | | ||||
| -			 MVNETA_GMAC_FORCE_LINK_DOWN | | ||||
| -			 MVNETA_GMAC_AN_FLOW_CTRL_EN); | ||||
| -		val |= MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| -		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| -		       MVNETA_GMAC_AN_DUPLEX_EN; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| -		val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| -		val |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| -	} else { | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -		val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| -		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| -		       MVNETA_GMAC_AN_DUPLEX_EN); | ||||
| -		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| -		val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| -		val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| -	} | ||||
| - | ||||
| +	mvneta_set_autoneg(pp, pp->use_inband_status); | ||||
|  	mvneta_set_ucast_table(pp, -1); | ||||
|  	mvneta_set_special_mcast_table(pp, -1); | ||||
|  	mvneta_set_other_mcast_table(pp, -1); | ||||
| @@ -2956,10 +2962,43 @@ int mvneta_ethtool_get_settings(struct n | ||||
|  int mvneta_ethtool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
| +	struct phy_device *phydev = pp->phy_dev; | ||||
|   | ||||
| -	if (!pp->phy_dev) | ||||
| +	if (!phydev) | ||||
|  		return -ENODEV; | ||||
|   | ||||
| +	if ((cmd->autoneg == AUTONEG_ENABLE) != pp->use_inband_status) { | ||||
| +		u32 val; | ||||
| + | ||||
| +		mvneta_set_autoneg(pp, cmd->autoneg == AUTONEG_ENABLE); | ||||
| + | ||||
| +		if (cmd->autoneg == AUTONEG_DISABLE) { | ||||
| +			val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| +			val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | | ||||
| +				 MVNETA_GMAC_CONFIG_GMII_SPEED | | ||||
| +				 MVNETA_GMAC_CONFIG_FULL_DUPLEX); | ||||
| + | ||||
| +			if (phydev->duplex) | ||||
| +				val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
| + | ||||
| +			if (phydev->speed == SPEED_1000) | ||||
| +				val |= MVNETA_GMAC_CONFIG_GMII_SPEED; | ||||
| +			else if (phydev->speed == SPEED_100) | ||||
| +				val |= MVNETA_GMAC_CONFIG_MII_SPEED; | ||||
| + | ||||
| +			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| +		} | ||||
| + | ||||
| +		pp->use_inband_status = (cmd->autoneg == AUTONEG_ENABLE); | ||||
| +		netdev_info(pp->dev, "autoneg status set to %i\n", | ||||
| +			    pp->use_inband_status); | ||||
| + | ||||
| +		if (netif_running(dev)) { | ||||
| +			mvneta_port_down(pp); | ||||
| +			mvneta_port_up(pp); | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
|  	return phy_ethtool_sset(pp->phy_dev, cmd); | ||||
|  } | ||||
|   | ||||
| @@ -1,131 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Wed, 9 Dec 2015 18:23:48 +0100 | ||||
| Subject: [PATCH] net: mvneta: Make the default queue related for each port | ||||
|  | ||||
| Instead of using the same default queue for all the port. Move it in the | ||||
| port struct. It will allow have a different default queue for each port. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -356,6 +356,7 @@ struct mvneta_port { | ||||
|  	struct mvneta_tx_queue *txqs; | ||||
|  	struct net_device *dev; | ||||
|  	struct notifier_block cpu_notifier; | ||||
| +	int rxq_def; | ||||
|   | ||||
|  	/* Core clock */ | ||||
|  	struct clk *clk; | ||||
| @@ -819,7 +820,7 @@ static void mvneta_port_up(struct mvneta | ||||
|  	mvreg_write(pp, MVNETA_TXQ_CMD, q_map); | ||||
|   | ||||
|  	/* Enable all initialized RXQs. */ | ||||
| -	mvreg_write(pp, MVNETA_RXQ_CMD, BIT(rxq_def)); | ||||
| +	mvreg_write(pp, MVNETA_RXQ_CMD, BIT(pp->rxq_def)); | ||||
|  } | ||||
|   | ||||
|  /* Stop the Ethernet port activity */ | ||||
| @@ -1067,7 +1068,7 @@ static void mvneta_defaults_set(struct m | ||||
|  	mvreg_write(pp, MVNETA_ACC_MODE, val); | ||||
|   | ||||
|  	/* Update val of portCfg register accordingly with all RxQueue types */ | ||||
| -	val = MVNETA_PORT_CONFIG_DEFL_VALUE(rxq_def); | ||||
| +	val = MVNETA_PORT_CONFIG_DEFL_VALUE(pp->rxq_def); | ||||
|  	mvreg_write(pp, MVNETA_PORT_CONFIG, val); | ||||
|   | ||||
|  	val = 0; | ||||
| @@ -2101,19 +2102,19 @@ static void mvneta_set_rx_mode(struct ne | ||||
|  	if (dev->flags & IFF_PROMISC) { | ||||
|  		/* Accept all: Multicast + Unicast */ | ||||
|  		mvneta_rx_unicast_promisc_set(pp, 1); | ||||
| -		mvneta_set_ucast_table(pp, rxq_def); | ||||
| -		mvneta_set_special_mcast_table(pp, rxq_def); | ||||
| -		mvneta_set_other_mcast_table(pp, rxq_def); | ||||
| +		mvneta_set_ucast_table(pp, pp->rxq_def); | ||||
| +		mvneta_set_special_mcast_table(pp, pp->rxq_def); | ||||
| +		mvneta_set_other_mcast_table(pp, pp->rxq_def); | ||||
|  	} else { | ||||
|  		/* Accept single Unicast */ | ||||
|  		mvneta_rx_unicast_promisc_set(pp, 0); | ||||
|  		mvneta_set_ucast_table(pp, -1); | ||||
| -		mvneta_mac_addr_set(pp, dev->dev_addr, rxq_def); | ||||
| +		mvneta_mac_addr_set(pp, dev->dev_addr, pp->rxq_def); | ||||
|   | ||||
|  		if (dev->flags & IFF_ALLMULTI) { | ||||
|  			/* Accept all multicast */ | ||||
| -			mvneta_set_special_mcast_table(pp, rxq_def); | ||||
| -			mvneta_set_other_mcast_table(pp, rxq_def); | ||||
| +			mvneta_set_special_mcast_table(pp, pp->rxq_def); | ||||
| +			mvneta_set_other_mcast_table(pp, pp->rxq_def); | ||||
|  		} else { | ||||
|  			/* Accept only initialized multicast */ | ||||
|  			mvneta_set_special_mcast_table(pp, -1); | ||||
| @@ -2122,7 +2123,7 @@ static void mvneta_set_rx_mode(struct ne | ||||
|  			if (!netdev_mc_empty(dev)) { | ||||
|  				netdev_for_each_mc_addr(ha, dev) { | ||||
|  					mvneta_mcast_addr_set(pp, ha->addr, | ||||
| -							      rxq_def); | ||||
| +							      pp->rxq_def); | ||||
|  				} | ||||
|  			} | ||||
|  		} | ||||
| @@ -2205,7 +2206,7 @@ static int mvneta_poll(struct napi_struc | ||||
|  	 * RX packets | ||||
|  	 */ | ||||
|  	cause_rx_tx |= port->cause_rx_tx; | ||||
| -	rx_done = mvneta_rx(pp, budget, &pp->rxqs[rxq_def]); | ||||
| +	rx_done = mvneta_rx(pp, budget, &pp->rxqs[pp->rxq_def]); | ||||
|  	budget -= rx_done; | ||||
|   | ||||
|  	if (budget > 0) { | ||||
| @@ -2418,17 +2419,17 @@ static void mvneta_cleanup_txqs(struct m | ||||
|  /* Cleanup all Rx queues */ | ||||
|  static void mvneta_cleanup_rxqs(struct mvneta_port *pp) | ||||
|  { | ||||
| -	mvneta_rxq_deinit(pp, &pp->rxqs[rxq_def]); | ||||
| +	mvneta_rxq_deinit(pp, &pp->rxqs[pp->rxq_def]); | ||||
|  } | ||||
|   | ||||
|   | ||||
|  /* Init all Rx queues */ | ||||
|  static int mvneta_setup_rxqs(struct mvneta_port *pp) | ||||
|  { | ||||
| -	int err = mvneta_rxq_init(pp, &pp->rxqs[rxq_def]); | ||||
| +	int err = mvneta_rxq_init(pp, &pp->rxqs[pp->rxq_def]); | ||||
|  	if (err) { | ||||
|  		netdev_err(pp->dev, "%s: can't create rxq=%d\n", | ||||
| -			   __func__, rxq_def); | ||||
| +			   __func__, pp->rxq_def); | ||||
|  		mvneta_cleanup_rxqs(pp); | ||||
|  		return err; | ||||
|  	} | ||||
| @@ -2634,7 +2635,7 @@ static int mvneta_set_mac_addr(struct ne | ||||
|  	mvneta_mac_addr_set(pp, dev->dev_addr, -1); | ||||
|   | ||||
|  	/* Set new addr in hw */ | ||||
| -	mvneta_mac_addr_set(pp, sockaddr->sa_data, rxq_def); | ||||
| +	mvneta_mac_addr_set(pp, sockaddr->sa_data, pp->rxq_def); | ||||
|   | ||||
|  	eth_commit_mac_addr_change(dev, addr); | ||||
|  	return 0; | ||||
| @@ -2753,7 +2754,7 @@ static void mvneta_percpu_elect(struct m | ||||
|  { | ||||
|  	int online_cpu_idx, cpu, i = 0; | ||||
|   | ||||
| -	online_cpu_idx = rxq_def % num_online_cpus(); | ||||
| +	online_cpu_idx = pp->rxq_def % num_online_cpus(); | ||||
|   | ||||
|  	for_each_online_cpu(cpu) { | ||||
|  		if (i == online_cpu_idx) | ||||
| @@ -3363,6 +3364,8 @@ static int mvneta_probe(struct platform_ | ||||
|  				 strcmp(managed, "in-band-status") == 0); | ||||
|  	pp->cpu_notifier.notifier_call = mvneta_percpu_notifier; | ||||
|   | ||||
| +	pp->rxq_def = rxq_def; | ||||
| + | ||||
|  	pp->clk = devm_clk_get(&pdev->dev, NULL); | ||||
|  	if (IS_ERR(pp->clk)) { | ||||
|  		err = PTR_ERR(pp->clk); | ||||
| @@ -1,278 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Wed, 9 Dec 2015 18:23:49 +0100 | ||||
| Subject: [PATCH] net: mvneta: Associate RX queues with each CPU | ||||
|  | ||||
| We enable the percpu interrupt for all the CPU and we just associate a | ||||
| CPU to a few queue at the neta level. The mapping between the CPUs and | ||||
| the queues is static. The queues are associated to the CPU module the | ||||
| number of CPUs. However currently we only use on RX queue for a given | ||||
| Ethernet port. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -110,9 +110,16 @@ | ||||
|  #define MVNETA_CPU_MAP(cpu)                      (0x2540 + ((cpu) << 2)) | ||||
|  #define      MVNETA_CPU_RXQ_ACCESS_ALL_MASK      0x000000ff | ||||
|  #define      MVNETA_CPU_TXQ_ACCESS_ALL_MASK      0x0000ff00 | ||||
| +#define      MVNETA_CPU_RXQ_ACCESS(rxq)		 BIT(rxq) | ||||
|  #define MVNETA_RXQ_TIME_COAL_REG(q)              (0x2580 + ((q) << 2)) | ||||
|   | ||||
| -/* Exception Interrupt Port/Queue Cause register */ | ||||
| +/* Exception Interrupt Port/Queue Cause register | ||||
| + * | ||||
| + * Their behavior depend of the mapping done using the PCPX2Q | ||||
| + * registers. For a given CPU if the bit associated to a queue is not | ||||
| + * set, then for the register a read from this CPU will always return | ||||
| + * 0 and a write won't do anything | ||||
| + */ | ||||
|   | ||||
|  #define MVNETA_INTR_NEW_CAUSE                    0x25a0 | ||||
|  #define MVNETA_INTR_NEW_MASK                     0x25a4 | ||||
| @@ -820,7 +827,13 @@ static void mvneta_port_up(struct mvneta | ||||
|  	mvreg_write(pp, MVNETA_TXQ_CMD, q_map); | ||||
|   | ||||
|  	/* Enable all initialized RXQs. */ | ||||
| -	mvreg_write(pp, MVNETA_RXQ_CMD, BIT(pp->rxq_def)); | ||||
| +	for (queue = 0; queue < rxq_number; queue++) { | ||||
| +		struct mvneta_rx_queue *rxq = &pp->rxqs[queue]; | ||||
| + | ||||
| +		if (rxq->descs != NULL) | ||||
| +			q_map |= (1 << queue); | ||||
| +	} | ||||
| +	mvreg_write(pp, MVNETA_RXQ_CMD, q_map); | ||||
|  } | ||||
|   | ||||
|  /* Stop the Ethernet port activity */ | ||||
| @@ -1026,6 +1039,7 @@ static void mvneta_defaults_set(struct m | ||||
|  	int cpu; | ||||
|  	int queue; | ||||
|  	u32 val; | ||||
| +	int max_cpu = num_present_cpus(); | ||||
|   | ||||
|  	/* Clear all Cause registers */ | ||||
|  	mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); | ||||
| @@ -1041,13 +1055,23 @@ static void mvneta_defaults_set(struct m | ||||
|  	/* Enable MBUS Retry bit16 */ | ||||
|  	mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20); | ||||
|   | ||||
| -	/* Set CPU queue access map - all CPUs have access to all RX | ||||
| -	 * queues and to all TX queues | ||||
| +	/* Set CPU queue access map. CPUs are assigned to the RX | ||||
| +	 * queues modulo their number and all the TX queues are | ||||
| +	 * assigned to the CPU associated to the default RX queue. | ||||
|  	 */ | ||||
| -	for_each_present_cpu(cpu) | ||||
| -		mvreg_write(pp, MVNETA_CPU_MAP(cpu), | ||||
| -			    (MVNETA_CPU_RXQ_ACCESS_ALL_MASK | | ||||
| -			     MVNETA_CPU_TXQ_ACCESS_ALL_MASK)); | ||||
| +	for_each_present_cpu(cpu) { | ||||
| +		int rxq_map = 0, txq_map = 0; | ||||
| +		int rxq; | ||||
| + | ||||
| +		for (rxq = 0; rxq < rxq_number; rxq++) | ||||
| +			if ((rxq % max_cpu) == cpu) | ||||
| +				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
| + | ||||
| +		if (cpu == rxq_def) | ||||
| +			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
| + | ||||
| +		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map); | ||||
| +	} | ||||
|   | ||||
|  	/* Reset RX and TX DMAs */ | ||||
|  	mvreg_write(pp, MVNETA_PORT_RX_RESET, MVNETA_PORT_RX_DMA_RESET); | ||||
| @@ -2174,6 +2198,7 @@ static int mvneta_poll(struct napi_struc | ||||
|  { | ||||
|  	int rx_done = 0; | ||||
|  	u32 cause_rx_tx; | ||||
| +	int rx_queue; | ||||
|  	struct mvneta_port *pp = netdev_priv(napi->dev); | ||||
|  	struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports); | ||||
|   | ||||
| @@ -2205,8 +2230,15 @@ static int mvneta_poll(struct napi_struc | ||||
|  	/* For the case where the last mvneta_poll did not process all | ||||
|  	 * RX packets | ||||
|  	 */ | ||||
| +	rx_queue = fls(((cause_rx_tx >> 8) & 0xff)); | ||||
| + | ||||
|  	cause_rx_tx |= port->cause_rx_tx; | ||||
| -	rx_done = mvneta_rx(pp, budget, &pp->rxqs[pp->rxq_def]); | ||||
| + | ||||
| +	if (rx_queue) { | ||||
| +		rx_queue = rx_queue - 1; | ||||
| +		rx_done = mvneta_rx(pp, budget, &pp->rxqs[rx_queue]); | ||||
| +	} | ||||
| + | ||||
|  	budget -= rx_done; | ||||
|   | ||||
|  	if (budget > 0) { | ||||
| @@ -2419,19 +2451,27 @@ static void mvneta_cleanup_txqs(struct m | ||||
|  /* Cleanup all Rx queues */ | ||||
|  static void mvneta_cleanup_rxqs(struct mvneta_port *pp) | ||||
|  { | ||||
| -	mvneta_rxq_deinit(pp, &pp->rxqs[pp->rxq_def]); | ||||
| +	int queue; | ||||
| + | ||||
| +	for (queue = 0; queue < txq_number; queue++) | ||||
| +		mvneta_rxq_deinit(pp, &pp->rxqs[queue]); | ||||
|  } | ||||
|   | ||||
|   | ||||
|  /* Init all Rx queues */ | ||||
|  static int mvneta_setup_rxqs(struct mvneta_port *pp) | ||||
|  { | ||||
| -	int err = mvneta_rxq_init(pp, &pp->rxqs[pp->rxq_def]); | ||||
| -	if (err) { | ||||
| -		netdev_err(pp->dev, "%s: can't create rxq=%d\n", | ||||
| -			   __func__, pp->rxq_def); | ||||
| -		mvneta_cleanup_rxqs(pp); | ||||
| -		return err; | ||||
| +	int queue; | ||||
| + | ||||
| +	for (queue = 0; queue < rxq_number; queue++) { | ||||
| +		int err = mvneta_rxq_init(pp, &pp->rxqs[queue]); | ||||
| + | ||||
| +		if (err) { | ||||
| +			netdev_err(pp->dev, "%s: can't create rxq=%d\n", | ||||
| +				   __func__, queue); | ||||
| +			mvneta_cleanup_rxqs(pp); | ||||
| +			return err; | ||||
| +		} | ||||
|  	} | ||||
|   | ||||
|  	return 0; | ||||
| @@ -2455,6 +2495,19 @@ static int mvneta_setup_txqs(struct mvne | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static void mvneta_percpu_unmask_interrupt(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	/* All the queue are unmasked, but actually only the ones | ||||
| +	 * maped to this CPU will be unmasked | ||||
| +	 */ | ||||
| +	mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| +		    MVNETA_RX_INTR_MASK_ALL | | ||||
| +		    MVNETA_TX_INTR_MASK_ALL | | ||||
| +		    MVNETA_MISCINTR_INTR_MASK); | ||||
| +} | ||||
| + | ||||
|  static void mvneta_start_dev(struct mvneta_port *pp) | ||||
|  { | ||||
|  	unsigned int cpu; | ||||
| @@ -2472,11 +2525,10 @@ static void mvneta_start_dev(struct mvne | ||||
|  		napi_enable(&port->napi); | ||||
|  	} | ||||
|   | ||||
| -	/* Unmask interrupts */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| -		    MVNETA_RX_INTR_MASK(rxq_number) | | ||||
| -		    MVNETA_TX_INTR_MASK(txq_number) | | ||||
| -		    MVNETA_MISCINTR_INTR_MASK); | ||||
| +	/* Unmask interrupts. It has to be done from each CPU */ | ||||
| +	for_each_online_cpu(cpu) | ||||
| +		smp_call_function_single(cpu, mvneta_percpu_unmask_interrupt, | ||||
| +					 pp, true); | ||||
|  	mvreg_write(pp, MVNETA_INTR_MISC_MASK, | ||||
|  		    MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
|  		    MVNETA_CAUSE_LINK_CHANGE | | ||||
| @@ -2752,22 +2804,35 @@ static void mvneta_percpu_disable(void * | ||||
|   | ||||
|  static void mvneta_percpu_elect(struct mvneta_port *pp) | ||||
|  { | ||||
| -	int online_cpu_idx, cpu, i = 0; | ||||
| +	int online_cpu_idx, max_cpu, cpu, i = 0; | ||||
|   | ||||
|  	online_cpu_idx = pp->rxq_def % num_online_cpus(); | ||||
| +	max_cpu = num_present_cpus(); | ||||
|   | ||||
|  	for_each_online_cpu(cpu) { | ||||
| -		if (i == online_cpu_idx) | ||||
| -			/* Enable per-CPU interrupt on the one CPU we | ||||
| -			 * just elected | ||||
| +		int rxq_map = 0, txq_map = 0; | ||||
| +		int rxq; | ||||
| + | ||||
| +		for (rxq = 0; rxq < rxq_number; rxq++) | ||||
| +			if ((rxq % max_cpu) == cpu) | ||||
| +				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
| + | ||||
| +		if (i == online_cpu_idx) { | ||||
| +			/* Map the default receive queue and transmit | ||||
| +			 * queue to the elected CPU | ||||
|  			 */ | ||||
| -			smp_call_function_single(cpu, mvneta_percpu_enable, | ||||
| -						pp, true); | ||||
| -		else | ||||
| -			/* Disable per-CPU interrupt on all the other CPU */ | ||||
| -			smp_call_function_single(cpu, mvneta_percpu_disable, | ||||
| -						pp, true); | ||||
| +			rxq_map |= MVNETA_CPU_RXQ_ACCESS(pp->rxq_def); | ||||
| +			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
| +		} | ||||
| +		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map); | ||||
| + | ||||
| +		/* Update the interrupt mask on each CPU according the | ||||
| +		 * new mapping | ||||
| +		 */ | ||||
| +		smp_call_function_single(cpu, mvneta_percpu_unmask_interrupt, | ||||
| +					 pp, true); | ||||
|  		i++; | ||||
| + | ||||
|  	} | ||||
|  }; | ||||
|   | ||||
| @@ -2802,12 +2867,22 @@ static int mvneta_percpu_notifier(struct | ||||
|  		mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
|  		napi_enable(&port->napi); | ||||
|   | ||||
| + | ||||
| +		/* Enable per-CPU interrupts on the CPU that is | ||||
| +		 * brought up. | ||||
| +		 */ | ||||
| +		smp_call_function_single(cpu, mvneta_percpu_enable, | ||||
| +					 pp, true); | ||||
| + | ||||
|  		/* Enable per-CPU interrupt on the one CPU we care | ||||
|  		 * about. | ||||
|  		 */ | ||||
|  		mvneta_percpu_elect(pp); | ||||
|   | ||||
| -		/* Unmask all ethernet port interrupts */ | ||||
| +		/* Unmask all ethernet port interrupts, as this | ||||
| +		 * notifier is called for each CPU then the CPU to | ||||
| +		 * Queue mapping is applied | ||||
| +		 */ | ||||
|  		mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
|  			MVNETA_RX_INTR_MASK(rxq_number) | | ||||
|  			MVNETA_TX_INTR_MASK(txq_number) | | ||||
| @@ -2858,7 +2933,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  static int mvneta_open(struct net_device *dev) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
| -	int ret; | ||||
| +	int ret, cpu; | ||||
|   | ||||
|  	pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); | ||||
|  	pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) + | ||||
| @@ -2888,8 +2963,13 @@ static int mvneta_open(struct net_device | ||||
|  	 */ | ||||
|  	mvneta_percpu_disable(pp); | ||||
|   | ||||
| -	/* Elect a CPU to handle our RX queue interrupt */ | ||||
| -	mvneta_percpu_elect(pp); | ||||
| +	/* Enable per-CPU interrupt on all the CPU to handle our RX | ||||
| +	 * queue interrupts | ||||
| +	 */ | ||||
| +	for_each_online_cpu(cpu) | ||||
| +		smp_call_function_single(cpu, mvneta_percpu_enable, | ||||
| +					 pp, true); | ||||
| + | ||||
|   | ||||
|  	/* Register a CPU notifier to handle the case where our CPU | ||||
|  	 * might be taken offline. | ||||
| @@ -1,191 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Wed, 9 Dec 2015 18:23:50 +0100 | ||||
| Subject: [PATCH] net: mvneta: Add naive RSS support | ||||
|  | ||||
| This patch adds the support for the RSS related ethtool | ||||
| function. Currently it only uses one entry in the indirection table which | ||||
| allows associating an mvneta interface to a given CPU. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Tested-by: Marcin Wojtas <mw@semihalf.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -261,6 +261,11 @@ | ||||
|   | ||||
|  #define MVNETA_TX_MTU_MAX		0x3ffff | ||||
|   | ||||
| +/* The RSS lookup table actually has 256 entries but we do not use | ||||
| + * them yet | ||||
| + */ | ||||
| +#define MVNETA_RSS_LU_TABLE_SIZE	1 | ||||
| + | ||||
|  /* TSO header size */ | ||||
|  #define TSO_HEADER_SIZE 128 | ||||
|   | ||||
| @@ -382,6 +387,8 @@ struct mvneta_port { | ||||
|  	unsigned int use_inband_status:1; | ||||
|   | ||||
|  	u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; | ||||
| + | ||||
| +	u32 indir[MVNETA_RSS_LU_TABLE_SIZE]; | ||||
|  }; | ||||
|   | ||||
|  /* The mvneta_tx_desc and mvneta_rx_desc structures describe the | ||||
| @@ -1067,7 +1074,7 @@ static void mvneta_defaults_set(struct m | ||||
|  			if ((rxq % max_cpu) == cpu) | ||||
|  				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
|   | ||||
| -		if (cpu == rxq_def) | ||||
| +		if (cpu == pp->rxq_def) | ||||
|  			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
|   | ||||
|  		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map); | ||||
| @@ -2508,6 +2515,18 @@ static void mvneta_percpu_unmask_interru | ||||
|  		    MVNETA_MISCINTR_INTR_MASK); | ||||
|  } | ||||
|   | ||||
| +static void mvneta_percpu_mask_interrupt(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	/* All the queue are masked, but actually only the ones | ||||
| +	 * maped to this CPU will be masked | ||||
| +	 */ | ||||
| +	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +} | ||||
| + | ||||
|  static void mvneta_start_dev(struct mvneta_port *pp) | ||||
|  { | ||||
|  	unsigned int cpu; | ||||
| @@ -3231,6 +3250,106 @@ static int mvneta_ethtool_get_sset_count | ||||
|  	return -EOPNOTSUPP; | ||||
|  } | ||||
|   | ||||
| +static u32 mvneta_ethtool_get_rxfh_indir_size(struct net_device *dev) | ||||
| +{ | ||||
| +	return MVNETA_RSS_LU_TABLE_SIZE; | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_get_rxnfc(struct net_device *dev, | ||||
| +				    struct ethtool_rxnfc *info, | ||||
| +				    u32 *rules __always_unused) | ||||
| +{ | ||||
| +	switch (info->cmd) { | ||||
| +	case ETHTOOL_GRXRINGS: | ||||
| +		info->data =  rxq_number; | ||||
| +		return 0; | ||||
| +	case ETHTOOL_GRXFH: | ||||
| +		return -EOPNOTSUPP; | ||||
| +	default: | ||||
| +		return -EOPNOTSUPP; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int  mvneta_config_rss(struct mvneta_port *pp) | ||||
| +{ | ||||
| +	int cpu; | ||||
| +	u32 val; | ||||
| + | ||||
| +	netif_tx_stop_all_queues(pp->dev); | ||||
| + | ||||
| +	for_each_online_cpu(cpu) | ||||
| +		smp_call_function_single(cpu, mvneta_percpu_mask_interrupt, | ||||
| +					 pp, true); | ||||
| + | ||||
| +	/* We have to synchronise on the napi of each CPU */ | ||||
| +	for_each_online_cpu(cpu) { | ||||
| +		struct mvneta_pcpu_port *pcpu_port = | ||||
| +			per_cpu_ptr(pp->ports, cpu); | ||||
| + | ||||
| +		napi_synchronize(&pcpu_port->napi); | ||||
| +		napi_disable(&pcpu_port->napi); | ||||
| +	} | ||||
| + | ||||
| +	pp->rxq_def = pp->indir[0]; | ||||
| + | ||||
| +	/* Update unicast mapping */ | ||||
| +	mvneta_set_rx_mode(pp->dev); | ||||
| + | ||||
| +	/* Update val of portCfg register accordingly with all RxQueue types */ | ||||
| +	val = MVNETA_PORT_CONFIG_DEFL_VALUE(pp->rxq_def); | ||||
| +	mvreg_write(pp, MVNETA_PORT_CONFIG, val); | ||||
| + | ||||
| +	/* Update the elected CPU matching the new rxq_def */ | ||||
| +	mvneta_percpu_elect(pp); | ||||
| + | ||||
| +	/* We have to synchronise on the napi of each CPU */ | ||||
| +	for_each_online_cpu(cpu) { | ||||
| +		struct mvneta_pcpu_port *pcpu_port = | ||||
| +			per_cpu_ptr(pp->ports, cpu); | ||||
| + | ||||
| +		napi_enable(&pcpu_port->napi); | ||||
| +	} | ||||
| + | ||||
| +	netif_tx_start_all_queues(pp->dev); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_set_rxfh(struct net_device *dev, const u32 *indir, | ||||
| +				   const u8 *key, const u8 hfunc) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| +	/* We require at least one supported parameter to be changed | ||||
| +	 * and no change in any of the unsupported parameters | ||||
| +	 */ | ||||
| +	if (key || | ||||
| +	    (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)) | ||||
| +		return -EOPNOTSUPP; | ||||
| + | ||||
| +	if (!indir) | ||||
| +		return 0; | ||||
| + | ||||
| +	memcpy(pp->indir, indir, MVNETA_RSS_LU_TABLE_SIZE); | ||||
| + | ||||
| +	return mvneta_config_rss(pp); | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, | ||||
| +				   u8 *hfunc) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	if (hfunc) | ||||
| +		*hfunc = ETH_RSS_HASH_TOP; | ||||
| + | ||||
| +	if (!indir) | ||||
| +		return 0; | ||||
| + | ||||
| +	memcpy(indir, pp->indir, MVNETA_RSS_LU_TABLE_SIZE); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
|  static const struct net_device_ops mvneta_netdev_ops = { | ||||
|  	.ndo_open            = mvneta_open, | ||||
|  	.ndo_stop            = mvneta_stop, | ||||
| @@ -3255,6 +3374,10 @@ const struct ethtool_ops mvneta_eth_tool | ||||
|  	.get_strings	= mvneta_ethtool_get_strings, | ||||
|  	.get_ethtool_stats = mvneta_ethtool_get_stats, | ||||
|  	.get_sset_count	= mvneta_ethtool_get_sset_count, | ||||
| +	.get_rxfh_indir_size = mvneta_ethtool_get_rxfh_indir_size, | ||||
| +	.get_rxnfc	= mvneta_ethtool_get_rxnfc, | ||||
| +	.get_rxfh	= mvneta_ethtool_get_rxfh, | ||||
| +	.set_rxfh	= mvneta_ethtool_set_rxfh, | ||||
|  }; | ||||
|   | ||||
|  /* Initialize hw */ | ||||
| @@ -3446,6 +3569,8 @@ static int mvneta_probe(struct platform_ | ||||
|   | ||||
|  	pp->rxq_def = rxq_def; | ||||
|   | ||||
| +	pp->indir[0] = rxq_def; | ||||
| + | ||||
|  	pp->clk = devm_clk_get(&pdev->dev, NULL); | ||||
|  	if (IS_ERR(pp->clk)) { | ||||
|  		err = PTR_ERR(pp->clk); | ||||
| @@ -1,124 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Wed, 9 Dec 2015 18:23:51 +0100 | ||||
| Subject: [PATCH] net: mvneta: Configure XPS support | ||||
|  | ||||
| With this patch each CPU is associated with its own set of TX queues. | ||||
|  | ||||
| It also setup the XPS with an initial configuration which set the | ||||
| affinity matching the hardware configuration. | ||||
|  | ||||
| Suggested-by: Arnd Bergmann <arnd@arndb.de> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -111,6 +111,7 @@ | ||||
|  #define      MVNETA_CPU_RXQ_ACCESS_ALL_MASK      0x000000ff | ||||
|  #define      MVNETA_CPU_TXQ_ACCESS_ALL_MASK      0x0000ff00 | ||||
|  #define      MVNETA_CPU_RXQ_ACCESS(rxq)		 BIT(rxq) | ||||
| +#define      MVNETA_CPU_TXQ_ACCESS(txq)		 BIT(txq + 8) | ||||
|  #define MVNETA_RXQ_TIME_COAL_REG(q)              (0x2580 + ((q) << 2)) | ||||
|   | ||||
|  /* Exception Interrupt Port/Queue Cause register | ||||
| @@ -514,6 +515,9 @@ struct mvneta_tx_queue { | ||||
|   | ||||
|  	/* DMA address of TSO headers */ | ||||
|  	dma_addr_t tso_hdrs_phys; | ||||
| + | ||||
| +	/* Affinity mask for CPUs*/ | ||||
| +	cpumask_t affinity_mask; | ||||
|  }; | ||||
|   | ||||
|  struct mvneta_rx_queue { | ||||
| @@ -1062,20 +1066,30 @@ static void mvneta_defaults_set(struct m | ||||
|  	/* Enable MBUS Retry bit16 */ | ||||
|  	mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20); | ||||
|   | ||||
| -	/* Set CPU queue access map. CPUs are assigned to the RX | ||||
| -	 * queues modulo their number and all the TX queues are | ||||
| -	 * assigned to the CPU associated to the default RX queue. | ||||
| +	/* Set CPU queue access map. CPUs are assigned to the RX and | ||||
| +	 * TX queues modulo their number. If there is only one TX | ||||
| +	 * queue then it is assigned to the CPU associated to the | ||||
| +	 * default RX queue. | ||||
|  	 */ | ||||
|  	for_each_present_cpu(cpu) { | ||||
|  		int rxq_map = 0, txq_map = 0; | ||||
| -		int rxq; | ||||
| +		int rxq, txq; | ||||
|   | ||||
|  		for (rxq = 0; rxq < rxq_number; rxq++) | ||||
|  			if ((rxq % max_cpu) == cpu) | ||||
|  				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
|   | ||||
| -		if (cpu == pp->rxq_def) | ||||
| -			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
| +		for (txq = 0; txq < txq_number; txq++) | ||||
| +			if ((txq % max_cpu) == cpu) | ||||
| +				txq_map |= MVNETA_CPU_TXQ_ACCESS(txq); | ||||
| + | ||||
| +		/* With only one TX queue we configure a special case | ||||
| +		 * which will allow to get all the irq on a single | ||||
| +		 * CPU | ||||
| +		 */ | ||||
| +		if (txq_number == 1) | ||||
| +			txq_map = (cpu == pp->rxq_def) ? | ||||
| +				MVNETA_CPU_TXQ_ACCESS(1) : 0; | ||||
|   | ||||
|  		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map); | ||||
|  	} | ||||
| @@ -2362,6 +2376,8 @@ static void mvneta_rxq_deinit(struct mvn | ||||
|  static int mvneta_txq_init(struct mvneta_port *pp, | ||||
|  			   struct mvneta_tx_queue *txq) | ||||
|  { | ||||
| +	int cpu; | ||||
| + | ||||
|  	txq->size = pp->tx_ring_size; | ||||
|   | ||||
|  	/* A queue must always have room for at least one skb. | ||||
| @@ -2414,6 +2430,14 @@ static int mvneta_txq_init(struct mvneta | ||||
|  	} | ||||
|  	mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal); | ||||
|   | ||||
| +	/* Setup XPS mapping */ | ||||
| +	if (txq_number > 1) | ||||
| +		cpu = txq->id % num_present_cpus(); | ||||
| +	else | ||||
| +		cpu = pp->rxq_def % num_present_cpus(); | ||||
| +	cpumask_set_cpu(cpu, &txq->affinity_mask); | ||||
| +	netif_set_xps_queue(pp->dev, &txq->affinity_mask, txq->id); | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -2836,13 +2860,23 @@ static void mvneta_percpu_elect(struct m | ||||
|  			if ((rxq % max_cpu) == cpu) | ||||
|  				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
|   | ||||
| -		if (i == online_cpu_idx) { | ||||
| -			/* Map the default receive queue and transmit | ||||
| -			 * queue to the elected CPU | ||||
| +		if (i == online_cpu_idx) | ||||
| +			/* Map the default receive queue queue to the | ||||
| +			 * elected CPU | ||||
|  			 */ | ||||
|  			rxq_map |= MVNETA_CPU_RXQ_ACCESS(pp->rxq_def); | ||||
| -			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
| -		} | ||||
| + | ||||
| +		/* We update the TX queue map only if we have one | ||||
| +		 * queue. In this case we associate the TX queue to | ||||
| +		 * the CPU bound to the default RX queue | ||||
| +		 */ | ||||
| +		if (txq_number == 1) | ||||
| +			txq_map = (i == online_cpu_idx) ? | ||||
| +				MVNETA_CPU_TXQ_ACCESS(1) : 0; | ||||
| +		else | ||||
| +			txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & | ||||
| +				MVNETA_CPU_TXQ_ACCESS_ALL_MASK; | ||||
| + | ||||
|  		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map); | ||||
|   | ||||
|  		/* Update the interrupt mask on each CPU according the | ||||
| @@ -1,46 +0,0 @@ | ||||
| From: Jisheng Zhang <jszhang@marvell.com> | ||||
| Date: Wed, 20 Jan 2016 16:36:25 +0800 | ||||
| Subject: [PATCH] net: mvneta: fix trivial cut-off issue in | ||||
|  mvneta_ethtool_update_stats | ||||
|  | ||||
| When s->type is T_REG_64, the high 32bits are lost in val. This patch | ||||
| fixes this trivial issue. | ||||
|  | ||||
| Signed-off-by: Jisheng Zhang <jszhang@marvell.com> | ||||
| Fixes: 9b0cdefa4cd5 ("net: mvneta: add ethtool statistics") | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3242,26 +3242,25 @@ static void mvneta_ethtool_update_stats( | ||||
|  	const struct mvneta_statistic *s; | ||||
|  	void __iomem *base = pp->base; | ||||
|  	u32 high, low, val; | ||||
| +	u64 val64; | ||||
|  	int i; | ||||
|   | ||||
|  	for (i = 0, s = mvneta_statistics; | ||||
|  	     s < mvneta_statistics + ARRAY_SIZE(mvneta_statistics); | ||||
|  	     s++, i++) { | ||||
| -		val = 0; | ||||
| - | ||||
|  		switch (s->type) { | ||||
|  		case T_REG_32: | ||||
|  			val = readl_relaxed(base + s->offset); | ||||
| +			pp->ethtool_stats[i] += val; | ||||
|  			break; | ||||
|  		case T_REG_64: | ||||
|  			/* Docs say to read low 32-bit then high */ | ||||
|  			low = readl_relaxed(base + s->offset); | ||||
|  			high = readl_relaxed(base + s->offset + 4); | ||||
| -			val = (u64)high << 32 | low; | ||||
| +			val64 = (u64)high << 32 | low; | ||||
| +			pp->ethtool_stats[i] += val64; | ||||
|  			break; | ||||
|  		} | ||||
| - | ||||
| -		pp->ethtool_stats[i] += val; | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| @@ -1,55 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:23 +0100 | ||||
| Subject: [PATCH] net: mvneta: Fix for_each_present_cpu usage | ||||
|  | ||||
| This patch convert the for_each_present in on_each_cpu, instead of | ||||
| applying on the present cpus it will be applied only on the online cpus. | ||||
| This fix a bug reported on | ||||
| http://thread.gmane.org/gmane.linux.ports.arm.kernel/468173. | ||||
|  | ||||
| Using the macro on_each_cpu (instead of a for_each_* loop) also ensures | ||||
| that all the calls will be done all at once. | ||||
|  | ||||
| Fixes: f86428854480 ("net: mvneta: Statically assign queues to CPUs") | ||||
| Reported-by: Stefan Roese <stefan.roese@gmail.com> | ||||
| Suggested-by: Jisheng Zhang <jszhang@marvell.com> | ||||
| Suggested-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -2562,7 +2562,7 @@ static void mvneta_start_dev(struct mvne | ||||
|  	mvneta_port_enable(pp); | ||||
|   | ||||
|  	/* Enable polling on the port */ | ||||
| -	for_each_present_cpu(cpu) { | ||||
| +	for_each_online_cpu(cpu) { | ||||
|  		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); | ||||
|   | ||||
|  		napi_enable(&port->napi); | ||||
| @@ -2587,7 +2587,7 @@ static void mvneta_stop_dev(struct mvnet | ||||
|   | ||||
|  	phy_stop(pp->phy_dev); | ||||
|   | ||||
| -	for_each_present_cpu(cpu) { | ||||
| +	for_each_online_cpu(cpu) { | ||||
|  		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); | ||||
|   | ||||
|  		napi_disable(&port->napi); | ||||
| @@ -3055,13 +3055,11 @@ err_cleanup_rxqs: | ||||
|  static int mvneta_stop(struct net_device *dev) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
| -	int cpu; | ||||
|   | ||||
|  	mvneta_stop_dev(pp); | ||||
|  	mvneta_mdio_remove(pp); | ||||
|  	unregister_cpu_notifier(&pp->cpu_notifier); | ||||
| -	for_each_present_cpu(cpu) | ||||
| -		smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); | ||||
| +	on_each_cpu(mvneta_percpu_disable, pp, true); | ||||
|  	free_percpu_irq(dev->irq, pp->ports); | ||||
|  	mvneta_cleanup_rxqs(pp); | ||||
|  	mvneta_cleanup_txqs(pp); | ||||
| @@ -1,57 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:24 +0100 | ||||
| Subject: [PATCH] net: mvneta: Fix the CPU choice in mvneta_percpu_elect | ||||
|  | ||||
| When passing to the management of multiple RX queue, the | ||||
| mvneta_percpu_elect function was broken. The use of the modulo can lead | ||||
| to elect the wrong cpu. For example with rxq_def=2, if the CPU 2 goes | ||||
| offline and then online, we ended with the third RX queue activated in | ||||
| the same time on CPU 0 and CPU2, which lead to a kernel crash. | ||||
|  | ||||
| With this fix, we don't try to get "the closer" CPU if the default CPU is | ||||
| gone, now we just use CPU 0 which always be there. Thanks to this, the | ||||
| code becomes more readable, easier to maintain and more predicable. | ||||
|  | ||||
| Cc: stable@vger.kernel.org | ||||
| Fixes: 2dcf75e2793c ("net: mvneta: Associate RX queues with each CPU") | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -2847,9 +2847,14 @@ static void mvneta_percpu_disable(void * | ||||
|   | ||||
|  static void mvneta_percpu_elect(struct mvneta_port *pp) | ||||
|  { | ||||
| -	int online_cpu_idx, max_cpu, cpu, i = 0; | ||||
| +	int elected_cpu = 0, max_cpu, cpu, i = 0; | ||||
| + | ||||
| +	/* Use the cpu associated to the rxq when it is online, in all | ||||
| +	 * the other cases, use the cpu 0 which can't be offline. | ||||
| +	 */ | ||||
| +	if (cpu_online(pp->rxq_def)) | ||||
| +		elected_cpu = pp->rxq_def; | ||||
|   | ||||
| -	online_cpu_idx = pp->rxq_def % num_online_cpus(); | ||||
|  	max_cpu = num_present_cpus(); | ||||
|   | ||||
|  	for_each_online_cpu(cpu) { | ||||
| @@ -2860,7 +2865,7 @@ static void mvneta_percpu_elect(struct m | ||||
|  			if ((rxq % max_cpu) == cpu) | ||||
|  				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq); | ||||
|   | ||||
| -		if (i == online_cpu_idx) | ||||
| +		if (cpu == elected_cpu) | ||||
|  			/* Map the default receive queue queue to the | ||||
|  			 * elected CPU | ||||
|  			 */ | ||||
| @@ -2871,7 +2876,7 @@ static void mvneta_percpu_elect(struct m | ||||
|  		 * the CPU bound to the default RX queue | ||||
|  		 */ | ||||
|  		if (txq_number == 1) | ||||
| -			txq_map = (i == online_cpu_idx) ? | ||||
| +			txq_map = (cpu == elected_cpu) ? | ||||
|  				MVNETA_CPU_TXQ_ACCESS(1) : 0; | ||||
|  		else | ||||
|  			txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) & | ||||
| @@ -1,68 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:25 +0100 | ||||
| Subject: [PATCH] net: mvneta: Use on_each_cpu when possible | ||||
|  | ||||
| Instead of using a for_each_* loop in which we just call the | ||||
| smp_call_function_single macro, it is more simple to directly use the | ||||
| on_each_cpu macro. Moreover, this macro ensures that the calls will be | ||||
| done all at once. | ||||
|  | ||||
| Suggested-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -2553,7 +2553,7 @@ static void mvneta_percpu_mask_interrupt | ||||
|   | ||||
|  static void mvneta_start_dev(struct mvneta_port *pp) | ||||
|  { | ||||
| -	unsigned int cpu; | ||||
| +	int cpu; | ||||
|   | ||||
|  	mvneta_max_rx_size_set(pp, pp->pkt_size); | ||||
|  	mvneta_txq_max_tx_size_set(pp, pp->pkt_size); | ||||
| @@ -2569,9 +2569,8 @@ static void mvneta_start_dev(struct mvne | ||||
|  	} | ||||
|   | ||||
|  	/* Unmask interrupts. It has to be done from each CPU */ | ||||
| -	for_each_online_cpu(cpu) | ||||
| -		smp_call_function_single(cpu, mvneta_percpu_unmask_interrupt, | ||||
| -					 pp, true); | ||||
| +	on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); | ||||
| + | ||||
|  	mvreg_write(pp, MVNETA_INTR_MISC_MASK, | ||||
|  		    MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
|  		    MVNETA_CAUSE_LINK_CHANGE | | ||||
| @@ -2991,7 +2990,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  static int mvneta_open(struct net_device *dev) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
| -	int ret, cpu; | ||||
| +	int ret; | ||||
|   | ||||
|  	pp->pkt_size = MVNETA_RX_PKT_SIZE(pp->dev->mtu); | ||||
|  	pp->frag_size = SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(pp->pkt_size)) + | ||||
| @@ -3024,9 +3023,7 @@ static int mvneta_open(struct net_device | ||||
|  	/* Enable per-CPU interrupt on all the CPU to handle our RX | ||||
|  	 * queue interrupts | ||||
|  	 */ | ||||
| -	for_each_online_cpu(cpu) | ||||
| -		smp_call_function_single(cpu, mvneta_percpu_enable, | ||||
| -					 pp, true); | ||||
| +	on_each_cpu(mvneta_percpu_enable, pp, true); | ||||
|   | ||||
|   | ||||
|  	/* Register a CPU notifier to handle the case where our CPU | ||||
| @@ -3313,9 +3310,7 @@ static int  mvneta_config_rss(struct mvn | ||||
|   | ||||
|  	netif_tx_stop_all_queues(pp->dev); | ||||
|   | ||||
| -	for_each_online_cpu(cpu) | ||||
| -		smp_call_function_single(cpu, mvneta_percpu_mask_interrupt, | ||||
| -					 pp, true); | ||||
| +	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
|   | ||||
|  	/* We have to synchronise on the napi of each CPU */ | ||||
|  	for_each_online_cpu(cpu) { | ||||
| @@ -1,179 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:27 +0100 | ||||
| Subject: [PATCH] net: mvneta: Modify the queue related fields from each cpu | ||||
|  | ||||
| In the MVNETA_INTR_* registers, the queues related fields are per cpu, | ||||
| according to the datasheet (comment in [] are added by me): | ||||
| "In a multi-CPU system, bits of RX[or TX] queues for which the access by | ||||
| the reading[or writing] CPU is disabled are read as 0, and cannot be | ||||
| cleared[or written]." | ||||
|  | ||||
| That means that each time we want to manipulate these bits we had to do | ||||
| it on each cpu and not only on the current cpu. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -1036,6 +1036,43 @@ static void mvneta_set_autoneg(struct mv | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| +static void mvneta_percpu_unmask_interrupt(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	/* All the queue are unmasked, but actually only the ones | ||||
| +	 * mapped to this CPU will be unmasked | ||||
| +	 */ | ||||
| +	mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| +		    MVNETA_RX_INTR_MASK_ALL | | ||||
| +		    MVNETA_TX_INTR_MASK_ALL | | ||||
| +		    MVNETA_MISCINTR_INTR_MASK); | ||||
| +} | ||||
| + | ||||
| +static void mvneta_percpu_mask_interrupt(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	/* All the queue are masked, but actually only the ones | ||||
| +	 * mapped to this CPU will be masked | ||||
| +	 */ | ||||
| +	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +} | ||||
| + | ||||
| +static void mvneta_percpu_clear_intr_cause(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	/* All the queue are cleared, but actually only the ones | ||||
| +	 * mapped to this CPU will be cleared | ||||
| +	 */ | ||||
| +	mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); | ||||
| +	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); | ||||
| +} | ||||
| + | ||||
|  /* This method sets defaults to the NETA port: | ||||
|   *	Clears interrupt Cause and Mask registers. | ||||
|   *	Clears all MAC tables. | ||||
| @@ -1053,14 +1090,10 @@ static void mvneta_defaults_set(struct m | ||||
|  	int max_cpu = num_present_cpus(); | ||||
|   | ||||
|  	/* Clear all Cause registers */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_CAUSE, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); | ||||
| +	on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true); | ||||
|   | ||||
|  	/* Mask all interrupts */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
|  	mvreg_write(pp, MVNETA_INTR_ENABLE, 0); | ||||
|   | ||||
|  	/* Enable MBUS Retry bit16 */ | ||||
| @@ -2526,31 +2559,6 @@ static int mvneta_setup_txqs(struct mvne | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| -static void mvneta_percpu_unmask_interrupt(void *arg) | ||||
| -{ | ||||
| -	struct mvneta_port *pp = arg; | ||||
| - | ||||
| -	/* All the queue are unmasked, but actually only the ones | ||||
| -	 * maped to this CPU will be unmasked | ||||
| -	 */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| -		    MVNETA_RX_INTR_MASK_ALL | | ||||
| -		    MVNETA_TX_INTR_MASK_ALL | | ||||
| -		    MVNETA_MISCINTR_INTR_MASK); | ||||
| -} | ||||
| - | ||||
| -static void mvneta_percpu_mask_interrupt(void *arg) | ||||
| -{ | ||||
| -	struct mvneta_port *pp = arg; | ||||
| - | ||||
| -	/* All the queue are masked, but actually only the ones | ||||
| -	 * maped to this CPU will be masked | ||||
| -	 */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| -} | ||||
| - | ||||
|  static void mvneta_start_dev(struct mvneta_port *pp) | ||||
|  { | ||||
|  	int cpu; | ||||
| @@ -2601,13 +2609,10 @@ static void mvneta_stop_dev(struct mvnet | ||||
|  	mvneta_port_disable(pp); | ||||
|   | ||||
|  	/* Clear all ethernet port interrupts */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0); | ||||
| +	on_each_cpu(mvneta_percpu_clear_intr_cause, pp, true); | ||||
|   | ||||
|  	/* Mask all ethernet port interrupts */ | ||||
| -	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| -	mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
|   | ||||
|  	mvneta_tx_reset(pp); | ||||
|  	mvneta_rx_reset(pp); | ||||
| @@ -2919,9 +2924,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  		} | ||||
|   | ||||
|  		/* Mask all ethernet port interrupts */ | ||||
| -		mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| -		mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| -		mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +		on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
|  		napi_enable(&port->napi); | ||||
|   | ||||
|   | ||||
| @@ -2936,14 +2939,8 @@ static int mvneta_percpu_notifier(struct | ||||
|  		 */ | ||||
|  		mvneta_percpu_elect(pp); | ||||
|   | ||||
| -		/* Unmask all ethernet port interrupts, as this | ||||
| -		 * notifier is called for each CPU then the CPU to | ||||
| -		 * Queue mapping is applied | ||||
| -		 */ | ||||
| -		mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| -			MVNETA_RX_INTR_MASK(rxq_number) | | ||||
| -			MVNETA_TX_INTR_MASK(txq_number) | | ||||
| -			MVNETA_MISCINTR_INTR_MASK); | ||||
| +		/* Unmask all ethernet port interrupts */ | ||||
| +		on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); | ||||
|  		mvreg_write(pp, MVNETA_INTR_MISC_MASK, | ||||
|  			MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
|  			MVNETA_CAUSE_LINK_CHANGE | | ||||
| @@ -2954,9 +2951,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  	case CPU_DOWN_PREPARE_FROZEN: | ||||
|  		netif_tx_stop_all_queues(pp->dev); | ||||
|  		/* Mask all ethernet port interrupts */ | ||||
| -		mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0); | ||||
| -		mvreg_write(pp, MVNETA_INTR_OLD_MASK, 0); | ||||
| -		mvreg_write(pp, MVNETA_INTR_MISC_MASK, 0); | ||||
| +		on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
|   | ||||
|  		napi_synchronize(&port->napi); | ||||
|  		napi_disable(&port->napi); | ||||
| @@ -2972,10 +2967,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  		/* Check if a new CPU must be elected now this on is down */ | ||||
|  		mvneta_percpu_elect(pp); | ||||
|  		/* Unmask all ethernet port interrupts */ | ||||
| -		mvreg_write(pp, MVNETA_INTR_NEW_MASK, | ||||
| -			MVNETA_RX_INTR_MASK(rxq_number) | | ||||
| -			MVNETA_TX_INTR_MASK(txq_number) | | ||||
| -			MVNETA_MISCINTR_INTR_MASK); | ||||
| +		on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); | ||||
|  		mvreg_write(pp, MVNETA_INTR_MISC_MASK, | ||||
|  			MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
|  			MVNETA_CAUSE_LINK_CHANGE | | ||||
| @@ -1,68 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:28 +0100 | ||||
| Subject: [PATCH] net: mvneta: The mvneta_percpu_elect function should be | ||||
|  atomic | ||||
|  | ||||
| Electing a CPU must be done in an atomic way: it should be done after or | ||||
| before the removal/insertion of a CPU and this function is not reentrant. | ||||
|  | ||||
| During the loop of mvneta_percpu_elect we associates the queues to the | ||||
| CPUs, if there is a topology change during this loop, then the mapping | ||||
| between the CPUs and the queues could be wrong. During this loop the | ||||
| interrupt mask is also updating for each CPUs, It should not be changed | ||||
| in the same time by other part of the driver. | ||||
|  | ||||
| This patch adds spinlock to create the needed critical sections. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -370,6 +370,10 @@ struct mvneta_port { | ||||
|  	struct net_device *dev; | ||||
|  	struct notifier_block cpu_notifier; | ||||
|  	int rxq_def; | ||||
| +	/* Protect the access to the percpu interrupt registers, | ||||
| +	 * ensuring that the configuration remains coherent. | ||||
| +	 */ | ||||
| +	spinlock_t lock; | ||||
|   | ||||
|  	/* Core clock */ | ||||
|  	struct clk *clk; | ||||
| @@ -2853,6 +2857,12 @@ static void mvneta_percpu_elect(struct m | ||||
|  { | ||||
|  	int elected_cpu = 0, max_cpu, cpu, i = 0; | ||||
|   | ||||
| +	/* Electing a CPU must be done in an atomic way: it should be | ||||
| +	 * done after or before the removal/insertion of a CPU and | ||||
| +	 * this function is not reentrant. | ||||
| +	 */ | ||||
| +	spin_lock(&pp->lock); | ||||
| + | ||||
|  	/* Use the cpu associated to the rxq when it is online, in all | ||||
|  	 * the other cases, use the cpu 0 which can't be offline. | ||||
|  	 */ | ||||
| @@ -2896,6 +2906,7 @@ static void mvneta_percpu_elect(struct m | ||||
|  		i++; | ||||
|   | ||||
|  	} | ||||
| +	spin_unlock(&pp->lock); | ||||
|  }; | ||||
|   | ||||
|  static int mvneta_percpu_notifier(struct notifier_block *nfb, | ||||
| @@ -2950,8 +2961,13 @@ static int mvneta_percpu_notifier(struct | ||||
|  	case CPU_DOWN_PREPARE: | ||||
|  	case CPU_DOWN_PREPARE_FROZEN: | ||||
|  		netif_tx_stop_all_queues(pp->dev); | ||||
| +		/* Thanks to this lock we are sure that any pending | ||||
| +		 * cpu election is done | ||||
| +		 */ | ||||
| +		spin_lock(&pp->lock); | ||||
|  		/* Mask all ethernet port interrupts */ | ||||
|  		on_each_cpu(mvneta_percpu_mask_interrupt, pp, true); | ||||
| +		spin_unlock(&pp->lock); | ||||
|   | ||||
|  		napi_synchronize(&port->napi); | ||||
|  		napi_disable(&port->napi); | ||||
| @@ -1,128 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Thu, 4 Feb 2016 22:09:29 +0100 | ||||
| Subject: [PATCH] net: mvneta: Fix race condition during stopping | ||||
|  | ||||
| When stopping the port, the CPU notifier are still there whereas the | ||||
| mvneta_stop_dev function calls mvneta_percpu_disable() on each CPUs. | ||||
| It was possible to have a new CPU coming at this point which could be | ||||
| racy. | ||||
|  | ||||
| This patch adds a flag preventing executing the code notifier for a new | ||||
| CPU when the port is stopping. It also uses the spinlock introduces | ||||
| previously. To avoid the deadlock, the lock has been moved outside the | ||||
| mvneta_percpu_elect function. | ||||
|  | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -374,6 +374,7 @@ struct mvneta_port { | ||||
|  	 * ensuring that the configuration remains coherent. | ||||
|  	 */ | ||||
|  	spinlock_t lock; | ||||
| +	bool is_stopped; | ||||
|   | ||||
|  	/* Core clock */ | ||||
|  	struct clk *clk; | ||||
| @@ -2853,16 +2854,14 @@ static void mvneta_percpu_disable(void * | ||||
|  	disable_percpu_irq(pp->dev->irq); | ||||
|  } | ||||
|   | ||||
| +/* Electing a CPU must be done in an atomic way: it should be done | ||||
| + * after or before the removal/insertion of a CPU and this function is | ||||
| + * not reentrant. | ||||
| + */ | ||||
|  static void mvneta_percpu_elect(struct mvneta_port *pp) | ||||
|  { | ||||
|  	int elected_cpu = 0, max_cpu, cpu, i = 0; | ||||
|   | ||||
| -	/* Electing a CPU must be done in an atomic way: it should be | ||||
| -	 * done after or before the removal/insertion of a CPU and | ||||
| -	 * this function is not reentrant. | ||||
| -	 */ | ||||
| -	spin_lock(&pp->lock); | ||||
| - | ||||
|  	/* Use the cpu associated to the rxq when it is online, in all | ||||
|  	 * the other cases, use the cpu 0 which can't be offline. | ||||
|  	 */ | ||||
| @@ -2906,7 +2905,6 @@ static void mvneta_percpu_elect(struct m | ||||
|  		i++; | ||||
|   | ||||
|  	} | ||||
| -	spin_unlock(&pp->lock); | ||||
|  }; | ||||
|   | ||||
|  static int mvneta_percpu_notifier(struct notifier_block *nfb, | ||||
| @@ -2920,6 +2918,14 @@ static int mvneta_percpu_notifier(struct | ||||
|  	switch (action) { | ||||
|  	case CPU_ONLINE: | ||||
|  	case CPU_ONLINE_FROZEN: | ||||
| +		spin_lock(&pp->lock); | ||||
| +		/* Configuring the driver for a new CPU while the | ||||
| +		 * driver is stopping is racy, so just avoid it. | ||||
| +		 */ | ||||
| +		if (pp->is_stopped) { | ||||
| +			spin_unlock(&pp->lock); | ||||
| +			break; | ||||
| +		} | ||||
|  		netif_tx_stop_all_queues(pp->dev); | ||||
|   | ||||
|  		/* We have to synchronise on tha napi of each CPU | ||||
| @@ -2957,6 +2963,7 @@ static int mvneta_percpu_notifier(struct | ||||
|  			MVNETA_CAUSE_LINK_CHANGE | | ||||
|  			MVNETA_CAUSE_PSC_SYNC_CHANGE); | ||||
|  		netif_tx_start_all_queues(pp->dev); | ||||
| +		spin_unlock(&pp->lock); | ||||
|  		break; | ||||
|  	case CPU_DOWN_PREPARE: | ||||
|  	case CPU_DOWN_PREPARE_FROZEN: | ||||
| @@ -2981,7 +2988,9 @@ static int mvneta_percpu_notifier(struct | ||||
|  	case CPU_DEAD: | ||||
|  	case CPU_DEAD_FROZEN: | ||||
|  		/* Check if a new CPU must be elected now this on is down */ | ||||
| +		spin_lock(&pp->lock); | ||||
|  		mvneta_percpu_elect(pp); | ||||
| +		spin_unlock(&pp->lock); | ||||
|  		/* Unmask all ethernet port interrupts */ | ||||
|  		on_each_cpu(mvneta_percpu_unmask_interrupt, pp, true); | ||||
|  		mvreg_write(pp, MVNETA_INTR_MISC_MASK, | ||||
| @@ -3033,7 +3042,7 @@ static int mvneta_open(struct net_device | ||||
|  	 */ | ||||
|  	on_each_cpu(mvneta_percpu_enable, pp, true); | ||||
|   | ||||
| - | ||||
| +	pp->is_stopped = false; | ||||
|  	/* Register a CPU notifier to handle the case where our CPU | ||||
|  	 * might be taken offline. | ||||
|  	 */ | ||||
| @@ -3066,9 +3075,18 @@ static int mvneta_stop(struct net_device | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
|   | ||||
| +	/* Inform that we are stopping so we don't want to setup the | ||||
| +	 * driver for new CPUs in the notifiers | ||||
| +	 */ | ||||
| +	spin_lock(&pp->lock); | ||||
| +	pp->is_stopped = true; | ||||
|  	mvneta_stop_dev(pp); | ||||
|  	mvneta_mdio_remove(pp); | ||||
|  	unregister_cpu_notifier(&pp->cpu_notifier); | ||||
| +	/* Now that the notifier are unregistered, we can release le | ||||
| +	 * lock | ||||
| +	 */ | ||||
| +	spin_unlock(&pp->lock); | ||||
|  	on_each_cpu(mvneta_percpu_disable, pp, true); | ||||
|  	free_percpu_irq(dev->irq, pp->ports); | ||||
|  	mvneta_cleanup_rxqs(pp); | ||||
| @@ -3339,7 +3357,9 @@ static int  mvneta_config_rss(struct mvn | ||||
|  	mvreg_write(pp, MVNETA_PORT_CONFIG, val); | ||||
|   | ||||
|  	/* Update the elected CPU matching the new rxq_def */ | ||||
| +	spin_lock(&pp->lock); | ||||
|  	mvneta_percpu_elect(pp); | ||||
| +	spin_unlock(&pp->lock); | ||||
|   | ||||
|  	/* We have to synchronise on the napi of each CPU */ | ||||
|  	for_each_online_cpu(cpu) { | ||||
| @@ -1,56 +0,0 @@ | ||||
| From: Jisheng Zhang <jszhang@marvell.com> | ||||
| Date: Wed, 20 Jan 2016 19:27:22 +0800 | ||||
| Subject: [PATCH] net: mvneta: sort the headers in alphabetic order | ||||
|  | ||||
| Sorting the headers in alphabetic order will help to reduce the conflict | ||||
| when adding new headers in the future. | ||||
|  | ||||
| Signed-off-by: Jisheng Zhang <jszhang@marvell.com> | ||||
| Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -11,28 +11,28 @@ | ||||
|   * warranty of any kind, whether express or implied. | ||||
|   */ | ||||
|   | ||||
| -#include <linux/kernel.h> | ||||
| -#include <linux/netdevice.h> | ||||
| +#include <linux/clk.h> | ||||
| +#include <linux/cpu.h> | ||||
|  #include <linux/etherdevice.h> | ||||
| -#include <linux/platform_device.h> | ||||
| -#include <linux/skbuff.h> | ||||
| +#include <linux/if_vlan.h> | ||||
|  #include <linux/inetdevice.h> | ||||
| -#include <linux/mbus.h> | ||||
| -#include <linux/module.h> | ||||
|  #include <linux/interrupt.h> | ||||
| -#include <linux/if_vlan.h> | ||||
| -#include <net/ip.h> | ||||
| -#include <net/ipv6.h> | ||||
|  #include <linux/io.h> | ||||
| -#include <net/tso.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/mbus.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/netdevice.h> | ||||
|  #include <linux/of.h> | ||||
| +#include <linux/of_address.h> | ||||
|  #include <linux/of_irq.h> | ||||
|  #include <linux/of_mdio.h> | ||||
|  #include <linux/of_net.h> | ||||
| -#include <linux/of_address.h> | ||||
|  #include <linux/phy.h> | ||||
| -#include <linux/clk.h> | ||||
| -#include <linux/cpu.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/skbuff.h> | ||||
| +#include <net/ip.h> | ||||
| +#include <net/ipv6.h> | ||||
| +#include <net/tso.h> | ||||
|   | ||||
|  /* Registers */ | ||||
|  #define MVNETA_RXQ_CONFIG_REG(q)                (0x1400 + ((q) << 2)) | ||||
| @@ -1,159 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Mon, 14 Mar 2016 09:39:04 +0100 | ||||
| Subject: [PATCH] net: add a hardware buffer management helper API | ||||
|  | ||||
| This basic implementation allows to share code between driver using | ||||
| hardware buffer management. As the code is hardware agnostic, there is | ||||
| few helpers, most of the optimization brought by the an HW BM has to be | ||||
| done at driver level. | ||||
|  | ||||
| Tested-by: Sebastian Careba <nitroshift@yahoo.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  create mode 100644 include/net/hwbm.h | ||||
|  create mode 100644 net/core/hwbm.c | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/include/net/hwbm.h | ||||
| @@ -0,0 +1,28 @@ | ||||
| +#ifndef _HWBM_H | ||||
| +#define _HWBM_H | ||||
| + | ||||
| +struct hwbm_pool { | ||||
| +	/* Capacity of the pool */ | ||||
| +	int size; | ||||
| +	/* Size of the buffers managed */ | ||||
| +	int frag_size; | ||||
| +	/* Number of buffers currently used by this pool */ | ||||
| +	int buf_num; | ||||
| +	/* constructor called during alocation */ | ||||
| +	int (*construct)(struct hwbm_pool *bm_pool, void *buf); | ||||
| +	/* protect acces to the buffer counter*/ | ||||
| +	spinlock_t lock; | ||||
| +	/* private data */ | ||||
| +	void *priv; | ||||
| +}; | ||||
| +#ifdef CONFIG_HWBM | ||||
| +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf); | ||||
| +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp); | ||||
| +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp); | ||||
| +#else | ||||
| +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {} | ||||
| +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; } | ||||
| +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp) | ||||
| +{ return 0; } | ||||
| +#endif /* CONFIG_HWBM */ | ||||
| +#endif /* _HWBM_H */ | ||||
| --- a/net/Kconfig | ||||
| +++ b/net/Kconfig | ||||
| @@ -259,6 +259,9 @@ config XPS | ||||
|  	depends on SMP | ||||
|  	default y | ||||
|   | ||||
| +config HWBM | ||||
| +	bool | ||||
| + | ||||
|  config CGROUP_NET_PRIO | ||||
|  	bool "Network priority cgroup" | ||||
|  	depends on CGROUPS | ||||
| --- a/net/core/Makefile | ||||
| +++ b/net/core/Makefile | ||||
| @@ -14,6 +14,7 @@ obj-y		     += dev.o ethtool.o dev_addr_ | ||||
|  obj-$(CONFIG_SOCK_DIAG) += sock_diag.o | ||||
|  obj-$(CONFIG_XFRM) += flow.o | ||||
|  obj-y += net-sysfs.o | ||||
| +obj-$(CONFIG_HWBM) += hwbm.o | ||||
|  obj-$(CONFIG_PROC_FS) += net-procfs.o | ||||
|  obj-$(CONFIG_NET_PKTGEN) += pktgen.o | ||||
|  obj-$(CONFIG_NETPOLL) += netpoll.o | ||||
| --- /dev/null | ||||
| +++ b/net/core/hwbm.c | ||||
| @@ -0,0 +1,87 @@ | ||||
| +/* Support for hardware buffer manager. | ||||
| + * | ||||
| + * Copyright (C) 2016 Marvell | ||||
| + * | ||||
| + * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify | ||||
| + *  it under the terms of the GNU General Public License as published by | ||||
| + *  the Free Software Foundation; either version 2 of the License, or | ||||
| + *  (at your option) any later version. | ||||
| + */ | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/printk.h> | ||||
| +#include <linux/skbuff.h> | ||||
| +#include <net/hwbm.h> | ||||
| + | ||||
| +void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) | ||||
| +{ | ||||
| +	if (likely(bm_pool->frag_size <= PAGE_SIZE)) | ||||
| +		skb_free_frag(buf); | ||||
| +	else | ||||
| +		kfree(buf); | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(hwbm_buf_free); | ||||
| + | ||||
| +/* Refill processing for HW buffer management */ | ||||
| +int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) | ||||
| +{ | ||||
| +	int frag_size = bm_pool->frag_size; | ||||
| +	void *buf; | ||||
| + | ||||
| +	if (likely(frag_size <= PAGE_SIZE)) | ||||
| +		buf = netdev_alloc_frag(frag_size); | ||||
| +	else | ||||
| +		buf = kmalloc(frag_size, gfp); | ||||
| + | ||||
| +	if (!buf) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	if (bm_pool->construct) | ||||
| +		if (bm_pool->construct(bm_pool, buf)) { | ||||
| +			hwbm_buf_free(bm_pool, buf); | ||||
| +			return -ENOMEM; | ||||
| +		} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(hwbm_pool_refill); | ||||
| + | ||||
| +int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp) | ||||
| +{ | ||||
| +	int err, i; | ||||
| +	unsigned long flags; | ||||
| + | ||||
| +	spin_lock_irqsave(&bm_pool->lock, flags); | ||||
| +	if (bm_pool->buf_num == bm_pool->size) { | ||||
| +		pr_warn("pool already filled\n"); | ||||
| +		return bm_pool->buf_num; | ||||
| +	} | ||||
| + | ||||
| +	if (buf_num + bm_pool->buf_num > bm_pool->size) { | ||||
| +		pr_warn("cannot allocate %d buffers for pool\n", | ||||
| +			buf_num); | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) { | ||||
| +		pr_warn("Adding %d buffers to the %d current buffers will overflow\n", | ||||
| +			buf_num,  bm_pool->buf_num); | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	for (i = 0; i < buf_num; i++) { | ||||
| +		err = hwbm_pool_refill(bm_pool, gfp); | ||||
| +		if (err < 0) | ||||
| +			break; | ||||
| +	} | ||||
| + | ||||
| +	/* Update BM driver with number of buffers added to pool */ | ||||
| +	bm_pool->buf_num += i; | ||||
| + | ||||
| +	pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num); | ||||
| +	spin_unlock_irqrestore(&bm_pool->lock, flags); | ||||
| + | ||||
| +	return i; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(hwbm_pool_add); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,359 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Mon, 14 Mar 2016 09:39:05 +0100 | ||||
| Subject: [PATCH] net: mvneta: Use the new hwbm framework | ||||
|  | ||||
| Now that the hardware buffer management framework had been introduced, | ||||
| let's use it. | ||||
|  | ||||
| Tested-by: Sebastian Careba <nitroshift@yahoo.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/Kconfig | ||||
| +++ b/drivers/net/ethernet/marvell/Kconfig | ||||
| @@ -43,6 +43,7 @@ config MVMDIO | ||||
|  config MVNETA_BM | ||||
|  	tristate "Marvell Armada 38x/XP network interface BM support" | ||||
|  	depends on MVNETA | ||||
| +	select HWBM | ||||
|  	---help--- | ||||
|  	  This driver supports auxiliary block of the network | ||||
|  	  interface units in the Marvell ARMADA XP and ARMADA 38x SoC | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -30,6 +30,7 @@ | ||||
|  #include <linux/phy.h> | ||||
|  #include <linux/platform_device.h> | ||||
|  #include <linux/skbuff.h> | ||||
| +#include <net/hwbm.h> | ||||
|  #include "mvneta_bm.h" | ||||
|  #include <net/ip.h> | ||||
|  #include <net/ipv6.h> | ||||
| @@ -1024,11 +1025,12 @@ static int mvneta_bm_port_init(struct pl | ||||
|  static void mvneta_bm_update_mtu(struct mvneta_port *pp, int mtu) | ||||
|  { | ||||
|  	struct mvneta_bm_pool *bm_pool = pp->pool_long; | ||||
| +	struct hwbm_pool *hwbm_pool = &bm_pool->hwbm_pool; | ||||
|  	int num; | ||||
|   | ||||
|  	/* Release all buffers from long pool */ | ||||
|  	mvneta_bm_bufs_free(pp->bm_priv, bm_pool, 1 << pp->id); | ||||
| -	if (bm_pool->buf_num) { | ||||
| +	if (hwbm_pool->buf_num) { | ||||
|  		WARN(1, "cannot free all buffers in pool %d\n", | ||||
|  		     bm_pool->id); | ||||
|  		goto bm_mtu_err; | ||||
| @@ -1036,14 +1038,14 @@ static void mvneta_bm_update_mtu(struct | ||||
|   | ||||
|  	bm_pool->pkt_size = MVNETA_RX_PKT_SIZE(mtu); | ||||
|  	bm_pool->buf_size = MVNETA_RX_BUF_SIZE(bm_pool->pkt_size); | ||||
| -	bm_pool->frag_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + | ||||
| -			  SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(bm_pool->pkt_size)); | ||||
| +	hwbm_pool->frag_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + | ||||
| +			SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(bm_pool->pkt_size)); | ||||
|   | ||||
|  	/* Fill entire long pool */ | ||||
| -	num = mvneta_bm_bufs_add(pp->bm_priv, bm_pool, bm_pool->size); | ||||
| -	if (num != bm_pool->size) { | ||||
| +	num = hwbm_pool_add(hwbm_pool, hwbm_pool->size, GFP_ATOMIC); | ||||
| +	if (num != hwbm_pool->size) { | ||||
|  		WARN(1, "pool %d: %d of %d allocated\n", | ||||
| -		     bm_pool->id, num, bm_pool->size); | ||||
| +		     bm_pool->id, num, hwbm_pool->size); | ||||
|  		goto bm_mtu_err; | ||||
|  	} | ||||
|  	mvneta_bm_pool_bufsize_set(pp, bm_pool->buf_size, bm_pool->id); | ||||
| @@ -2064,14 +2066,14 @@ err_drop_frame: | ||||
|  		} | ||||
|   | ||||
|  		/* Refill processing */ | ||||
| -		err = mvneta_bm_pool_refill(pp->bm_priv, bm_pool); | ||||
| +		err = hwbm_pool_refill(&bm_pool->hwbm_pool, GFP_ATOMIC); | ||||
|  		if (err) { | ||||
|  			netdev_err(dev, "Linux processing - Can't refill\n"); | ||||
|  			rxq->missed++; | ||||
|  			goto err_drop_frame_ret_pool; | ||||
|  		} | ||||
|   | ||||
| -		frag_size = bm_pool->frag_size; | ||||
| +		frag_size = bm_pool->hwbm_pool.frag_size; | ||||
|   | ||||
|  		skb = build_skb(data, frag_size > PAGE_SIZE ? 0 : frag_size); | ||||
|   | ||||
| --- a/drivers/net/ethernet/marvell/mvneta_bm.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta_bm.c | ||||
| @@ -10,16 +10,17 @@ | ||||
|   * warranty of any kind, whether express or implied. | ||||
|   */ | ||||
|   | ||||
| -#include <linux/kernel.h> | ||||
| +#include <linux/clk.h> | ||||
|  #include <linux/genalloc.h> | ||||
| -#include <linux/platform_device.h> | ||||
| -#include <linux/netdevice.h> | ||||
| -#include <linux/skbuff.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/kernel.h> | ||||
|  #include <linux/mbus.h> | ||||
|  #include <linux/module.h> | ||||
| -#include <linux/io.h> | ||||
| +#include <linux/netdevice.h> | ||||
|  #include <linux/of.h> | ||||
| -#include <linux/clk.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/skbuff.h> | ||||
| +#include <net/hwbm.h> | ||||
|  #include "mvneta_bm.h" | ||||
|   | ||||
|  #define MVNETA_BM_DRIVER_NAME "mvneta_bm" | ||||
| @@ -88,17 +89,13 @@ static void mvneta_bm_pool_target_set(st | ||||
|  	mvneta_bm_write(priv, MVNETA_BM_XBAR_POOL_REG(pool_id), val); | ||||
|  } | ||||
|   | ||||
| -/* Allocate skb for BM pool */ | ||||
| -void *mvneta_buf_alloc(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
| -		       dma_addr_t *buf_phys_addr) | ||||
| +int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) | ||||
|  { | ||||
| -	void *buf; | ||||
| +	struct mvneta_bm_pool *bm_pool = | ||||
| +		(struct mvneta_bm_pool *)hwbm_pool->priv; | ||||
| +	struct mvneta_bm *priv = bm_pool->priv; | ||||
|  	dma_addr_t phys_addr; | ||||
|   | ||||
| -	buf = mvneta_frag_alloc(bm_pool->frag_size); | ||||
| -	if (!buf) | ||||
| -		return NULL; | ||||
| - | ||||
|  	/* In order to update buf_cookie field of RX descriptor properly, | ||||
|  	 * BM hardware expects buf virtual address to be placed in the | ||||
|  	 * first four bytes of mapped buffer. | ||||
| @@ -106,75 +103,13 @@ void *mvneta_buf_alloc(struct mvneta_bm | ||||
|  	*(u32 *)buf = (u32)buf; | ||||
|  	phys_addr = dma_map_single(&priv->pdev->dev, buf, bm_pool->buf_size, | ||||
|  				   DMA_FROM_DEVICE); | ||||
| -	if (unlikely(dma_mapping_error(&priv->pdev->dev, phys_addr))) { | ||||
| -		mvneta_frag_free(bm_pool->frag_size, buf); | ||||
| -		return NULL; | ||||
| -	} | ||||
| -	*buf_phys_addr = phys_addr; | ||||
| - | ||||
| -	return buf; | ||||
| -} | ||||
| - | ||||
| -/* Refill processing for HW buffer management */ | ||||
| -int mvneta_bm_pool_refill(struct mvneta_bm *priv, | ||||
| -			  struct mvneta_bm_pool *bm_pool) | ||||
| -{ | ||||
| -	dma_addr_t buf_phys_addr; | ||||
| -	void *buf; | ||||
| - | ||||
| -	buf = mvneta_buf_alloc(priv, bm_pool, &buf_phys_addr); | ||||
| -	if (!buf) | ||||
| +	if (unlikely(dma_mapping_error(&priv->pdev->dev, phys_addr))) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| -	mvneta_bm_pool_put_bp(priv, bm_pool, buf_phys_addr); | ||||
| - | ||||
| +	mvneta_bm_pool_put_bp(priv, bm_pool, phys_addr); | ||||
|  	return 0; | ||||
|  } | ||||
| -EXPORT_SYMBOL_GPL(mvneta_bm_pool_refill); | ||||
| - | ||||
| -/* Allocate buffers for the pool */ | ||||
| -int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
| -		       int buf_num) | ||||
| -{ | ||||
| -	int err, i; | ||||
| - | ||||
| -	if (bm_pool->buf_num == bm_pool->size) { | ||||
| -		dev_dbg(&priv->pdev->dev, "pool %d already filled\n", | ||||
| -			bm_pool->id); | ||||
| -		return bm_pool->buf_num; | ||||
| -	} | ||||
| - | ||||
| -	if (buf_num < 0 || | ||||
| -	    (buf_num + bm_pool->buf_num > bm_pool->size)) { | ||||
| -		dev_err(&priv->pdev->dev, | ||||
| -			"cannot allocate %d buffers for pool %d\n", | ||||
| -			buf_num, bm_pool->id); | ||||
| -		return 0; | ||||
| -	} | ||||
| - | ||||
| -	for (i = 0; i < buf_num; i++) { | ||||
| -		err = mvneta_bm_pool_refill(priv, bm_pool); | ||||
| -		if (err < 0) | ||||
| -			break; | ||||
| -	} | ||||
| - | ||||
| -	/* Update BM driver with number of buffers added to pool */ | ||||
| -	bm_pool->buf_num += i; | ||||
| - | ||||
| -	dev_dbg(&priv->pdev->dev, | ||||
| -		"%s pool %d: pkt_size=%4d, buf_size=%4d, frag_size=%4d\n", | ||||
| -		bm_pool->type == MVNETA_BM_SHORT ? "short" : "long", | ||||
| -		bm_pool->id, bm_pool->pkt_size, bm_pool->buf_size, | ||||
| -		bm_pool->frag_size); | ||||
| - | ||||
| -	dev_dbg(&priv->pdev->dev, | ||||
| -		"%s pool %d: %d of %d buffers added\n", | ||||
| -		bm_pool->type == MVNETA_BM_SHORT ? "short" : "long", | ||||
| -		bm_pool->id, i, buf_num); | ||||
| - | ||||
| -	return i; | ||||
| -} | ||||
| -EXPORT_SYMBOL_GPL(mvneta_bm_bufs_add); | ||||
| +EXPORT_SYMBOL_GPL(mvneta_bm_construct); | ||||
|   | ||||
|  /* Create pool */ | ||||
|  static int mvneta_bm_pool_create(struct mvneta_bm *priv, | ||||
| @@ -183,8 +118,7 @@ static int mvneta_bm_pool_create(struct | ||||
|  	struct platform_device *pdev = priv->pdev; | ||||
|  	u8 target_id, attr; | ||||
|  	int size_bytes, err; | ||||
| - | ||||
| -	size_bytes = sizeof(u32) * bm_pool->size; | ||||
| +	size_bytes = sizeof(u32) * bm_pool->hwbm_pool.size; | ||||
|  	bm_pool->virt_addr = dma_alloc_coherent(&pdev->dev, size_bytes, | ||||
|  						&bm_pool->phys_addr, | ||||
|  						GFP_KERNEL); | ||||
| @@ -245,11 +179,16 @@ struct mvneta_bm_pool *mvneta_bm_pool_us | ||||
|   | ||||
|  	/* Allocate buffers in case BM pool hasn't been used yet */ | ||||
|  	if (new_pool->type == MVNETA_BM_FREE) { | ||||
| +		struct hwbm_pool *hwbm_pool = &new_pool->hwbm_pool; | ||||
| + | ||||
| +		new_pool->priv = priv; | ||||
|  		new_pool->type = type; | ||||
|  		new_pool->buf_size = MVNETA_RX_BUF_SIZE(new_pool->pkt_size); | ||||
| -		new_pool->frag_size = | ||||
| +		hwbm_pool->frag_size = | ||||
|  			SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(new_pool->pkt_size)) + | ||||
|  			SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); | ||||
| +		hwbm_pool->construct = mvneta_bm_construct; | ||||
| +		hwbm_pool->priv = new_pool; | ||||
|   | ||||
|  		/* Create new pool */ | ||||
|  		err = mvneta_bm_pool_create(priv, new_pool); | ||||
| @@ -260,10 +199,10 @@ struct mvneta_bm_pool *mvneta_bm_pool_us | ||||
|  		} | ||||
|   | ||||
|  		/* Allocate buffers for this pool */ | ||||
| -		num = mvneta_bm_bufs_add(priv, new_pool, new_pool->size); | ||||
| -		if (num != new_pool->size) { | ||||
| +		num = hwbm_pool_add(hwbm_pool, hwbm_pool->size, GFP_ATOMIC); | ||||
| +		if (num != hwbm_pool->size) { | ||||
|  			WARN(1, "pool %d: %d of %d allocated\n", | ||||
| -			     new_pool->id, num, new_pool->size); | ||||
| +			     new_pool->id, num, hwbm_pool->size); | ||||
|  			return NULL; | ||||
|  		} | ||||
|  	} | ||||
| @@ -284,7 +223,7 @@ void mvneta_bm_bufs_free(struct mvneta_b | ||||
|   | ||||
|  	mvneta_bm_config_set(priv, MVNETA_BM_EMPTY_LIMIT_MASK); | ||||
|   | ||||
| -	for (i = 0; i < bm_pool->buf_num; i++) { | ||||
| +	for (i = 0; i < bm_pool->hwbm_pool.buf_num; i++) { | ||||
|  		dma_addr_t buf_phys_addr; | ||||
|  		u32 *vaddr; | ||||
|   | ||||
| @@ -303,13 +242,13 @@ void mvneta_bm_bufs_free(struct mvneta_b | ||||
|   | ||||
|  		dma_unmap_single(&priv->pdev->dev, buf_phys_addr, | ||||
|  				 bm_pool->buf_size, DMA_FROM_DEVICE); | ||||
| -		mvneta_frag_free(bm_pool->frag_size, vaddr); | ||||
| +		hwbm_buf_free(&bm_pool->hwbm_pool, vaddr); | ||||
|  	} | ||||
|   | ||||
|  	mvneta_bm_config_clear(priv, MVNETA_BM_EMPTY_LIMIT_MASK); | ||||
|   | ||||
|  	/* Update BM driver with number of buffers removed from pool */ | ||||
| -	bm_pool->buf_num -= i; | ||||
| +	bm_pool->hwbm_pool.buf_num -= i; | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(mvneta_bm_bufs_free); | ||||
|   | ||||
| @@ -317,6 +256,7 @@ EXPORT_SYMBOL_GPL(mvneta_bm_bufs_free); | ||||
|  void mvneta_bm_pool_destroy(struct mvneta_bm *priv, | ||||
|  			    struct mvneta_bm_pool *bm_pool, u8 port_map) | ||||
|  { | ||||
| +	struct hwbm_pool *hwbm_pool = &bm_pool->hwbm_pool; | ||||
|  	bm_pool->port_map &= ~port_map; | ||||
|  	if (bm_pool->port_map) | ||||
|  		return; | ||||
| @@ -324,11 +264,12 @@ void mvneta_bm_pool_destroy(struct mvnet | ||||
|  	bm_pool->type = MVNETA_BM_FREE; | ||||
|   | ||||
|  	mvneta_bm_bufs_free(priv, bm_pool, port_map); | ||||
| -	if (bm_pool->buf_num) | ||||
| +	if (hwbm_pool->buf_num) | ||||
|  		WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id); | ||||
|   | ||||
|  	if (bm_pool->virt_addr) { | ||||
| -		dma_free_coherent(&priv->pdev->dev, sizeof(u32) * bm_pool->size, | ||||
| +		dma_free_coherent(&priv->pdev->dev, | ||||
| +				  sizeof(u32) * hwbm_pool->size, | ||||
|  				  bm_pool->virt_addr, bm_pool->phys_addr); | ||||
|  		bm_pool->virt_addr = NULL; | ||||
|  	} | ||||
| @@ -381,10 +322,10 @@ static void mvneta_bm_pools_init(struct | ||||
|  				 MVNETA_BM_POOL_CAP_ALIGN)); | ||||
|  			size = ALIGN(size, MVNETA_BM_POOL_CAP_ALIGN); | ||||
|  		} | ||||
| -		bm_pool->size = size; | ||||
| +		bm_pool->hwbm_pool.size = size; | ||||
|   | ||||
|  		mvneta_bm_write(priv, MVNETA_BM_POOL_SIZE_REG(i), | ||||
| -				bm_pool->size); | ||||
| +				bm_pool->hwbm_pool.size); | ||||
|   | ||||
|  		/* Obtain custom pkt_size from DT */ | ||||
|  		sprintf(prop, "pool%d,pkt-size", i); | ||||
| --- a/drivers/net/ethernet/marvell/mvneta_bm.h | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta_bm.h | ||||
| @@ -108,20 +108,15 @@ struct mvneta_bm { | ||||
|  }; | ||||
|   | ||||
|  struct mvneta_bm_pool { | ||||
| +	struct hwbm_pool hwbm_pool; | ||||
|  	/* Pool number in the range 0-3 */ | ||||
|  	u8 id; | ||||
|  	enum mvneta_bm_type type; | ||||
|   | ||||
| -	/* Buffer Pointers Pool External (BPPE) size in number of bytes */ | ||||
| -	int size; | ||||
| -	/* Number of buffers used by this pool */ | ||||
| -	int buf_num; | ||||
| -	/* Pool buffer size */ | ||||
| -	int buf_size; | ||||
|  	/* Packet size */ | ||||
|  	int pkt_size; | ||||
| -	/* Single frag size */ | ||||
| -	u32 frag_size; | ||||
| +	/* Size of the buffer acces through DMA*/ | ||||
| +	u32 buf_size; | ||||
|   | ||||
|  	/* BPPE virtual base address */ | ||||
|  	u32 *virt_addr; | ||||
| @@ -143,8 +138,7 @@ void mvneta_bm_pool_destroy(struct mvnet | ||||
|  			    struct mvneta_bm_pool *bm_pool, u8 port_map); | ||||
|  void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
|  			 u8 port_map); | ||||
| -int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
| -		       int buf_num); | ||||
| +int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf); | ||||
|  int mvneta_bm_pool_refill(struct mvneta_bm *priv, | ||||
|  			  struct mvneta_bm_pool *bm_pool); | ||||
|  struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id, | ||||
| @@ -170,8 +164,7 @@ void mvneta_bm_pool_destroy(struct mvnet | ||||
|  			    struct mvneta_bm_pool *bm_pool, u8 port_map) {} | ||||
|  void mvneta_bm_bufs_free(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
|  			 u8 port_map) {} | ||||
| -int mvneta_bm_bufs_add(struct mvneta_bm *priv, struct mvneta_bm_pool *bm_pool, | ||||
| -		       int buf_num) { return 0; } | ||||
| +int mvneta_bm_construct(struct hwbm_pool *hwbm_pool, void *buf) { return 0; } | ||||
|  int mvneta_bm_pool_refill(struct mvneta_bm *priv, | ||||
|  			  struct mvneta_bm_pool *bm_pool) {return 0; } | ||||
|  struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id, | ||||
| @@ -1,52 +0,0 @@ | ||||
| From: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Date: Sat, 12 Mar 2016 18:44:17 +0100 | ||||
| Subject: [PATCH] net: mvneta: Fix spinlock usage | ||||
|  | ||||
| In the previous patch, the spinlock was not initialized. While it didn't | ||||
| cause any trouble yet it could be a problem to use it uninitialized. | ||||
|  | ||||
| The most annoying part was the critical section protected by the spinlock | ||||
| in mvneta_stop(). Some of the functions could sleep as pointed when | ||||
| activated CONFIG_DEBUG_ATOMIC_SLEEP. Actually, in mvneta_stop() we only | ||||
| need to protect the is_stopped flagged, indeed the code of the notifier | ||||
| for CPU online is protected by the same spinlock, so when we get the | ||||
| lock, the notifer work is done. | ||||
|  | ||||
| Reported-by: Patrick Uiterwijk <patrick@puiterwijk.org> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3484,17 +3484,17 @@ static int mvneta_stop(struct net_device | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
|   | ||||
|  	/* Inform that we are stopping so we don't want to setup the | ||||
| -	 * driver for new CPUs in the notifiers | ||||
| +	 * driver for new CPUs in the notifiers. The code of the | ||||
| +	 * notifier for CPU online is protected by the same spinlock, | ||||
| +	 * so when we get the lock, the notifer work is done. | ||||
|  	 */ | ||||
|  	spin_lock(&pp->lock); | ||||
|  	pp->is_stopped = true; | ||||
| +	spin_unlock(&pp->lock); | ||||
| + | ||||
|  	mvneta_stop_dev(pp); | ||||
|  	mvneta_mdio_remove(pp); | ||||
|  	unregister_cpu_notifier(&pp->cpu_notifier); | ||||
| -	/* Now that the notifier are unregistered, we can release le | ||||
| -	 * lock | ||||
| -	 */ | ||||
| -	spin_unlock(&pp->lock); | ||||
|  	on_each_cpu(mvneta_percpu_disable, pp, true); | ||||
|  	free_percpu_irq(dev->irq, pp->ports); | ||||
|  	mvneta_cleanup_rxqs(pp); | ||||
| @@ -4027,6 +4027,7 @@ static int mvneta_probe(struct platform_ | ||||
|  	dev->ethtool_ops = &mvneta_eth_tool_ops; | ||||
|   | ||||
|  	pp = netdev_priv(dev); | ||||
| +	spin_lock_init(&pp->lock); | ||||
|  	pp->phy_node = phy_node; | ||||
|  	pp->phy_interface = phy_mode; | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| From: Dmitri Epshtein <dima@marvell.com> | ||||
| Date: Sat, 12 Mar 2016 18:44:19 +0100 | ||||
| Subject: [PATCH] net: mvneta: fix error messages in mvneta_port_down function | ||||
|  | ||||
| This commit corrects error printing when shutting down the port. | ||||
|  | ||||
| [gregory.clement@free-electrons.com: split initial commit in two | ||||
| individual changes] | ||||
| Signed-off-by: Dmitri Epshtein <dima@marvell.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -1105,7 +1105,7 @@ static void mvneta_port_down(struct mvne | ||||
|  	do { | ||||
|  		if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) { | ||||
|  			netdev_warn(pp->dev, | ||||
| -				    "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n", | ||||
| +				    "TIMEOUT for RX stopped ! rx_queue_cmd: 0x%08x\n", | ||||
|  				    val); | ||||
|  			break; | ||||
|  		} | ||||
| @@ -1144,7 +1144,7 @@ static void mvneta_port_down(struct mvne | ||||
|  	do { | ||||
|  		if (count++ >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) { | ||||
|  			netdev_warn(pp->dev, | ||||
| -				    "TX FIFO empty timeout status=0x08%x\n", | ||||
| +				    "TX FIFO empty timeout status=0x%08x\n", | ||||
|  				    val); | ||||
|  			break; | ||||
|  		} | ||||
| @@ -1,56 +0,0 @@ | ||||
| From: Jisheng Zhang <jszhang@marvell.com> | ||||
| Date: Wed, 30 Mar 2016 19:55:21 +0800 | ||||
| Subject: [PATCH] net: mvneta: replace MVNETA_CPU_D_CACHE_LINE_SIZE with | ||||
|  L1_CACHE_BYTES | ||||
|  | ||||
| The mvneta is also used in some Marvell berlin family SoCs which may | ||||
| have 64bytes cacheline size. Replace the MVNETA_CPU_D_CACHE_LINE_SIZE | ||||
| usage with L1_CACHE_BYTES. | ||||
|  | ||||
| And since dma_alloc_coherent() is always cacheline size aligned, so | ||||
| remove the align checks. | ||||
|  | ||||
| Signed-off-by: Jisheng Zhang <jszhang@marvell.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -260,7 +260,6 @@ | ||||
|   | ||||
|  #define MVNETA_VLAN_TAG_LEN             4 | ||||
|   | ||||
| -#define MVNETA_CPU_D_CACHE_LINE_SIZE    32 | ||||
|  #define MVNETA_TX_CSUM_DEF_SIZE		1600 | ||||
|  #define MVNETA_TX_CSUM_MAX_SIZE		9800 | ||||
|  #define MVNETA_ACC_MODE_EXT1		1 | ||||
| @@ -300,7 +299,7 @@ | ||||
|  #define MVNETA_RX_PKT_SIZE(mtu) \ | ||||
|  	ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \ | ||||
|  	      ETH_HLEN + ETH_FCS_LEN,			     \ | ||||
| -	      MVNETA_CPU_D_CACHE_LINE_SIZE) | ||||
| +	      L1_CACHE_BYTES) | ||||
|   | ||||
|  #define IS_TSO_HEADER(txq, addr) \ | ||||
|  	((addr >= txq->tso_hdrs_phys) && \ | ||||
| @@ -2762,9 +2761,6 @@ static int mvneta_rxq_init(struct mvneta | ||||
|  	if (rxq->descs == NULL) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| -	BUG_ON(rxq->descs != | ||||
| -	       PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); | ||||
| - | ||||
|  	rxq->last_desc = rxq->size - 1; | ||||
|   | ||||
|  	/* Set Rx descriptors queue starting address */ | ||||
| @@ -2835,10 +2831,6 @@ static int mvneta_txq_init(struct mvneta | ||||
|  	if (txq->descs == NULL) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| -	/* Make sure descriptor address is cache line size aligned  */ | ||||
| -	BUG_ON(txq->descs != | ||||
| -	       PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); | ||||
| - | ||||
|  	txq->last_desc = txq->size - 1; | ||||
|   | ||||
|  	/* Set maximum bandwidth for enabled TXQs */ | ||||
| @@ -1,75 +0,0 @@ | ||||
| From: Marcin Wojtas <mw@semihalf.com> | ||||
| Date: Fri, 1 Apr 2016 15:21:18 +0200 | ||||
| Subject: [PATCH] net: mvneta: fix changing MTU when using per-cpu processing | ||||
|  | ||||
| After enabling per-cpu processing it appeared that under heavy load | ||||
| changing MTU can result in blocking all port's interrupts and | ||||
| transmitting data is not possible after the change. | ||||
|  | ||||
| This commit fixes above issue by disabling percpu interrupts for the | ||||
| time, when TXQs and RXQs are reconfigured. | ||||
|  | ||||
| Signed-off-by: Marcin Wojtas <mw@semihalf.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3040,6 +3040,20 @@ static int mvneta_check_mtu_valid(struct | ||||
|  	return mtu; | ||||
|  } | ||||
|   | ||||
| +static void mvneta_percpu_enable(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); | ||||
| +} | ||||
| + | ||||
| +static void mvneta_percpu_disable(void *arg) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = arg; | ||||
| + | ||||
| +	disable_percpu_irq(pp->dev->irq); | ||||
| +} | ||||
| + | ||||
|  /* Change the device mtu */ | ||||
|  static int mvneta_change_mtu(struct net_device *dev, int mtu) | ||||
|  { | ||||
| @@ -3064,6 +3078,7 @@ static int mvneta_change_mtu(struct net_ | ||||
|  	 * reallocation of the queues | ||||
|  	 */ | ||||
|  	mvneta_stop_dev(pp); | ||||
| +	on_each_cpu(mvneta_percpu_disable, pp, true); | ||||
|   | ||||
|  	mvneta_cleanup_txqs(pp); | ||||
|  	mvneta_cleanup_rxqs(pp); | ||||
| @@ -3087,6 +3102,7 @@ static int mvneta_change_mtu(struct net_ | ||||
|  		return ret; | ||||
|  	} | ||||
|   | ||||
| +	on_each_cpu(mvneta_percpu_enable, pp, true); | ||||
|  	mvneta_start_dev(pp); | ||||
|  	mvneta_port_up(pp); | ||||
|   | ||||
| @@ -3240,20 +3256,6 @@ static void mvneta_mdio_remove(struct mv | ||||
|  	pp->phy_dev = NULL; | ||||
|  } | ||||
|   | ||||
| -static void mvneta_percpu_enable(void *arg) | ||||
| -{ | ||||
| -	struct mvneta_port *pp = arg; | ||||
| - | ||||
| -	enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); | ||||
| -} | ||||
| - | ||||
| -static void mvneta_percpu_disable(void *arg) | ||||
| -{ | ||||
| -	struct mvneta_port *pp = arg; | ||||
| - | ||||
| -	disable_percpu_irq(pp->dev->irq); | ||||
| -} | ||||
| - | ||||
|  /* Electing a CPU must be done in an atomic way: it should be done | ||||
|   * after or before the removal/insertion of a CPU and this function is | ||||
|   * not reentrant. | ||||
| @@ -1,53 +0,0 @@ | ||||
| From: Marcin Wojtas <mw@semihalf.com> | ||||
| Date: Mon, 14 Mar 2016 09:38:57 +0100 | ||||
| Subject: [PATCH] ARM: dts: armada-38x: add buffer manager nodes | ||||
|  | ||||
| Armada 38x network controller supports hardware buffer management (BM). | ||||
| Since it is now enabled in mvneta driver, appropriate nodes can be added | ||||
| to armada-38x.dtsi - for the actual common BM unit (bm@c8000) and its | ||||
| internal SRAM (bm-bppi), which is used for indirect access to buffer | ||||
| pointer ring residing in DRAM. | ||||
|  | ||||
| Pools - ports mapping, bm-bppi entry in 'soc' node's ranges and optional | ||||
| parameters are supposed to be set in board files. | ||||
|  | ||||
| Signed-off-by: Marcin Wojtas <mw@semihalf.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-38x.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-38x.dtsi | ||||
| @@ -540,6 +540,14 @@ | ||||
|  				status = "disabled"; | ||||
|  			}; | ||||
|   | ||||
| +			bm: bm@c8000 { | ||||
| +				compatible = "marvell,armada-380-neta-bm"; | ||||
| +				reg = <0xc8000 0xac>; | ||||
| +				clocks = <&gateclk 13>; | ||||
| +				internal-mem = <&bm_bppi>; | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| + | ||||
|  			sata@e0000 { | ||||
|  				compatible = "marvell,armada-380-ahci"; | ||||
|  				reg = <0xe0000 0x2000>; | ||||
| @@ -618,6 +626,17 @@ | ||||
|  			#size-cells = <1>; | ||||
|  			ranges = <0 MBUS_ID(0x09, 0x15) 0 0x800>; | ||||
|  		}; | ||||
| + | ||||
| +		bm_bppi: bm-bppi { | ||||
| +			compatible = "mmio-sram"; | ||||
| +			reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; | ||||
| +			ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; | ||||
| +			#address-cells = <1>; | ||||
| +			#size-cells = <1>; | ||||
| +			clocks = <&gateclk 13>; | ||||
| +			no-memory-wc; | ||||
| +			status = "disabled"; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	clocks { | ||||
| @@ -1,53 +0,0 @@ | ||||
| From: Marcin Wojtas <mw@semihalf.com> | ||||
| Date: Mon, 14 Mar 2016 09:38:59 +0100 | ||||
| Subject: [PATCH] ARM: dts: armada-xp: add buffer manager nodes | ||||
|  | ||||
| Armada XP network controller supports hardware buffer management (BM). | ||||
| Since it is now enabled in mvneta driver, appropriate nodes can be added | ||||
| to armada-xp.dtsi - for the actual common BM unit (bm@c0000) and its | ||||
| internal SRAM (bm-bppi), which is used for indirect access to buffer | ||||
| pointer ring residing in DRAM. | ||||
|  | ||||
| Pools - ports mapping, bm-bppi entry in 'soc' node's ranges and optional | ||||
| parameters are supposed to be set in board files. | ||||
|  | ||||
| Signed-off-by: Marcin Wojtas <mw@semihalf.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-xp.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-xp.dtsi | ||||
| @@ -253,6 +253,14 @@ | ||||
|  				marvell,crypto-sram-size = <0x800>; | ||||
|  			}; | ||||
|   | ||||
| +			bm: bm@c0000 { | ||||
| +				compatible = "marvell,armada-380-neta-bm"; | ||||
| +				reg = <0xc0000 0xac>; | ||||
| +				clocks = <&gateclk 13>; | ||||
| +				internal-mem = <&bm_bppi>; | ||||
| +				status = "disabled"; | ||||
| +			}; | ||||
| + | ||||
|  			xor@f0900 { | ||||
|  				compatible = "marvell,orion-xor"; | ||||
|  				reg = <0xF0900 0x100 | ||||
| @@ -291,6 +299,17 @@ | ||||
|  			#size-cells = <1>; | ||||
|  			ranges = <0 MBUS_ID(0x09, 0x05) 0 0x800>; | ||||
|  		}; | ||||
| + | ||||
| +		bm_bppi: bm-bppi { | ||||
| +			compatible = "mmio-sram"; | ||||
| +			reg = <MBUS_ID(0x0c, 0x04) 0 0x100000>; | ||||
| +			ranges = <0 MBUS_ID(0x0c, 0x04) 0 0x100000>; | ||||
| +			#address-cells = <1>; | ||||
| +			#size-cells = <1>; | ||||
| +			clocks = <&gateclk 13>; | ||||
| +			no-memory-wc; | ||||
| +			status = "disabled"; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	clocks { | ||||
| @@ -1,611 +0,0 @@ | ||||
| From 4c945e8556ec7ea5b19d4f8721b212f468656e0d Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 6 Dec 2015 21:52:06 +0000 | ||||
| Subject: [PATCH] ARM: dts: Add SolidRun Armada 388 Clearfog A1 DT file | ||||
|  | ||||
| Add support for the SolidRun Armada 388 Clearfog A1 board.  This board | ||||
| has an Armada 388 microsom, dedicated gigabit ethernet, six switched | ||||
| gigabit ethernet ports, SFP cage, two Mini-PCIe/mSATA slots, a m.2 SATA | ||||
| slot, and a MikroBUS connector to allow MikroBUS modules to be added. | ||||
|  | ||||
| This DT file adds support for all board facilities with the exception | ||||
| of full SFP support. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| --- | ||||
|  arch/arm/boot/dts/Makefile                         |   1 + | ||||
|  arch/arm/boot/dts/armada-388-clearfog.dts          | 456 +++++++++++++++++++++ | ||||
|  .../arm/boot/dts/armada-38x-solidrun-microsom.dtsi | 115 ++++++ | ||||
|  3 files changed, 572 insertions(+) | ||||
|  create mode 100644 arch/arm/boot/dts/armada-388-clearfog.dts | ||||
|  create mode 100644 arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | ||||
|  | ||||
| --- a/arch/arm/boot/dts/Makefile | ||||
| +++ b/arch/arm/boot/dts/Makefile | ||||
| @@ -750,6 +750,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \ | ||||
|  	armada-385-linksys-cobra.dtb \ | ||||
|  	armada-385-linksys-rango.dtb \ | ||||
|  	armada-385-linksys-shelby.dtb \ | ||||
| +	armada-388-clearfog.dtb \ | ||||
|  	armada-388-db.dtb \ | ||||
|  	armada-388-gp.dtb \ | ||||
|  	armada-388-rd.dtb | ||||
| --- /dev/null | ||||
| +++ b/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| @@ -0,0 +1,456 @@ | ||||
| +/* | ||||
| + * Device Tree file for SolidRun Clearfog revision A1 rev 2.0 (88F6828) | ||||
| + * | ||||
| + *  Copyright (C) 2015 Russell King | ||||
| + * | ||||
| + * This board is in development; the contents of this file work with | ||||
| + * the A1 rev 2.0 of the board, which does not represent final | ||||
| + * production board.  Things will change, don't expect this file to | ||||
| + * remain compatible info the future. | ||||
| + * | ||||
| + * 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 | ||||
| + *     version 2 as published by the Free Software Foundation. | ||||
| + * | ||||
| + *     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 , 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 "armada-388.dtsi" | ||||
| +#include "armada-38x-solidrun-microsom.dtsi" | ||||
| + | ||||
| +/ { | ||||
| +	model = "SolidRun Clearfog A1"; | ||||
| +	compatible = "solidrun,clearfog-a1", "marvell,armada388", | ||||
| +		"marvell,armada385", "marvell,armada380"; | ||||
| + | ||||
| +	aliases { | ||||
| +		/* So that mvebu u-boot can update the MAC addresses */ | ||||
| +		ethernet1 = ð0; | ||||
| +		ethernet2 = ð1; | ||||
| +		ethernet3 = ð2; | ||||
| +	}; | ||||
| + | ||||
| +	chosen { | ||||
| +		stdout-path = "serial0:115200n8"; | ||||
| +	}; | ||||
| + | ||||
| +	reg_3p3v: regulator-3p3v { | ||||
| +		compatible = "regulator-fixed"; | ||||
| +		regulator-name = "3P3V"; | ||||
| +		regulator-min-microvolt = <3300000>; | ||||
| +		regulator-max-microvolt = <3300000>; | ||||
| +		regulator-always-on; | ||||
| +	}; | ||||
| + | ||||
| +	soc { | ||||
| +		internal-regs { | ||||
| +			ethernet@30000 { | ||||
| +				phy-mode = "sgmii"; | ||||
| +				status = "okay"; | ||||
| + | ||||
| +				fixed-link { | ||||
| +					speed = <1000>; | ||||
| +					full-duplex; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			ethernet@34000 { | ||||
| +				phy-mode = "sgmii"; | ||||
| +				status = "okay"; | ||||
| + | ||||
| +				fixed-link { | ||||
| +					speed = <1000>; | ||||
| +					full-duplex; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			i2c@11000 { | ||||
| +				/* Is there anything on this? */ | ||||
| +				clock-frequency = <100000>; | ||||
| +				pinctrl-0 = <&i2c0_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| + | ||||
| +				/* | ||||
| +				 * PCA9655 GPIO expander, up to 1MHz clock. | ||||
| +				 *  0-CON3 CLKREQ# | ||||
| +				 *  1-CON3 PERST# | ||||
| +				 *  2-CON2 PERST# | ||||
| +				 *  3-CON3 W_DISABLE | ||||
| +				 *  4-CON2 CLKREQ# | ||||
| +				 *  5-USB3 overcurrent | ||||
| +				 *  6-USB3 power | ||||
| +				 *  7-CON2 W_DISABLE | ||||
| +				 *  8-JP4 P1 | ||||
| +				 *  9-JP4 P4 | ||||
| +				 * 10-JP4 P5 | ||||
| +				 * 11-m.2 DEVSLP | ||||
| +				 * 12-SFP_LOS | ||||
| +				 * 13-SFP_TX_FAULT | ||||
| +				 * 14-SFP_TX_DISABLE | ||||
| +				 * 15-SFP_MOD_DEF0 | ||||
| +				 */ | ||||
| +				expander0: gpio-expander@20 { | ||||
| +					/* | ||||
| +					 * This is how it should be: | ||||
| +					 * compatible = "onnn,pca9655", | ||||
| +					 *	 "nxp,pca9555"; | ||||
| +					 * but you can't do this because of | ||||
| +					 * the way I2C works. | ||||
| +					 */ | ||||
| +					compatible = "nxp,pca9555"; | ||||
| +					gpio-controller; | ||||
| +					#gpio-cells = <2>; | ||||
| +					reg = <0x20>; | ||||
| + | ||||
| +					pcie1_0_clkreq { | ||||
| +						gpio-hog; | ||||
| +						gpios = <0 GPIO_ACTIVE_LOW>; | ||||
| +						input; | ||||
| +						line-name = "pcie1.0-clkreq"; | ||||
| +					}; | ||||
| +					pcie1_0_w_disable { | ||||
| +						gpio-hog; | ||||
| +						gpios = <3 GPIO_ACTIVE_LOW>; | ||||
| +						output-low; | ||||
| +						line-name = "pcie1.0-w-disable"; | ||||
| +					}; | ||||
| +					pcie2_0_clkreq { | ||||
| +						gpio-hog; | ||||
| +						gpios = <4 GPIO_ACTIVE_LOW>; | ||||
| +						input; | ||||
| +						line-name = "pcie2.0-clkreq"; | ||||
| +					}; | ||||
| +					pcie2_0_w_disable { | ||||
| +						gpio-hog; | ||||
| +						gpios = <7 GPIO_ACTIVE_LOW>; | ||||
| +						output-low; | ||||
| +						line-name = "pcie2.0-w-disable"; | ||||
| +					}; | ||||
| +					usb3_ilimit { | ||||
| +						gpio-hog; | ||||
| +						gpios = <5 GPIO_ACTIVE_LOW>; | ||||
| +						input; | ||||
| +						line-name = "usb3-current-limit"; | ||||
| +					}; | ||||
| +					usb3_power { | ||||
| +						gpio-hog; | ||||
| +						gpios = <6 GPIO_ACTIVE_HIGH>; | ||||
| +						output-high; | ||||
| +						line-name = "usb3-power"; | ||||
| +					}; | ||||
| +					m2_devslp { | ||||
| +						gpio-hog; | ||||
| +						gpios = <11 GPIO_ACTIVE_HIGH>; | ||||
| +						output-low; | ||||
| +						line-name = "m.2 devslp"; | ||||
| +					}; | ||||
| +					sfp_los { | ||||
| +						/* SFP loss of signal */ | ||||
| +						gpio-hog; | ||||
| +						gpios = <12 GPIO_ACTIVE_HIGH>; | ||||
| +						input; | ||||
| +						line-name = "sfp-los"; | ||||
| +					}; | ||||
| +					sfp_tx_fault { | ||||
| +						/* SFP laser fault */ | ||||
| +						gpio-hog; | ||||
| +						gpios = <13 GPIO_ACTIVE_HIGH>; | ||||
| +						input; | ||||
| +						line-name = "sfp-tx-fault"; | ||||
| +					}; | ||||
| +					sfp_tx_disable { | ||||
| +						/* SFP transmit disable */ | ||||
| +						gpio-hog; | ||||
| +						gpios = <14 GPIO_ACTIVE_HIGH>; | ||||
| +						output-low; | ||||
| +						line-name = "sfp-tx-disable"; | ||||
| +					}; | ||||
| +					sfp_mod_def0 { | ||||
| +						/* SFP module present */ | ||||
| +						gpio-hog; | ||||
| +						gpios = <15 GPIO_ACTIVE_LOW>; | ||||
| +						input; | ||||
| +						line-name = "sfp-mod-def0"; | ||||
| +					}; | ||||
| +				}; | ||||
| + | ||||
| +				/* The MCP3021 is 100kHz clock only */ | ||||
| +				mikrobus_adc: mcp3021@4c { | ||||
| +					compatible = "microchip,mcp3021"; | ||||
| +					reg = <0x4c>; | ||||
| +				}; | ||||
| + | ||||
| +				/* Also something at 0x64 */ | ||||
| +			}; | ||||
| + | ||||
| +			i2c@11100 { | ||||
| +				/* | ||||
| +				 * Routed to SFP, mikrobus, and PCIe. | ||||
| +				 * SFP limits this to 100kHz, and requires | ||||
| +				 *  an AT24C01A/02/04 with address pins tied | ||||
| +				 *  low, which takes addresses 0x50 and 0x51. | ||||
| +				 * Mikrobus doesn't specify beyond an I2C | ||||
| +				 *  bus being present. | ||||
| +				 * PCIe uses ARP to assign addresses, or | ||||
| +				 *  0x63-0x64. | ||||
| +				 */ | ||||
| +				clock-frequency = <100000>; | ||||
| +				pinctrl-0 = <&clearfog_i2c1_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			mdio@72004 { | ||||
| +				pinctrl-0 = <&mdio_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| + | ||||
| +				phy_dedicated: ethernet-phy@0 { | ||||
| +					/* | ||||
| +					 * Annoyingly, the marvell phy driver | ||||
| +					 * configures the LED register, rather | ||||
| +					 * than preserving reset-loaded setting. | ||||
| +					 * We undo that rubbish here. | ||||
| +					 */ | ||||
| +					marvell,reg-init = <3 16 0 0x101e>; | ||||
| +					reg = <0>; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			pinctrl@18000 { | ||||
| +				clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins { | ||||
| +					marvell,pins = "mpp46"; | ||||
| +					marvell,function = "ref"; | ||||
| +				}; | ||||
| +				clearfog_dsa0_pins: clearfog-dsa0-pins { | ||||
| +					marvell,pins = "mpp23", "mpp41"; | ||||
| +					marvell,function = "gpio"; | ||||
| +				}; | ||||
| +				clearfog_i2c1_pins: i2c1-pins { | ||||
| +					/* SFP, PCIe, mSATA, mikrobus */ | ||||
| +					marvell,pins = "mpp26", "mpp27"; | ||||
| +					marvell,function = "i2c1"; | ||||
| +				}; | ||||
| +				clearfog_sdhci_cd_pins: clearfog-sdhci-cd-pins { | ||||
| +					marvell,pins = "mpp20"; | ||||
| +					marvell,function = "gpio"; | ||||
| +				}; | ||||
| +				clearfog_sdhci_pins: clearfog-sdhci-pins { | ||||
| +					marvell,pins = "mpp21", "mpp28", | ||||
| +						       "mpp37", "mpp38", | ||||
| +						       "mpp39", "mpp40"; | ||||
| +					marvell,function = "sd0"; | ||||
| +				}; | ||||
| +				clearfog_spi1_cs_pins: spi1-cs-pins { | ||||
| +					marvell,pins = "mpp55"; | ||||
| +					marvell,function = "spi1"; | ||||
| +				}; | ||||
| +				mikro_pins: mikro-pins { | ||||
| +					/* int: mpp22 rst: mpp29 */ | ||||
| +					marvell,pins = "mpp22", "mpp29"; | ||||
| +					marvell,function = "gpio"; | ||||
| +				}; | ||||
| +				mikro_spi_pins: mikro-spi-pins { | ||||
| +					marvell,pins = "mpp43"; | ||||
| +					marvell,function = "spi1"; | ||||
| +				}; | ||||
| +				mikro_uart_pins: mikro-uart-pins { | ||||
| +					marvell,pins = "mpp24", "mpp25"; | ||||
| +					marvell,function = "ua1"; | ||||
| +				}; | ||||
| +				rear_button_pins: rear-button-pins { | ||||
| +					marvell,pins = "mpp34"; | ||||
| +					marvell,function = "gpio"; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			sata@a8000 { | ||||
| +				/* pinctrl? */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			sata@e0000 { | ||||
| +				/* pinctrl? */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			sdhci@d8000 { | ||||
| +				bus-width = <4>; | ||||
| +				cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; | ||||
| +				no-1-8-v; | ||||
| +				pinctrl-0 = <&clearfog_sdhci_pins | ||||
| +					     &clearfog_sdhci_cd_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| +				vmmc = <®_3p3v>; | ||||
| +				wp-inverted; | ||||
| +			}; | ||||
| + | ||||
| +			serial@12100 { | ||||
| +				/* mikrobus uart */ | ||||
| +				pinctrl-0 = <&mikro_uart_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			spi@10680 { | ||||
| +				/* | ||||
| +				 * We don't seem to have the W25Q32 on the | ||||
| +				 * A1 Rev 2.0 boards, so disable SPI. | ||||
| +				 * CS0: W25Q32 (doesn't appear to be present) | ||||
| +				 * CS1: | ||||
| +				 * CS2: mikrobus | ||||
| +				 */ | ||||
| +				pinctrl-0 = <&spi1_pins | ||||
| +					     &clearfog_spi1_cs_pins | ||||
| +					     &mikro_spi_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| + | ||||
| +				spi-flash@0 { | ||||
| +					#address-cells = <1>; | ||||
| +					#size-cells = <0>; | ||||
| +					compatible = "w25q32", "jedec,spi-nor"; | ||||
| +					reg = <0>; /* Chip select 0 */ | ||||
| +					spi-max-frequency = <3000000>; | ||||
| +					status = "disabled"; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			usb@58000 { | ||||
| +				/* CON3, nearest  power. */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			usb3@f0000 { | ||||
| +				/* CON2, nearest CPU, USB2 only. */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			usb3@f8000 { | ||||
| +				/* CON7 */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| +		}; | ||||
| + | ||||
| +		pcie-controller { | ||||
| +			status = "okay"; | ||||
| +			/* | ||||
| +			 * The two PCIe units are accessible through | ||||
| +			 * the mini-PCIe connectors on the board. | ||||
| +			 */ | ||||
| +			pcie@2,0 { | ||||
| +				/* Port 1, Lane 0. CON3, nearest power. */ | ||||
| +				reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| +			pcie@3,0 { | ||||
| +				/* Port 2, Lane 0. CON2, nearest CPU. */ | ||||
| +				reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| +		}; | ||||
| +	}; | ||||
| + | ||||
| +	dsa@0 { | ||||
| +		compatible = "marvell,dsa"; | ||||
| +		dsa,ethernet = <ð1>; | ||||
| +		dsa,mii-bus = <&mdio>; | ||||
| +		pinctrl-0 = <&clearfog_dsa0_clk_pins &clearfog_dsa0_pins>; | ||||
| +		pinctrl-names = "default"; | ||||
| +		#address-cells = <2>; | ||||
| +		#size-cells = <0>; | ||||
| + | ||||
| +		switch@0 { | ||||
| +			#address-cells = <1>; | ||||
| +			#size-cells = <0>; | ||||
| +			reg = <4 0>; | ||||
| + | ||||
| +			port@0 { | ||||
| +				reg = <0>; | ||||
| +				label = "lan1"; | ||||
| +			}; | ||||
| + | ||||
| +			port@1 { | ||||
| +				reg = <1>; | ||||
| +				label = "lan2"; | ||||
| +			}; | ||||
| + | ||||
| +			port@2 { | ||||
| +				reg = <2>; | ||||
| +				label = "lan3"; | ||||
| +			}; | ||||
| + | ||||
| +			port@3 { | ||||
| +				reg = <3>; | ||||
| +				label = "lan4"; | ||||
| +			}; | ||||
| + | ||||
| +			port@4 { | ||||
| +				reg = <4>; | ||||
| +				label = "lan5"; | ||||
| +			}; | ||||
| + | ||||
| +			port@5 { | ||||
| +				reg = <5>; | ||||
| +				label = "cpu"; | ||||
| +			}; | ||||
| + | ||||
| +			port@6 { | ||||
| +				/* 88E1512 external phy */ | ||||
| +				reg = <6>; | ||||
| +				label = "lan6"; | ||||
| +				fixed-link { | ||||
| +					speed = <1000>; | ||||
| +					full-duplex; | ||||
| +				}; | ||||
| +			}; | ||||
| +		}; | ||||
| +	}; | ||||
| + | ||||
| +	gpio-keys { | ||||
| +		compatible = "gpio-keys"; | ||||
| +		pinctrl-0 = <&rear_button_pins>; | ||||
| +		pinctrl-names = "default"; | ||||
| + | ||||
| +		button_0 { | ||||
| +			/* The rear SW3 button */ | ||||
| +			label = "Rear Button"; | ||||
| +			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; | ||||
| +			linux,can-disable; | ||||
| +			linux,code = <BTN_0>; | ||||
| +		}; | ||||
| +	}; | ||||
| +}; | ||||
| --- /dev/null | ||||
| +++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | ||||
| @@ -0,0 +1,115 @@ | ||||
| +/* | ||||
| + * Device Tree file for SolidRun Armada 38x Microsom | ||||
| + * | ||||
| + *  Copyright (C) 2015 Russell King | ||||
| + * | ||||
| + * This board is in development; the contents of this file work with | ||||
| + * the A1 rev 2.0 of the board, which does not represent final | ||||
| + * production board.  Things will change, don't expect this file to | ||||
| + * remain compatible info the future. | ||||
| + * | ||||
| + * 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 | ||||
| + *     version 2 as published by the Free Software Foundation. | ||||
| + * | ||||
| + *     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 , 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 <dt-bindings/input/input.h> | ||||
| +#include <dt-bindings/gpio/gpio.h> | ||||
| + | ||||
| +/ { | ||||
| +	memory { | ||||
| +		device_type = "memory"; | ||||
| +		reg = <0x00000000 0x10000000>; /* 256 MB */ | ||||
| +	}; | ||||
| + | ||||
| +	soc { | ||||
| +		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
| +			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
| +			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| + | ||||
| +		internal-regs { | ||||
| +			ethernet@70000 { | ||||
| +				pinctrl-0 = <&ge0_rgmii_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				phy = <&phy_dedicated>; | ||||
| +				phy-mode = "rgmii-id"; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			mdio@72004 { | ||||
| +				/* | ||||
| +				 * Add the phy clock here, so the phy can be | ||||
| +				 * accessed to read its IDs prior to binding | ||||
| +				 * with the driver. | ||||
| +				 */ | ||||
| +				pinctrl-0 = <&mdio_pins µsom_phy_clk_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| + | ||||
| +				phy_dedicated: ethernet-phy@0 { | ||||
| +					/* | ||||
| +					 * Annoyingly, the marvell phy driver | ||||
| +					 * configures the LED register, rather | ||||
| +					 * than preserving reset-loaded setting. | ||||
| +					 * We undo that rubbish here. | ||||
| +					 */ | ||||
| +					marvell,reg-init = <3 16 0 0x101e>; | ||||
| +					reg = <0>; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			pinctrl@18000 { | ||||
| +				microsom_phy_clk_pins: microsom-phy-clk-pins { | ||||
| +					marvell,pins = "mpp45"; | ||||
| +					marvell,function = "ref"; | ||||
| +				}; | ||||
| +			}; | ||||
| + | ||||
| +			rtc@a3800 { | ||||
| +				/* | ||||
| +				 * If the rtc doesn't work, run "date reset" | ||||
| +				 * twice in u-boot. | ||||
| +				 */ | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
| +			serial@12000 { | ||||
| +				pinctrl-0 = <&uart0_pins>; | ||||
| +				pinctrl-names = "default"; | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| +		}; | ||||
| +	}; | ||||
| +}; | ||||
| @@ -1,256 +0,0 @@ | ||||
| From c49e99c2b25a412623412a461bb751239208b9b3 Mon Sep 17 00:00:00 2001 | ||||
| From: Marcin Wojtas <mw@semihalf.com> | ||||
| Date: Mon, 14 Mar 2016 09:38:58 +0100 | ||||
| Subject: [PATCH] ARM: dts: armada-38x: enable buffer manager support on Armada | ||||
|  38x boards | ||||
|  | ||||
| Since mvneta driver supports using hardware buffer management (BM), in | ||||
| order to use it, board files have to be adjusted accordingly. This commit | ||||
| enables BM on: | ||||
| * A385-DB-AP - each port has its own pool for long and common pool for | ||||
| short packets, | ||||
| * A388-ClearFog - same as above, | ||||
| * A388-DB - to each port unique 'short' and 'long' pools are mapped, | ||||
| * A388-GP - same as above. | ||||
|  | ||||
| Moreover appropriate entry is added to 'soc' node ranges, as well as "okay" | ||||
| status for 'bm' and 'bm-bppi' (internal SRAM) nodes. | ||||
|  | ||||
| [gregory.clement@free-electrons.com: add suppport for the ClearFog board] | ||||
|  | ||||
| Signed-off-by: Marcin Wojtas <mw@semihalf.com> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Signed-off-by: David S. Miller <davem@davemloft.net> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-385-db-ap.dts              | 20 +++++++++++++++++++- | ||||
|  arch/arm/boot/dts/armada-388-clearfog.dts           |  6 ++++++ | ||||
|  arch/arm/boot/dts/armada-388-db.dts                 | 17 ++++++++++++++++- | ||||
|  arch/arm/boot/dts/armada-388-gp.dts                 | 17 ++++++++++++++++- | ||||
|  arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | 15 ++++++++++++++- | ||||
|  5 files changed, 71 insertions(+), 4 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-385-db-ap.dts | ||||
| +++ b/arch/arm/boot/dts/armada-385-db-ap.dts | ||||
| @@ -61,7 +61,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		internal-regs { | ||||
|  			spi1: spi@10680 { | ||||
| @@ -138,12 +139,18 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy2>; | ||||
|  				phy-mode = "sgmii"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <1>; | ||||
| +				bm,pool-short = <3>; | ||||
|  			}; | ||||
|   | ||||
|  			ethernet@34000 { | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy1>; | ||||
|  				phy-mode = "sgmii"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <2>; | ||||
| +				bm,pool-short = <3>; | ||||
|  			}; | ||||
|   | ||||
|  			ethernet@70000 { | ||||
| @@ -157,6 +164,13 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy0>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <3>; | ||||
| +			}; | ||||
| + | ||||
| +			bm@c8000 { | ||||
| +				status = "okay"; | ||||
|  			}; | ||||
|   | ||||
|  			nfc: flash@d0000 { | ||||
| @@ -178,6 +192,10 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|   | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
| + | ||||
|  		pcie-controller { | ||||
|  			status = "okay"; | ||||
|   | ||||
| --- a/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| @@ -78,6 +78,9 @@ | ||||
|  		internal-regs { | ||||
|  			ethernet@30000 { | ||||
|  				phy-mode = "sgmii"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <2>; | ||||
| +				bm,pool-short = <1>; | ||||
|  				status = "okay"; | ||||
|   | ||||
|  				fixed-link { | ||||
| @@ -88,6 +91,9 @@ | ||||
|   | ||||
|  			ethernet@34000 { | ||||
|  				phy-mode = "sgmii"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <3>; | ||||
| +				bm,pool-short = <1>; | ||||
|  				status = "okay"; | ||||
|   | ||||
|  				fixed-link { | ||||
| --- a/arch/arm/boot/dts/armada-388-db.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-db.dts | ||||
| @@ -66,7 +66,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		internal-regs { | ||||
|  			spi@10600 { | ||||
| @@ -99,6 +100,9 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy1>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <2>; | ||||
| +				bm,pool-short = <3>; | ||||
|  			}; | ||||
|   | ||||
|  			usb@58000 { | ||||
| @@ -109,6 +113,9 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy0>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <1>; | ||||
|  			}; | ||||
|   | ||||
|  			mdio@72004 { | ||||
| @@ -129,6 +136,10 @@ | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
|   | ||||
| +			bm@c8000 { | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
|  			flash@d0000 { | ||||
|  				status = "okay"; | ||||
|  				num-cs = <1>; | ||||
| @@ -169,6 +180,10 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|   | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
| + | ||||
|  		pcie-controller { | ||||
|  			status = "okay"; | ||||
|  			/* | ||||
| --- a/arch/arm/boot/dts/armada-388-gp.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-gp.dts | ||||
| @@ -60,7 +60,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		internal-regs { | ||||
|  			spi@10600 { | ||||
| @@ -133,6 +134,9 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy1>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <2>; | ||||
| +				bm,pool-short = <3>; | ||||
|  			}; | ||||
|   | ||||
|  			/* CON4 */ | ||||
| @@ -152,6 +156,9 @@ | ||||
|  				status = "okay"; | ||||
|  				phy = <&phy0>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <1>; | ||||
|  			}; | ||||
|   | ||||
|   | ||||
| @@ -186,6 +193,10 @@ | ||||
|  				}; | ||||
|  			}; | ||||
|   | ||||
| +			bm@c8000 { | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
|  			sata@e0000 { | ||||
|  				pinctrl-names = "default"; | ||||
|  				pinctrl-0 = <&sata2_pins>, <&sata3_pins>; | ||||
| @@ -240,6 +251,10 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|   | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
| + | ||||
|  		pcie-controller { | ||||
|  			status = "okay"; | ||||
|  			/* | ||||
| --- a/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi | ||||
| @@ -58,7 +58,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		internal-regs { | ||||
|  			ethernet@70000 { | ||||
| @@ -66,6 +67,9 @@ | ||||
|  				pinctrl-names = "default"; | ||||
|  				phy = <&phy_dedicated>; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <1>; | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
|   | ||||
| @@ -110,6 +114,15 @@ | ||||
|  				pinctrl-names = "default"; | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
| + | ||||
| +			bm@c8000 { | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
|  		}; | ||||
| + | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
| + | ||||
|  	}; | ||||
|  }; | ||||
| @@ -1,41 +0,0 @@ | ||||
| From d261861ab52623e34a25fe6ae76714456edda033 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@armlinux.org.uk> | ||||
| Date: Sun, 10 Jul 2016 16:27:38 +0100 | ||||
| Subject: [PATCH] ARM: dts: armada-388-clearfog: remove duplicate mdio entry | ||||
|  | ||||
| The clearfog DTS should not be defining the on-board phy, this device | ||||
| is located on the microsom.  Remove the duplicated definition. | ||||
|  | ||||
| Reported-by: Jon Nettleton <jon@solid-run.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> | ||||
| Reviewed-by: Andrew Lunn <andrew@lunn.ch> | ||||
| Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-388-clearfog.dts | 16 ---------------- | ||||
|  1 file changed, 16 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| @@ -239,22 +239,6 @@ | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
|   | ||||
| -			mdio@72004 { | ||||
| -				pinctrl-0 = <&mdio_pins>; | ||||
| -				pinctrl-names = "default"; | ||||
| - | ||||
| -				phy_dedicated: ethernet-phy@0 { | ||||
| -					/* | ||||
| -					 * Annoyingly, the marvell phy driver | ||||
| -					 * configures the LED register, rather | ||||
| -					 * than preserving reset-loaded setting. | ||||
| -					 * We undo that rubbish here. | ||||
| -					 */ | ||||
| -					marvell,reg-init = <3 16 0 0x101e>; | ||||
| -					reg = <0>; | ||||
| -				}; | ||||
| -			}; | ||||
| - | ||||
|  			pinctrl@18000 { | ||||
|  				clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins { | ||||
|  					marvell,pins = "mpp46"; | ||||
| @@ -1,62 +0,0 @@ | ||||
| The WRT1900AC among other Linksys routers uses a dual-firmware layout. | ||||
| Dynamically rename the active partition to "ubi". | ||||
|  | ||||
| Signed-off-by: Imre Kaloz <kaloz@openwrt.org> | ||||
|  | ||||
| --- a/drivers/mtd/ofpart.c | ||||
| +++ b/drivers/mtd/ofpart.c | ||||
| @@ -25,6 +25,8 @@ static bool node_has_compatible(struct d | ||||
|  	return of_get_property(pp, "compatible", NULL); | ||||
|  } | ||||
|   | ||||
| +static int mangled_rootblock; | ||||
| + | ||||
|  static int parse_ofpart_partitions(struct mtd_info *master, | ||||
|  				   struct mtd_partition **pparts, | ||||
|  				   struct mtd_part_parser_data *data) | ||||
| @@ -32,6 +34,7 @@ static int parse_ofpart_partitions(struc | ||||
|  	struct device_node *mtd_node; | ||||
|  	struct device_node *ofpart_node; | ||||
|  	const char *partname; | ||||
| +	const char *owrtpart = "ubi"; | ||||
|  	struct device_node *pp; | ||||
|  	int nr_parts, i, ret = 0; | ||||
|  	bool dedicated = true; | ||||
| @@ -110,9 +113,15 @@ static int parse_ofpart_partitions(struc | ||||
|  		(*pparts)[i].offset = of_read_number(reg, a_cells); | ||||
|  		(*pparts)[i].size = of_read_number(reg + a_cells, s_cells); | ||||
|   | ||||
| -		partname = of_get_property(pp, "label", &len); | ||||
| -		if (!partname) | ||||
| -			partname = of_get_property(pp, "name", &len); | ||||
| +		if (mangled_rootblock && (i == mangled_rootblock)) { | ||||
| +				partname = owrtpart; | ||||
| +		} else { | ||||
| +			partname = of_get_property(pp, "label", &len); | ||||
| + | ||||
| +			if (!partname) | ||||
| +				partname = of_get_property(pp, "name", &len); | ||||
| +		} | ||||
| + | ||||
|  		(*pparts)[i].name = partname; | ||||
|   | ||||
|  		if (of_get_property(pp, "read-only", &len)) | ||||
| @@ -215,6 +224,18 @@ static int __init ofpart_parser_init(voi | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static int __init active_root(char *str) | ||||
| +{ | ||||
| +	get_option(&str, &mangled_rootblock); | ||||
| + | ||||
| +	if (!mangled_rootblock) | ||||
| +		return 1; | ||||
| + | ||||
| +	return 1; | ||||
| +} | ||||
| + | ||||
| +__setup("mangled_rootblock=", active_root); | ||||
| + | ||||
|  static void __exit ofpart_parser_exit(void) | ||||
|  { | ||||
|  	deregister_mtd_parser(&ofpart_parser); | ||||
| @@ -1,15 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-xp.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-xp.dtsi | ||||
| @@ -98,12 +98,10 @@ | ||||
|   | ||||
|   | ||||
|  			i2c0: i2c@11000 { | ||||
| -				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; | ||||
|  				reg = <0x11000 0x100>; | ||||
|  			}; | ||||
|   | ||||
|  			i2c1: i2c@11100 { | ||||
| -				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; | ||||
|  				reg = <0x11100 0x100>; | ||||
|  			}; | ||||
|   | ||||
| @@ -1,13 +0,0 @@ | ||||
| Remove a BUG() call that would crash on a race condition that should | ||||
| otherwise be harmless. | ||||
|  | ||||
| --- a/drivers/mtd/nand/pxa3xx_nand.c | ||||
| +++ b/drivers/mtd/nand/pxa3xx_nand.c | ||||
| @@ -701,7 +701,6 @@ static void handle_data_pio(struct pxa3x | ||||
|  	default: | ||||
|  		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, | ||||
|  				info->state); | ||||
| -		BUG(); | ||||
|  	} | ||||
|   | ||||
|  	/* Update buffer pointers for multi-page read/write */ | ||||
| @@ -1,10 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| @@ -298,7 +298,6 @@ | ||||
|  			nand@d0000 { | ||||
|  				status = "okay"; | ||||
|  				num-cs = <1>; | ||||
| -				marvell,nand-keep-config; | ||||
|  				marvell,nand-enable-arbiter; | ||||
|  				nand-on-flash-bbt; | ||||
|  				nand-ecc-strength = <4>; | ||||
| @@ -1,107 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-385-linksys.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-385-linksys.dtsi | ||||
| @@ -59,7 +59,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		internal-regs { | ||||
|   | ||||
| @@ -93,6 +94,9 @@ | ||||
|  			ethernet@70000 { | ||||
|  				status = "okay"; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <3>; | ||||
|  				fixed-link { | ||||
|  					speed = <1000>; | ||||
|  					full-duplex; | ||||
| @@ -102,6 +106,9 @@ | ||||
|  			ethernet@34000 { | ||||
|  				status = "okay"; | ||||
|  				phy-mode = "sgmii"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <2>; | ||||
| +				bm,pool-short = <3>; | ||||
|  				fixed-link { | ||||
|  					speed = <1000>; | ||||
|  					full-duplex; | ||||
| @@ -112,6 +119,10 @@ | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
|   | ||||
| +			bm@c8000 { | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
|  			sata@a8000 { | ||||
|  				status = "okay"; | ||||
|  			}; | ||||
| @@ -198,6 +209,10 @@ | ||||
|  			}; | ||||
|  		}; | ||||
|   | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
| + | ||||
|  		pcie-controller { | ||||
|  			status = "okay"; | ||||
|   | ||||
| --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| @@ -71,7 +71,8 @@ | ||||
|  		ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 | ||||
|  			  MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 | ||||
|  			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000 | ||||
| -			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>; | ||||
| +			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000 | ||||
| +			  MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>; | ||||
|   | ||||
|  		pcie-controller { | ||||
|  			status = "okay"; | ||||
| @@ -205,6 +206,9 @@ | ||||
|  				pinctrl-names = "default"; | ||||
|  				status = "okay"; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <0>; | ||||
| +				bm,pool-short = <3>; | ||||
|  				fixed-link { | ||||
|  					speed = <1000>; | ||||
|  					full-duplex; | ||||
| @@ -216,12 +220,19 @@ | ||||
|  				pinctrl-names = "default"; | ||||
|  				status = "okay"; | ||||
|  				phy-mode = "rgmii-id"; | ||||
| +				buffer-manager = <&bm>; | ||||
| +				bm,pool-long = <1>; | ||||
| +				bm,pool-short = <3>; | ||||
|  				fixed-link { | ||||
|  					speed = <1000>; | ||||
|  					full-duplex; | ||||
|  				}; | ||||
|  			}; | ||||
|   | ||||
| +			bm@c0000 { | ||||
| +				status = "okay"; | ||||
| +			}; | ||||
| + | ||||
|  			/* USB part of the eSATA/USB 2.0 port */ | ||||
|  			usb@50000 { | ||||
|  				status = "okay"; | ||||
| @@ -379,6 +390,10 @@ | ||||
|  				}; | ||||
|  			}; | ||||
|  		}; | ||||
| + | ||||
| +		bm-bppi { | ||||
| +			status = "okay"; | ||||
| +		}; | ||||
|  	}; | ||||
|   | ||||
|  	gpio_keys { | ||||
| @@ -1,69 +0,0 @@ | ||||
| Revert "mtd: pxa3xx-nand: handle PIO in threaded interrupt" | ||||
|  | ||||
| This reverts commit 24542257a3b987025d4b998ec2d15e556c98ad3f | ||||
| This upstream change has been causing spurious timeouts on accesses | ||||
| to the NAND flash if something else on the system is causing | ||||
| significant latency. | ||||
|  | ||||
| Nothing guarantees that the thread will run in time, so the | ||||
| usual timeout is unreliable. | ||||
|  | ||||
| Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||
|  | ||||
| --- a/drivers/mtd/nand/pxa3xx_nand.c | ||||
| +++ b/drivers/mtd/nand/pxa3xx_nand.c | ||||
| @@ -765,24 +765,11 @@ static void start_data_dma(struct pxa3xx | ||||
|  		__func__, direction, info->dma_cookie, info->sg.length); | ||||
|  } | ||||
|   | ||||
| -static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data) | ||||
| -{ | ||||
| -	struct pxa3xx_nand_info *info = data; | ||||
| - | ||||
| -	handle_data_pio(info); | ||||
| - | ||||
| -	info->state = STATE_CMD_DONE; | ||||
| -	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); | ||||
| - | ||||
| -	return IRQ_HANDLED; | ||||
| -} | ||||
| - | ||||
|  static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | ||||
|  { | ||||
|  	struct pxa3xx_nand_info *info = devid; | ||||
|  	unsigned int status, is_completed = 0, is_ready = 0; | ||||
|  	unsigned int ready, cmd_done; | ||||
| -	irqreturn_t ret = IRQ_HANDLED; | ||||
|   | ||||
|  	if (info->cs == 0) { | ||||
|  		ready           = NDSR_FLASH_RDY; | ||||
| @@ -824,8 +811,7 @@ static irqreturn_t pxa3xx_nand_irq(int i | ||||
|  		} else { | ||||
|  			info->state = (status & NDSR_RDDREQ) ? | ||||
|  				      STATE_PIO_READING : STATE_PIO_WRITING; | ||||
| -			ret = IRQ_WAKE_THREAD; | ||||
| -			goto NORMAL_IRQ_EXIT; | ||||
| +			handle_data_pio(info); | ||||
|  		} | ||||
|  	} | ||||
|  	if (status & cmd_done) { | ||||
| @@ -870,7 +856,7 @@ static irqreturn_t pxa3xx_nand_irq(int i | ||||
|  	if (is_ready) | ||||
|  		complete(&info->dev_ready); | ||||
|  NORMAL_IRQ_EXIT: | ||||
| -	return ret; | ||||
| +	return IRQ_HANDLED; | ||||
|  } | ||||
|   | ||||
|  static inline int is_buf_blank(uint8_t *buf, size_t len) | ||||
| @@ -1849,9 +1835,7 @@ static int alloc_nand_resource(struct pl | ||||
|  	/* initialize all interrupts to be disabled */ | ||||
|  	disable_int(info, NDSR_MASK); | ||||
|   | ||||
| -	ret = request_threaded_irq(irq, pxa3xx_nand_irq, | ||||
| -				   pxa3xx_nand_irq_thread, IRQF_ONESHOT, | ||||
| -				   pdev->name, info); | ||||
| +	ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info); | ||||
|  	if (ret < 0) { | ||||
|  		dev_err(&pdev->dev, "failed to request IRQ\n"); | ||||
|  		goto fail_free_buf; | ||||
| @@ -1,306 +0,0 @@ | ||||
| From 4d5621372f6e7ddbfd5879602f82073987bcc722 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 20 Sep 2015 09:57:10 +0100 | ||||
| Subject: [PATCH 709/744] phy: move fixed_phy MII register generation to a | ||||
|  library | ||||
|  | ||||
| Move the fixed_phy MII register generation to a library to allow other | ||||
| software phy implementations to use this code. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/Kconfig     |   4 ++ | ||||
|  drivers/net/phy/Makefile    |   3 +- | ||||
|  drivers/net/phy/fixed_phy.c |  95 ++------------------------------- | ||||
|  drivers/net/phy/swphy.c     | 126 ++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/net/phy/swphy.h     |   8 +++ | ||||
|  5 files changed, 143 insertions(+), 93 deletions(-) | ||||
|  create mode 100644 drivers/net/phy/swphy.c | ||||
|  create mode 100644 drivers/net/phy/swphy.h | ||||
|  | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -26,6 +26,9 @@ config SWCONFIG_LEDS | ||||
|  	bool "Switch LED trigger support" | ||||
|  	depends on (SWCONFIG && LEDS_TRIGGERS) | ||||
|   | ||||
| +config SWPHY | ||||
| +	bool | ||||
| + | ||||
|  comment "MII PHY device drivers" | ||||
|   | ||||
|  config AQUANTIA_PHY | ||||
| @@ -205,6 +208,7 @@ config RTL8306_PHY | ||||
|  config FIXED_PHY | ||||
|  	tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | ||||
|  	depends on PHYLIB | ||||
| +	select SWPHY | ||||
|  	---help--- | ||||
|  	  Adds the platform "fixed" MDIO Bus to cover the boards that use | ||||
|  	  PHYs that are not connected to the real MDIO bus. | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -1,6 +1,7 @@ | ||||
|  # Makefile for Linux PHY drivers | ||||
|   | ||||
| -libphy-objs			:= phy.o phy_device.o mdio_bus.o | ||||
| +libphy-y			:= phy.o phy_device.o mdio_bus.o | ||||
| +libphy-$(CONFIG_SWPHY)		+= swphy.o | ||||
|   | ||||
|  obj-$(CONFIG_MDIO_BOARDINFO)	+= mdio-boardinfo.o | ||||
|   | ||||
| --- a/drivers/net/phy/fixed_phy.c | ||||
| +++ b/drivers/net/phy/fixed_phy.c | ||||
| @@ -24,6 +24,8 @@ | ||||
|  #include <linux/of.h> | ||||
|  #include <linux/gpio.h> | ||||
|   | ||||
| +#include "swphy.h" | ||||
| + | ||||
|  #define MII_REGS_NUM 29 | ||||
|   | ||||
|  struct fixed_mdio_bus { | ||||
| @@ -49,101 +51,10 @@ static struct fixed_mdio_bus platform_fm | ||||
|   | ||||
|  static int fixed_phy_update_regs(struct fixed_phy *fp) | ||||
|  { | ||||
| -	u16 bmsr = BMSR_ANEGCAPABLE; | ||||
| -	u16 bmcr = 0; | ||||
| -	u16 lpagb = 0; | ||||
| -	u16 lpa = 0; | ||||
| - | ||||
|  	if (gpio_is_valid(fp->link_gpio)) | ||||
|  		fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); | ||||
|   | ||||
| -	if (fp->status.duplex) { | ||||
| -		switch (fp->status.speed) { | ||||
| -		case 1000: | ||||
| -			bmsr |= BMSR_ESTATEN; | ||||
| -			break; | ||||
| -		case 100: | ||||
| -			bmsr |= BMSR_100FULL; | ||||
| -			break; | ||||
| -		case 10: | ||||
| -			bmsr |= BMSR_10FULL; | ||||
| -			break; | ||||
| -		default: | ||||
| -			break; | ||||
| -		} | ||||
| -	} else { | ||||
| -		switch (fp->status.speed) { | ||||
| -		case 1000: | ||||
| -			bmsr |= BMSR_ESTATEN; | ||||
| -			break; | ||||
| -		case 100: | ||||
| -			bmsr |= BMSR_100HALF; | ||||
| -			break; | ||||
| -		case 10: | ||||
| -			bmsr |= BMSR_10HALF; | ||||
| -			break; | ||||
| -		default: | ||||
| -			break; | ||||
| -		} | ||||
| -	} | ||||
| - | ||||
| -	if (fp->status.link) { | ||||
| -		bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; | ||||
| - | ||||
| -		if (fp->status.duplex) { | ||||
| -			bmcr |= BMCR_FULLDPLX; | ||||
| - | ||||
| -			switch (fp->status.speed) { | ||||
| -			case 1000: | ||||
| -				bmcr |= BMCR_SPEED1000; | ||||
| -				lpagb |= LPA_1000FULL; | ||||
| -				break; | ||||
| -			case 100: | ||||
| -				bmcr |= BMCR_SPEED100; | ||||
| -				lpa |= LPA_100FULL; | ||||
| -				break; | ||||
| -			case 10: | ||||
| -				lpa |= LPA_10FULL; | ||||
| -				break; | ||||
| -			default: | ||||
| -				pr_warn("fixed phy: unknown speed\n"); | ||||
| -				return -EINVAL; | ||||
| -			} | ||||
| -		} else { | ||||
| -			switch (fp->status.speed) { | ||||
| -			case 1000: | ||||
| -				bmcr |= BMCR_SPEED1000; | ||||
| -				lpagb |= LPA_1000HALF; | ||||
| -				break; | ||||
| -			case 100: | ||||
| -				bmcr |= BMCR_SPEED100; | ||||
| -				lpa |= LPA_100HALF; | ||||
| -				break; | ||||
| -			case 10: | ||||
| -				lpa |= LPA_10HALF; | ||||
| -				break; | ||||
| -			default: | ||||
| -				pr_warn("fixed phy: unknown speed\n"); | ||||
| -			return -EINVAL; | ||||
| -			} | ||||
| -		} | ||||
| - | ||||
| -		if (fp->status.pause) | ||||
| -			lpa |= LPA_PAUSE_CAP; | ||||
| - | ||||
| -		if (fp->status.asym_pause) | ||||
| -			lpa |= LPA_PAUSE_ASYM; | ||||
| -	} | ||||
| - | ||||
| -	fp->regs[MII_PHYSID1] = 0; | ||||
| -	fp->regs[MII_PHYSID2] = 0; | ||||
| - | ||||
| -	fp->regs[MII_BMSR] = bmsr; | ||||
| -	fp->regs[MII_BMCR] = bmcr; | ||||
| -	fp->regs[MII_LPA] = lpa; | ||||
| -	fp->regs[MII_STAT1000] = lpagb; | ||||
| - | ||||
| -	return 0; | ||||
| +	return swphy_update_regs(fp->regs, &fp->status); | ||||
|  } | ||||
|   | ||||
|  static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) | ||||
| --- /dev/null | ||||
| +++ b/drivers/net/phy/swphy.c | ||||
| @@ -0,0 +1,126 @@ | ||||
| +/* | ||||
| + * Software PHY emulation | ||||
| + * | ||||
| + * Code taken from fixed_phy.c by Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| + * | ||||
| + * Author: Vitaly Bordug <vbordug@ru.mvista.com> | ||||
| + *         Anton Vorontsov <avorontsov@ru.mvista.com> | ||||
| + * | ||||
| + * Copyright (c) 2006-2007 MontaVista Software, Inc. | ||||
| + * | ||||
| + * This program is free software; you can redistribute  it and/or modify it | ||||
| + * under  the terms of  the GNU General  Public License as published by the | ||||
| + * Free Software Foundation;  either version 2 of the  License, or (at your | ||||
| + * option) any later version. | ||||
| + */ | ||||
| +#include <linux/export.h> | ||||
| +#include <linux/mii.h> | ||||
| +#include <linux/phy.h> | ||||
| +#include <linux/phy_fixed.h> | ||||
| + | ||||
| +#include "swphy.h" | ||||
| + | ||||
| +/** | ||||
| + * swphy_update_regs - update MII register array with fixed phy state | ||||
| + * @regs: array of 32 registers to update | ||||
| + * @state: fixed phy status | ||||
| + * | ||||
| + * Update the array of MII registers with the fixed phy link, speed, | ||||
| + * duplex and pause mode settings. | ||||
| + */ | ||||
| +int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) | ||||
| +{ | ||||
| +	u16 bmsr = BMSR_ANEGCAPABLE; | ||||
| +	u16 bmcr = 0; | ||||
| +	u16 lpagb = 0; | ||||
| +	u16 lpa = 0; | ||||
| + | ||||
| +	if (state->duplex) { | ||||
| +		switch (state->speed) { | ||||
| +		case 1000: | ||||
| +			bmsr |= BMSR_ESTATEN; | ||||
| +			break; | ||||
| +		case 100: | ||||
| +			bmsr |= BMSR_100FULL; | ||||
| +			break; | ||||
| +		case 10: | ||||
| +			bmsr |= BMSR_10FULL; | ||||
| +			break; | ||||
| +		default: | ||||
| +			break; | ||||
| +		} | ||||
| +	} else { | ||||
| +		switch (state->speed) { | ||||
| +		case 1000: | ||||
| +			bmsr |= BMSR_ESTATEN; | ||||
| +			break; | ||||
| +		case 100: | ||||
| +			bmsr |= BMSR_100HALF; | ||||
| +			break; | ||||
| +		case 10: | ||||
| +			bmsr |= BMSR_10HALF; | ||||
| +			break; | ||||
| +		default: | ||||
| +			break; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	if (state->link) { | ||||
| +		bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; | ||||
| + | ||||
| +		if (state->duplex) { | ||||
| +			bmcr |= BMCR_FULLDPLX; | ||||
| + | ||||
| +			switch (state->speed) { | ||||
| +			case 1000: | ||||
| +				bmcr |= BMCR_SPEED1000; | ||||
| +				lpagb |= LPA_1000FULL; | ||||
| +				break; | ||||
| +			case 100: | ||||
| +				bmcr |= BMCR_SPEED100; | ||||
| +				lpa |= LPA_100FULL; | ||||
| +				break; | ||||
| +			case 10: | ||||
| +				lpa |= LPA_10FULL; | ||||
| +				break; | ||||
| +			default: | ||||
| +				pr_warn("swphy: unknown speed\n"); | ||||
| +				return -EINVAL; | ||||
| +			} | ||||
| +		} else { | ||||
| +			switch (state->speed) { | ||||
| +			case 1000: | ||||
| +				bmcr |= BMCR_SPEED1000; | ||||
| +				lpagb |= LPA_1000HALF; | ||||
| +				break; | ||||
| +			case 100: | ||||
| +				bmcr |= BMCR_SPEED100; | ||||
| +				lpa |= LPA_100HALF; | ||||
| +				break; | ||||
| +			case 10: | ||||
| +				lpa |= LPA_10HALF; | ||||
| +				break; | ||||
| +			default: | ||||
| +				pr_warn("swphy: unknown speed\n"); | ||||
| +				return -EINVAL; | ||||
| +			} | ||||
| +		} | ||||
| + | ||||
| +		if (state->pause) | ||||
| +			lpa |= LPA_PAUSE_CAP; | ||||
| + | ||||
| +		if (state->asym_pause) | ||||
| +			lpa |= LPA_PAUSE_ASYM; | ||||
| +	} | ||||
| + | ||||
| +	regs[MII_PHYSID1] = 0; | ||||
| +	regs[MII_PHYSID2] = 0; | ||||
| + | ||||
| +	regs[MII_BMSR] = bmsr; | ||||
| +	regs[MII_BMCR] = bmcr; | ||||
| +	regs[MII_LPA] = lpa; | ||||
| +	regs[MII_STAT1000] = lpagb; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(swphy_update_regs); | ||||
| --- /dev/null | ||||
| +++ b/drivers/net/phy/swphy.h | ||||
| @@ -0,0 +1,8 @@ | ||||
| +#ifndef SWPHY_H | ||||
| +#define SWPHY_H | ||||
| + | ||||
| +struct fixed_phy_status; | ||||
| + | ||||
| +int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state); | ||||
| + | ||||
| +#endif | ||||
| @@ -1,203 +0,0 @@ | ||||
| From cd834fe430f030a63bfa9277bba194e8eef4dbd0 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 20 Sep 2015 10:18:59 +0100 | ||||
| Subject: [PATCH 710/744] phy: convert swphy register generation to tabular | ||||
|  form | ||||
|  | ||||
| Convert the swphy register generation to tabular form which allows us | ||||
| to eliminate multiple switch() statements.  This results in a smaller | ||||
| object code size, more efficient, and easier to add support for faster | ||||
| speeds. | ||||
|  | ||||
| Before: | ||||
|  | ||||
| Idx Name          Size      VMA       LMA       File off  Algn | ||||
|   0 .text         00000164  00000000  00000000  00000034  2**2 | ||||
|  | ||||
|    text    data     bss     dec     hex filename | ||||
|     388       0       0     388     184 swphy.o | ||||
|  | ||||
| After: | ||||
|  | ||||
| Idx Name          Size      VMA       LMA       File off  Algn | ||||
|   0 .text         000000fc  00000000  00000000  00000034  2**2 | ||||
|   5 .rodata       00000028  00000000  00000000  00000138  2**2 | ||||
|  | ||||
|    text    data     bss     dec     hex filename | ||||
|     324       0       0     324     144 swphy.o | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/swphy.c | 143 ++++++++++++++++++++++++++---------------------- | ||||
|  1 file changed, 78 insertions(+), 65 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/swphy.c | ||||
| +++ b/drivers/net/phy/swphy.c | ||||
| @@ -20,6 +20,72 @@ | ||||
|   | ||||
|  #include "swphy.h" | ||||
|   | ||||
| +struct swmii_regs { | ||||
| +	u16 bmcr; | ||||
| +	u16 bmsr; | ||||
| +	u16 lpa; | ||||
| +	u16 lpagb; | ||||
| +}; | ||||
| + | ||||
| +enum { | ||||
| +	SWMII_SPEED_10 = 0, | ||||
| +	SWMII_SPEED_100, | ||||
| +	SWMII_SPEED_1000, | ||||
| +	SWMII_DUPLEX_HALF = 0, | ||||
| +	SWMII_DUPLEX_FULL, | ||||
| +}; | ||||
| + | ||||
| +/* | ||||
| + * These two tables get bitwise-anded together to produce the final result. | ||||
| + * This means the speed table must contain both duplex settings, and the | ||||
| + * duplex table must contain all speed settings. | ||||
| + */ | ||||
| +static const struct swmii_regs speed[] = { | ||||
| +	[SWMII_SPEED_10] = { | ||||
| +		.bmcr  = BMCR_FULLDPLX, | ||||
| +		.lpa   = LPA_10FULL | LPA_10HALF, | ||||
| +	}, | ||||
| +	[SWMII_SPEED_100] = { | ||||
| +		.bmcr  = BMCR_FULLDPLX | BMCR_SPEED100, | ||||
| +		.bmsr  = BMSR_100FULL | BMSR_100HALF, | ||||
| +		.lpa   = LPA_100FULL | LPA_100HALF, | ||||
| +	}, | ||||
| +	[SWMII_SPEED_1000] = { | ||||
| +		.bmcr  = BMCR_FULLDPLX | BMCR_SPEED1000, | ||||
| +		.bmsr  = BMSR_ESTATEN, | ||||
| +		.lpagb = LPA_1000FULL | LPA_1000HALF, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static const struct swmii_regs duplex[] = { | ||||
| +	[SWMII_DUPLEX_HALF] = { | ||||
| +		.bmcr  = ~BMCR_FULLDPLX, | ||||
| +		.bmsr  = BMSR_ESTATEN | BMSR_100HALF, | ||||
| +		.lpa   = LPA_10HALF | LPA_100HALF, | ||||
| +		.lpagb = LPA_1000HALF, | ||||
| +	}, | ||||
| +	[SWMII_DUPLEX_FULL] = { | ||||
| +		.bmcr  = ~0, | ||||
| +		.bmsr  = BMSR_ESTATEN | BMSR_100FULL, | ||||
| +		.lpa   = LPA_10FULL | LPA_100FULL, | ||||
| +		.lpagb = LPA_1000FULL, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int swphy_decode_speed(int speed) | ||||
| +{ | ||||
| +	switch (speed) { | ||||
| +	case 1000: | ||||
| +		return SWMII_SPEED_1000; | ||||
| +	case 100: | ||||
| +		return SWMII_SPEED_100; | ||||
| +	case 10: | ||||
| +		return SWMII_SPEED_10; | ||||
| +	default: | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
|  /** | ||||
|   * swphy_update_regs - update MII register array with fixed phy state | ||||
|   * @regs: array of 32 registers to update | ||||
| @@ -30,81 +96,28 @@ | ||||
|   */ | ||||
|  int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) | ||||
|  { | ||||
| +	int speed_index, duplex_index; | ||||
|  	u16 bmsr = BMSR_ANEGCAPABLE; | ||||
|  	u16 bmcr = 0; | ||||
|  	u16 lpagb = 0; | ||||
|  	u16 lpa = 0; | ||||
|   | ||||
| -	if (state->duplex) { | ||||
| -		switch (state->speed) { | ||||
| -		case 1000: | ||||
| -			bmsr |= BMSR_ESTATEN; | ||||
| -			break; | ||||
| -		case 100: | ||||
| -			bmsr |= BMSR_100FULL; | ||||
| -			break; | ||||
| -		case 10: | ||||
| -			bmsr |= BMSR_10FULL; | ||||
| -			break; | ||||
| -		default: | ||||
| -			break; | ||||
| -		} | ||||
| -	} else { | ||||
| -		switch (state->speed) { | ||||
| -		case 1000: | ||||
| -			bmsr |= BMSR_ESTATEN; | ||||
| -			break; | ||||
| -		case 100: | ||||
| -			bmsr |= BMSR_100HALF; | ||||
| -			break; | ||||
| -		case 10: | ||||
| -			bmsr |= BMSR_10HALF; | ||||
| -			break; | ||||
| -		default: | ||||
| -			break; | ||||
| -		} | ||||
| +	speed_index = swphy_decode_speed(state->speed); | ||||
| +	if (speed_index < 0) { | ||||
| +		pr_warn("swphy: unknown speed\n"); | ||||
| +		return -EINVAL; | ||||
|  	} | ||||
|   | ||||
| +	duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF; | ||||
| + | ||||
| +	bmsr |= speed[speed_index].bmsr & duplex[duplex_index].bmsr; | ||||
| + | ||||
|  	if (state->link) { | ||||
|  		bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; | ||||
|   | ||||
| -		if (state->duplex) { | ||||
| -			bmcr |= BMCR_FULLDPLX; | ||||
| - | ||||
| -			switch (state->speed) { | ||||
| -			case 1000: | ||||
| -				bmcr |= BMCR_SPEED1000; | ||||
| -				lpagb |= LPA_1000FULL; | ||||
| -				break; | ||||
| -			case 100: | ||||
| -				bmcr |= BMCR_SPEED100; | ||||
| -				lpa |= LPA_100FULL; | ||||
| -				break; | ||||
| -			case 10: | ||||
| -				lpa |= LPA_10FULL; | ||||
| -				break; | ||||
| -			default: | ||||
| -				pr_warn("swphy: unknown speed\n"); | ||||
| -				return -EINVAL; | ||||
| -			} | ||||
| -		} else { | ||||
| -			switch (state->speed) { | ||||
| -			case 1000: | ||||
| -				bmcr |= BMCR_SPEED1000; | ||||
| -				lpagb |= LPA_1000HALF; | ||||
| -				break; | ||||
| -			case 100: | ||||
| -				bmcr |= BMCR_SPEED100; | ||||
| -				lpa |= LPA_100HALF; | ||||
| -				break; | ||||
| -			case 10: | ||||
| -				lpa |= LPA_10HALF; | ||||
| -				break; | ||||
| -			default: | ||||
| -				pr_warn("swphy: unknown speed\n"); | ||||
| -				return -EINVAL; | ||||
| -			} | ||||
| -		} | ||||
| +		bmcr  |= speed[speed_index].bmcr  & duplex[duplex_index].bmcr; | ||||
| +		lpa   |= speed[speed_index].lpa   & duplex[duplex_index].lpa; | ||||
| +		lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb; | ||||
|   | ||||
|  		if (state->pause) | ||||
|  			lpa |= LPA_PAUSE_CAP; | ||||
| @@ -1,138 +0,0 @@ | ||||
| From e07630ad84c7dc145863f079f108154fb7c975e7 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 20 Sep 2015 11:12:15 +0100 | ||||
| Subject: [PATCH 711/744] phy: separate swphy state validation from register | ||||
|  generation | ||||
|  | ||||
| Separate out the generation of MII registers from the state validation. | ||||
| This allows us to simplify the error handing in fixed_phy() by allowing | ||||
| earlier error detection. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/fixed_phy.c | 15 +++++++-------- | ||||
|  drivers/net/phy/swphy.c     | 33 ++++++++++++++++++++++++++------- | ||||
|  drivers/net/phy/swphy.h     |  3 ++- | ||||
|  3 files changed, 35 insertions(+), 16 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/fixed_phy.c | ||||
| +++ b/drivers/net/phy/fixed_phy.c | ||||
| @@ -49,12 +49,12 @@ static struct fixed_mdio_bus platform_fm | ||||
|  	.phys = LIST_HEAD_INIT(platform_fmb.phys), | ||||
|  }; | ||||
|   | ||||
| -static int fixed_phy_update_regs(struct fixed_phy *fp) | ||||
| +static void fixed_phy_update_regs(struct fixed_phy *fp) | ||||
|  { | ||||
|  	if (gpio_is_valid(fp->link_gpio)) | ||||
|  		fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); | ||||
|   | ||||
| -	return swphy_update_regs(fp->regs, &fp->status); | ||||
| +	swphy_update_regs(fp->regs, &fp->status); | ||||
|  } | ||||
|   | ||||
|  static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) | ||||
| @@ -161,6 +161,10 @@ int fixed_phy_add(unsigned int irq, int | ||||
|  	struct fixed_mdio_bus *fmb = &platform_fmb; | ||||
|  	struct fixed_phy *fp; | ||||
|   | ||||
| +	ret = swphy_validate_state(status); | ||||
| +	if (ret < 0) | ||||
| +		return ret; | ||||
| + | ||||
|  	fp = kzalloc(sizeof(*fp), GFP_KERNEL); | ||||
|  	if (!fp) | ||||
|  		return -ENOMEM; | ||||
| @@ -180,17 +184,12 @@ int fixed_phy_add(unsigned int irq, int | ||||
|  			goto err_regs; | ||||
|  	} | ||||
|   | ||||
| -	ret = fixed_phy_update_regs(fp); | ||||
| -	if (ret) | ||||
| -		goto err_gpio; | ||||
| +	fixed_phy_update_regs(fp); | ||||
|   | ||||
|  	list_add_tail(&fp->node, &fmb->phys); | ||||
|   | ||||
|  	return 0; | ||||
|   | ||||
| -err_gpio: | ||||
| -	if (gpio_is_valid(fp->link_gpio)) | ||||
| -		gpio_free(fp->link_gpio); | ||||
|  err_regs: | ||||
|  	kfree(fp); | ||||
|  	return ret; | ||||
| --- a/drivers/net/phy/swphy.c | ||||
| +++ b/drivers/net/phy/swphy.c | ||||
| @@ -87,6 +87,29 @@ static int swphy_decode_speed(int speed) | ||||
|  } | ||||
|   | ||||
|  /** | ||||
| + * swphy_validate_state - validate the software phy status | ||||
| + * @state: software phy status | ||||
| + * | ||||
| + * This checks that we can represent the state stored in @state can be | ||||
| + * represented in the emulated MII registers.  Returns 0 if it can, | ||||
| + * otherwise returns -EINVAL. | ||||
| + */ | ||||
| +int swphy_validate_state(const struct fixed_phy_status *state) | ||||
| +{ | ||||
| +	int err; | ||||
| + | ||||
| +	if (state->link) { | ||||
| +		err = swphy_decode_speed(state->speed); | ||||
| +		if (err < 0) { | ||||
| +			pr_warn("swphy: unknown speed\n"); | ||||
| +			return -EINVAL; | ||||
| +		} | ||||
| +	} | ||||
| +	return 0; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(swphy_validate_state); | ||||
| + | ||||
| +/** | ||||
|   * swphy_update_regs - update MII register array with fixed phy state | ||||
|   * @regs: array of 32 registers to update | ||||
|   * @state: fixed phy status | ||||
| @@ -94,7 +117,7 @@ static int swphy_decode_speed(int speed) | ||||
|   * Update the array of MII registers with the fixed phy link, speed, | ||||
|   * duplex and pause mode settings. | ||||
|   */ | ||||
| -int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) | ||||
| +void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) | ||||
|  { | ||||
|  	int speed_index, duplex_index; | ||||
|  	u16 bmsr = BMSR_ANEGCAPABLE; | ||||
| @@ -103,10 +126,8 @@ int swphy_update_regs(u16 *regs, const s | ||||
|  	u16 lpa = 0; | ||||
|   | ||||
|  	speed_index = swphy_decode_speed(state->speed); | ||||
| -	if (speed_index < 0) { | ||||
| -		pr_warn("swphy: unknown speed\n"); | ||||
| -		return -EINVAL; | ||||
| -	} | ||||
| +	if (WARN_ON(speed_index < 0)) | ||||
| +		return; | ||||
|   | ||||
|  	duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF; | ||||
|   | ||||
| @@ -133,7 +154,5 @@ int swphy_update_regs(u16 *regs, const s | ||||
|  	regs[MII_BMCR] = bmcr; | ||||
|  	regs[MII_LPA] = lpa; | ||||
|  	regs[MII_STAT1000] = lpagb; | ||||
| - | ||||
| -	return 0; | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(swphy_update_regs); | ||||
| --- a/drivers/net/phy/swphy.h | ||||
| +++ b/drivers/net/phy/swphy.h | ||||
| @@ -3,6 +3,7 @@ | ||||
|   | ||||
|  struct fixed_phy_status; | ||||
|   | ||||
| -int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state); | ||||
| +int swphy_validate_state(const struct fixed_phy_status *state); | ||||
| +void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state); | ||||
|   | ||||
|  #endif | ||||
| @@ -1,204 +0,0 @@ | ||||
| From e0f33a88243329da1aa5a90fe10ab25c9fb0a091 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 20 Sep 2015 11:28:39 +0100 | ||||
| Subject: [PATCH 712/744] phy: generate swphy registers on the fly | ||||
|  | ||||
| Generate software phy registers as and when requested, rather than | ||||
| duplicating the state in fixed_phy.  This allows us to eliminate | ||||
| the duplicate storage of of the same data, which is only different | ||||
| in format. | ||||
|  | ||||
| As fixed_phy_update_regs() no longer updates register state, rename | ||||
| it to fixed_phy_update(). | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/fixed_phy.c | 31 +++++------------------------- | ||||
|  drivers/net/phy/swphy.c     | 47 ++++++++++++++++++++++++++++++++------------- | ||||
|  drivers/net/phy/swphy.h     |  2 +- | ||||
|  3 files changed, 40 insertions(+), 40 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/fixed_phy.c | ||||
| +++ b/drivers/net/phy/fixed_phy.c | ||||
| @@ -26,8 +26,6 @@ | ||||
|   | ||||
|  #include "swphy.h" | ||||
|   | ||||
| -#define MII_REGS_NUM 29 | ||||
| - | ||||
|  struct fixed_mdio_bus { | ||||
|  	int irqs[PHY_MAX_ADDR]; | ||||
|  	struct mii_bus *mii_bus; | ||||
| @@ -36,7 +34,6 @@ struct fixed_mdio_bus { | ||||
|   | ||||
|  struct fixed_phy { | ||||
|  	int addr; | ||||
| -	u16 regs[MII_REGS_NUM]; | ||||
|  	struct phy_device *phydev; | ||||
|  	struct fixed_phy_status status; | ||||
|  	int (*link_update)(struct net_device *, struct fixed_phy_status *); | ||||
| @@ -49,12 +46,10 @@ static struct fixed_mdio_bus platform_fm | ||||
|  	.phys = LIST_HEAD_INIT(platform_fmb.phys), | ||||
|  }; | ||||
|   | ||||
| -static void fixed_phy_update_regs(struct fixed_phy *fp) | ||||
| +static void fixed_phy_update(struct fixed_phy *fp) | ||||
|  { | ||||
|  	if (gpio_is_valid(fp->link_gpio)) | ||||
|  		fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); | ||||
| - | ||||
| -	swphy_update_regs(fp->regs, &fp->status); | ||||
|  } | ||||
|   | ||||
|  static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) | ||||
| @@ -62,29 +57,15 @@ static int fixed_mdio_read(struct mii_bu | ||||
|  	struct fixed_mdio_bus *fmb = bus->priv; | ||||
|  	struct fixed_phy *fp; | ||||
|   | ||||
| -	if (reg_num >= MII_REGS_NUM) | ||||
| -		return -1; | ||||
| - | ||||
| -	/* We do not support emulating Clause 45 over Clause 22 register reads | ||||
| -	 * return an error instead of bogus data. | ||||
| -	 */ | ||||
| -	switch (reg_num) { | ||||
| -	case MII_MMD_CTRL: | ||||
| -	case MII_MMD_DATA: | ||||
| -		return -1; | ||||
| -	default: | ||||
| -		break; | ||||
| -	} | ||||
| - | ||||
|  	list_for_each_entry(fp, &fmb->phys, node) { | ||||
|  		if (fp->addr == phy_addr) { | ||||
|  			/* Issue callback if user registered it. */ | ||||
|  			if (fp->link_update) { | ||||
|  				fp->link_update(fp->phydev->attached_dev, | ||||
|  						&fp->status); | ||||
| -				fixed_phy_update_regs(fp); | ||||
| +				fixed_phy_update(fp); | ||||
|  			} | ||||
| -			return fp->regs[reg_num]; | ||||
| +			return swphy_read_reg(reg_num, &fp->status); | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| @@ -144,7 +125,7 @@ int fixed_phy_update_state(struct phy_de | ||||
|  			_UPD(pause); | ||||
|  			_UPD(asym_pause); | ||||
|  #undef _UPD | ||||
| -			fixed_phy_update_regs(fp); | ||||
| +			fixed_phy_update(fp); | ||||
|  			return 0; | ||||
|  		} | ||||
|  	} | ||||
| @@ -169,8 +150,6 @@ int fixed_phy_add(unsigned int irq, int | ||||
|  	if (!fp) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| -	memset(fp->regs, 0xFF,  sizeof(fp->regs[0]) * MII_REGS_NUM); | ||||
| - | ||||
|  	fmb->irqs[phy_addr] = irq; | ||||
|   | ||||
|  	fp->addr = phy_addr; | ||||
| @@ -184,7 +163,7 @@ int fixed_phy_add(unsigned int irq, int | ||||
|  			goto err_regs; | ||||
|  	} | ||||
|   | ||||
| -	fixed_phy_update_regs(fp); | ||||
| +	fixed_phy_update(fp); | ||||
|   | ||||
|  	list_add_tail(&fp->node, &fmb->phys); | ||||
|   | ||||
| --- a/drivers/net/phy/swphy.c | ||||
| +++ b/drivers/net/phy/swphy.c | ||||
| @@ -20,6 +20,8 @@ | ||||
|   | ||||
|  #include "swphy.h" | ||||
|   | ||||
| +#define MII_REGS_NUM 29 | ||||
| + | ||||
|  struct swmii_regs { | ||||
|  	u16 bmcr; | ||||
|  	u16 bmsr; | ||||
| @@ -110,14 +112,13 @@ int swphy_validate_state(const struct fi | ||||
|  EXPORT_SYMBOL_GPL(swphy_validate_state); | ||||
|   | ||||
|  /** | ||||
| - * swphy_update_regs - update MII register array with fixed phy state | ||||
| - * @regs: array of 32 registers to update | ||||
| + * swphy_read_reg - return a MII register from the fixed phy state | ||||
| + * @reg: MII register | ||||
|   * @state: fixed phy status | ||||
|   * | ||||
| - * Update the array of MII registers with the fixed phy link, speed, | ||||
| - * duplex and pause mode settings. | ||||
| + * Return the MII @reg register generated from the fixed phy state @state. | ||||
|   */ | ||||
| -void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state) | ||||
| +int swphy_read_reg(int reg, const struct fixed_phy_status *state) | ||||
|  { | ||||
|  	int speed_index, duplex_index; | ||||
|  	u16 bmsr = BMSR_ANEGCAPABLE; | ||||
| @@ -125,9 +126,12 @@ void swphy_update_regs(u16 *regs, const | ||||
|  	u16 lpagb = 0; | ||||
|  	u16 lpa = 0; | ||||
|   | ||||
| +	if (reg > MII_REGS_NUM) | ||||
| +		return -1; | ||||
| + | ||||
|  	speed_index = swphy_decode_speed(state->speed); | ||||
|  	if (WARN_ON(speed_index < 0)) | ||||
| -		return; | ||||
| +		return 0; | ||||
|   | ||||
|  	duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF; | ||||
|   | ||||
| @@ -147,12 +151,29 @@ void swphy_update_regs(u16 *regs, const | ||||
|  			lpa |= LPA_PAUSE_ASYM; | ||||
|  	} | ||||
|   | ||||
| -	regs[MII_PHYSID1] = 0; | ||||
| -	regs[MII_PHYSID2] = 0; | ||||
| +	switch (reg) { | ||||
| +	case MII_BMCR: | ||||
| +		return bmcr; | ||||
| +	case MII_BMSR: | ||||
| +		return bmsr; | ||||
| +	case MII_PHYSID1: | ||||
| +	case MII_PHYSID2: | ||||
| +		return 0; | ||||
| +	case MII_LPA: | ||||
| +		return lpa; | ||||
| +	case MII_STAT1000: | ||||
| +		return lpagb; | ||||
| + | ||||
| +	/* | ||||
| +	 * We do not support emulating Clause 45 over Clause 22 register | ||||
| +	 * reads.  Return an error instead of bogus data. | ||||
| +	 */ | ||||
| +	case MII_MMD_CTRL: | ||||
| +	case MII_MMD_DATA: | ||||
| +		return -1; | ||||
|   | ||||
| -	regs[MII_BMSR] = bmsr; | ||||
| -	regs[MII_BMCR] = bmcr; | ||||
| -	regs[MII_LPA] = lpa; | ||||
| -	regs[MII_STAT1000] = lpagb; | ||||
| +	default: | ||||
| +		return 0xffff; | ||||
| +	} | ||||
|  } | ||||
| -EXPORT_SYMBOL_GPL(swphy_update_regs); | ||||
| +EXPORT_SYMBOL_GPL(swphy_read_reg); | ||||
| --- a/drivers/net/phy/swphy.h | ||||
| +++ b/drivers/net/phy/swphy.h | ||||
| @@ -4,6 +4,6 @@ | ||||
|  struct fixed_phy_status; | ||||
|   | ||||
|  int swphy_validate_state(const struct fixed_phy_status *state); | ||||
| -void swphy_update_regs(u16 *regs, const struct fixed_phy_status *state); | ||||
| +int swphy_read_reg(int reg, const struct fixed_phy_status *state); | ||||
|   | ||||
|  #endif | ||||
| @@ -1,92 +0,0 @@ | ||||
| From c36739c3cfd277a4cc9820a29dd0f4b7fbac795b Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 20 Sep 2015 18:31:36 +0100 | ||||
| Subject: [PATCH 713/744] phy: improve safety of fixed-phy MII register reading | ||||
|  | ||||
| There is no prevention of a concurrent call to both fixed_mdio_read() | ||||
| and fixed_phy_update_state(), which can result in the state being | ||||
| modified while it's being inspected.  Fix this by using a seqcount | ||||
| to detect modifications, and memcpy()ing the state. | ||||
|  | ||||
| We remain slightly naughty here, calling link_update() and updating | ||||
| the link status within the read-side loop - which would need rework | ||||
| of the design to change. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/fixed_phy.c | 28 +++++++++++++++++++++------- | ||||
|  1 file changed, 21 insertions(+), 7 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/fixed_phy.c | ||||
| +++ b/drivers/net/phy/fixed_phy.c | ||||
| @@ -23,6 +23,7 @@ | ||||
|  #include <linux/slab.h> | ||||
|  #include <linux/of.h> | ||||
|  #include <linux/gpio.h> | ||||
| +#include <linux/seqlock.h> | ||||
|   | ||||
|  #include "swphy.h" | ||||
|   | ||||
| @@ -35,6 +36,7 @@ struct fixed_mdio_bus { | ||||
|  struct fixed_phy { | ||||
|  	int addr; | ||||
|  	struct phy_device *phydev; | ||||
| +	seqcount_t seqcount; | ||||
|  	struct fixed_phy_status status; | ||||
|  	int (*link_update)(struct net_device *, struct fixed_phy_status *); | ||||
|  	struct list_head node; | ||||
| @@ -59,13 +61,21 @@ static int fixed_mdio_read(struct mii_bu | ||||
|   | ||||
|  	list_for_each_entry(fp, &fmb->phys, node) { | ||||
|  		if (fp->addr == phy_addr) { | ||||
| -			/* Issue callback if user registered it. */ | ||||
| -			if (fp->link_update) { | ||||
| -				fp->link_update(fp->phydev->attached_dev, | ||||
| -						&fp->status); | ||||
| -				fixed_phy_update(fp); | ||||
| -			} | ||||
| -			return swphy_read_reg(reg_num, &fp->status); | ||||
| +			struct fixed_phy_status state; | ||||
| +			int s; | ||||
| + | ||||
| +			do { | ||||
| +				s = read_seqcount_begin(&fp->seqcount); | ||||
| +				/* Issue callback if user registered it. */ | ||||
| +				if (fp->link_update) { | ||||
| +					fp->link_update(fp->phydev->attached_dev, | ||||
| +							&fp->status); | ||||
| +					fixed_phy_update(fp); | ||||
| +				} | ||||
| +				state = fp->status; | ||||
| +			} while (read_seqcount_retry(&fp->seqcount, s)); | ||||
| + | ||||
| +			return swphy_read_reg(reg_num, &state); | ||||
|  		} | ||||
|  	} | ||||
|   | ||||
| @@ -117,6 +127,7 @@ int fixed_phy_update_state(struct phy_de | ||||
|   | ||||
|  	list_for_each_entry(fp, &fmb->phys, node) { | ||||
|  		if (fp->addr == phydev->addr) { | ||||
| +			write_seqcount_begin(&fp->seqcount); | ||||
|  #define _UPD(x) if (changed->x) \ | ||||
|  	fp->status.x = status->x | ||||
|  			_UPD(link); | ||||
| @@ -126,6 +137,7 @@ int fixed_phy_update_state(struct phy_de | ||||
|  			_UPD(asym_pause); | ||||
|  #undef _UPD | ||||
|  			fixed_phy_update(fp); | ||||
| +			write_seqcount_end(&fp->seqcount); | ||||
|  			return 0; | ||||
|  		} | ||||
|  	} | ||||
| @@ -150,6 +162,8 @@ int fixed_phy_add(unsigned int irq, int | ||||
|  	if (!fp) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| +	seqcount_init(&fp->seqcount); | ||||
| + | ||||
|  	fmb->irqs[phy_addr] = irq; | ||||
|   | ||||
|  	fp->addr = phy_addr; | ||||
| @@ -1,183 +0,0 @@ | ||||
| From d8b4e728f598d3c8a9b219d4679d5de350caa082 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Fri, 18 Sep 2015 14:42:16 +0100 | ||||
| Subject: [PATCH 714/744] phy: provide a hook for link up/link down events | ||||
|  | ||||
| Sometimes, we need to do additional work between the PHY coming up and | ||||
| marking the carrier present - for example, we may need to wait for the | ||||
| PHY to MAC link to finish negotiation.  This changes phylib to provide | ||||
| a notification function pointer which avoids the built-in | ||||
| netif_carrier_on() and netif_carrier_off() functions. | ||||
|  | ||||
| Standard ->adjust_link functionality is provided by hooking a helper | ||||
| into the new ->phy_link_change method. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phy.c        | 42 ++++++++++++++++++++++-------------------- | ||||
|  drivers/net/phy/phy_device.c | 14 ++++++++++++++ | ||||
|  include/linux/phy.h          |  1 + | ||||
|  3 files changed, 37 insertions(+), 20 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/phy.c | ||||
| +++ b/drivers/net/phy/phy.c | ||||
| @@ -849,6 +849,16 @@ void phy_start(struct phy_device *phydev | ||||
|  } | ||||
|  EXPORT_SYMBOL(phy_start); | ||||
|   | ||||
| +static void phy_link_up(struct phy_device *phydev) | ||||
| +{ | ||||
| +	phydev->phy_link_change(phydev, true, true); | ||||
| +} | ||||
| + | ||||
| +static void phy_link_down(struct phy_device *phydev, bool do_carrier) | ||||
| +{ | ||||
| +	phydev->phy_link_change(phydev, false, do_carrier); | ||||
| +} | ||||
| + | ||||
|  /** | ||||
|   * phy_state_machine - Handle the state machine | ||||
|   * @work: work_struct that describes the work to be done | ||||
| @@ -890,8 +900,7 @@ void phy_state_machine(struct work_struc | ||||
|  		/* If the link is down, give up on negotiation for now */ | ||||
|  		if (!phydev->link) { | ||||
|  			phydev->state = PHY_NOLINK; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| -			phydev->adjust_link(phydev->attached_dev); | ||||
| +			phy_link_down(phydev, true); | ||||
|  			break; | ||||
|  		} | ||||
|   | ||||
| @@ -903,9 +912,7 @@ void phy_state_machine(struct work_struc | ||||
|  		/* If AN is done, we're running */ | ||||
|  		if (err > 0) { | ||||
|  			phydev->state = PHY_RUNNING; | ||||
| -			netif_carrier_on(phydev->attached_dev); | ||||
| -			phydev->adjust_link(phydev->attached_dev); | ||||
| - | ||||
| +			phy_link_up(phydev); | ||||
|  		} else if (0 == phydev->link_timeout--) | ||||
|  			needs_aneg = true; | ||||
|  		break; | ||||
| @@ -930,8 +937,7 @@ void phy_state_machine(struct work_struc | ||||
|  				} | ||||
|  			} | ||||
|  			phydev->state = PHY_RUNNING; | ||||
| -			netif_carrier_on(phydev->attached_dev); | ||||
| -			phydev->adjust_link(phydev->attached_dev); | ||||
| +			phy_link_up(phydev); | ||||
|  		} | ||||
|  		break; | ||||
|  	case PHY_FORCING: | ||||
| @@ -941,13 +947,12 @@ void phy_state_machine(struct work_struc | ||||
|   | ||||
|  		if (phydev->link) { | ||||
|  			phydev->state = PHY_RUNNING; | ||||
| -			netif_carrier_on(phydev->attached_dev); | ||||
| +			phy_link_up(phydev); | ||||
|  		} else { | ||||
|  			if (0 == phydev->link_timeout--) | ||||
|  				needs_aneg = true; | ||||
| +			phy_link_down(phydev, false); | ||||
|  		} | ||||
| - | ||||
| -		phydev->adjust_link(phydev->attached_dev); | ||||
|  		break; | ||||
|  	case PHY_RUNNING: | ||||
|  		/* Only register a CHANGE if we are polling or ignoring | ||||
| @@ -970,14 +975,12 @@ void phy_state_machine(struct work_struc | ||||
|   | ||||
|  		if (phydev->link) { | ||||
|  			phydev->state = PHY_RUNNING; | ||||
| -			netif_carrier_on(phydev->attached_dev); | ||||
| +			phy_link_up(phydev); | ||||
|  		} else { | ||||
|  			phydev->state = PHY_NOLINK; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| +			phy_link_down(phydev, true); | ||||
|  		} | ||||
|   | ||||
| -		phydev->adjust_link(phydev->attached_dev); | ||||
| - | ||||
|  		if (phy_interrupt_is_valid(phydev)) | ||||
|  			err = phy_config_interrupt(phydev, | ||||
|  						   PHY_INTERRUPT_ENABLED); | ||||
| @@ -985,8 +988,7 @@ void phy_state_machine(struct work_struc | ||||
|  	case PHY_HALTED: | ||||
|  		if (phydev->link) { | ||||
|  			phydev->link = 0; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| -			phydev->adjust_link(phydev->attached_dev); | ||||
| +			phy_link_down(phydev, true); | ||||
|  			do_suspend = true; | ||||
|  		} | ||||
|  		break; | ||||
| @@ -1006,11 +1008,11 @@ void phy_state_machine(struct work_struc | ||||
|   | ||||
|  				if (phydev->link) { | ||||
|  					phydev->state = PHY_RUNNING; | ||||
| -					netif_carrier_on(phydev->attached_dev); | ||||
| +					phy_link_up(phydev); | ||||
|  				} else	{ | ||||
|  					phydev->state = PHY_NOLINK; | ||||
| +					phy_link_down(phydev, false); | ||||
|  				} | ||||
| -				phydev->adjust_link(phydev->attached_dev); | ||||
|  			} else { | ||||
|  				phydev->state = PHY_AN; | ||||
|  				phydev->link_timeout = PHY_AN_TIMEOUT; | ||||
| @@ -1022,11 +1024,11 @@ void phy_state_machine(struct work_struc | ||||
|   | ||||
|  			if (phydev->link) { | ||||
|  				phydev->state = PHY_RUNNING; | ||||
| -				netif_carrier_on(phydev->attached_dev); | ||||
| +				phy_link_up(phydev); | ||||
|  			} else	{ | ||||
|  				phydev->state = PHY_NOLINK; | ||||
| +				phy_link_down(phydev, false); | ||||
|  			} | ||||
| -			phydev->adjust_link(phydev->attached_dev); | ||||
|  		} | ||||
|  		break; | ||||
|  	} | ||||
| --- a/drivers/net/phy/phy_device.c | ||||
| +++ b/drivers/net/phy/phy_device.c | ||||
| @@ -441,6 +441,19 @@ struct phy_device *phy_find_first(struct | ||||
|  } | ||||
|  EXPORT_SYMBOL(phy_find_first); | ||||
|   | ||||
| +static void phy_link_change(struct phy_device *phydev, bool up, bool do_carrier) | ||||
| +{ | ||||
| +	struct net_device *netdev = phydev->attached_dev; | ||||
| + | ||||
| +	if (do_carrier) { | ||||
| +		if (up) | ||||
| +			netif_carrier_on(netdev); | ||||
| +		else | ||||
| +			netif_carrier_off(netdev); | ||||
| +	} | ||||
| +	phydev->adjust_link(netdev); | ||||
| +} | ||||
| + | ||||
|  /** | ||||
|   * phy_prepare_link - prepares the PHY layer to monitor link status | ||||
|   * @phydev: target phy_device struct | ||||
| @@ -659,6 +672,7 @@ int phy_attach_direct(struct net_device | ||||
|  		goto error; | ||||
|  	} | ||||
|   | ||||
| +	phydev->phy_link_change = phy_link_change; | ||||
|  	phydev->attached_dev = dev; | ||||
|  	dev->phydev = phydev; | ||||
|   | ||||
| --- a/include/linux/phy.h | ||||
| +++ b/include/linux/phy.h | ||||
| @@ -433,6 +433,7 @@ struct phy_device { | ||||
|   | ||||
|  	u8 mdix; | ||||
|   | ||||
| +	void (*phy_link_change)(struct phy_device *, bool up, bool do_carrier); | ||||
|  	void (*adjust_link)(struct net_device *dev); | ||||
|  }; | ||||
|  #define to_phy_device(d) container_of(d, struct phy_device, dev) | ||||
| @@ -1,26 +0,0 @@ | ||||
| From 5eed0bf3bc3e69b20a13d8ffcdf97cb720391637 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 00:34:08 +0100 | ||||
| Subject: [PATCH 735/744] phy: marvell: 88E1512: add flow control support | ||||
|  | ||||
| The Marvell PHYs support pause frame advertisments, so we should not be | ||||
| masking their support off.  Add the necessary flag to the Marvell PHY | ||||
| to allow any MAC level pause frame support to be advertised. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/marvell.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/net/phy/marvell.c | ||||
| +++ b/drivers/net/phy/marvell.c | ||||
| @@ -1142,7 +1142,7 @@ static struct phy_driver marvell_drivers | ||||
|  		.phy_id = MARVELL_PHY_ID_88E1510, | ||||
|  		.phy_id_mask = MARVELL_PHY_ID_MASK, | ||||
|  		.name = "Marvell 88E1510", | ||||
| -		.features = PHY_GBIT_FEATURES, | ||||
| +		.features = PHY_GBIT_FEATURES | SUPPORTED_Pause, | ||||
|  		.flags = PHY_HAS_INTERRUPT, | ||||
|  		.config_aneg = &m88e1510_config_aneg, | ||||
|  		.read_status = &marvell_read_status, | ||||
| @@ -1,25 +0,0 @@ | ||||
| From f2a9687b39cda3fb67ecd5eaa88e3545e78c982c Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Fri, 16 Oct 2015 12:18:41 +0100 | ||||
| Subject: [PATCH 715/744] phy: export phy_start_machine() for phylink | ||||
|  | ||||
| phylink will need phy_start_machine exported, so lets export it as a | ||||
| GPL symbol.  Documentation/networking/phy.txt indicates that this | ||||
| should be a PHY API function. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phy.c | 1 + | ||||
|  1 file changed, 1 insertion(+) | ||||
|  | ||||
| --- a/drivers/net/phy/phy.c | ||||
| +++ b/drivers/net/phy/phy.c | ||||
| @@ -568,6 +568,7 @@ void phy_start_machine(struct phy_device | ||||
|  { | ||||
|  	queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ); | ||||
|  } | ||||
| +EXPORT_SYMBOL_GPL(phy_start_machine); | ||||
|   | ||||
|  /** | ||||
|   * phy_stop_machine - stop the PHY state machine tracking | ||||
| @@ -1,44 +0,0 @@ | ||||
| From 5c77cc2ffd5deb4762d9551409472f2441297fe7 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 18 Oct 2015 19:51:10 +0100 | ||||
| Subject: [PATCH 716/744] phy: export phy_speed_to_str() for phylink | ||||
|  | ||||
| phylink would like to reuse phy_speed_to_str() to convert the speed | ||||
| to a string.  Add a prototype and export this helper function. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phy.c | 3 ++- | ||||
|  include/linux/phy.h   | 1 + | ||||
|  2 files changed, 3 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/net/phy/phy.c | ||||
| +++ b/drivers/net/phy/phy.c | ||||
| @@ -38,7 +38,7 @@ | ||||
|   | ||||
|  #include <asm/irq.h> | ||||
|   | ||||
| -static const char *phy_speed_to_str(int speed) | ||||
| +const char *phy_speed_to_str(int speed) | ||||
|  { | ||||
|  	switch (speed) { | ||||
|  	case SPEED_10: | ||||
| @@ -57,6 +57,7 @@ static const char *phy_speed_to_str(int | ||||
|  		return "Unsupported (update phy.c)"; | ||||
|  	} | ||||
|  } | ||||
| +EXPORT_SYMBOL_GPL(phy_speed_to_str); | ||||
|   | ||||
|  #define PHY_STATE_STR(_state)			\ | ||||
|  	case PHY_##_state:			\ | ||||
| --- a/include/linux/phy.h | ||||
| +++ b/include/linux/phy.h | ||||
| @@ -812,6 +812,7 @@ int phy_ethtool_gset(struct phy_device * | ||||
|  int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr); | ||||
|  int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd); | ||||
|  int phy_start_interrupts(struct phy_device *phydev); | ||||
| +const char *phy_speed_to_str(int speed); | ||||
|  void phy_print_status(struct phy_device *phydev); | ||||
|  void phy_device_free(struct phy_device *phydev); | ||||
|  int phy_set_max_speed(struct phy_device *phydev, u32 max_speed); | ||||
| @@ -1,163 +0,0 @@ | ||||
| From 7f36ac946bfbd4090b8b94be3661b41ac73e21f4 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Fri, 25 Sep 2015 17:43:52 +0100 | ||||
| Subject: [PATCH 717/744] phy: add I2C mdio bus | ||||
|  | ||||
| Add an I2C MDIO bus bridge library, to allow phylib to access PHYs which | ||||
| are connected to an I2C bus instead of the more conventional MDIO bus. | ||||
| Such PHYs can be found in SFP adapters and SFF modules. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/Kconfig    | 10 ++++++ | ||||
|  drivers/net/phy/Makefile   |  1 + | ||||
|  drivers/net/phy/mdio-i2c.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/net/phy/mdio-i2c.h | 19 ++++++++++ | ||||
|  4 files changed, 120 insertions(+) | ||||
|  create mode 100644 drivers/net/phy/mdio-i2c.c | ||||
|  create mode 100644 drivers/net/phy/mdio-i2c.h | ||||
|  | ||||
| --- a/drivers/net/phy/Kconfig | ||||
| +++ b/drivers/net/phy/Kconfig | ||||
| @@ -233,6 +233,16 @@ config MDIO_GPIO | ||||
|  	  To compile this driver as a module, choose M here: the module | ||||
|  	  will be called mdio-gpio. | ||||
|   | ||||
| +config MDIO_I2C | ||||
| +	tristate | ||||
| +	depends on I2C | ||||
| +	help | ||||
| +	  Support I2C based PHYs.  This provides a MDIO bus bridged | ||||
| +	  to I2C to allow PHYs connected in I2C mode to be accessed | ||||
| +	  using the existing infrastructure. | ||||
| + | ||||
| +	  This is library mode. | ||||
| + | ||||
|  config MDIO_OCTEON | ||||
|  	tristate "Support for MDIO buses on Octeon and ThunderX SOCs" | ||||
|  	depends on 64BIT | ||||
| --- a/drivers/net/phy/Makefile | ||||
| +++ b/drivers/net/phy/Makefile | ||||
| @@ -41,6 +41,7 @@ obj-$(CONFIG_SWCONFIG_B53)	+= b53/ | ||||
|  obj-$(CONFIG_FIXED_PHY)		+= fixed_phy.o | ||||
|  obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o | ||||
|  obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o | ||||
| +obj-$(CONFIG_MDIO_I2C)		+= mdio-i2c.o | ||||
|  obj-$(CONFIG_NATIONAL_PHY)	+= national.o | ||||
|  obj-$(CONFIG_DP83640_PHY)	+= dp83640.o | ||||
|  obj-$(CONFIG_DP83848_PHY)	+= dp83848.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/net/phy/mdio-i2c.c | ||||
| @@ -0,0 +1,90 @@ | ||||
| +/* | ||||
| + * MDIO I2C bridge | ||||
| + * | ||||
| + * Copyright (C) 2015 Russell King | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + */ | ||||
| +#include <linux/i2c.h> | ||||
| +#include <linux/phy.h> | ||||
| + | ||||
| +#include "mdio-i2c.h" | ||||
| + | ||||
| +static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg) | ||||
| +{ | ||||
| +	struct i2c_adapter *i2c = bus->priv; | ||||
| +	struct i2c_msg msgs[2]; | ||||
| +	u8 data[2], dev_addr = reg; | ||||
| +	int bus_addr, ret; | ||||
| + | ||||
| +	bus_addr = 0x40 + phy_id; | ||||
| +	if (bus_addr == 0x50 || bus_addr == 0x51) | ||||
| +		return 0xffff; | ||||
| + | ||||
| +	msgs[0].addr = bus_addr; | ||||
| +	msgs[0].flags = 0; | ||||
| +	msgs[0].len = 1; | ||||
| +	msgs[0].buf = &dev_addr; | ||||
| +	msgs[1].addr = bus_addr; | ||||
| +	msgs[1].flags = I2C_M_RD; | ||||
| +	msgs[1].len = sizeof(data); | ||||
| +	msgs[1].buf = data; | ||||
| + | ||||
| +	ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs)); | ||||
| +	if (ret != ARRAY_SIZE(msgs)) | ||||
| +		return 0xffff; | ||||
| + | ||||
| +	return data[0] << 8 | data[1]; | ||||
| +} | ||||
| + | ||||
| +static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val) | ||||
| +{ | ||||
| +	struct i2c_adapter *i2c = bus->priv; | ||||
| +	struct i2c_msg msg; | ||||
| +	int bus_addr, ret; | ||||
| +	u8 data[3]; | ||||
| + | ||||
| +	bus_addr = 0x40 + phy_id; | ||||
| +	if (bus_addr == 0x50 || bus_addr == 0x51) | ||||
| +		return 0; | ||||
| + | ||||
| +	data[0] = reg; | ||||
| +	data[1] = val >> 8; | ||||
| +	data[2] = val; | ||||
| + | ||||
| +	msg.addr = bus_addr; | ||||
| +	msg.flags = 0; | ||||
| +	msg.len = 3; | ||||
| +	msg.buf = data; | ||||
| + | ||||
| +	ret = i2c_transfer(i2c, &msg, 1); | ||||
| + | ||||
| +	return ret < 0 ? ret : 0; | ||||
| +} | ||||
| + | ||||
| +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c) | ||||
| +{ | ||||
| +	struct mii_bus *mii; | ||||
| + | ||||
| +	if (!i2c_check_functionality(i2c, I2C_FUNC_I2C)) | ||||
| +		return ERR_PTR(-EINVAL); | ||||
| + | ||||
| +	mii = mdiobus_alloc(); | ||||
| +	if (!mii) | ||||
| +		return ERR_PTR(-ENOMEM); | ||||
| + | ||||
| +	snprintf(mii->id, MII_BUS_ID_SIZE, "i2c:%s", dev_name(parent)); | ||||
| +	mii->parent = parent; | ||||
| +	mii->read = i2c_mii_read; | ||||
| +	mii->write = i2c_mii_write; | ||||
| +	mii->priv = i2c; | ||||
| + | ||||
| +	return mii; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(mdio_i2c_alloc); | ||||
| + | ||||
| +MODULE_AUTHOR("Russell King"); | ||||
| +MODULE_DESCRIPTION("MDIO I2C bridge library"); | ||||
| +MODULE_LICENSE("GPL v2"); | ||||
| --- /dev/null | ||||
| +++ b/drivers/net/phy/mdio-i2c.h | ||||
| @@ -0,0 +1,19 @@ | ||||
| +/* | ||||
| + * MDIO I2C bridge | ||||
| + * | ||||
| + * Copyright (C) 2015 Russell King | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + */ | ||||
| +#ifndef MDIO_I2C_H | ||||
| +#define MDIO_I2C_H | ||||
| + | ||||
| +struct device; | ||||
| +struct i2c_adapter; | ||||
| +struct mii_bus; | ||||
| + | ||||
| +struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c); | ||||
| + | ||||
| +#endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,156 +0,0 @@ | ||||
| From 0a0c4b3dd4f34df4532f254a5940b520015d766f Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 24 Sep 2015 11:01:13 +0100 | ||||
| Subject: [PATCH 719/744] phylink: add hooks for SFP support | ||||
|  | ||||
| Add support to phylink for SFP, which needs to control and configure | ||||
| the ethernet MAC link state.  Specifically, SFP needs to: | ||||
|  | ||||
| 1. set the negotiation mode between SGMII and 1000base-X | ||||
| 2. attach and detach the module PHY | ||||
| 3. prevent the link coming up when errors are reported | ||||
|  | ||||
| In the absence of a PHY, we also need to set the ethtool port type | ||||
| according to the module plugged in. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phylink.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  include/linux/phylink.h   |  6 ++++ | ||||
|  2 files changed, 88 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/phy/phylink.c | ||||
| +++ b/drivers/net/phy/phylink.c | ||||
| @@ -11,6 +11,7 @@ | ||||
|  #include <linux/ethtool.h> | ||||
|  #include <linux/export.h> | ||||
|  #include <linux/gpio/consumer.h> | ||||
| +#include <linux/list.h> | ||||
|  #include <linux/netdevice.h> | ||||
|  #include <linux/of.h> | ||||
|  #include <linux/of_mdio.h> | ||||
| @@ -29,11 +30,16 @@ | ||||
|  	(ADVERTISED_TP | ADVERTISED_MII | ADVERTISED_FIBRE | \ | ||||
|  	 ADVERTISED_BNC | ADVERTISED_AUI | ADVERTISED_Backplane) | ||||
|   | ||||
| +static LIST_HEAD(phylinks); | ||||
| +static DEFINE_MUTEX(phylink_mutex); | ||||
| + | ||||
|  enum { | ||||
|  	PHYLINK_DISABLE_STOPPED, | ||||
| +	PHYLINK_DISABLE_LINK, | ||||
|  }; | ||||
|   | ||||
|  struct phylink { | ||||
| +	struct list_head node; | ||||
|  	struct net_device *netdev; | ||||
|  	const struct phylink_mac_ops *ops; | ||||
|  	struct mutex config_mutex; | ||||
| @@ -341,12 +347,20 @@ struct phylink *phylink_create(struct ne | ||||
|  		return ERR_PTR(ret); | ||||
|  	} | ||||
|   | ||||
| +	mutex_lock(&phylink_mutex); | ||||
| +	list_add_tail(&pl->node, &phylinks); | ||||
| +	mutex_unlock(&phylink_mutex); | ||||
| + | ||||
|  	return pl; | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_create); | ||||
|   | ||||
|  void phylink_destroy(struct phylink *pl) | ||||
|  { | ||||
| +	mutex_lock(&phylink_mutex); | ||||
| +	list_del(&pl->node); | ||||
| +	mutex_unlock(&phylink_mutex); | ||||
| + | ||||
|  	cancel_work_sync(&pl->resolve); | ||||
|  	kfree(pl); | ||||
|  } | ||||
| @@ -813,4 +827,72 @@ int phylink_mii_ioctl(struct phylink *pl | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_mii_ioctl); | ||||
|   | ||||
| + | ||||
| + | ||||
| +void phylink_disable(struct phylink *pl) | ||||
| +{ | ||||
| +	set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); | ||||
| +	flush_work(&pl->resolve); | ||||
| + | ||||
| +	netif_carrier_off(pl->netdev); | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_disable); | ||||
| + | ||||
| +void phylink_enable(struct phylink *pl) | ||||
| +{ | ||||
| +	clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); | ||||
| +	phylink_run_resolve(pl); | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_enable); | ||||
| + | ||||
| +void phylink_set_link_port(struct phylink *pl, u32 support, u8 port) | ||||
| +{ | ||||
| +	WARN_ON(support & ~SUPPORTED_INTERFACES); | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	pl->link_port_support = support; | ||||
| +	pl->link_port = port; | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_set_link_port); | ||||
| + | ||||
| +int phylink_set_link_an_mode(struct phylink *pl, unsigned int mode) | ||||
| +{ | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->link_an_mode != mode) { | ||||
| +		ret = phylink_get_support(pl, mode); | ||||
| +		if (ret == 0) { | ||||
| +			if (!test_bit(PHYLINK_DISABLE_STOPPED, | ||||
| +				      &pl->phylink_disable_state)) | ||||
| +				phylink_mac_config(pl, &pl->link_config); | ||||
| + | ||||
| +			netdev_info(pl->netdev, "switched to %s link mode\n", | ||||
| +				    phylink_an_mode_str(mode)); | ||||
| +		} | ||||
| +	} | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_set_link_an_mode); | ||||
| + | ||||
| +struct phylink *phylink_lookup_by_netdev(struct net_device *ndev) | ||||
| +{ | ||||
| +	struct phylink *pl, *found = NULL; | ||||
| + | ||||
| +	mutex_lock(&phylink_mutex); | ||||
| +	list_for_each_entry(pl, &phylinks, node) | ||||
| +		if (pl->netdev == ndev) { | ||||
| +			found = pl; | ||||
| +			break; | ||||
| +		} | ||||
| + | ||||
| +	mutex_unlock(&phylink_mutex); | ||||
| + | ||||
| +	return found; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_lookup_by_netdev); | ||||
| + | ||||
|  MODULE_LICENSE("GPL"); | ||||
| --- a/include/linux/phylink.h | ||||
| +++ b/include/linux/phylink.h | ||||
| @@ -67,4 +67,10 @@ int phylink_ethtool_get_settings(struct | ||||
|  int phylink_ethtool_set_settings(struct phylink *, struct ethtool_cmd *); | ||||
|  int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); | ||||
|   | ||||
| +void phylink_set_link_port(struct phylink *pl, u32 support, u8 port); | ||||
| +int phylink_set_link_an_mode(struct phylink *pl, unsigned int mode); | ||||
| +void phylink_disable(struct phylink *pl); | ||||
| +void phylink_enable(struct phylink *pl); | ||||
| +struct phylink *phylink_lookup_by_netdev(struct net_device *ndev); | ||||
| + | ||||
|  #endif | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,283 +0,0 @@ | ||||
| From 66c248886538d7ee97ef2fe498061f857d4c906a Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sun, 13 Sep 2015 01:06:31 +0100 | ||||
| Subject: [PATCH 721/744] sfp: display SFP module information | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/sfp.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++- | ||||
|  1 file changed, 246 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/net/phy/sfp.c | ||||
| +++ b/drivers/net/phy/sfp.c | ||||
| @@ -248,6 +248,182 @@ static unsigned int sfp_check(void *buf, | ||||
|  	return check; | ||||
|  } | ||||
|   | ||||
| +static const char *sfp_link_len(char *buf, size_t size, unsigned int length, | ||||
| +	unsigned int multiplier) | ||||
| +{ | ||||
| +	if (length == 0) | ||||
| +		return "unsupported/unspecified"; | ||||
| + | ||||
| +	if (length == 255) { | ||||
| +		*buf++ = '>'; | ||||
| +		size -= 1; | ||||
| +		length -= 1; | ||||
| +	} | ||||
| + | ||||
| +	length *= multiplier; | ||||
| + | ||||
| +	if (length >= 1000) | ||||
| +		snprintf(buf, size, "%u.%0*ukm", | ||||
| +			length / 1000, | ||||
| +			multiplier > 100 ? 1 : | ||||
| +			multiplier > 10 ? 2 : 3, | ||||
| +			length % 1000); | ||||
| +	else | ||||
| +		snprintf(buf, size, "%um", length); | ||||
| + | ||||
| +	return buf; | ||||
| +} | ||||
| + | ||||
| +struct bitfield { | ||||
| +	unsigned int mask; | ||||
| +	unsigned int val; | ||||
| +	const char *str; | ||||
| +}; | ||||
| + | ||||
| +static const struct bitfield sfp_options[] = { | ||||
| +	{ | ||||
| +		.mask = SFP_OPTIONS_HIGH_POWER_LEVEL, | ||||
| +		.val = SFP_OPTIONS_HIGH_POWER_LEVEL, | ||||
| +		.str = "hpl", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_PAGING_A2, | ||||
| +		.val = SFP_OPTIONS_PAGING_A2, | ||||
| +		.str = "paginga2", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_RETIMER, | ||||
| +		.val = SFP_OPTIONS_RETIMER, | ||||
| +		.str = "retimer", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_COOLED_XCVR, | ||||
| +		.val = SFP_OPTIONS_COOLED_XCVR, | ||||
| +		.str = "cooled", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_POWER_DECL, | ||||
| +		.val = SFP_OPTIONS_POWER_DECL, | ||||
| +		.str = "powerdecl", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_RX_LINEAR_OUT, | ||||
| +		.val = SFP_OPTIONS_RX_LINEAR_OUT, | ||||
| +		.str = "rxlinear", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_RX_DECISION_THRESH, | ||||
| +		.val = SFP_OPTIONS_RX_DECISION_THRESH, | ||||
| +		.str = "rxthresh", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_TUNABLE_TX, | ||||
| +		.val = SFP_OPTIONS_TUNABLE_TX, | ||||
| +		.str = "tunabletx", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_RATE_SELECT, | ||||
| +		.val = SFP_OPTIONS_RATE_SELECT, | ||||
| +		.str = "ratesel", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_TX_DISABLE, | ||||
| +		.val = SFP_OPTIONS_TX_DISABLE, | ||||
| +		.str = "txdisable", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_TX_FAULT, | ||||
| +		.val = SFP_OPTIONS_TX_FAULT, | ||||
| +		.str = "txfault", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_LOS_INVERTED, | ||||
| +		.val = SFP_OPTIONS_LOS_INVERTED, | ||||
| +		.str = "los-", | ||||
| +	}, { | ||||
| +		.mask = SFP_OPTIONS_LOS_NORMAL, | ||||
| +		.val = SFP_OPTIONS_LOS_NORMAL, | ||||
| +		.str = "los+", | ||||
| +	}, { } | ||||
| +}; | ||||
| + | ||||
| +static const struct bitfield diagmon[] = { | ||||
| +	{ | ||||
| +		.mask = SFP_DIAGMON_DDM, | ||||
| +		.val = SFP_DIAGMON_DDM, | ||||
| +		.str = "ddm", | ||||
| +	}, { | ||||
| +		.mask = SFP_DIAGMON_INT_CAL, | ||||
| +		.val = SFP_DIAGMON_INT_CAL, | ||||
| +		.str = "intcal", | ||||
| +	}, { | ||||
| +		.mask = SFP_DIAGMON_EXT_CAL, | ||||
| +		.val = SFP_DIAGMON_EXT_CAL, | ||||
| +		.str = "extcal", | ||||
| +	}, { | ||||
| +		.mask = SFP_DIAGMON_RXPWR_AVG, | ||||
| +		.val = SFP_DIAGMON_RXPWR_AVG, | ||||
| +		.str = "rxpwravg", | ||||
| +	}, { } | ||||
| +}; | ||||
| + | ||||
| +static const char *sfp_bitfield(char *out, size_t outsz, const struct bitfield *bits, unsigned int val) | ||||
| +{ | ||||
| +	char *p = out; | ||||
| +	int n; | ||||
| + | ||||
| +	*p = '\0'; | ||||
| +	while (bits->mask) { | ||||
| +		if ((val & bits->mask) == bits->val) { | ||||
| +			n = snprintf(p, outsz, "%s%s", | ||||
| +				     out != p ? ", " : "", | ||||
| +				     bits->str); | ||||
| +			if (n == outsz) | ||||
| +				break; | ||||
| +			p += n; | ||||
| +			outsz -= n; | ||||
| +		} | ||||
| +		bits++; | ||||
| +	} | ||||
| + | ||||
| +	return out; | ||||
| +} | ||||
| + | ||||
| +static const char *sfp_connector(unsigned int connector) | ||||
| +{ | ||||
| +	switch (connector) { | ||||
| +	case SFP_CONNECTOR_UNSPEC: | ||||
| +		return "unknown/unspecified"; | ||||
| +	case SFP_CONNECTOR_SC: | ||||
| +		return "SC"; | ||||
| +	case SFP_CONNECTOR_FIBERJACK: | ||||
| +		return "Fiberjack"; | ||||
| +	case SFP_CONNECTOR_LC: | ||||
| +		return "LC"; | ||||
| +	case SFP_CONNECTOR_MT_RJ: | ||||
| +		return "MT-RJ"; | ||||
| +	case SFP_CONNECTOR_MU: | ||||
| +		return "MU"; | ||||
| +	case SFP_CONNECTOR_SG: | ||||
| +		return "SG"; | ||||
| +	case SFP_CONNECTOR_OPTICAL_PIGTAIL: | ||||
| +		return "Optical pigtail"; | ||||
| +	case SFP_CONNECTOR_HSSDC_II: | ||||
| +		return "HSSDC II"; | ||||
| +	case SFP_CONNECTOR_COPPER_PIGTAIL: | ||||
| +		return "Copper pigtail"; | ||||
| +	default: | ||||
| +		return "unknown"; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static const char *sfp_encoding(unsigned int encoding) | ||||
| +{ | ||||
| +	switch (encoding) { | ||||
| +	case SFP_ENCODING_UNSPEC: | ||||
| +		return "unspecified"; | ||||
| +	case SFP_ENCODING_8B10B: | ||||
| +		return "8b10b"; | ||||
| +	case SFP_ENCODING_4B5B: | ||||
| +		return "4b5b"; | ||||
| +	case SFP_ENCODING_NRZ: | ||||
| +		return "NRZ"; | ||||
| +	case SFP_ENCODING_MANCHESTER: | ||||
| +		return "MANCHESTER"; | ||||
| +	default: | ||||
| +		return "unknown"; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
|  /* Helpers */ | ||||
|  static void sfp_module_tx_disable(struct sfp *sfp) | ||||
|  { | ||||
| @@ -426,6 +602,7 @@ static int sfp_sm_mod_probe(struct sfp * | ||||
|  	char sn[17]; | ||||
|  	char date[9]; | ||||
|  	char rev[5]; | ||||
| +	char options[80]; | ||||
|  	u8 check; | ||||
|  	int err; | ||||
|   | ||||
| @@ -462,10 +639,78 @@ static int sfp_sm_mod_probe(struct sfp * | ||||
|  	rev[4] = '\0'; | ||||
|  	memcpy(sn, sfp->id.ext.vendor_sn, 16); | ||||
|  	sn[16] = '\0'; | ||||
| -	memcpy(date, sfp->id.ext.datecode, 8); | ||||
| +	date[0] = sfp->id.ext.datecode[4]; | ||||
| +	date[1] = sfp->id.ext.datecode[5]; | ||||
| +	date[2] = '-'; | ||||
| +	date[3] = sfp->id.ext.datecode[2]; | ||||
| +	date[4] = sfp->id.ext.datecode[3]; | ||||
| +	date[5] = '-'; | ||||
| +	date[6] = sfp->id.ext.datecode[0]; | ||||
| +	date[7] = sfp->id.ext.datecode[1]; | ||||
|  	date[8] = '\0'; | ||||
|   | ||||
|  	dev_info(sfp->dev, "module %s %s rev %s sn %s dc %s\n", vendor, part, rev, sn, date); | ||||
| +	dev_info(sfp->dev, "  %s connector, encoding %s, nominal bitrate %u.%uGbps +%u%% -%u%%\n", | ||||
| +		 sfp_connector(sfp->id.base.connector), | ||||
| +		 sfp_encoding(sfp->id.base.encoding), | ||||
| +		 sfp->id.base.br_nominal / 10, | ||||
| +		 sfp->id.base.br_nominal % 10, | ||||
| +		 sfp->id.ext.br_max, sfp->id.ext.br_min); | ||||
| +	dev_info(sfp->dev, "  1000BaseSX%c 1000BaseLX%c 1000BaseCX%c 1000BaseT%c 100BaseTLX%c 1000BaseFX%c BaseBX10%c BasePX%c\n", | ||||
| +		 sfp->id.base.e1000_base_sx ? '+' : '-', | ||||
| +		 sfp->id.base.e1000_base_lx ? '+' : '-', | ||||
| +		 sfp->id.base.e1000_base_cx ? '+' : '-', | ||||
| +		 sfp->id.base.e1000_base_t ? '+' : '-', | ||||
| +		 sfp->id.base.e100_base_lx ? '+' : '-', | ||||
| +		 sfp->id.base.e100_base_fx ? '+' : '-', | ||||
| +		 sfp->id.base.e_base_bx10 ? '+' : '-', | ||||
| +		 sfp->id.base.e_base_px ? '+' : '-'); | ||||
| + | ||||
| +	if (!sfp->id.base.sfp_ct_passive && !sfp->id.base.sfp_ct_active && | ||||
| +	    !sfp->id.base.e1000_base_t) { | ||||
| +		char len_9um[16], len_om[16]; | ||||
| + | ||||
| +		dev_info(sfp->dev, "  Wavelength %unm, fiber lengths:\n", | ||||
| +			 be16_to_cpup(&sfp->id.base.optical_wavelength)); | ||||
| + | ||||
| +		if (sfp->id.base.link_len[0] == 255) | ||||
| +			strcpy(len_9um, ">254km"); | ||||
| +		else if (sfp->id.base.link_len[1] && sfp->id.base.link_len[1] != 255) | ||||
| +			sprintf(len_9um, "%um", | ||||
| +				sfp->id.base.link_len[1] * 100); | ||||
| +		else if (sfp->id.base.link_len[0]) | ||||
| +			sprintf(len_9um, "%ukm", sfp->id.base.link_len[0]); | ||||
| +		else if (sfp->id.base.link_len[1] == 255) | ||||
| +			strcpy(len_9um, ">25.4km"); | ||||
| +		else | ||||
| +			strcpy(len_9um, "unsupported"); | ||||
| + | ||||
| +		dev_info(sfp->dev, "    9µm SM    : %s\n", len_9um); | ||||
| +		dev_info(sfp->dev, " 62.5µm MM OM1: %s\n", | ||||
| +			 sfp_link_len(len_om, sizeof(len_om), | ||||
| +				      sfp->id.base.link_len[3], 10)); | ||||
| +		dev_info(sfp->dev, "   50µm MM OM2: %s\n", | ||||
| +			 sfp_link_len(len_om, sizeof(len_om), | ||||
| +				      sfp->id.base.link_len[2], 10)); | ||||
| +		dev_info(sfp->dev, "   50µm MM OM3: %s\n", | ||||
| +			 sfp_link_len(len_om, sizeof(len_om), | ||||
| +				      sfp->id.base.link_len[5], 10)); | ||||
| +		dev_info(sfp->dev, "   50µm MM OM4: %s\n", | ||||
| +			 sfp_link_len(len_om, sizeof(len_om), | ||||
| +				      sfp->id.base.link_len[4], 10)); | ||||
| +	} else { | ||||
| +		char len[16]; | ||||
| +		dev_info(sfp->dev, "  Copper length: %s\n", | ||||
| +			 sfp_link_len(len, sizeof(len), | ||||
| +				      sfp->id.base.link_len[4], 1)); | ||||
| +	} | ||||
| + | ||||
| +	dev_info(sfp->dev, "  Options: %s\n", | ||||
| +		 sfp_bitfield(options, sizeof(options), sfp_options, | ||||
| +			      be16_to_cpu(sfp->id.ext.options))); | ||||
| +	dev_info(sfp->dev, "  Diagnostics: %s\n", | ||||
| +		 sfp_bitfield(options, sizeof(options), diagmon, | ||||
| +			      sfp->id.ext.diagmon)); | ||||
|   | ||||
|  	/* We only support SFP modules, not the legacy GBIC modules. */ | ||||
|  	if (sfp->id.base.phys_id != SFP_PHYS_ID_SFP || | ||||
| @@ -1,697 +0,0 @@ | ||||
| From e268be0ddc666f4a98db462cbed2a97637e82b5c Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Wed, 16 Sep 2015 21:27:10 +0100 | ||||
| Subject: [PATCH 722/744] net: mvneta: convert to phylink | ||||
|  | ||||
| Convert mvneta to use phylink, which models the MAC to PHY link in | ||||
| a generic, reusable form. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/Kconfig  |   2 +- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 451 +++++++++++++++++----------------- | ||||
|  2 files changed, 227 insertions(+), 226 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/Kconfig | ||||
| +++ b/drivers/net/ethernet/marvell/Kconfig | ||||
| @@ -58,7 +58,7 @@ config MVNETA | ||||
|  	tristate "Marvell Armada 370/38x/XP network interface support" | ||||
|  	depends on PLAT_ORION | ||||
|  	select MVMDIO | ||||
| -	select FIXED_PHY | ||||
| +	select PHYLINK | ||||
|  	---help--- | ||||
|  	  This driver supports the network interface units in the | ||||
|  	  Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family. | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -28,6 +28,7 @@ | ||||
|  #include <linux/of_mdio.h> | ||||
|  #include <linux/of_net.h> | ||||
|  #include <linux/phy.h> | ||||
| +#include <linux/phylink.h> | ||||
|  #include <linux/platform_device.h> | ||||
|  #include <linux/skbuff.h> | ||||
|  #include <net/hwbm.h> | ||||
| @@ -188,6 +189,7 @@ | ||||
|  #define MVNETA_GMAC_CTRL_0                       0x2c00 | ||||
|  #define      MVNETA_GMAC_MAX_RX_SIZE_SHIFT       2 | ||||
|  #define      MVNETA_GMAC_MAX_RX_SIZE_MASK        0x7ffc | ||||
| +#define      MVNETA_GMAC0_PORT_1000BASE_X        BIT(1) | ||||
|  #define      MVNETA_GMAC0_PORT_ENABLE            BIT(0) | ||||
|  #define MVNETA_GMAC_CTRL_2                       0x2c08 | ||||
|  #define      MVNETA_GMAC2_INBAND_AN_ENABLE       BIT(0) | ||||
| @@ -203,13 +205,19 @@ | ||||
|  #define      MVNETA_GMAC_TX_FLOW_CTRL_ENABLE     BIT(5) | ||||
|  #define      MVNETA_GMAC_RX_FLOW_CTRL_ACTIVE     BIT(6) | ||||
|  #define      MVNETA_GMAC_TX_FLOW_CTRL_ACTIVE     BIT(7) | ||||
| +#define      MVNETA_GMAC_AN_COMPLETE             BIT(11) | ||||
| +#define      MVNETA_GMAC_SYNC_OK                 BIT(14) | ||||
|  #define MVNETA_GMAC_AUTONEG_CONFIG               0x2c0c | ||||
|  #define      MVNETA_GMAC_FORCE_LINK_DOWN         BIT(0) | ||||
|  #define      MVNETA_GMAC_FORCE_LINK_PASS         BIT(1) | ||||
|  #define      MVNETA_GMAC_INBAND_AN_ENABLE        BIT(2) | ||||
| +#define      MVNETA_GMAC_AN_BYPASS_ENABLE        BIT(3) | ||||
| +#define      MVNETA_GMAC_INBAND_RESTART_AN       BIT(4) | ||||
|  #define      MVNETA_GMAC_CONFIG_MII_SPEED        BIT(5) | ||||
|  #define      MVNETA_GMAC_CONFIG_GMII_SPEED       BIT(6) | ||||
|  #define      MVNETA_GMAC_AN_SPEED_EN             BIT(7) | ||||
| +#define      MVNETA_GMAC_CONFIG_FLOW_CTRL        BIT(8) | ||||
| +#define      MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL    BIT(9) | ||||
|  #define      MVNETA_GMAC_AN_FLOW_CTRL_EN         BIT(11) | ||||
|  #define      MVNETA_GMAC_CONFIG_FULL_DUPLEX      BIT(12) | ||||
|  #define      MVNETA_GMAC_AN_DUPLEX_EN            BIT(13) | ||||
| @@ -396,15 +404,9 @@ struct mvneta_port { | ||||
|  	u16 tx_ring_size; | ||||
|  	u16 rx_ring_size; | ||||
|   | ||||
| -	struct mii_bus *mii_bus; | ||||
| -	struct phy_device *phy_dev; | ||||
| -	phy_interface_t phy_interface; | ||||
| -	struct device_node *phy_node; | ||||
| -	unsigned int link; | ||||
| -	unsigned int duplex; | ||||
| -	unsigned int speed; | ||||
| +	struct device_node *dn; | ||||
|  	unsigned int tx_csum_limit; | ||||
| -	unsigned int use_inband_status:1; | ||||
| +	struct phylink *phylink; | ||||
|   | ||||
|  	struct mvneta_bm *bm_priv; | ||||
|  	struct mvneta_bm_pool *pool_long; | ||||
| @@ -1236,44 +1238,6 @@ static void mvneta_set_other_mcast_table | ||||
|  		mvreg_write(pp, MVNETA_DA_FILT_OTH_MCAST + offset, val); | ||||
|  } | ||||
|   | ||||
| -static void mvneta_set_autoneg(struct mvneta_port *pp, int enable) | ||||
| -{ | ||||
| -	u32 val; | ||||
| - | ||||
| -	if (enable) { | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -		val &= ~(MVNETA_GMAC_FORCE_LINK_PASS | | ||||
| -			 MVNETA_GMAC_FORCE_LINK_DOWN | | ||||
| -			 MVNETA_GMAC_AN_FLOW_CTRL_EN); | ||||
| -		val |= MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| -		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| -		       MVNETA_GMAC_AN_DUPLEX_EN; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| -		val |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| -		val |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| -	} else { | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -		val &= ~(MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| -		       MVNETA_GMAC_AN_SPEED_EN | | ||||
| -		       MVNETA_GMAC_AN_DUPLEX_EN); | ||||
| -		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| -		val &= ~MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, val); | ||||
| - | ||||
| -		val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| -		val &= ~MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| -		mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); | ||||
| -	} | ||||
| -} | ||||
| - | ||||
|  static void mvneta_percpu_unmask_interrupt(void *arg) | ||||
|  { | ||||
|  	struct mvneta_port *pp = arg; | ||||
| @@ -1421,7 +1385,6 @@ static void mvneta_defaults_set(struct m | ||||
|  	val &= ~MVNETA_PHY_POLLING_ENABLE; | ||||
|  	mvreg_write(pp, MVNETA_UNIT_CONTROL, val); | ||||
|   | ||||
| -	mvneta_set_autoneg(pp, pp->use_inband_status); | ||||
|  	mvneta_set_ucast_table(pp, -1); | ||||
|  	mvneta_set_special_mcast_table(pp, -1); | ||||
|  	mvneta_set_other_mcast_table(pp, -1); | ||||
| @@ -2614,26 +2577,11 @@ static irqreturn_t mvneta_isr(int irq, v | ||||
|  	return IRQ_HANDLED; | ||||
|  } | ||||
|   | ||||
| -static int mvneta_fixed_link_update(struct mvneta_port *pp, | ||||
| -				    struct phy_device *phy) | ||||
| +static void mvneta_link_change(struct mvneta_port *pp) | ||||
|  { | ||||
| -	struct fixed_phy_status status; | ||||
| -	struct fixed_phy_status changed = {}; | ||||
|  	u32 gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); | ||||
|   | ||||
| -	status.link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); | ||||
| -	if (gmac_stat & MVNETA_GMAC_SPEED_1000) | ||||
| -		status.speed = SPEED_1000; | ||||
| -	else if (gmac_stat & MVNETA_GMAC_SPEED_100) | ||||
| -		status.speed = SPEED_100; | ||||
| -	else | ||||
| -		status.speed = SPEED_10; | ||||
| -	status.duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); | ||||
| -	changed.link = 1; | ||||
| -	changed.speed = 1; | ||||
| -	changed.duplex = 1; | ||||
| -	fixed_phy_update_state(phy, &status, &changed); | ||||
| -	return 0; | ||||
| +	phylink_mac_change(pp->phylink, !!(gmac_stat & MVNETA_GMAC_LINK_UP)); | ||||
|  } | ||||
|   | ||||
|  /* NAPI handler | ||||
| @@ -2662,12 +2610,11 @@ static int mvneta_poll(struct napi_struc | ||||
|  		u32 cause_misc = mvreg_read(pp, MVNETA_INTR_MISC_CAUSE); | ||||
|   | ||||
|  		mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0); | ||||
| -		if (pp->use_inband_status && (cause_misc & | ||||
| -				(MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
| -				 MVNETA_CAUSE_LINK_CHANGE | | ||||
| -				 MVNETA_CAUSE_PSC_SYNC_CHANGE))) { | ||||
| -			mvneta_fixed_link_update(pp, pp->phy_dev); | ||||
| -		} | ||||
| + | ||||
| +		if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE | | ||||
| +				  MVNETA_CAUSE_LINK_CHANGE | | ||||
| +				  MVNETA_CAUSE_PSC_SYNC_CHANGE)) | ||||
| +			mvneta_link_change(pp); | ||||
|  	} | ||||
|   | ||||
|  	/* Release Tx descriptors */ | ||||
| @@ -2983,7 +2930,7 @@ static void mvneta_start_dev(struct mvne | ||||
|  		    MVNETA_CAUSE_LINK_CHANGE | | ||||
|  		    MVNETA_CAUSE_PSC_SYNC_CHANGE); | ||||
|   | ||||
| -	phy_start(pp->phy_dev); | ||||
| +	phylink_start(pp->phylink); | ||||
|  	netif_tx_start_all_queues(pp->dev); | ||||
|  } | ||||
|   | ||||
| @@ -2991,7 +2938,7 @@ static void mvneta_stop_dev(struct mvnet | ||||
|  { | ||||
|  	unsigned int cpu; | ||||
|   | ||||
| -	phy_stop(pp->phy_dev); | ||||
| +	phylink_stop(pp->phylink); | ||||
|   | ||||
|  	for_each_online_cpu(cpu) { | ||||
|  		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); | ||||
| @@ -3161,99 +3108,219 @@ static int mvneta_set_mac_addr(struct ne | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| -static void mvneta_adjust_link(struct net_device *ndev) | ||||
| +static int mvneta_mac_support(struct net_device *ndev, unsigned int mode, | ||||
| +			      struct phylink_link_state *state) | ||||
| +{ | ||||
| +	switch (mode) { | ||||
| +	case MLO_AN_8023Z: | ||||
| +		state->supported = SUPPORTED_1000baseT_Full | | ||||
| +				   SUPPORTED_Autoneg | SUPPORTED_Pause; | ||||
| +		state->advertising = ADVERTISED_1000baseT_Full | | ||||
| +				     ADVERTISED_Autoneg | ADVERTISED_Pause; | ||||
| +		state->an_enabled = 1; | ||||
| +		break; | ||||
| + | ||||
| +	case MLO_AN_FIXED: | ||||
| +		break; | ||||
| + | ||||
| +	default: | ||||
| +		state->supported = PHY_10BT_FEATURES | | ||||
| +				   PHY_100BT_FEATURES | | ||||
| +				   SUPPORTED_1000baseT_Full | | ||||
| +				   SUPPORTED_Autoneg; | ||||
| +		state->advertising = ADVERTISED_10baseT_Half | | ||||
| +				     ADVERTISED_10baseT_Full | | ||||
| +				     ADVERTISED_100baseT_Half | | ||||
| +				     ADVERTISED_100baseT_Full | | ||||
| +				     ADVERTISED_1000baseT_Full | | ||||
| +				     ADVERTISED_Autoneg; | ||||
| +		state->an_enabled = 1; | ||||
| +		break; | ||||
| +	} | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mvneta_mac_link_state(struct net_device *ndev, | ||||
| +				 struct phylink_link_state *state) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| -	struct phy_device *phydev = pp->phy_dev; | ||||
| -	int status_change = 0; | ||||
| +	u32 gmac_stat; | ||||
|   | ||||
| -	if (phydev->link) { | ||||
| -		if ((pp->speed != phydev->speed) || | ||||
| -		    (pp->duplex != phydev->duplex)) { | ||||
| -			u32 val; | ||||
| - | ||||
| -			val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -			val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | | ||||
| -				 MVNETA_GMAC_CONFIG_GMII_SPEED | | ||||
| -				 MVNETA_GMAC_CONFIG_FULL_DUPLEX); | ||||
| - | ||||
| -			if (phydev->duplex) | ||||
| -				val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
| - | ||||
| -			if (phydev->speed == SPEED_1000) | ||||
| -				val |= MVNETA_GMAC_CONFIG_GMII_SPEED; | ||||
| -			else if (phydev->speed == SPEED_100) | ||||
| -				val |= MVNETA_GMAC_CONFIG_MII_SPEED; | ||||
| +	gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS); | ||||
|   | ||||
| -			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| +	if (gmac_stat & MVNETA_GMAC_SPEED_1000) | ||||
| +		state->speed = SPEED_1000; | ||||
| +	else if (gmac_stat & MVNETA_GMAC_SPEED_100) | ||||
| +		state->speed = SPEED_100; | ||||
| +	else | ||||
| +		state->speed = SPEED_10; | ||||
|   | ||||
| -			pp->duplex = phydev->duplex; | ||||
| -			pp->speed  = phydev->speed; | ||||
| -		} | ||||
| +	state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE); | ||||
| +	state->sync = !!(gmac_stat & MVNETA_GMAC_SYNC_OK); | ||||
| +	state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP); | ||||
| +	state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX); | ||||
| + | ||||
| +	state->pause = 0; | ||||
| +	if (gmac_stat & MVNETA_GMAC_RX_FLOW_CTRL_ENABLE) | ||||
| +		state->pause |= MLO_PAUSE_RX; | ||||
| +	if (gmac_stat & MVNETA_GMAC_TX_FLOW_CTRL_ENABLE) | ||||
| +		state->pause |= MLO_PAUSE_TX; | ||||
| + | ||||
| +	return 1; | ||||
| +} | ||||
| + | ||||
| +static void mvneta_mac_an_restart(struct net_device *ndev, unsigned int mode) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| + | ||||
| +	if (mode == MLO_AN_8023Z) { | ||||
| +		u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| + | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, | ||||
| +			    gmac_an | MVNETA_GMAC_INBAND_RESTART_AN); | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, | ||||
| +			    gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN); | ||||
|  	} | ||||
| +} | ||||
|   | ||||
| -	if (phydev->link != pp->link) { | ||||
| -		if (!phydev->link) { | ||||
| -			pp->duplex = -1; | ||||
| -			pp->speed = 0; | ||||
| -		} | ||||
| +static void mvneta_mac_config(struct net_device *ndev, unsigned int mode, | ||||
| +	const struct phylink_link_state *state) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| +	u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0); | ||||
| +	u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2); | ||||
| +	u32 new_clk, gmac_clk = mvreg_read(pp, MVNETA_GMAC_CLOCK_DIVIDER); | ||||
| +	u32 new_an, gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| + | ||||
| +	new_ctrl0 = gmac_ctrl0 & ~MVNETA_GMAC0_PORT_1000BASE_X; | ||||
| +	new_ctrl2 = gmac_ctrl2 & ~MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +	new_clk = gmac_clk & ~MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +	new_an = gmac_an & ~(MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| +			     MVNETA_GMAC_INBAND_RESTART_AN | | ||||
| +			     MVNETA_GMAC_CONFIG_MII_SPEED | | ||||
| +			     MVNETA_GMAC_CONFIG_GMII_SPEED | | ||||
| +			     MVNETA_GMAC_AN_SPEED_EN | | ||||
| +			     MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL | | ||||
| +			     MVNETA_GMAC_CONFIG_FLOW_CTRL | | ||||
| +			     MVNETA_GMAC_AN_FLOW_CTRL_EN | | ||||
| +			     MVNETA_GMAC_CONFIG_FULL_DUPLEX | | ||||
| +			     MVNETA_GMAC_AN_DUPLEX_EN); | ||||
| + | ||||
| +	if (state->advertising & ADVERTISED_Pause) | ||||
| +		new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; | ||||
| + | ||||
| +	switch (mode) { | ||||
| +	case MLO_AN_SGMII: | ||||
| +		/* SGMII mode receives the state from the PHY */ | ||||
| +		new_ctrl2 |= MVNETA_GMAC2_INBAND_AN_ENABLE; | ||||
| +		new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +		new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | | ||||
| +				     MVNETA_GMAC_FORCE_LINK_PASS)) | | ||||
| +			 MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| +			 MVNETA_GMAC_AN_SPEED_EN | | ||||
| +			 MVNETA_GMAC_AN_DUPLEX_EN; | ||||
| +		break; | ||||
| + | ||||
| +	case MLO_AN_8023Z: | ||||
| +		/* 802.3z negotiation - only 1000base-X */ | ||||
| +		new_ctrl0 |= MVNETA_GMAC0_PORT_1000BASE_X; | ||||
| +		new_clk |= MVNETA_GMAC_1MS_CLOCK_ENABLE; | ||||
| +		new_an = (new_an & ~(MVNETA_GMAC_FORCE_LINK_DOWN | | ||||
| +				     MVNETA_GMAC_FORCE_LINK_PASS)) | | ||||
| +			 MVNETA_GMAC_INBAND_AN_ENABLE | | ||||
| +			 MVNETA_GMAC_CONFIG_GMII_SPEED | | ||||
| +			 /* The MAC only supports FD mode */ | ||||
| +			 MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
| + | ||||
| +		if (state->an_enabled) | ||||
| +			new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; | ||||
| +		break; | ||||
|   | ||||
| -		pp->link = phydev->link; | ||||
| -		status_change = 1; | ||||
| +	default: | ||||
| +		/* Phy or fixed speed */ | ||||
| +		if (state->duplex) | ||||
| +			new_an |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
| + | ||||
| +		if (state->speed == SPEED_1000) | ||||
| +			new_an |= MVNETA_GMAC_CONFIG_GMII_SPEED; | ||||
| +		else if (state->speed == SPEED_100) | ||||
| +			new_an |= MVNETA_GMAC_CONFIG_MII_SPEED; | ||||
| +		break; | ||||
|  	} | ||||
|   | ||||
| -	if (status_change) { | ||||
| -		if (phydev->link) { | ||||
| -			if (!pp->use_inband_status) { | ||||
| -				u32 val = mvreg_read(pp, | ||||
| -						  MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -				val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; | ||||
| -				val |= MVNETA_GMAC_FORCE_LINK_PASS; | ||||
| -				mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, | ||||
| -					    val); | ||||
| -			} | ||||
| -			mvneta_port_up(pp); | ||||
| -		} else { | ||||
| -			if (!pp->use_inband_status) { | ||||
| -				u32 val = mvreg_read(pp, | ||||
| -						  MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -				val &= ~MVNETA_GMAC_FORCE_LINK_PASS; | ||||
| -				val |= MVNETA_GMAC_FORCE_LINK_DOWN; | ||||
| -				mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, | ||||
| -					    val); | ||||
| -			} | ||||
| -			mvneta_port_down(pp); | ||||
| -		} | ||||
| -		phy_print_status(phydev); | ||||
| +	/* Armada 370 documentation says we can only change the port mode | ||||
| +	 * and in-band enable when the link is down, so force it down | ||||
| +	 * while making these changes. We also do this for GMAC_CTRL2 */ | ||||
| +	if ((new_ctrl0 ^ gmac_ctrl0) & MVNETA_GMAC0_PORT_1000BASE_X || | ||||
| +	    (new_ctrl2 ^ gmac_ctrl2) & MVNETA_GMAC2_INBAND_AN_ENABLE || | ||||
| +	    (new_an  ^ gmac_an) & MVNETA_GMAC_INBAND_AN_ENABLE) { | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, | ||||
| +			    (gmac_an & ~MVNETA_GMAC_FORCE_LINK_PASS) | | ||||
| +			    MVNETA_GMAC_FORCE_LINK_DOWN); | ||||
| +	} | ||||
| + | ||||
| +	if (new_ctrl0 != gmac_ctrl0) | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_0, new_ctrl0); | ||||
| +	if (new_ctrl2 != gmac_ctrl2) | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CTRL_2, new_ctrl2); | ||||
| +	if (new_clk != gmac_clk) | ||||
| +		mvreg_write(pp, MVNETA_GMAC_CLOCK_DIVIDER, new_clk); | ||||
| +	if (new_an != gmac_an) | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); | ||||
| +} | ||||
| + | ||||
| +static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| +	u32 val; | ||||
| + | ||||
| +	mvneta_port_down(pp); | ||||
| + | ||||
| +	if (mode == MLO_AN_PHY || mode == MLO_AN_FIXED) { | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| +		val &= ~MVNETA_GMAC_FORCE_LINK_PASS; | ||||
| +		val |= MVNETA_GMAC_FORCE_LINK_DOWN; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| -static int mvneta_mdio_probe(struct mvneta_port *pp) | ||||
| +static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode, | ||||
| +			       struct phy_device *phy) | ||||
|  { | ||||
| -	struct phy_device *phy_dev; | ||||
| +	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| +	u32 val; | ||||
| + | ||||
| +	if (mode == MLO_AN_PHY || mode == MLO_AN_FIXED) { | ||||
| +		val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| +		val &= ~MVNETA_GMAC_FORCE_LINK_DOWN; | ||||
| +		val |= MVNETA_GMAC_FORCE_LINK_PASS; | ||||
| +		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| +	} | ||||
|   | ||||
| -	phy_dev = of_phy_connect(pp->dev, pp->phy_node, mvneta_adjust_link, 0, | ||||
| -				 pp->phy_interface); | ||||
| -	if (!phy_dev) { | ||||
| -		netdev_err(pp->dev, "could not find the PHY\n"); | ||||
| -		return -ENODEV; | ||||
| -	} | ||||
| - | ||||
| -	phy_dev->supported &= PHY_GBIT_FEATURES; | ||||
| -	phy_dev->advertising = phy_dev->supported; | ||||
| - | ||||
| -	pp->phy_dev = phy_dev; | ||||
| -	pp->link    = 0; | ||||
| -	pp->duplex  = 0; | ||||
| -	pp->speed   = 0; | ||||
| +	mvneta_port_up(pp); | ||||
| +} | ||||
|   | ||||
| -	return 0; | ||||
| +static const struct phylink_mac_ops mvneta_phylink_ops = { | ||||
| +	.mac_get_support = mvneta_mac_support, | ||||
| +	.mac_link_state = mvneta_mac_link_state, | ||||
| +	.mac_an_restart = mvneta_mac_an_restart, | ||||
| +	.mac_config = mvneta_mac_config, | ||||
| +	.mac_link_down = mvneta_mac_link_down, | ||||
| +	.mac_link_up = mvneta_mac_link_up, | ||||
| +}; | ||||
| + | ||||
| +static int mvneta_mdio_probe(struct mvneta_port *pp) | ||||
| +{ | ||||
| +	int err = phylink_of_phy_connect(pp->phylink, pp->dn); | ||||
| +	if (err) | ||||
| +		netdev_err(pp->dev, "could not attach PHY\n"); | ||||
| + | ||||
| +	return err; | ||||
|  } | ||||
|   | ||||
|  static void mvneta_mdio_remove(struct mvneta_port *pp) | ||||
|  { | ||||
| -	phy_disconnect(pp->phy_dev); | ||||
| -	pp->phy_dev = NULL; | ||||
| +	phylink_disconnect_phy(pp->phylink); | ||||
|  } | ||||
|   | ||||
|  /* Electing a CPU must be done in an atomic way: it should be done | ||||
| @@ -3501,10 +3568,7 @@ static int mvneta_ioctl(struct net_devic | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
|   | ||||
| -	if (!pp->phy_dev) | ||||
| -		return -ENOTSUPP; | ||||
| - | ||||
| -	return phy_mii_ioctl(pp->phy_dev, ifr, cmd); | ||||
| +	return phylink_mii_ioctl(pp->phylink, ifr, cmd); | ||||
|  } | ||||
|   | ||||
|  /* Ethtool methods */ | ||||
| @@ -3514,54 +3578,15 @@ int mvneta_ethtool_get_settings(struct n | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
|   | ||||
| -	if (!pp->phy_dev) | ||||
| -		return -ENODEV; | ||||
| - | ||||
| -	return phy_ethtool_gset(pp->phy_dev, cmd); | ||||
| +	return phylink_ethtool_get_settings(pp->phylink, cmd); | ||||
|  } | ||||
|   | ||||
|  /* Set settings (phy address, speed) for ethtools */ | ||||
|  int mvneta_ethtool_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(dev); | ||||
| -	struct phy_device *phydev = pp->phy_dev; | ||||
| - | ||||
| -	if (!phydev) | ||||
| -		return -ENODEV; | ||||
|   | ||||
| -	if ((cmd->autoneg == AUTONEG_ENABLE) != pp->use_inband_status) { | ||||
| -		u32 val; | ||||
| - | ||||
| -		mvneta_set_autoneg(pp, cmd->autoneg == AUTONEG_ENABLE); | ||||
| - | ||||
| -		if (cmd->autoneg == AUTONEG_DISABLE) { | ||||
| -			val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); | ||||
| -			val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | | ||||
| -				 MVNETA_GMAC_CONFIG_GMII_SPEED | | ||||
| -				 MVNETA_GMAC_CONFIG_FULL_DUPLEX); | ||||
| - | ||||
| -			if (phydev->duplex) | ||||
| -				val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
| - | ||||
| -			if (phydev->speed == SPEED_1000) | ||||
| -				val |= MVNETA_GMAC_CONFIG_GMII_SPEED; | ||||
| -			else if (phydev->speed == SPEED_100) | ||||
| -				val |= MVNETA_GMAC_CONFIG_MII_SPEED; | ||||
| - | ||||
| -			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
| -		} | ||||
| - | ||||
| -		pp->use_inband_status = (cmd->autoneg == AUTONEG_ENABLE); | ||||
| -		netdev_info(pp->dev, "autoneg status set to %i\n", | ||||
| -			    pp->use_inband_status); | ||||
| - | ||||
| -		if (netif_running(dev)) { | ||||
| -			mvneta_port_down(pp); | ||||
| -			mvneta_port_up(pp); | ||||
| -		} | ||||
| -	} | ||||
| - | ||||
| -	return phy_ethtool_sset(pp->phy_dev, cmd); | ||||
| +	return phylink_ethtool_set_settings(pp->phylink, cmd); | ||||
|  } | ||||
|   | ||||
|  /* Set interrupt coalescing for ethtools */ | ||||
| @@ -3669,7 +3694,8 @@ static void mvneta_ethtool_update_stats( | ||||
|  { | ||||
|  	const struct mvneta_statistic *s; | ||||
|  	void __iomem *base = pp->base; | ||||
| -	u32 high, low, val; | ||||
| +	u32 high, low; | ||||
| +	u64 val; | ||||
|  	u64 val64; | ||||
|  	int i; | ||||
|   | ||||
| @@ -3964,14 +3990,13 @@ static int mvneta_probe(struct platform_ | ||||
|  	const struct mbus_dram_target_info *dram_target_info; | ||||
|  	struct resource *res; | ||||
|  	struct device_node *dn = pdev->dev.of_node; | ||||
| -	struct device_node *phy_node; | ||||
|  	struct device_node *bm_node; | ||||
|  	struct mvneta_port *pp; | ||||
|  	struct net_device *dev; | ||||
| +	struct phylink *phylink; | ||||
|  	const char *dt_mac_addr; | ||||
|  	char hw_mac_addr[ETH_ALEN]; | ||||
|  	const char *mac_from; | ||||
| -	const char *managed; | ||||
|  	int tx_csum_limit; | ||||
|  	int phy_mode; | ||||
|  	int err; | ||||
| @@ -3987,31 +4012,11 @@ static int mvneta_probe(struct platform_ | ||||
|  		goto err_free_netdev; | ||||
|  	} | ||||
|   | ||||
| -	phy_node = of_parse_phandle(dn, "phy", 0); | ||||
| -	if (!phy_node) { | ||||
| -		if (!of_phy_is_fixed_link(dn)) { | ||||
| -			dev_err(&pdev->dev, "no PHY specified\n"); | ||||
| -			err = -ENODEV; | ||||
| -			goto err_free_irq; | ||||
| -		} | ||||
| - | ||||
| -		err = of_phy_register_fixed_link(dn); | ||||
| -		if (err < 0) { | ||||
| -			dev_err(&pdev->dev, "cannot register fixed PHY\n"); | ||||
| -			goto err_free_irq; | ||||
| -		} | ||||
| - | ||||
| -		/* In the case of a fixed PHY, the DT node associated | ||||
| -		 * to the PHY is the Ethernet MAC DT node. | ||||
| -		 */ | ||||
| -		phy_node = of_node_get(dn); | ||||
| -	} | ||||
| - | ||||
|  	phy_mode = of_get_phy_mode(dn); | ||||
|  	if (phy_mode < 0) { | ||||
|  		dev_err(&pdev->dev, "incorrect phy-mode\n"); | ||||
|  		err = -EINVAL; | ||||
| -		goto err_put_phy_node; | ||||
| +		goto err_free_irq; | ||||
|  	} | ||||
|   | ||||
|  	dev->tx_queue_len = MVNETA_MAX_TXD; | ||||
| @@ -4022,12 +4027,7 @@ static int mvneta_probe(struct platform_ | ||||
|   | ||||
|  	pp = netdev_priv(dev); | ||||
|  	spin_lock_init(&pp->lock); | ||||
| -	pp->phy_node = phy_node; | ||||
| -	pp->phy_interface = phy_mode; | ||||
| - | ||||
| -	err = of_property_read_string(dn, "managed", &managed); | ||||
| -	pp->use_inband_status = (err == 0 && | ||||
| -				 strcmp(managed, "in-band-status") == 0); | ||||
| +	pp->dn = dn; | ||||
|  	pp->cpu_notifier.notifier_call = mvneta_percpu_notifier; | ||||
|   | ||||
|  	pp->rxq_def = rxq_def; | ||||
| @@ -4037,7 +4037,7 @@ static int mvneta_probe(struct platform_ | ||||
|  	pp->clk = devm_clk_get(&pdev->dev, NULL); | ||||
|  	if (IS_ERR(pp->clk)) { | ||||
|  		err = PTR_ERR(pp->clk); | ||||
| -		goto err_put_phy_node; | ||||
| +		goto err_free_irq; | ||||
|  	} | ||||
|   | ||||
|  	clk_prepare_enable(pp->clk); | ||||
| @@ -4140,6 +4140,14 @@ static int mvneta_probe(struct platform_ | ||||
|  	dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; | ||||
|  	dev->gso_max_segs = MVNETA_MAX_TSO_SEGS; | ||||
|   | ||||
| +	phylink = phylink_create(dev, dn, phy_mode, &mvneta_phylink_ops); | ||||
| +	if (IS_ERR(phylink)) { | ||||
| +		err = PTR_ERR(phylink); | ||||
| +		goto err_free_stats; | ||||
| +	} | ||||
| + | ||||
| +	pp->phylink = phylink; | ||||
| + | ||||
|  	err = register_netdev(dev); | ||||
|  	if (err < 0) { | ||||
|  		dev_err(&pdev->dev, "failed to register\n"); | ||||
| @@ -4151,13 +4159,6 @@ static int mvneta_probe(struct platform_ | ||||
|   | ||||
|  	platform_set_drvdata(pdev, pp->dev); | ||||
|   | ||||
| -	if (pp->use_inband_status) { | ||||
| -		struct phy_device *phy = of_phy_find_device(dn); | ||||
| - | ||||
| -		mvneta_fixed_link_update(pp, phy); | ||||
| - | ||||
| -		put_device(&phy->dev); | ||||
| -	} | ||||
|   | ||||
|  	return 0; | ||||
|   | ||||
| @@ -4169,13 +4170,13 @@ err_netdev: | ||||
|  				       1 << pp->id); | ||||
|  	} | ||||
|  err_free_stats: | ||||
| +	if (pp->phylink) | ||||
| +		phylink_destroy(pp->phylink); | ||||
|  	free_percpu(pp->stats); | ||||
|  err_free_ports: | ||||
|  	free_percpu(pp->ports); | ||||
|  err_clk: | ||||
|  	clk_disable_unprepare(pp->clk); | ||||
| -err_put_phy_node: | ||||
| -	of_node_put(phy_node); | ||||
|  err_free_irq: | ||||
|  	irq_dispose_mapping(dev->irq); | ||||
|  err_free_netdev: | ||||
| @@ -4194,7 +4195,7 @@ static int mvneta_remove(struct platform | ||||
|  	free_percpu(pp->ports); | ||||
|  	free_percpu(pp->stats); | ||||
|  	irq_dispose_mapping(dev->irq); | ||||
| -	of_node_put(pp->phy_node); | ||||
| +	phylink_destroy(pp->phylink); | ||||
|  	free_netdev(dev); | ||||
|   | ||||
|  	if (pp->bm_priv) { | ||||
| @@ -1,80 +0,0 @@ | ||||
| From 9be436bdb67c1f4aa9f33f2477f94e1f58a0ff02 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Fri, 2 Oct 2015 22:46:54 +0100 | ||||
| Subject: [PATCH 723/744] phy: fixed-phy: remove fixed_phy_update_state() | ||||
|  | ||||
| mvneta is the only user of fixed_phy_update_state(), which has been | ||||
| converted to use phylink instead.  Remove fixed_phy_update_state(). | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/fixed_phy.c | 31 ------------------------------- | ||||
|  include/linux/phy_fixed.h   |  9 --------- | ||||
|  2 files changed, 40 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/fixed_phy.c | ||||
| +++ b/drivers/net/phy/fixed_phy.c | ||||
| @@ -115,37 +115,6 @@ int fixed_phy_set_link_update(struct phy | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(fixed_phy_set_link_update); | ||||
|   | ||||
| -int fixed_phy_update_state(struct phy_device *phydev, | ||||
| -			   const struct fixed_phy_status *status, | ||||
| -			   const struct fixed_phy_status *changed) | ||||
| -{ | ||||
| -	struct fixed_mdio_bus *fmb = &platform_fmb; | ||||
| -	struct fixed_phy *fp; | ||||
| - | ||||
| -	if (!phydev || phydev->bus != fmb->mii_bus) | ||||
| -		return -EINVAL; | ||||
| - | ||||
| -	list_for_each_entry(fp, &fmb->phys, node) { | ||||
| -		if (fp->addr == phydev->addr) { | ||||
| -			write_seqcount_begin(&fp->seqcount); | ||||
| -#define _UPD(x) if (changed->x) \ | ||||
| -	fp->status.x = status->x | ||||
| -			_UPD(link); | ||||
| -			_UPD(speed); | ||||
| -			_UPD(duplex); | ||||
| -			_UPD(pause); | ||||
| -			_UPD(asym_pause); | ||||
| -#undef _UPD | ||||
| -			fixed_phy_update(fp); | ||||
| -			write_seqcount_end(&fp->seqcount); | ||||
| -			return 0; | ||||
| -		} | ||||
| -	} | ||||
| - | ||||
| -	return -ENOENT; | ||||
| -} | ||||
| -EXPORT_SYMBOL(fixed_phy_update_state); | ||||
| - | ||||
|  int fixed_phy_add(unsigned int irq, int phy_addr, | ||||
|  		  struct fixed_phy_status *status, | ||||
|  		  int link_gpio) | ||||
| --- a/include/linux/phy_fixed.h | ||||
| +++ b/include/linux/phy_fixed.h | ||||
| @@ -23,9 +23,6 @@ extern void fixed_phy_del(int phy_addr); | ||||
|  extern int fixed_phy_set_link_update(struct phy_device *phydev, | ||||
|  			int (*link_update)(struct net_device *, | ||||
|  					   struct fixed_phy_status *)); | ||||
| -extern int fixed_phy_update_state(struct phy_device *phydev, | ||||
| -			   const struct fixed_phy_status *status, | ||||
| -			   const struct fixed_phy_status *changed); | ||||
|  #else | ||||
|  static inline int fixed_phy_add(unsigned int irq, int phy_id, | ||||
|  				struct fixed_phy_status *status, | ||||
| @@ -50,12 +47,6 @@ static inline int fixed_phy_set_link_upd | ||||
|  { | ||||
|  	return -ENODEV; | ||||
|  } | ||||
| -static inline int fixed_phy_update_state(struct phy_device *phydev, | ||||
| -			   const struct fixed_phy_status *status, | ||||
| -			   const struct fixed_phy_status *changed) | ||||
| -{ | ||||
| -	return -ENODEV; | ||||
| -} | ||||
|  #endif /* CONFIG_FIXED_PHY */ | ||||
|   | ||||
|  #endif /* __PHY_FIXED_H */ | ||||
| @@ -1,48 +0,0 @@ | ||||
| From d6bd25b692378ec17bdb1023d398c03c45829947 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 20:27:19 +0100 | ||||
| Subject: [PATCH 724/744] phylink: add ethtool nway_reset support | ||||
|  | ||||
| Add ethtool nway_reset support to phylink, to allow userspace to | ||||
| request a re-negotiation of the link. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phylink.c | 14 ++++++++++++++ | ||||
|  include/linux/phylink.h   |  1 + | ||||
|  2 files changed, 15 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/phy/phylink.c | ||||
| +++ b/drivers/net/phy/phylink.c | ||||
| @@ -687,6 +687,20 @@ int phylink_ethtool_set_settings(struct | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_ethtool_set_settings); | ||||
|   | ||||
| +int phylink_ethtool_nway_reset(struct phylink *pl) | ||||
| +{ | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->phydev) | ||||
| +		ret = genphy_restart_aneg(pl->phydev); | ||||
| +	phylink_mac_an_restart(pl); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_nway_reset); | ||||
| + | ||||
|  /* This emulates MII registers for a fixed-mode phy operating as per the | ||||
|   * passed in state. "aneg" defines if we report negotiation is possible. | ||||
|   * | ||||
| --- a/include/linux/phylink.h | ||||
| +++ b/include/linux/phylink.h | ||||
| @@ -65,6 +65,7 @@ void phylink_stop(struct phylink *); | ||||
|   | ||||
|  int phylink_ethtool_get_settings(struct phylink *, struct ethtool_cmd *); | ||||
|  int phylink_ethtool_set_settings(struct phylink *, struct ethtool_cmd *); | ||||
| +int phylink_ethtool_nway_reset(struct phylink *); | ||||
|  int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); | ||||
|   | ||||
|  void phylink_set_link_port(struct phylink *pl, u32 support, u8 port); | ||||
| @@ -1,38 +0,0 @@ | ||||
| From 244bee2889d08f876c64c335765a8ea6de0f5381 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 19:40:31 +0100 | ||||
| Subject: [PATCH 725/744] net: mvneta: add nway_reset support | ||||
|  | ||||
| Add ethtool nway_reset support to mvneta via phylink, so that userspace | ||||
| can request the link in whatever mode to be renegotiated via | ||||
| ethtool -r ethX. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 8 ++++++++ | ||||
|  1 file changed, 8 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3589,6 +3589,13 @@ int mvneta_ethtool_set_settings(struct n | ||||
|  	return phylink_ethtool_set_settings(pp->phylink, cmd); | ||||
|  } | ||||
|   | ||||
| +static int mvneta_ethtool_nway_reset(struct net_device *dev) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	return phylink_ethtool_nway_reset(pp->phylink); | ||||
| +} | ||||
| + | ||||
|  /* Set interrupt coalescing for ethtools */ | ||||
|  static int mvneta_ethtool_set_coalesce(struct net_device *dev, | ||||
|  				       struct ethtool_coalesce *c) | ||||
| @@ -3853,6 +3860,7 @@ const struct ethtool_ops mvneta_eth_tool | ||||
|  	.get_link       = ethtool_op_get_link, | ||||
|  	.get_settings   = mvneta_ethtool_get_settings, | ||||
|  	.set_settings   = mvneta_ethtool_set_settings, | ||||
| +	.nway_reset	= mvneta_ethtool_nway_reset, | ||||
|  	.set_coalesce   = mvneta_ethtool_set_coalesce, | ||||
|  	.get_coalesce   = mvneta_ethtool_get_coalesce, | ||||
|  	.get_drvinfo    = mvneta_ethtool_get_drvinfo, | ||||
| @@ -1,262 +0,0 @@ | ||||
| From f566177aa6661e646b83526f24391a568ffd1a75 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 20:32:07 +0100 | ||||
| Subject: [PATCH 726/744] phylink: add flow control support | ||||
|  | ||||
| Add flow control support, including ethtool support, to phylink.  We | ||||
| add support to allow ethtool to get and set the current flow control | ||||
| settings, and the 802.3 specified resolution for the local and remote | ||||
| link partner abilities. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phylink.c | 145 +++++++++++++++++++++++++++++++++++++++++----- | ||||
|  include/linux/phylink.h   |   8 +++ | ||||
|  2 files changed, 139 insertions(+), 14 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/phylink.c | ||||
| +++ b/drivers/net/phy/phylink.c | ||||
| @@ -91,10 +91,12 @@ static int phylink_parse_fixedlink(struc | ||||
|  		pl->link_config.an_complete = 1; | ||||
|  		pl->link_config.speed = speed; | ||||
|  		pl->link_config.duplex = DUPLEX_HALF; | ||||
| -		pl->link_config.pause = MLO_PAUSE_NONE; | ||||
|   | ||||
|  		if (of_property_read_bool(fixed_node, "full-duplex")) | ||||
|  			pl->link_config.duplex = DUPLEX_FULL; | ||||
| + | ||||
| +		/* We treat the "pause" and "asym-pause" terminology as | ||||
| +		 * defining the link partner's ability. */ | ||||
|  		if (of_property_read_bool(fixed_node, "pause")) | ||||
|  			pl->link_config.pause |= MLO_PAUSE_SYM; | ||||
|  		if (of_property_read_bool(fixed_node, "asym-pause")) | ||||
| @@ -118,7 +120,6 @@ static int phylink_parse_fixedlink(struc | ||||
|  			pl->link_config.duplex = be32_to_cpu(fixed_prop[1]) ? | ||||
|  						DUPLEX_FULL : DUPLEX_HALF; | ||||
|  			pl->link_config.speed = be32_to_cpu(fixed_prop[2]); | ||||
| -			pl->link_config.pause = MLO_PAUSE_NONE; | ||||
|  			if (be32_to_cpu(fixed_prop[3])) | ||||
|  				pl->link_config.pause |= MLO_PAUSE_SYM; | ||||
|  			if (be32_to_cpu(fixed_prop[4])) | ||||
| @@ -130,16 +131,6 @@ static int phylink_parse_fixedlink(struc | ||||
|  	} | ||||
|   | ||||
|  	if (pl->link_an_mode == MLO_AN_FIXED) { | ||||
| -		/* Generate the supported/advertising masks */ | ||||
| -		if (pl->link_config.pause & MLO_PAUSE_SYM) { | ||||
| -			pl->link_config.supported |= SUPPORTED_Pause; | ||||
| -			pl->link_config.advertising |= ADVERTISED_Pause; | ||||
| -		} | ||||
| -		if (pl->link_config.pause & MLO_PAUSE_ASYM) { | ||||
| -			pl->link_config.supported |= SUPPORTED_Asym_Pause; | ||||
| -			pl->link_config.advertising |= ADVERTISED_Asym_Pause; | ||||
| -		} | ||||
| - | ||||
|  		if (pl->link_config.speed > SPEED_1000 && | ||||
|  		    pl->link_config.duplex != DUPLEX_FULL) | ||||
|  			netdev_warn(pl->netdev, "fixed link specifies half duplex for %dMbps link?\n", | ||||
| @@ -242,6 +233,56 @@ static void phylink_get_fixed_state(stru | ||||
|  		state->link = !!gpiod_get_value(pl->link_gpio); | ||||
|  } | ||||
|   | ||||
| +/* Flow control is resolved according to our and the link partners | ||||
| + * advertisments using the following drawn from the 802.3 specs: | ||||
| + *  Local device  Link partner | ||||
| + *  Pause AsymDir Pause AsymDir Result | ||||
| + *    1     X       1     X     TX+RX | ||||
| + *    0     1       1     1     RX | ||||
| + *    1     1       0     1     TX | ||||
| + */ | ||||
| +static void phylink_resolve_flow(struct phylink *pl, | ||||
| +	struct phylink_link_state *state) | ||||
| +{ | ||||
| +	int new_pause = 0; | ||||
| + | ||||
| +	if (pl->link_config.pause & MLO_PAUSE_AN) { | ||||
| +		int pause = 0; | ||||
| + | ||||
| +		if (pl->link_config.advertising & ADVERTISED_Pause) | ||||
| +			pause |= MLO_PAUSE_SYM; | ||||
| +		if (pl->link_config.advertising & ADVERTISED_Asym_Pause) | ||||
| +			pause |= MLO_PAUSE_ASYM; | ||||
| + | ||||
| +		pause &= state->pause; | ||||
| + | ||||
| +		if (pause & MLO_PAUSE_SYM) | ||||
| +			new_pause = MLO_PAUSE_TX | MLO_PAUSE_RX; | ||||
| +		else if (pause & MLO_PAUSE_ASYM) | ||||
| +			new_pause = state->pause & MLO_PAUSE_SYM ? | ||||
| +				 MLO_PAUSE_RX : MLO_PAUSE_TX; | ||||
| +	} else { | ||||
| +		new_pause = pl->link_config.pause & MLO_PAUSE_TXRX_MASK; | ||||
| +	} | ||||
| + | ||||
| +	state->pause &= ~MLO_PAUSE_TXRX_MASK; | ||||
| +	state->pause |= new_pause; | ||||
| +} | ||||
| + | ||||
| +static const char *phylink_pause_to_str(int pause) | ||||
| +{ | ||||
| +	switch (pause & MLO_PAUSE_TXRX_MASK) { | ||||
| +	case MLO_PAUSE_TX | MLO_PAUSE_RX: | ||||
| +		return "rx/tx"; | ||||
| +	case MLO_PAUSE_TX: | ||||
| +		return "tx"; | ||||
| +	case MLO_PAUSE_RX: | ||||
| +		return "rx"; | ||||
| +	default: | ||||
| +		return "off"; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
|  extern const char *phy_speed_to_str(int speed); | ||||
|   | ||||
|  static void phylink_resolve(struct work_struct *w) | ||||
| @@ -257,6 +298,7 @@ static void phylink_resolve(struct work_ | ||||
|  		switch (pl->link_an_mode) { | ||||
|  		case MLO_AN_PHY: | ||||
|  			link_state = pl->phy_state; | ||||
| +			phylink_resolve_flow(pl, &link_state); | ||||
|  			break; | ||||
|   | ||||
|  		case MLO_AN_FIXED: | ||||
| @@ -265,9 +307,12 @@ static void phylink_resolve(struct work_ | ||||
|   | ||||
|  		case MLO_AN_SGMII: | ||||
|  			phylink_get_mac_state(pl, &link_state); | ||||
| -			if (pl->phydev) | ||||
| +			if (pl->phydev) { | ||||
|  				link_state.link = link_state.link && | ||||
|  						  pl->phy_state.link; | ||||
| +				link_state.pause |= pl->phy_state.pause; | ||||
| +				phylink_resolve_flow(pl, &link_state); | ||||
| +			} | ||||
|  			break; | ||||
|   | ||||
|  		case MLO_AN_8023Z: | ||||
| @@ -297,7 +342,7 @@ static void phylink_resolve(struct work_ | ||||
|  				    "Link is Up - %s/%s - flow control %s\n", | ||||
|  				    phy_speed_to_str(link_state.speed), | ||||
|  				    link_state.duplex ? "Full" : "Half", | ||||
| -				    link_state.pause ? "rx/tx" : "off"); | ||||
| +				    phylink_pause_to_str(link_state.pause)); | ||||
|  		} | ||||
|  	} | ||||
|  	mutex_unlock(&pl->state_mutex); | ||||
| @@ -326,6 +371,7 @@ struct phylink *phylink_create(struct ne | ||||
|  	pl->link_interface = iface; | ||||
|  	pl->link_port_support = SUPPORTED_MII; | ||||
|  	pl->link_port = PORT_MII; | ||||
| +	pl->link_config.pause = MLO_PAUSE_AN; | ||||
|  	pl->ops = ops; | ||||
|  	__set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); | ||||
|   | ||||
| @@ -507,6 +553,7 @@ void phylink_start(struct phylink *pl) | ||||
|  	 * a fixed-link to start with the correct parameters, and also | ||||
|  	 * ensures that we set the appropriate advertisment for Serdes links. | ||||
|  	 */ | ||||
| +	phylink_resolve_flow(pl, &pl->link_config); | ||||
|  	phylink_mac_config(pl, &pl->link_config); | ||||
|   | ||||
|  	clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); | ||||
| @@ -701,6 +748,76 @@ int phylink_ethtool_nway_reset(struct ph | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_ethtool_nway_reset); | ||||
|   | ||||
| +void phylink_ethtool_get_pauseparam(struct phylink *pl, | ||||
| +				    struct ethtool_pauseparam *pause) | ||||
| +{ | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| + | ||||
| +	pause->autoneg = !!(pl->link_config.pause & MLO_PAUSE_AN); | ||||
| +	pause->rx_pause = !!(pl->link_config.pause & MLO_PAUSE_RX); | ||||
| +	pause->tx_pause = !!(pl->link_config.pause & MLO_PAUSE_TX); | ||||
| + | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_get_pauseparam); | ||||
| + | ||||
| +static int __phylink_ethtool_set_pauseparam(struct phylink *pl, | ||||
| +					    struct ethtool_pauseparam *pause) | ||||
| +{ | ||||
| +	struct phylink_link_state *config = &pl->link_config; | ||||
| + | ||||
| +	if (!(config->supported & (SUPPORTED_Pause | SUPPORTED_Asym_Pause))) | ||||
| +		return -EOPNOTSUPP; | ||||
| + | ||||
| +	if (!(config->supported & SUPPORTED_Asym_Pause) && | ||||
| +	    !pause->autoneg && pause->rx_pause != pause->tx_pause) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	config->pause &= ~(MLO_PAUSE_AN | MLO_PAUSE_TXRX_MASK); | ||||
| + | ||||
| +	if (pause->autoneg) | ||||
| +		config->pause |= MLO_PAUSE_AN; | ||||
| +	if (pause->rx_pause) | ||||
| +		config->pause |= MLO_PAUSE_RX; | ||||
| +	if (pause->tx_pause) | ||||
| +		config->pause |= MLO_PAUSE_TX; | ||||
| + | ||||
| +	switch (pl->link_an_mode) { | ||||
| +	case MLO_AN_PHY: | ||||
| +		/* Silently mark the carrier down, and then trigger a resolve */ | ||||
| +		netif_carrier_off(pl->netdev); | ||||
| +		phylink_run_resolve(pl); | ||||
| +		break; | ||||
| + | ||||
| +	case MLO_AN_FIXED: | ||||
| +		/* Should we allow fixed links to change against the config? */ | ||||
| +		phylink_resolve_flow(pl, config); | ||||
| +		phylink_mac_config(pl, config); | ||||
| +		break; | ||||
| + | ||||
| +	case MLO_AN_SGMII: | ||||
| +	case MLO_AN_8023Z: | ||||
| +		phylink_mac_config(pl, config); | ||||
| +		phylink_mac_an_restart(pl); | ||||
| +		break; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +int phylink_ethtool_set_pauseparam(struct phylink *pl, | ||||
| +				   struct ethtool_pauseparam *pause) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	ret = __phylink_ethtool_set_pauseparam(pl, pause); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam); | ||||
| + | ||||
|  /* This emulates MII registers for a fixed-mode phy operating as per the | ||||
|   * passed in state. "aneg" defines if we report negotiation is possible. | ||||
|   * | ||||
| --- a/include/linux/phylink.h | ||||
| +++ b/include/linux/phylink.h | ||||
| @@ -13,6 +13,10 @@ enum { | ||||
|  	MLO_PAUSE_NONE, | ||||
|  	MLO_PAUSE_ASYM = BIT(0), | ||||
|  	MLO_PAUSE_SYM = BIT(1), | ||||
| +	MLO_PAUSE_RX = BIT(2), | ||||
| +	MLO_PAUSE_TX = BIT(3), | ||||
| +	MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX, | ||||
| +	MLO_PAUSE_AN = BIT(4), | ||||
|   | ||||
|  	MLO_AN_PHY = 0, | ||||
|  	MLO_AN_FIXED, | ||||
| @@ -66,6 +70,10 @@ void phylink_stop(struct phylink *); | ||||
|  int phylink_ethtool_get_settings(struct phylink *, struct ethtool_cmd *); | ||||
|  int phylink_ethtool_set_settings(struct phylink *, struct ethtool_cmd *); | ||||
|  int phylink_ethtool_nway_reset(struct phylink *); | ||||
| +void phylink_ethtool_get_pauseparam(struct phylink *, | ||||
| +				    struct ethtool_pauseparam *); | ||||
| +int phylink_ethtool_set_pauseparam(struct phylink *, | ||||
| +				   struct ethtool_pauseparam *); | ||||
|  int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); | ||||
|   | ||||
|  void phylink_set_link_port(struct phylink *pl, u32 support, u8 port); | ||||
| @@ -1,66 +0,0 @@ | ||||
| From 7bd34822b9922beb22a6384d9190646105d259d8 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 17:41:44 +0100 | ||||
| Subject: [PATCH 727/744] net: mvneta: add flow control support via phylink | ||||
|  | ||||
| Add flow control support to mvneta, including the ethtool hooks.  This | ||||
| uses the phylink code to calculate the result of autonegotiation where | ||||
| a phy is attached, and to handle the ethtool settings. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 22 +++++++++++++++++++++- | ||||
|  1 file changed, 21 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3208,6 +3208,8 @@ static void mvneta_mac_config(struct net | ||||
|   | ||||
|  	if (state->advertising & ADVERTISED_Pause) | ||||
|  		new_an |= MVNETA_GMAC_ADVERT_SYM_FLOW_CTRL; | ||||
| +	if (state->pause & MLO_PAUSE_TXRX_MASK) | ||||
| +		new_an |= MVNETA_GMAC_CONFIG_FLOW_CTRL; | ||||
|   | ||||
|  	switch (mode) { | ||||
|  	case MLO_AN_SGMII: | ||||
| @@ -3232,7 +3234,7 @@ static void mvneta_mac_config(struct net | ||||
|  			 /* The MAC only supports FD mode */ | ||||
|  			 MVNETA_GMAC_CONFIG_FULL_DUPLEX; | ||||
|   | ||||
| -		if (state->an_enabled) | ||||
| +		if (state->pause & MLO_PAUSE_AN && state->an_enabled) | ||||
|  			new_an |= MVNETA_GMAC_AN_FLOW_CTRL_EN; | ||||
|  		break; | ||||
|   | ||||
| @@ -3685,6 +3687,22 @@ static int mvneta_ethtool_set_ringparam( | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static void mvneta_ethtool_get_pauseparam(struct net_device *dev, | ||||
| +					  struct ethtool_pauseparam *pause) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	phylink_ethtool_get_pauseparam(pp->phylink, pause); | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_set_pauseparam(struct net_device *dev, | ||||
| +					 struct ethtool_pauseparam *pause) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	return phylink_ethtool_set_pauseparam(pp->phylink, pause); | ||||
| +} | ||||
| + | ||||
|  static void mvneta_ethtool_get_strings(struct net_device *netdev, u32 sset, | ||||
|  				       u8 *data) | ||||
|  { | ||||
| @@ -3866,6 +3884,8 @@ const struct ethtool_ops mvneta_eth_tool | ||||
|  	.get_drvinfo    = mvneta_ethtool_get_drvinfo, | ||||
|  	.get_ringparam  = mvneta_ethtool_get_ringparam, | ||||
|  	.set_ringparam	= mvneta_ethtool_set_ringparam, | ||||
| +	.get_pauseparam	= mvneta_ethtool_get_pauseparam, | ||||
| +	.set_pauseparam	= mvneta_ethtool_set_pauseparam, | ||||
|  	.get_strings	= mvneta_ethtool_get_strings, | ||||
|  	.get_ethtool_stats = mvneta_ethtool_get_stats, | ||||
|  	.get_sset_count	= mvneta_ethtool_get_sset_count, | ||||
| @@ -1,32 +0,0 @@ | ||||
| From 62f8a12044265df11531750a240e516a5f1ff433 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 00:34:08 +0100 | ||||
| Subject: [PATCH 728/744] net: mvneta: enable flow control for PHY connections | ||||
|  | ||||
| Enable flow control support for PHY connections by indicating our | ||||
| support via the ethtool capabilities.  phylink takes care of the | ||||
| appropriate handling. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 2 ++ | ||||
|  1 file changed, 2 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3127,12 +3127,14 @@ static int mvneta_mac_support(struct net | ||||
|  		state->supported = PHY_10BT_FEATURES | | ||||
|  				   PHY_100BT_FEATURES | | ||||
|  				   SUPPORTED_1000baseT_Full | | ||||
| +				   SUPPORTED_Pause | | ||||
|  				   SUPPORTED_Autoneg; | ||||
|  		state->advertising = ADVERTISED_10baseT_Half | | ||||
|  				     ADVERTISED_10baseT_Full | | ||||
|  				     ADVERTISED_100baseT_Half | | ||||
|  				     ADVERTISED_100baseT_Full | | ||||
|  				     ADVERTISED_1000baseT_Full | | ||||
| +				     ADVERTISED_Pause | | ||||
|  				     ADVERTISED_Autoneg; | ||||
|  		state->an_enabled = 1; | ||||
|  		break; | ||||
| @@ -1,53 +0,0 @@ | ||||
| From 4c3e2dc08a11fb1273ca62467f1d06e59866bad3 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@armlinux.org.uk> | ||||
| Date: Tue, 12 Jul 2016 00:04:13 +0100 | ||||
| Subject: [PATCH 729/744] net: mvneta: enable flow control for fixed | ||||
|  connections | ||||
|  | ||||
| Allow symetric flow control to be enabled for fixed link connections as | ||||
| well as other types of connections by setting the supported and | ||||
| advertised capability bits. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 11 +++++++---- | ||||
|  1 file changed, 7 insertions(+), 4 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3114,9 +3114,9 @@ static int mvneta_mac_support(struct net | ||||
|  	switch (mode) { | ||||
|  	case MLO_AN_8023Z: | ||||
|  		state->supported = SUPPORTED_1000baseT_Full | | ||||
| -				   SUPPORTED_Autoneg | SUPPORTED_Pause; | ||||
| +				   SUPPORTED_Autoneg; | ||||
|  		state->advertising = ADVERTISED_1000baseT_Full | | ||||
| -				     ADVERTISED_Autoneg | ADVERTISED_Pause; | ||||
| +				     ADVERTISED_Autoneg; | ||||
|  		state->an_enabled = 1; | ||||
|  		break; | ||||
|   | ||||
| @@ -3127,18 +3127,21 @@ static int mvneta_mac_support(struct net | ||||
|  		state->supported = PHY_10BT_FEATURES | | ||||
|  				   PHY_100BT_FEATURES | | ||||
|  				   SUPPORTED_1000baseT_Full | | ||||
| -				   SUPPORTED_Pause | | ||||
|  				   SUPPORTED_Autoneg; | ||||
|  		state->advertising = ADVERTISED_10baseT_Half | | ||||
|  				     ADVERTISED_10baseT_Full | | ||||
|  				     ADVERTISED_100baseT_Half | | ||||
|  				     ADVERTISED_100baseT_Full | | ||||
|  				     ADVERTISED_1000baseT_Full | | ||||
| -				     ADVERTISED_Pause | | ||||
|  				     ADVERTISED_Autoneg; | ||||
|  		state->an_enabled = 1; | ||||
|  		break; | ||||
|  	} | ||||
| + | ||||
| +	/* All modes support flow control */ | ||||
| +	state->supported |= SUPPORTED_Pause; | ||||
| +	state->advertising |= ADVERTISED_Pause; | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -1,111 +0,0 @@ | ||||
| From ffba226d73a2be262fff12d30aecf76d107b2ace Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 21:19:53 +0100 | ||||
| Subject: [PATCH 730/744] phylink: add EEE support | ||||
|  | ||||
| Add EEE hooks to phylink to allow the phylib EEE functions for the | ||||
| connected phy to be safely accessed. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phylink.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++- | ||||
|  include/linux/phylink.h   |  7 +++++- | ||||
|  2 files changed, 63 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/phylink.c | ||||
| +++ b/drivers/net/phy/phylink.c | ||||
| @@ -334,7 +334,8 @@ static void phylink_resolve(struct work_ | ||||
|  			if (pl->phydev) | ||||
|  				phylink_mac_config(pl, &link_state); | ||||
|   | ||||
| -			pl->ops->mac_link_up(ndev, pl->link_an_mode); | ||||
| +			pl->ops->mac_link_up(ndev, pl->link_an_mode, | ||||
| +					     pl->phydev); | ||||
|   | ||||
|  			netif_carrier_on(ndev); | ||||
|   | ||||
| @@ -818,6 +819,61 @@ int phylink_ethtool_set_pauseparam(struc | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam); | ||||
|   | ||||
| +int phylink_init_eee(struct phylink *pl, bool clk_stop_enable) | ||||
| +{ | ||||
| +	int ret = -EPROTONOSUPPORT; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->phydev) | ||||
| +		ret = phy_init_eee(pl->phydev, clk_stop_enable); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_init_eee); | ||||
| + | ||||
| +int phylink_get_eee_err(struct phylink *pl) | ||||
| +{ | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->phydev) | ||||
| +		ret = phy_get_eee_err(pl->phydev); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_get_eee_err); | ||||
| + | ||||
| +int phylink_ethtool_get_eee(struct phylink *pl, struct ethtool_eee *eee) | ||||
| +{ | ||||
| +	int ret = -EOPNOTSUPP; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->phydev) | ||||
| +		ret = phy_ethtool_get_eee(pl->phydev, eee); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_get_eee); | ||||
| + | ||||
| +int phylink_ethtool_set_eee(struct phylink *pl, struct ethtool_eee *eee) | ||||
| +{ | ||||
| +	int ret = -EOPNOTSUPP; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->phydev) { | ||||
| +		ret = phy_ethtool_set_eee(pl->phydev, eee); | ||||
| +		if (ret == 0 && eee->eee_enabled) | ||||
| +			phy_start_aneg(pl->phydev); | ||||
| +	} | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_set_eee); | ||||
| + | ||||
|  /* This emulates MII registers for a fixed-mode phy operating as per the | ||||
|   * passed in state. "aneg" defines if we report negotiation is possible. | ||||
|   * | ||||
| --- a/include/linux/phylink.h | ||||
| +++ b/include/linux/phylink.h | ||||
| @@ -51,7 +51,8 @@ struct phylink_mac_ops { | ||||
|  	void (*mac_an_restart)(struct net_device *, unsigned int mode); | ||||
|   | ||||
|  	void (*mac_link_down)(struct net_device *, unsigned int mode); | ||||
| -	void (*mac_link_up)(struct net_device *, unsigned int mode); | ||||
| +	void (*mac_link_up)(struct net_device *, unsigned int mode, | ||||
| +			    struct phy_device *); | ||||
|  }; | ||||
|   | ||||
|  struct phylink *phylink_create(struct net_device *, struct device_node *, | ||||
| @@ -74,6 +75,10 @@ void phylink_ethtool_get_pauseparam(stru | ||||
|  				    struct ethtool_pauseparam *); | ||||
|  int phylink_ethtool_set_pauseparam(struct phylink *, | ||||
|  				   struct ethtool_pauseparam *); | ||||
| +int phylink_init_eee(struct phylink *, bool); | ||||
| +int phylink_get_eee_err(struct phylink *); | ||||
| +int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *); | ||||
| +int phylink_ethtool_set_eee(struct phylink *, struct ethtool_eee *); | ||||
|  int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); | ||||
|   | ||||
|  void phylink_set_link_port(struct phylink *pl, u32 support, u8 port); | ||||
| @@ -1,182 +0,0 @@ | ||||
| From b7dacf514e41d6efff0ccc170f660cc6dc2aeae2 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Tue, 29 Sep 2015 15:17:39 +0100 | ||||
| Subject: [PATCH 731/744] net: mvneta: add EEE support | ||||
|  | ||||
| Add EEE support to mvneta.  This allows us to enable the low power idle | ||||
| support at MAC level if there is a PHY attached through phylink which | ||||
| supports LPI.  The appropriate ethtool support is provided to allow the | ||||
| feature to be controlled, including ethtool statistics for EEE wakeup | ||||
| errors. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 87 +++++++++++++++++++++++++++++++++++ | ||||
|  1 file changed, 87 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -243,6 +243,12 @@ | ||||
|  #define MVNETA_TXQ_TOKEN_SIZE_REG(q)             (0x3e40 + ((q) << 2)) | ||||
|  #define      MVNETA_TXQ_TOKEN_SIZE_MAX           0x7fffffff | ||||
|   | ||||
| +#define MVNETA_LPI_CTRL_0                        0x2cc0 | ||||
| +#define MVNETA_LPI_CTRL_1                        0x2cc4 | ||||
| +#define      MVNETA_LPI_REQUEST_ENABLE           BIT(0) | ||||
| +#define MVNETA_LPI_CTRL_2                        0x2cc8 | ||||
| +#define MVNETA_LPI_STATUS                        0x2ccc | ||||
| + | ||||
|  #define MVNETA_CAUSE_TXQ_SENT_DESC_ALL_MASK	 0xff | ||||
|   | ||||
|  /* Descriptor ring Macros */ | ||||
| @@ -316,6 +322,11 @@ | ||||
|  #define MVNETA_RX_GET_BM_POOL_ID(rxd) \ | ||||
|  	(((rxd)->status & MVNETA_RXD_BM_POOL_MASK) >> MVNETA_RXD_BM_POOL_SHIFT) | ||||
|   | ||||
| +enum { | ||||
| +	ETHTOOL_STAT_EEE_WAKEUP, | ||||
| +	ETHTOOL_MAX_STATS, | ||||
| +}; | ||||
| + | ||||
|  struct mvneta_statistic { | ||||
|  	unsigned short offset; | ||||
|  	unsigned short type; | ||||
| @@ -324,6 +335,7 @@ struct mvneta_statistic { | ||||
|   | ||||
|  #define T_REG_32	32 | ||||
|  #define T_REG_64	64 | ||||
| +#define T_SW		1 | ||||
|   | ||||
|  static const struct mvneta_statistic mvneta_statistics[] = { | ||||
|  	{ 0x3000, T_REG_64, "good_octets_received", }, | ||||
| @@ -358,6 +370,7 @@ static const struct mvneta_statistic mvn | ||||
|  	{ 0x304c, T_REG_32, "broadcast_frames_sent", }, | ||||
|  	{ 0x3054, T_REG_32, "fc_sent", }, | ||||
|  	{ 0x300c, T_REG_32, "internal_mac_transmit_err", }, | ||||
| +	{ ETHTOOL_STAT_EEE_WAKEUP, T_SW, "eee_wakeup_errors", }, | ||||
|  }; | ||||
|   | ||||
|  struct mvneta_pcpu_stats { | ||||
| @@ -413,6 +426,10 @@ struct mvneta_port { | ||||
|  	struct mvneta_bm_pool *pool_short; | ||||
|  	int bm_win_id; | ||||
|   | ||||
| +	bool eee_enabled; | ||||
| +	bool eee_active; | ||||
| +	bool tx_lpi_enabled; | ||||
| + | ||||
|  	u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)]; | ||||
|   | ||||
|  	u32 indir[MVNETA_RSS_LU_TABLE_SIZE]; | ||||
| @@ -3276,6 +3293,18 @@ static void mvneta_mac_config(struct net | ||||
|  		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, new_an); | ||||
|  } | ||||
|   | ||||
| +static void mvneta_set_eee(struct mvneta_port *pp, bool enable) | ||||
| +{ | ||||
| +	u32 lpi_ctl1; | ||||
| + | ||||
| +	lpi_ctl1 = mvreg_read(pp, MVNETA_LPI_CTRL_1); | ||||
| +	if (enable) | ||||
| +		lpi_ctl1 |= MVNETA_LPI_REQUEST_ENABLE; | ||||
| +	else | ||||
| +		lpi_ctl1 &= ~MVNETA_LPI_REQUEST_ENABLE; | ||||
| +	mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1); | ||||
| +} | ||||
| + | ||||
|  static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode) | ||||
|  { | ||||
|  	struct mvneta_port *pp = netdev_priv(ndev); | ||||
| @@ -3289,6 +3318,9 @@ static void mvneta_mac_link_down(struct | ||||
|  		val |= MVNETA_GMAC_FORCE_LINK_DOWN; | ||||
|  		mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); | ||||
|  	} | ||||
| + | ||||
| +	pp->eee_active = false; | ||||
| +	mvneta_set_eee(pp, false); | ||||
|  } | ||||
|   | ||||
|  static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode, | ||||
| @@ -3305,6 +3337,11 @@ static void mvneta_mac_link_up(struct ne | ||||
|  	} | ||||
|   | ||||
|  	mvneta_port_up(pp); | ||||
| + | ||||
| +	if (phy && pp->eee_enabled) { | ||||
| +		pp->eee_active = phy_init_eee(phy, 0) >= 0; | ||||
| +		mvneta_set_eee(pp, pp->eee_active && pp->tx_lpi_enabled); | ||||
| +	} | ||||
|  } | ||||
|   | ||||
|  static const struct phylink_mac_ops mvneta_phylink_ops = { | ||||
| @@ -3744,6 +3781,13 @@ static void mvneta_ethtool_update_stats( | ||||
|  			val64 = (u64)high << 32 | low; | ||||
|  			pp->ethtool_stats[i] += val64; | ||||
|  			break; | ||||
| +		case T_SW: | ||||
| +			switch (s->offset) { | ||||
| +			case ETHTOOL_STAT_EEE_WAKEUP: | ||||
| +				val = phylink_get_eee_err(pp->phylink); | ||||
| +				break; | ||||
| +			} | ||||
| +			break; | ||||
|  		} | ||||
|  	} | ||||
|  } | ||||
| @@ -3867,6 +3911,47 @@ static int mvneta_ethtool_get_rxfh(struc | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static int mvneta_ethtool_get_eee(struct net_device *dev, | ||||
| +				  struct ethtool_eee *eee) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| +	u32 lpi_ctl0; | ||||
| + | ||||
| +	lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); | ||||
| + | ||||
| +	eee->eee_enabled = pp->eee_enabled; | ||||
| +	eee->eee_active = pp->eee_active; | ||||
| +	eee->tx_lpi_enabled = pp->tx_lpi_enabled; | ||||
| +	eee->tx_lpi_timer = (lpi_ctl0) >> 8; // * scale; | ||||
| + | ||||
| +	return phylink_ethtool_get_eee(pp->phylink, eee); | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_set_eee(struct net_device *dev, | ||||
| +				  struct ethtool_eee *eee) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| +	u32 lpi_ctl0; | ||||
| + | ||||
| +	/* The Armada 37x documents do not give limits for this other than | ||||
| +	 * it being an 8-bit register. */ | ||||
| +	if (eee->tx_lpi_enabled && | ||||
| +	    (eee->tx_lpi_timer < 0 || eee->tx_lpi_timer > 255)) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	lpi_ctl0 = mvreg_read(pp, MVNETA_LPI_CTRL_0); | ||||
| +	lpi_ctl0 &= ~(0xff << 8); | ||||
| +	lpi_ctl0 |= eee->tx_lpi_timer << 8; | ||||
| +	mvreg_write(pp, MVNETA_LPI_CTRL_0, lpi_ctl0); | ||||
| + | ||||
| +	pp->eee_enabled = eee->eee_enabled; | ||||
| +	pp->tx_lpi_enabled = eee->tx_lpi_enabled; | ||||
| + | ||||
| +	mvneta_set_eee(pp, eee->tx_lpi_enabled && eee->eee_enabled); | ||||
| + | ||||
| +	return phylink_ethtool_set_eee(pp->phylink, eee); | ||||
| +} | ||||
| + | ||||
|  static const struct net_device_ops mvneta_netdev_ops = { | ||||
|  	.ndo_open            = mvneta_open, | ||||
|  	.ndo_stop            = mvneta_stop, | ||||
| @@ -3898,6 +3983,8 @@ const struct ethtool_ops mvneta_eth_tool | ||||
|  	.get_rxnfc	= mvneta_ethtool_get_rxnfc, | ||||
|  	.get_rxfh	= mvneta_ethtool_get_rxfh, | ||||
|  	.set_rxfh	= mvneta_ethtool_set_rxfh, | ||||
| +	.get_eee	= mvneta_ethtool_get_eee, | ||||
| +	.set_eee	= mvneta_ethtool_set_eee, | ||||
|  }; | ||||
|   | ||||
|  /* Initialize hw */ | ||||
| @@ -1,137 +0,0 @@ | ||||
| From 5419ccb638aa5c353ea88815e98953d9fc02e6ca Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 23:10:05 +0100 | ||||
| Subject: [PATCH 732/744] phylink: add module EEPROM support | ||||
|  | ||||
| Add support for reading module EEPROMs through phylink. | ||||
|  | ||||
| Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/phylink.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  include/linux/phylink.h   | 12 +++++++++ | ||||
|  2 files changed, 78 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/phy/phylink.c | ||||
| +++ b/drivers/net/phy/phylink.c | ||||
| @@ -60,6 +60,9 @@ struct phylink { | ||||
|  	struct work_struct resolve; | ||||
|   | ||||
|  	bool mac_link_up; | ||||
| + | ||||
| +	const struct phylink_module_ops *module_ops; | ||||
| +	void *module_data; | ||||
|  }; | ||||
|   | ||||
|  static const char *phylink_an_mode_str(unsigned int mode) | ||||
| @@ -819,6 +822,36 @@ int phylink_ethtool_set_pauseparam(struc | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam); | ||||
|   | ||||
| +int phylink_ethtool_get_module_info(struct phylink *pl, | ||||
| +				    struct ethtool_modinfo *modinfo) | ||||
| +{ | ||||
| +	int ret = -EOPNOTSUPP; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->module_ops) | ||||
| +		ret = pl->module_ops->get_module_info(pl->module_data, | ||||
| +						      modinfo); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info); | ||||
| + | ||||
| +int phylink_ethtool_get_module_eeprom(struct phylink *pl, | ||||
| +				      struct ethtool_eeprom *ee, u8 *buf) | ||||
| +{ | ||||
| +	int ret = -EOPNOTSUPP; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->module_ops) | ||||
| +		ret = pl->module_ops->get_module_eeprom(pl->module_data, ee, | ||||
| +							buf); | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_eeprom); | ||||
| + | ||||
|  int phylink_init_eee(struct phylink *pl, bool clk_stop_enable) | ||||
|  { | ||||
|  	int ret = -EPROTONOSUPPORT; | ||||
| @@ -1016,6 +1049,39 @@ EXPORT_SYMBOL_GPL(phylink_mii_ioctl); | ||||
|   | ||||
|   | ||||
|   | ||||
| +int phylink_register_module(struct phylink *pl, void *data, | ||||
| +			    const struct phylink_module_ops *ops) | ||||
| +{ | ||||
| +	int ret = -EBUSY; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (!pl->module_ops) { | ||||
| +		pl->module_ops = ops; | ||||
| +		pl->module_data = data; | ||||
| +		ret = 0; | ||||
| +	} | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_register_module); | ||||
| + | ||||
| +int phylink_unregister_module(struct phylink *pl, void *data) | ||||
| +{ | ||||
| +	int ret = -EINVAL; | ||||
| + | ||||
| +	mutex_lock(&pl->config_mutex); | ||||
| +	if (pl->module_data == data) { | ||||
| +		pl->module_ops = NULL; | ||||
| +		pl->module_data = NULL; | ||||
| +		ret = 0; | ||||
| +	} | ||||
| +	mutex_unlock(&pl->config_mutex); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(phylink_unregister_module); | ||||
| + | ||||
|  void phylink_disable(struct phylink *pl) | ||||
|  { | ||||
|  	set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); | ||||
| --- a/include/linux/phylink.h | ||||
| +++ b/include/linux/phylink.h | ||||
| @@ -55,6 +55,11 @@ struct phylink_mac_ops { | ||||
|  			    struct phy_device *); | ||||
|  }; | ||||
|   | ||||
| +struct phylink_module_ops { | ||||
| +	int (*get_module_info)(void *, struct ethtool_modinfo *); | ||||
| +	int (*get_module_eeprom)(void *, struct ethtool_eeprom *, u8 *); | ||||
| +}; | ||||
| + | ||||
|  struct phylink *phylink_create(struct net_device *, struct device_node *, | ||||
|  	phy_interface_t iface, const struct phylink_mac_ops *ops); | ||||
|  void phylink_destroy(struct phylink *); | ||||
| @@ -75,12 +80,19 @@ void phylink_ethtool_get_pauseparam(stru | ||||
|  				    struct ethtool_pauseparam *); | ||||
|  int phylink_ethtool_set_pauseparam(struct phylink *, | ||||
|  				   struct ethtool_pauseparam *); | ||||
| +int phylink_ethtool_get_module_info(struct phylink *, struct ethtool_modinfo *); | ||||
| +int phylink_ethtool_get_module_eeprom(struct phylink *, | ||||
| +				      struct ethtool_eeprom *, u8 *); | ||||
|  int phylink_init_eee(struct phylink *, bool); | ||||
|  int phylink_get_eee_err(struct phylink *); | ||||
|  int phylink_ethtool_get_eee(struct phylink *, struct ethtool_eee *); | ||||
|  int phylink_ethtool_set_eee(struct phylink *, struct ethtool_eee *); | ||||
|  int phylink_mii_ioctl(struct phylink *, struct ifreq *, int); | ||||
|   | ||||
| +int phylink_register_module(struct phylink *, void *, | ||||
| +			    const struct phylink_module_ops *); | ||||
| +int phylink_unregister_module(struct phylink *, void *); | ||||
| + | ||||
|  void phylink_set_link_port(struct phylink *pl, u32 support, u8 port); | ||||
|  int phylink_set_link_an_mode(struct phylink *pl, unsigned int mode); | ||||
|  void phylink_disable(struct phylink *pl); | ||||
| @@ -1,44 +0,0 @@ | ||||
| From 665e1fe77dedcfc6b5669214ebfd252c803290d4 Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 1 Oct 2015 23:32:39 +0100 | ||||
| Subject: [PATCH 733/744] net: mvneta: add module EEPROM reading support | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/ethernet/marvell/mvneta.c | 18 ++++++++++++++++++ | ||||
|  1 file changed, 18 insertions(+) | ||||
|  | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3911,6 +3911,22 @@ static int mvneta_ethtool_get_rxfh(struc | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static int mvneta_ethtool_get_module_info(struct net_device *dev, | ||||
| +					  struct ethtool_modinfo *modinfo) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	return phylink_ethtool_get_module_info(pp->phylink, modinfo); | ||||
| +} | ||||
| + | ||||
| +static int mvneta_ethtool_get_module_eeprom(struct net_device *dev, | ||||
| +					    struct ethtool_eeprom *ee, u8 *buf) | ||||
| +{ | ||||
| +	struct mvneta_port *pp = netdev_priv(dev); | ||||
| + | ||||
| +	return phylink_ethtool_get_module_eeprom(pp->phylink, ee, buf); | ||||
| +} | ||||
| + | ||||
|  static int mvneta_ethtool_get_eee(struct net_device *dev, | ||||
|  				  struct ethtool_eee *eee) | ||||
|  { | ||||
| @@ -3983,6 +3999,8 @@ const struct ethtool_ops mvneta_eth_tool | ||||
|  	.get_rxnfc	= mvneta_ethtool_get_rxnfc, | ||||
|  	.get_rxfh	= mvneta_ethtool_get_rxfh, | ||||
|  	.set_rxfh	= mvneta_ethtool_set_rxfh, | ||||
| +	.get_module_info = mvneta_ethtool_get_module_info, | ||||
| +	.get_module_eeprom = mvneta_ethtool_get_module_eeprom, | ||||
|  	.get_eee	= mvneta_ethtool_get_eee, | ||||
|  	.set_eee	= mvneta_ethtool_set_eee, | ||||
|  }; | ||||
| @@ -1,68 +0,0 @@ | ||||
| From a7091ef24223ed39b39c6b73b77c55c8a607f34a Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Thu, 8 Oct 2015 23:49:47 +0100 | ||||
| Subject: [PATCH 734/744] sfp/phylink: hook up eeprom functions | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  drivers/net/phy/sfp.c | 19 +++++++++++-------- | ||||
|  1 file changed, 11 insertions(+), 8 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/sfp.c | ||||
| +++ b/drivers/net/phy/sfp.c | ||||
| @@ -901,11 +901,9 @@ static void sfp_sm_event(struct sfp *sfp | ||||
|  	mutex_unlock(&sfp->sm_mutex); | ||||
|  } | ||||
|   | ||||
| -#if 0 | ||||
| -static int sfp_phy_module_info(struct phy_device *phy, | ||||
| -			       struct ethtool_modinfo *modinfo) | ||||
| +static int sfp_module_info(void *priv, struct ethtool_modinfo *modinfo) | ||||
|  { | ||||
| -	struct sfp *sfp = phy->priv; | ||||
| +	struct sfp *sfp = priv; | ||||
|   | ||||
|  	/* locking... and check module is present */ | ||||
|   | ||||
| @@ -919,10 +917,9 @@ static int sfp_phy_module_info(struct ph | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| -static int sfp_phy_module_eeprom(struct phy_device *phy, | ||||
| -	struct ethtool_eeprom *ee, u8 *data) | ||||
| +static int sfp_module_eeprom(void *priv, struct ethtool_eeprom *ee, u8 *data) | ||||
|  { | ||||
| -	struct sfp *sfp = phy->priv; | ||||
| +	struct sfp *sfp = priv; | ||||
|  	unsigned int first, last, len; | ||||
|  	int ret; | ||||
|   | ||||
| @@ -953,7 +950,11 @@ static int sfp_phy_module_eeprom(struct | ||||
|  	} | ||||
|  	return 0; | ||||
|  } | ||||
| -#endif | ||||
| + | ||||
| +static const struct phylink_module_ops sfp_module_ops = { | ||||
| +	.get_module_info = sfp_module_info, | ||||
| +	.get_module_eeprom = sfp_module_eeprom, | ||||
| +}; | ||||
|   | ||||
|  static void sfp_timeout(struct work_struct *work) | ||||
|  { | ||||
| @@ -1029,6 +1030,7 @@ static int sfp_netdev_notify(struct noti | ||||
|  	case NETDEV_UNREGISTER: | ||||
|  		if (sfp->mod_phy && sfp->phylink) | ||||
|  			phylink_disconnect_phy(sfp->phylink); | ||||
| +		phylink_unregister_module(sfp->phylink, sfp); | ||||
|  		sfp->phylink = NULL; | ||||
|  		dev_put(sfp->ndev); | ||||
|  		sfp->ndev = NULL; | ||||
| @@ -1145,6 +1147,7 @@ static int sfp_probe(struct platform_dev | ||||
|  		} | ||||
|   | ||||
|  		phylink_disable(sfp->phylink); | ||||
| +		phylink_register_module(sfp->phylink, sfp, &sfp_module_ops); | ||||
|  	} | ||||
|   | ||||
|  	sfp->state = sfp_get_state(sfp); | ||||
| @@ -1,83 +0,0 @@ | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -1695,8 +1695,10 @@ static struct mvneta_tx_queue *mvneta_tx | ||||
|   | ||||
|  /* Free tx queue skbuffs */ | ||||
|  static void mvneta_txq_bufs_free(struct mvneta_port *pp, | ||||
| -				 struct mvneta_tx_queue *txq, int num) | ||||
| +				 struct mvneta_tx_queue *txq, int num, | ||||
| +				 struct netdev_queue *nq) | ||||
|  { | ||||
| +	unsigned int bytes_compl = 0, pkts_compl = 0; | ||||
|  	int i; | ||||
|   | ||||
|  	for (i = 0; i < num; i++) { | ||||
| @@ -1704,6 +1706,11 @@ static void mvneta_txq_bufs_free(struct | ||||
|  			txq->txq_get_index; | ||||
|  		struct sk_buff *skb = txq->tx_skb[txq->txq_get_index]; | ||||
|   | ||||
| +		if (skb) { | ||||
| +			bytes_compl += skb->len; | ||||
| +			pkts_compl++; | ||||
| +		} | ||||
| + | ||||
|  		mvneta_txq_inc_get(txq); | ||||
|   | ||||
|  		if (!IS_TSO_HEADER(txq, tx_desc->buf_phys_addr)) | ||||
| @@ -1714,6 +1721,8 @@ static void mvneta_txq_bufs_free(struct | ||||
|  			continue; | ||||
|  		dev_kfree_skb_any(skb); | ||||
|  	} | ||||
| + | ||||
| +	netdev_tx_completed_queue(nq, pkts_compl, bytes_compl); | ||||
|  } | ||||
|   | ||||
|  /* Handle end of transmission */ | ||||
| @@ -1727,7 +1736,7 @@ static void mvneta_txq_done(struct mvnet | ||||
|  	if (!tx_done) | ||||
|  		return; | ||||
|   | ||||
| -	mvneta_txq_bufs_free(pp, txq, tx_done); | ||||
| +	mvneta_txq_bufs_free(pp, txq, tx_done, nq); | ||||
|   | ||||
|  	txq->count -= tx_done; | ||||
|   | ||||
| @@ -2334,6 +2343,8 @@ out: | ||||
|  		struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats); | ||||
|  		struct netdev_queue *nq = netdev_get_tx_queue(dev, txq_id); | ||||
|   | ||||
| +		netdev_tx_sent_queue(nq, len); | ||||
| + | ||||
|  		txq->count += frags; | ||||
|  		mvneta_txq_pend_desc_add(pp, txq, frags); | ||||
|   | ||||
| @@ -2358,9 +2369,10 @@ static void mvneta_txq_done_force(struct | ||||
|  				  struct mvneta_tx_queue *txq) | ||||
|   | ||||
|  { | ||||
| +	struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id); | ||||
|  	int tx_done = txq->count; | ||||
|   | ||||
| -	mvneta_txq_bufs_free(pp, txq, tx_done); | ||||
| +	mvneta_txq_bufs_free(pp, txq, tx_done, nq); | ||||
|   | ||||
|  	/* reset txq */ | ||||
|  	txq->count = 0; | ||||
| @@ -2841,6 +2853,8 @@ static int mvneta_txq_init(struct mvneta | ||||
|  static void mvneta_txq_deinit(struct mvneta_port *pp, | ||||
|  			      struct mvneta_tx_queue *txq) | ||||
|  { | ||||
| +	struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id); | ||||
| + | ||||
|  	kfree(txq->tx_skb); | ||||
|   | ||||
|  	if (txq->tso_hdrs) | ||||
| @@ -2852,6 +2866,8 @@ static void mvneta_txq_deinit(struct mvn | ||||
|  				  txq->size * MVNETA_DESC_ALIGNED_SIZE, | ||||
|  				  txq->descs, txq->descs_phys); | ||||
|   | ||||
| +	netdev_tx_reset_queue(nq); | ||||
| + | ||||
|  	txq->descs             = NULL; | ||||
|  	txq->last_desc         = 0; | ||||
|  	txq->next_desc_to_proc = 0; | ||||
| @@ -1,433 +0,0 @@ | ||||
| Armada 370/XP devices can 'blink' gpio lines with a configurable on | ||||
| and off period. This can be modelled as a PWM. | ||||
|  | ||||
| However, there are only two sets of PWM configuration registers for | ||||
| all the gpio lines. This driver simply allows a single gpio line per | ||||
| gpio chip of 32 lines to be used as a PWM. Attempts to use more return | ||||
| EBUSY. | ||||
|  | ||||
| Due to the interleaving of registers it is not simple to separate the | ||||
| PWM driver from the gpio driver. Thus the gpio driver has been | ||||
| extended with a PWM driver. | ||||
|  | ||||
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> | ||||
| --- | ||||
|  drivers/gpio/Kconfig          |   5 ++ | ||||
|  drivers/gpio/Makefile         |   1 + | ||||
|  drivers/gpio/gpio-mvebu-pwm.c | 202 ++++++++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/gpio/gpio-mvebu.c     |  37 +++----- | ||||
|  drivers/gpio/gpio-mvebu.h     |  79 +++++++++++++++++ | ||||
|  5 files changed, 299 insertions(+), 25 deletions(-) | ||||
|  create mode 100644 drivers/gpio/gpio-mvebu-pwm.c | ||||
|  create mode 100644 drivers/gpio/gpio-mvebu.h | ||||
|  | ||||
| --- a/drivers/gpio/Kconfig | ||||
| +++ b/drivers/gpio/Kconfig | ||||
| @@ -295,6 +295,11 @@ config GPIO_MVEBU | ||||
|  	depends on OF | ||||
|  	select GENERIC_IRQ_CHIP | ||||
|   | ||||
| +config GPIO_MVEBU_PWM | ||||
| +	def_bool y | ||||
| +	depends on GPIO_MVEBU | ||||
| +	depends on PWM | ||||
| + | ||||
|  config GPIO_MXC | ||||
|  	def_bool y | ||||
|  	depends on ARCH_MXC | ||||
| --- a/drivers/gpio/Makefile | ||||
| +++ b/drivers/gpio/Makefile | ||||
| @@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_MPC5200)	+= gpio-mpc52 | ||||
|  obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o | ||||
|  obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o | ||||
|  obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o | ||||
| +obj-$(CONFIG_GPIO_MVEBU_PWM)	+= gpio-mvebu-pwm.o | ||||
|  obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o | ||||
|  obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o | ||||
|  obj-$(CONFIG_GPIO_OCTEON)	+= gpio-octeon.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/gpio/gpio-mvebu-pwm.c | ||||
| @@ -0,0 +1,202 @@ | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/gpio.h> | ||||
| +#include <linux/pwm.h> | ||||
| +#include <linux/clk.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include "gpio-mvebu.h" | ||||
| +#include "gpiolib.h" | ||||
| + | ||||
| +static void __iomem *mvebu_gpioreg_blink_select(struct mvebu_gpio_chip *mvchip) | ||||
| +{ | ||||
| +	return mvchip->membase + GPIO_BLINK_CNT_SELECT; | ||||
| +} | ||||
| + | ||||
| +static inline struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip) | ||||
| +{ | ||||
| +	return container_of(chip, struct mvebu_pwm, chip); | ||||
| +} | ||||
| + | ||||
| +static inline struct mvebu_gpio_chip *to_mvchip(struct mvebu_pwm *pwm) | ||||
| +{ | ||||
| +	return container_of(pwm, struct mvebu_gpio_chip, pwm); | ||||
| +} | ||||
| + | ||||
| +static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwmd) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = to_mvebu_pwm(chip); | ||||
| +	struct mvebu_gpio_chip *mvchip = to_mvchip(pwm); | ||||
| +	struct gpio_desc *desc = gpio_to_desc(pwmd->pwm); | ||||
| +	unsigned long flags; | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	spin_lock_irqsave(&pwm->lock, flags); | ||||
| +	if (pwm->used) { | ||||
| +		ret = -EBUSY; | ||||
| +	} else { | ||||
| +		if (!desc) { | ||||
| +			ret = -ENODEV; | ||||
| +			goto out; | ||||
| +		} | ||||
| +		ret = gpiod_request(desc, "mvebu-pwm"); | ||||
| +		if (ret) | ||||
| +			goto out; | ||||
| + | ||||
| +		ret = gpiod_direction_output(desc, 0); | ||||
| +		if (ret) { | ||||
| +			gpiod_free(desc); | ||||
| +			goto out; | ||||
| +		} | ||||
| + | ||||
| +		pwm->pin = pwmd->pwm - mvchip->chip.base; | ||||
| +		pwm->used = true; | ||||
| +	} | ||||
| + | ||||
| +out: | ||||
| +	spin_unlock_irqrestore(&pwm->lock, flags); | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwmd) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = to_mvebu_pwm(chip); | ||||
| +	struct gpio_desc *desc = gpio_to_desc(pwmd->pwm); | ||||
| +	unsigned long flags; | ||||
| + | ||||
| +	spin_lock_irqsave(&pwm->lock, flags); | ||||
| +	gpiod_free(desc); | ||||
| +	pwm->used = false; | ||||
| +	spin_unlock_irqrestore(&pwm->lock, flags); | ||||
| +} | ||||
| + | ||||
| +static int mvebu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwmd, | ||||
| +			    int duty_ns, int period_ns) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = to_mvebu_pwm(chip); | ||||
| +	struct mvebu_gpio_chip *mvchip = to_mvchip(pwm); | ||||
| +	unsigned int on, off; | ||||
| +	unsigned long long val; | ||||
| +	u32 u; | ||||
| + | ||||
| +	val = (unsigned long long) pwm->clk_rate * duty_ns; | ||||
| +	do_div(val, NSEC_PER_SEC); | ||||
| +	if (val > UINT_MAX) | ||||
| +		return -EINVAL; | ||||
| +	if (val) | ||||
| +		on = val; | ||||
| +	else | ||||
| +		on = 1; | ||||
| + | ||||
| +	val = (unsigned long long) pwm->clk_rate * (period_ns - duty_ns); | ||||
| +	do_div(val, NSEC_PER_SEC); | ||||
| +	if (val > UINT_MAX) | ||||
| +		return -EINVAL; | ||||
| +	if (val) | ||||
| +		off = val; | ||||
| +	else | ||||
| +		off = 1; | ||||
| + | ||||
| +	u = readl_relaxed(mvebu_gpioreg_blink_select(mvchip)); | ||||
| +	u &= ~(1 << pwm->pin); | ||||
| +	u |= (pwm->id << pwm->pin); | ||||
| +	writel_relaxed(u, mvebu_gpioreg_blink_select(mvchip)); | ||||
| + | ||||
| +	writel_relaxed(on, pwm->membase + BLINK_ON_DURATION); | ||||
| +	writel_relaxed(off, pwm->membase + BLINK_OFF_DURATION); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mvebu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwmd) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = to_mvebu_pwm(chip); | ||||
| +	struct mvebu_gpio_chip *mvchip = to_mvchip(pwm); | ||||
| + | ||||
| +	mvebu_gpio_blink(&mvchip->chip, pwm->pin, 1); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void mvebu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwmd) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = to_mvebu_pwm(chip); | ||||
| +	struct mvebu_gpio_chip *mvchip = to_mvchip(pwm); | ||||
| + | ||||
| +	mvebu_gpio_blink(&mvchip->chip, pwm->pin, 0); | ||||
| +} | ||||
| + | ||||
| +static const struct pwm_ops mvebu_pwm_ops = { | ||||
| +	.request = mvebu_pwm_request, | ||||
| +	.free = mvebu_pwm_free, | ||||
| +	.config = mvebu_pwm_config, | ||||
| +	.enable = mvebu_pwm_enable, | ||||
| +	.disable = mvebu_pwm_disable, | ||||
| +	.owner = THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = &mvchip->pwm; | ||||
| + | ||||
| +	pwm->blink_select = readl_relaxed(mvebu_gpioreg_blink_select(mvchip)); | ||||
| +	pwm->blink_on_duration = | ||||
| +		readl_relaxed(pwm->membase + BLINK_ON_DURATION); | ||||
| +	pwm->blink_off_duration = | ||||
| +		readl_relaxed(pwm->membase + BLINK_OFF_DURATION); | ||||
| +} | ||||
| + | ||||
| +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) | ||||
| +{ | ||||
| +	struct mvebu_pwm *pwm = &mvchip->pwm; | ||||
| + | ||||
| +	writel_relaxed(pwm->blink_select, mvebu_gpioreg_blink_select(mvchip)); | ||||
| +	writel_relaxed(pwm->blink_on_duration, | ||||
| +		       pwm->membase + BLINK_ON_DURATION); | ||||
| +	writel_relaxed(pwm->blink_off_duration, | ||||
| +		       pwm->membase + BLINK_OFF_DURATION); | ||||
| +} | ||||
| + | ||||
| +/* | ||||
| + * Armada 370/XP has simple PWM support for gpio lines. Other SoCs | ||||
| + * don't have this hardware. So if we don't have the necessary | ||||
| + * resource, it is not an error. | ||||
| + */ | ||||
| +int mvebu_pwm_probe(struct platform_device *pdev, | ||||
| +		    struct mvebu_gpio_chip *mvchip, | ||||
| +		    int id) | ||||
| +{ | ||||
| +	struct device *dev = &pdev->dev; | ||||
| +	struct mvebu_pwm *pwm = &mvchip->pwm; | ||||
| +	struct resource *res; | ||||
| + | ||||
| +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm"); | ||||
| +	if (!res) | ||||
| +		return 0; | ||||
| + | ||||
| +	mvchip->pwm.membase = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (IS_ERR(mvchip->pwm.membase)) | ||||
| +		return PTR_ERR(mvchip->percpu_membase); | ||||
| + | ||||
| +	if (id < 0 || id > 1) | ||||
| +		return -EINVAL; | ||||
| +	pwm->id = id; | ||||
| + | ||||
| +	if (IS_ERR(mvchip->clk)) | ||||
| +		return PTR_ERR(mvchip->clk); | ||||
| + | ||||
| +	pwm->clk_rate = clk_get_rate(mvchip->clk); | ||||
| +	if (!pwm->clk_rate) { | ||||
| +		dev_err(dev, "failed to get clock rate\n"); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	pwm->chip.dev = dev; | ||||
| +	pwm->chip.ops = &mvebu_pwm_ops; | ||||
| +	pwm->chip.base = mvchip->chip.base; | ||||
| +	pwm->chip.npwm = mvchip->chip.ngpio; | ||||
| +	pwm->chip.can_sleep = false; | ||||
| + | ||||
| +	spin_lock_init(&pwm->lock); | ||||
| + | ||||
| +	return pwmchip_add(&pwm->chip); | ||||
| +} | ||||
| --- a/drivers/gpio/gpio-mvebu.c | ||||
| +++ b/drivers/gpio/gpio-mvebu.c | ||||
| @@ -42,10 +42,11 @@ | ||||
|  #include <linux/io.h> | ||||
|  #include <linux/of_irq.h> | ||||
|  #include <linux/of_device.h> | ||||
| +#include <linux/pwm.h> | ||||
|  #include <linux/clk.h> | ||||
|  #include <linux/pinctrl/consumer.h> | ||||
|  #include <linux/irqchip/chained_irq.h> | ||||
| - | ||||
| +#include "gpio-mvebu.h" | ||||
|  /* | ||||
|   * GPIO unit register offsets. | ||||
|   */ | ||||
| @@ -75,24 +76,6 @@ | ||||
|   | ||||
|  #define MVEBU_MAX_GPIO_PER_BANK		32 | ||||
|   | ||||
| -struct mvebu_gpio_chip { | ||||
| -	struct gpio_chip   chip; | ||||
| -	spinlock_t	   lock; | ||||
| -	void __iomem	  *membase; | ||||
| -	void __iomem	  *percpu_membase; | ||||
| -	int		   irqbase; | ||||
| -	struct irq_domain *domain; | ||||
| -	int		   soc_variant; | ||||
| - | ||||
| -	/* Used to preserve GPIO registers across suspend/resume */ | ||||
| -	u32                out_reg; | ||||
| -	u32                io_conf_reg; | ||||
| -	u32                blink_en_reg; | ||||
| -	u32                in_pol_reg; | ||||
| -	u32                edge_mask_regs[4]; | ||||
| -	u32                level_mask_regs[4]; | ||||
| -}; | ||||
| - | ||||
|  /* | ||||
|   * Functions returning addresses of individual registers for a given | ||||
|   * GPIO controller. | ||||
| @@ -218,7 +201,7 @@ static int mvebu_gpio_get(struct gpio_ch | ||||
|  	return (u >> pin) & 1; | ||||
|  } | ||||
|   | ||||
| -static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) | ||||
| +void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) | ||||
|  { | ||||
|  	struct mvebu_gpio_chip *mvchip = | ||||
|  		container_of(chip, struct mvebu_gpio_chip, chip); | ||||
| @@ -607,6 +590,8 @@ static int mvebu_gpio_suspend(struct pla | ||||
|  		BUG(); | ||||
|  	} | ||||
|   | ||||
| +	mvebu_pwm_suspend(mvchip); | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -650,6 +635,8 @@ static int mvebu_gpio_resume(struct plat | ||||
|  		BUG(); | ||||
|  	} | ||||
|   | ||||
| +	mvebu_pwm_resume(mvchip); | ||||
| + | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| @@ -661,7 +648,6 @@ static int mvebu_gpio_probe(struct platf | ||||
|  	struct resource *res; | ||||
|  	struct irq_chip_generic *gc; | ||||
|  	struct irq_chip_type *ct; | ||||
| -	struct clk *clk; | ||||
|  	unsigned int ngpios; | ||||
|  	int soc_variant; | ||||
|  	int i, cpu, id; | ||||
| @@ -691,10 +677,10 @@ static int mvebu_gpio_probe(struct platf | ||||
|  		return id; | ||||
|  	} | ||||
|   | ||||
| -	clk = devm_clk_get(&pdev->dev, NULL); | ||||
| +	mvchip->clk = devm_clk_get(&pdev->dev, NULL); | ||||
|  	/* Not all SoCs require a clock.*/ | ||||
| -	if (!IS_ERR(clk)) | ||||
| -		clk_prepare_enable(clk); | ||||
| +	if (!IS_ERR(mvchip->clk)) | ||||
| +		clk_prepare_enable(mvchip->clk); | ||||
|   | ||||
|  	mvchip->soc_variant = soc_variant; | ||||
|  	mvchip->chip.label = dev_name(&pdev->dev); | ||||
| @@ -828,7 +814,8 @@ static int mvebu_gpio_probe(struct platf | ||||
|  		goto err_generic_chip; | ||||
|  	} | ||||
|   | ||||
| -	return 0; | ||||
| +	/* Armada 370/XP has simple PWM support for gpio lines */ | ||||
| +	return mvebu_pwm_probe(pdev, mvchip, id); | ||||
|   | ||||
|  err_generic_chip: | ||||
|  	irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | ||||
| --- /dev/null | ||||
| +++ b/drivers/gpio/gpio-mvebu.h | ||||
| @@ -0,0 +1,79 @@ | ||||
| +/* | ||||
| + * Interface between MVEBU GPIO driver and PWM driver for GPIO pins | ||||
| + * | ||||
| + * Copyright (C) 2015, Andrew Lunn <andrew@lunn.ch> | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + */ | ||||
| + | ||||
| +#ifndef MVEBU_GPIO_PWM_H | ||||
| +#define MVEBU_GPIO_PWM_H | ||||
| + | ||||
| +#define BLINK_ON_DURATION	0x0 | ||||
| +#define BLINK_OFF_DURATION	0x4 | ||||
| +#define GPIO_BLINK_CNT_SELECT	0x0020 | ||||
| + | ||||
| +struct mvebu_pwm { | ||||
| +	void __iomem	*membase; | ||||
| +	unsigned long	 clk_rate; | ||||
| +	bool		 used; | ||||
| +	unsigned	 pin; | ||||
| +	struct pwm_chip	 chip; | ||||
| +	int		 id; | ||||
| +	spinlock_t	 lock; | ||||
| + | ||||
| +	/* Used to preserve GPIO/PWM registers across suspend / | ||||
| +	 * resume */ | ||||
| +	u32		 blink_select; | ||||
| +	u32		 blink_on_duration; | ||||
| +	u32		 blink_off_duration; | ||||
| +}; | ||||
| + | ||||
| +struct mvebu_gpio_chip { | ||||
| +	struct gpio_chip   chip; | ||||
| +	spinlock_t	   lock; | ||||
| +	void __iomem	  *membase; | ||||
| +	void __iomem	  *percpu_membase; | ||||
| +	int		   irqbase; | ||||
| +	struct irq_domain *domain; | ||||
| +	int		   soc_variant; | ||||
| +	struct clk	  *clk; | ||||
| +#ifdef CONFIG_PWM | ||||
| +	struct mvebu_pwm pwm; | ||||
| +#endif | ||||
| +	/* Used to preserve GPIO registers across suspend/resume */ | ||||
| +	u32		   out_reg; | ||||
| +	u32		   io_conf_reg; | ||||
| +	u32		   blink_en_reg; | ||||
| +	u32		   in_pol_reg; | ||||
| +	u32		   edge_mask_regs[4]; | ||||
| +	u32		   level_mask_regs[4]; | ||||
| +}; | ||||
| + | ||||
| +void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value); | ||||
| + | ||||
| +#ifdef CONFIG_PWM | ||||
| +int mvebu_pwm_probe(struct platform_device *pdev, | ||||
| +		    struct mvebu_gpio_chip *mvchip, | ||||
| +		    int id); | ||||
| +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip); | ||||
| +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip); | ||||
| +#else | ||||
| +int mvebu_pwm_probe(struct platform_device *pdev, | ||||
| +		    struct mvebu_gpio_chip *mvchip, | ||||
| +		    int id) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +void mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip) | ||||
| +{ | ||||
| +} | ||||
| + | ||||
| +void mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip) | ||||
| +{ | ||||
| +} | ||||
| +#endif | ||||
| +#endif | ||||
| @@ -1,52 +0,0 @@ | ||||
| Document the optional parameters needed for PWM operation of gpio | ||||
| lines. | ||||
|  | ||||
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> | ||||
| --- | ||||
|  .../devicetree/bindings/gpio/gpio-mvebu.txt        | 31 ++++++++++++++++++++++ | ||||
|  1 file changed, 31 insertions(+) | ||||
|  | ||||
| --- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt | ||||
| +++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt | ||||
| @@ -38,6 +38,23 @@ Required properties: | ||||
|  - #gpio-cells: Should be two. The first cell is the pin number. The | ||||
|    second cell is reserved for flags, unused at the moment. | ||||
|   | ||||
| +Optional properties: | ||||
| + | ||||
| +In order to use the gpio lines in PWM mode, some additional optional | ||||
| +properties are required. Only Armada 370 and XP supports these | ||||
| +properties. | ||||
| + | ||||
| +- reg: an additional register set is needed, for the GPIO Blink | ||||
| +  Counter on/off registers. | ||||
| + | ||||
| +- reg-names: Must contain an entry "pwm" corresponding to the | ||||
| +  additional register range needed for pwm operation. | ||||
| + | ||||
| +- #pwm-cells: Should be two. The first cell is the pin number. The | ||||
| +  second cell is reserved for flags, unused at the moment. | ||||
| + | ||||
| +- clocks: Must be a phandle to the clock for the gpio controller. | ||||
| + | ||||
|  Example: | ||||
|   | ||||
|  		gpio0: gpio@d0018100 { | ||||
| @@ -51,3 +68,17 @@ Example: | ||||
|  			#interrupt-cells = <2>; | ||||
|  			interrupts = <16>, <17>, <18>, <19>; | ||||
|  		}; | ||||
| + | ||||
| +		gpio1: gpio@18140 { | ||||
| +			compatible = "marvell,orion-gpio"; | ||||
| +			reg = <0x18140 0x40>, <0x181c8 0x08>; | ||||
| +			reg-names = "gpio", "pwm"; | ||||
| +			ngpios = <17>; | ||||
| +			gpio-controller; | ||||
| +			#gpio-cells = <2>; | ||||
| +			#pwm-cells = <2>; | ||||
| +			interrupt-controller; | ||||
| +			#interrupt-cells = <2>; | ||||
| +			interrupts = <87>, <88>, <89>; | ||||
| +			clocks = <&coreclk 0>; | ||||
| +		}; | ||||
| @@ -1,149 +0,0 @@ | ||||
| Add properties to the gpio nodes to allow them to be also used | ||||
| as pwm lines. | ||||
|  | ||||
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-370.dtsi        | 10 ++++++++-- | ||||
|  arch/arm/boot/dts/armada-xp-mv78230.dtsi | 10 ++++++++-- | ||||
|  arch/arm/boot/dts/armada-xp-mv78260.dtsi |  8 ++++++-- | ||||
|  arch/arm/boot/dts/armada-xp-mv78460.dtsi | 10 ++++++++-- | ||||
|  4 files changed, 30 insertions(+), 8 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-370.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-370.dtsi | ||||
| @@ -162,24 +162,30 @@ | ||||
|   | ||||
|  			gpio0: gpio@18100 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18100 0x40>; | ||||
| +				reg = <0x18100 0x40>, <0x181c0 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <82>, <83>, <84>, <85>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio1: gpio@18140 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18140 0x40>; | ||||
| +				reg = <0x18140 0x40>, <0x181c8 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <87>, <88>, <89>, <90>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio2: gpio@18180 { | ||||
| --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi | ||||
| @@ -203,24 +203,30 @@ | ||||
|  		internal-regs { | ||||
|  			gpio0: gpio@18100 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18100 0x40>; | ||||
| +				reg = <0x18100 0x40>, <0x181c0 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <82>, <83>, <84>, <85>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio1: gpio@18140 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18140 0x40>; | ||||
| +				reg = <0x18140 0x40>, <0x181c8 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <17>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <87>, <88>, <89>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|  		}; | ||||
|  	}; | ||||
| --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi | ||||
| @@ -286,24 +286,28 @@ | ||||
|  		internal-regs { | ||||
|  			gpio0: gpio@18100 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18100 0x40>; | ||||
| +				reg = <0x18100 0x40>, <0x181c0 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <82>, <83>, <84>, <85>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio1: gpio@18140 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18140 0x40>; | ||||
| +				reg = <0x18140 0x40>, <0x181c8 0x08>; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <87>, <88>, <89>, <90>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio2: gpio@18180 { | ||||
| --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi | ||||
| +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi | ||||
| @@ -324,24 +324,30 @@ | ||||
|  		internal-regs { | ||||
|  			gpio0: gpio@18100 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18100 0x40>; | ||||
| +				reg = <0x18100 0x40>, <0x181c0 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <82>, <83>, <84>, <85>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio1: gpio@18140 { | ||||
|  				compatible = "marvell,orion-gpio"; | ||||
| -				reg = <0x18140 0x40>; | ||||
| +				reg = <0x18140 0x40>, <0x181c8 0x08>; | ||||
| +				reg-names = "gpio", "pwm"; | ||||
|  				ngpios = <32>; | ||||
|  				gpio-controller; | ||||
|  				#gpio-cells = <2>; | ||||
| +				#pwm-cells = <2>; | ||||
|  				interrupt-controller; | ||||
|  				#interrupt-cells = <2>; | ||||
|  				interrupts = <87>, <88>, <89>, <90>; | ||||
| +				clocks = <&coreclk 0>; | ||||
|  			}; | ||||
|   | ||||
|  			gpio2: gpio@18180 { | ||||
| @@ -1,18 +0,0 @@ | ||||
| Now that the gpio driver also supports PWM operation, enable | ||||
| the PWM framework in mvebu_v7_defconfig. | ||||
|  | ||||
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> | ||||
| --- | ||||
|  arch/arm/configs/mvebu_v7_defconfig | 1 + | ||||
|  1 file changed, 1 insertion(+) | ||||
|  | ||||
| --- a/arch/arm/configs/mvebu_v7_defconfig | ||||
| +++ b/arch/arm/configs/mvebu_v7_defconfig | ||||
| @@ -131,6 +131,7 @@ CONFIG_DMADEVICES=y | ||||
|  CONFIG_MV_XOR=y | ||||
|  # CONFIG_IOMMU_SUPPORT is not set | ||||
|  CONFIG_MEMORY=y | ||||
| +CONFIG_PWM=y | ||||
|  CONFIG_EXT4_FS=y | ||||
|  CONFIG_ISO9660_FS=y | ||||
|  CONFIG_JOLIET=y | ||||
| @@ -1,28 +0,0 @@ | ||||
| The mvebu gpio driver can also perform PWM on some pins. Us the | ||||
| pwm-fan driver to control the fan of the WRT1900AC, giving us fine | ||||
| grain control over its speed and hence noise. | ||||
|  | ||||
| Signed-off-by: Andrew Lunn <andrew@lunn.ch> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-xp-wrt1900ac.dts | 8 +++----- | ||||
|  1 file changed, 3 insertions(+), 5 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| +++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts | ||||
| @@ -428,13 +428,11 @@ | ||||
|  		}; | ||||
|  	}; | ||||
|   | ||||
| -	gpio_fan { | ||||
| +	pwm_fan { | ||||
|  		/* SUNON HA4010V4-0000-C99 */ | ||||
| -		compatible = "gpio-fan"; | ||||
| -		gpios = <&gpio0 24 0>; | ||||
|   | ||||
| -		gpio-fan,speed-map = <0    0 | ||||
| -				      4500 1>; | ||||
| +		compatible = "pwm-fan"; | ||||
| +		pwms = <&gpio0 24 4000 0>; | ||||
|  	}; | ||||
|   | ||||
|  	dsa@0 { | ||||
| @@ -1,19 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-388-rd.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-rd.dts | ||||
| @@ -79,6 +79,16 @@ | ||||
|  					compatible = "st,m25p128", "jedec,spi-nor"; | ||||
|  					reg = <0>; /* Chip select 0 */ | ||||
|  					spi-max-frequency = <108000000>; | ||||
| + | ||||
| +					partition@0 { | ||||
| +						label = "uboot"; | ||||
| +						reg = <0 0x400000>; | ||||
| +					}; | ||||
| + | ||||
| +					partition@1 { | ||||
| +						label = "firmware"; | ||||
| +						reg = <0x400000 0xc00000>; | ||||
| +					}; | ||||
|  				}; | ||||
|  			}; | ||||
|   | ||||
| @@ -1,34 +0,0 @@ | ||||
| From 9861f93a59142a3131870df2521eb2deb73026d7 Mon Sep 17 00:00:00 2001 | ||||
| From: Maxime Ripard <maxime.ripard@free-electrons.com> | ||||
| Date: Tue, 13 Jan 2015 11:14:09 +0100 | ||||
| Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions | ||||
|  | ||||
| Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-385-db-ap.dts | 15 +++++++++++++++ | ||||
|  1 file changed, 15 insertions(+) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-385-db-ap.dts | ||||
| +++ b/arch/arm/boot/dts/armada-385-db-ap.dts | ||||
| @@ -184,6 +184,21 @@ | ||||
|  				marvell,nand-keep-config; | ||||
|  				marvell,nand-enable-arbiter; | ||||
|  				nand-on-flash-bbt; | ||||
| + | ||||
| +				mtd0@00000000 { | ||||
| +					label = "u-boot"; | ||||
| +					reg = <0x00000000 0x00800000>; | ||||
| +				}; | ||||
| + | ||||
| +				mtd1@00800000 { | ||||
| +					label = "kernel"; | ||||
| +					reg = <0x00800000 0x00800000>; | ||||
| +				}; | ||||
| + | ||||
| +				mtd2@01000000 { | ||||
| +					label = "ubi"; | ||||
| +					reg = <0x01000000 0x3f000000>; | ||||
| +				}; | ||||
|  			}; | ||||
|   | ||||
|  			usb3@f0000 { | ||||
| @@ -1,21 +0,0 @@ | ||||
| --- a/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| @@ -430,6 +430,18 @@ | ||||
|  		}; | ||||
|  	}; | ||||
|   | ||||
| +	mvsw61xx { | ||||
| +		#address-cells = <1>; | ||||
| +		#size-cells = <0>; | ||||
| +		compatible = "marvell,88e6176"; | ||||
| +		status = "okay"; | ||||
| +		reg = <0x4>; | ||||
| +		is-indirect; | ||||
| + | ||||
| +		mii-bus = <&mdio>; | ||||
| +		cpu-port-0 = <5>; | ||||
| +	}; | ||||
| + | ||||
|  	gpio-keys { | ||||
|  		compatible = "gpio-keys"; | ||||
|  		pinctrl-0 = <&rear_button_pins>; | ||||
| @@ -1,84 +0,0 @@ | ||||
| From 63ff73593c2f5d3fc1cba479321d192caaca48aa Mon Sep 17 00:00:00 2001 | ||||
| From: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| Date: Sat, 12 Sep 2015 18:43:39 +0100 | ||||
| Subject: [PATCH 738/744] ARM: dts: armada388-clearfog: add SFP module support | ||||
|  | ||||
| Add SFP module support for Clearfog using the SFP phylink support. | ||||
|  | ||||
| Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> | ||||
| --- | ||||
|  arch/arm/boot/dts/armada-388-clearfog.dts | 44 ++++++++----------------------- | ||||
|  1 file changed, 11 insertions(+), 33 deletions(-) | ||||
|  | ||||
| --- a/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| +++ b/arch/arm/boot/dts/armada-388-clearfog.dts | ||||
| @@ -90,16 +90,12 @@ | ||||
|  			}; | ||||
|   | ||||
|  			ethernet@34000 { | ||||
| +				managed = "in-band-status"; | ||||
|  				phy-mode = "sgmii"; | ||||
|  				buffer-manager = <&bm>; | ||||
|  				bm,pool-long = <3>; | ||||
|  				bm,pool-short = <1>; | ||||
|  				status = "okay"; | ||||
| - | ||||
| -				fixed-link { | ||||
| -					speed = <1000>; | ||||
| -					full-duplex; | ||||
| -				}; | ||||
|  			}; | ||||
|   | ||||
|  			i2c@11000 { | ||||
| @@ -183,34 +179,6 @@ | ||||
|  						output-low; | ||||
|  						line-name = "m.2 devslp"; | ||||
|  					}; | ||||
| -					sfp_los { | ||||
| -						/* SFP loss of signal */ | ||||
| -						gpio-hog; | ||||
| -						gpios = <12 GPIO_ACTIVE_HIGH>; | ||||
| -						input; | ||||
| -						line-name = "sfp-los"; | ||||
| -					}; | ||||
| -					sfp_tx_fault { | ||||
| -						/* SFP laser fault */ | ||||
| -						gpio-hog; | ||||
| -						gpios = <13 GPIO_ACTIVE_HIGH>; | ||||
| -						input; | ||||
| -						line-name = "sfp-tx-fault"; | ||||
| -					}; | ||||
| -					sfp_tx_disable { | ||||
| -						/* SFP transmit disable */ | ||||
| -						gpio-hog; | ||||
| -						gpios = <14 GPIO_ACTIVE_HIGH>; | ||||
| -						output-low; | ||||
| -						line-name = "sfp-tx-disable"; | ||||
| -					}; | ||||
| -					sfp_mod_def0 { | ||||
| -						/* SFP module present */ | ||||
| -						gpio-hog; | ||||
| -						gpios = <15 GPIO_ACTIVE_LOW>; | ||||
| -						input; | ||||
| -						line-name = "sfp-mod-def0"; | ||||
| -					}; | ||||
|  				}; | ||||
|   | ||||
|  				/* The MCP3021 is 100kHz clock only */ | ||||
| @@ -374,6 +342,16 @@ | ||||
|  		}; | ||||
|  	}; | ||||
|   | ||||
| +	sfp: sfp { | ||||
| +		compatible = "sff,sfp"; | ||||
| +		i2c-bus = <&i2c1>; | ||||
| +		los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; | ||||
| +		moddef0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>; | ||||
| +		sfp,ethernet = <ð2>; | ||||
| +		tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>; | ||||
| +		tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>; | ||||
| +	}; | ||||
| + | ||||
|  	dsa@0 { | ||||
|  		compatible = "marvell,dsa"; | ||||
|  		dsa,ethernet = <ð1>; | ||||
| @@ -1,96 +0,0 @@ | ||||
| From 28baa5e2635285b178326b301f534ed95c65dd01 Mon Sep 17 00:00:00 2001 | ||||
| From: Jonas Gorski <jonas.gorski@gmail.com> | ||||
| Date: Thu, 29 Sep 2016 11:44:39 +0200 | ||||
| Subject: [PATCH] sfp: retry phy probe if unsuccessful | ||||
|  | ||||
| Some phys seem to take longer than 50 ms to come out of reset, so retry | ||||
| until we find a phy. | ||||
|  | ||||
| Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> | ||||
| --- | ||||
|  drivers/net/phy/sfp.c | 38 +++++++++++++++++++++++++------------- | ||||
|  1 file changed, 25 insertions(+), 13 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/sfp.c | ||||
| +++ b/drivers/net/phy/sfp.c | ||||
| @@ -488,7 +488,7 @@ static void sfp_sm_phy_detach(struct sfp | ||||
|  	sfp->mod_phy = NULL; | ||||
|  } | ||||
|   | ||||
| -static void sfp_sm_probe_phy(struct sfp *sfp) | ||||
| +static int sfp_sm_probe_phy(struct sfp *sfp) | ||||
|  { | ||||
|  	struct phy_device *phy; | ||||
|  	int err; | ||||
| @@ -498,11 +498,11 @@ static void sfp_sm_probe_phy(struct sfp | ||||
|  	phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR); | ||||
|  	if (IS_ERR(phy)) { | ||||
|  		dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy)); | ||||
| -		return; | ||||
| +		return PTR_ERR(phy); | ||||
|  	} | ||||
|  	if (!phy) { | ||||
| -		dev_info(sfp->dev, "no PHY detected\n"); | ||||
| -		return; | ||||
| +		dev_dbg(sfp->dev, "no PHY detected\n"); | ||||
| +		return -EAGAIN; | ||||
|  	} | ||||
|   | ||||
|  	err = phylink_connect_phy(sfp->phylink, phy); | ||||
| @@ -510,11 +510,13 @@ static void sfp_sm_probe_phy(struct sfp | ||||
|  		phy_device_remove(phy); | ||||
|  		phy_device_free(phy); | ||||
|  		dev_err(sfp->dev, "phylink_connect_phy failed: %d\n", err); | ||||
| -		return; | ||||
| +		return err; | ||||
|  	} | ||||
|   | ||||
|  	sfp->mod_phy = phy; | ||||
|  	phy_start(phy); | ||||
| + | ||||
| +	return 0; | ||||
|  } | ||||
|   | ||||
|  static void sfp_sm_link_up(struct sfp *sfp) | ||||
| @@ -565,13 +567,6 @@ static void sfp_sm_mod_init(struct sfp * | ||||
|  { | ||||
|  	sfp_module_tx_enable(sfp); | ||||
|   | ||||
| -	/* Wait t_init before indicating that the link is up, provided the | ||||
| -	 * current state indicates no TX_FAULT.  If TX_FAULT clears before | ||||
| -	 * this time, that's fine too. | ||||
| -	 */ | ||||
| -	sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); | ||||
| -	sfp->sm_retries = 5; | ||||
| - | ||||
|  	if (sfp->phylink) { | ||||
|  		/* Setting the serdes link mode is guesswork: there's no | ||||
|  		 * field in the EEPROM which indicates what mode should | ||||
| @@ -587,9 +582,26 @@ static void sfp_sm_mod_init(struct sfp * | ||||
|  		    !sfp->id.base.e100_base_fx) { | ||||
|  			phylink_set_link_an_mode(sfp->phylink, MLO_AN_8023Z); | ||||
|  		} else { | ||||
| +			int ret; | ||||
| + | ||||
|  			phylink_set_link_an_mode(sfp->phylink, MLO_AN_SGMII); | ||||
| -			sfp_sm_probe_phy(sfp); | ||||
| + | ||||
| +			ret = sfp_sm_probe_phy(sfp); | ||||
| +			if (ret) { | ||||
| +				if (ret == -EAGAIN) | ||||
| +					sfp_sm_set_timer(sfp, T_PROBE_RETRY); | ||||
| +				else | ||||
| +					sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0); | ||||
| +				return; | ||||
| +			} | ||||
|  		} | ||||
| + | ||||
| +		/* Wait t_init before indicating that the link is up, provided the | ||||
| +		 * current state indicates no TX_FAULT.  If TX_FAULT clears before | ||||
| +		 * this time, that's fine too. | ||||
| +		 */ | ||||
| +		sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES); | ||||
| +		sfp->sm_retries = 5; | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| The hardware queue scheduling is apparently configured with fixed | ||||
| priorities, which creates a nasty fairness issue where traffic from one | ||||
| CPU can starve traffic from all other CPUs. | ||||
|  | ||||
| Work around this issue by forcing all tx packets to go through one CPU, | ||||
| until this issue is fixed properly. | ||||
|  | ||||
| Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||
| --- | ||||
| --- a/drivers/net/ethernet/marvell/mvneta.c | ||||
| +++ b/drivers/net/ethernet/marvell/mvneta.c | ||||
| @@ -3984,6 +3984,16 @@ static int mvneta_ethtool_set_eee(struct | ||||
|  	return phylink_ethtool_set_eee(pp->phylink, eee); | ||||
|  } | ||||
|   | ||||
| +static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, | ||||
| +			       void *accel_priv, | ||||
| +			       select_queue_fallback_t fallback) | ||||
| +{ | ||||
| +	/* XXX: hardware queue scheduling is broken, | ||||
| +	 * use only one queue until it is fixed */ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| + | ||||
|  static const struct net_device_ops mvneta_netdev_ops = { | ||||
|  	.ndo_open            = mvneta_open, | ||||
|  	.ndo_stop            = mvneta_stop, | ||||
| @@ -3994,6 +4004,7 @@ static const struct net_device_ops mvnet | ||||
|  	.ndo_fix_features    = mvneta_fix_features, | ||||
|  	.ndo_get_stats64     = mvneta_get_stats64, | ||||
|  	.ndo_do_ioctl        = mvneta_ioctl, | ||||
| +	.ndo_select_queue    = mvneta_select_queue, | ||||
|  }; | ||||
|   | ||||
|  const struct ethtool_ops mvneta_eth_tool_ops = { | ||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau