mvebu: add linux 4.9 support
Signed-off-by: Felix Fietkau <nbd@nbd.name> Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
This commit is contained in:
		@@ -14,7 +14,7 @@ CPU_TYPE:=cortex-a9
 | 
				
			|||||||
CPU_SUBTYPE:=vfpv3
 | 
					CPU_SUBTYPE:=vfpv3
 | 
				
			||||||
MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
 | 
					MAINTAINER:=Imre Kaloz <kaloz@openwrt.org>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KERNEL_PATCHVER:=4.4
 | 
					KERNEL_PATCHVER:=4.9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(INCLUDE_DIR)/target.mk
 | 
					include $(INCLUDE_DIR)/target.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,11 +16,31 @@ preinit_set_mac_address() {
 | 
				
			|||||||
		ifconfig eth1 hw ether $mac 2>/dev/null
 | 
							ifconfig eth1 hw ether $mac 2>/dev/null
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
	armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby)
 | 
						armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby)
 | 
				
			||||||
 | 
							# rename interfaces back to the way they were with 4.4
 | 
				
			||||||
 | 
							case "$(readlink /sys/class/net/eth0)" in
 | 
				
			||||||
 | 
								*f1070000*)
 | 
				
			||||||
 | 
									ip link set eth0 name tmp0
 | 
				
			||||||
 | 
									ip link set eth1 name eth0
 | 
				
			||||||
 | 
									ip link set tmp0 name eth1
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
 | 
							mac=$(mtd_get_mac_ascii devinfo hw_mac_addr)
 | 
				
			||||||
		mac_wan=$(macaddr_setbit_la "$mac")
 | 
							mac_wan=$(macaddr_setbit_la "$mac")
 | 
				
			||||||
		ifconfig eth1 hw ether $mac 2>/dev/null
 | 
							ifconfig eth1 hw ether $mac 2>/dev/null
 | 
				
			||||||
		ifconfig eth0 hw ether $mac_wan 2>/dev/null
 | 
							ifconfig eth0 hw ether $mac_wan 2>/dev/null
 | 
				
			||||||
		;;
 | 
							;;
 | 
				
			||||||
 | 
						armada-385-db-ap|armada-388-clearfog)
 | 
				
			||||||
 | 
							# rename interfaces back to the way they were with 4.4
 | 
				
			||||||
 | 
							case "$(readlink /sys/class/net/eth0)" in
 | 
				
			||||||
 | 
								*f1070000*)
 | 
				
			||||||
 | 
									ip link set eth0 name tmp0
 | 
				
			||||||
 | 
									ip link set eth1 name eth0
 | 
				
			||||||
 | 
									ip link set eth2 name eth1
 | 
				
			||||||
 | 
									ip link set tmp0 name eth2
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
	esac
 | 
						esac
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										454
									
								
								target/linux/mvebu/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										454
									
								
								target/linux/mvebu/config-4.9
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,454 @@
 | 
				
			|||||||
 | 
					CONFIG_AHCI_MVEBU=y
 | 
				
			||||||
 | 
					CONFIG_ALIGNMENT_TRAP=y
 | 
				
			||||||
 | 
					CONFIG_ARCH_CLOCKSOURCE_DATA=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_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_ARM=y
 | 
				
			||||||
 | 
					CONFIG_ARMADA_370_CLK=y
 | 
				
			||||||
 | 
					CONFIG_ARMADA_370_XP_IRQ=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_IDIV=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_BINFMT_FLAT is not set
 | 
				
			||||||
 | 
					CONFIG_BLK_DEV_LOOP=y
 | 
				
			||||||
 | 
					CONFIG_BLK_MQ_PCI=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_CPUFREQ_DT_PLATDEV=y
 | 
				
			||||||
 | 
					CONFIG_CPU_32v6K=y
 | 
				
			||||||
 | 
					CONFIG_CPU_32v7=y
 | 
				
			||||||
 | 
					CONFIG_CPU_ABRT_EV7=y
 | 
				
			||||||
 | 
					# CONFIG_CPU_BIG_ENDIAN is not set
 | 
				
			||||||
 | 
					# CONFIG_CPU_BPREDICT_DISABLE is not set
 | 
				
			||||||
 | 
					CONFIG_CPU_CACHE_V7=y
 | 
				
			||||||
 | 
					CONFIG_CPU_CACHE_VIPT=y
 | 
				
			||||||
 | 
					CONFIG_CPU_COPY_V6=y
 | 
				
			||||||
 | 
					CONFIG_CPU_CP15=y
 | 
				
			||||||
 | 
					CONFIG_CPU_CP15_MMU=y
 | 
				
			||||||
 | 
					CONFIG_CPU_FREQ=y
 | 
				
			||||||
 | 
					CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 | 
				
			||||||
 | 
					# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
 | 
				
			||||||
 | 
					CONFIG_CPU_FREQ_GOV_ATTR_SET=y
 | 
				
			||||||
 | 
					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_HOTPLUG_STATE_CONTROL is not set
 | 
				
			||||||
 | 
					# 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_CRC32=y
 | 
				
			||||||
 | 
					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_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_EARLY_IOREMAP=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_IDLE_POLL_SETUP=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_IO=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_IRQ_CHIP=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_IRQ_SHOW=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_MSI_IRQ=y
 | 
				
			||||||
 | 
					CONFIG_GENERIC_MSI_IRQ_DOMAIN=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_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_SMCCC=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_ARM_TWD=y
 | 
				
			||||||
 | 
					# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
 | 
				
			||||||
 | 
					CONFIG_HAVE_CBPF_JIT=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_CC_STACKPROTECTOR=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_CLK=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_CLK_PREPARE=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_CONTEXT_TRACKING=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_C_RECORDMCOUNT=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_DEBUG_KMEMLEAK=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_DMA_API_DEBUG=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_DMA_CONTIGUOUS=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_DYNAMIC_FTRACE=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_FUNCTION_TRACER=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 | 
				
			||||||
 | 
					CONFIG_HAVE_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_MFD_MAX77620 is not set
 | 
				
			||||||
 | 
					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_MVNETA_BM_ENABLE=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_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_PADATA=y
 | 
				
			||||||
 | 
					CONFIG_PAGE_OFFSET=0xC0000000
 | 
				
			||||||
 | 
					CONFIG_PCI=y
 | 
				
			||||||
 | 
					CONFIG_PCI_DOMAINS=y
 | 
				
			||||||
 | 
					CONFIG_PCI_DOMAINS_GENERIC=y
 | 
				
			||||||
 | 
					CONFIG_PCI_MSI=y
 | 
				
			||||||
 | 
					CONFIG_PCI_MSI_IRQ_DOMAIN=y
 | 
				
			||||||
 | 
					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_REGMAP_SPI=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_RTC_I2C_AND_SPI=y
 | 
				
			||||||
 | 
					CONFIG_RTC_MC146818_LIB=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_SERIAL_MVEBU_CONSOLE=y
 | 
				
			||||||
 | 
					CONFIG_SERIAL_MVEBU_UART=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_CADENCE_QUADSPI is not set
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										748
									
								
								target/linux/mvebu/patches-4.9/002-add_powertables.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										748
									
								
								target/linux/mvebu/patches-4.9/002-add_powertables.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,748 @@
 | 
				
			|||||||
 | 
					--- 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 {
 | 
				
			||||||
							
								
								
									
										40
									
								
								target/linux/mvebu/patches-4.9/003-add_switch_nodes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								target/linux/mvebu/patches-4.9/003-add_switch_nodes.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
 | 
				
			||||||
 | 
					@@ -455,6 +455,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
 | 
				
			||||||
 | 
					@@ -304,6 +304,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 {
 | 
				
			||||||
							
								
								
									
										11
									
								
								target/linux/mvebu/patches-4.9/010-build_new_dtbs.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								target/linux/mvebu/patches-4.9/010-build_new_dtbs.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					--- a/arch/arm/boot/dts/Makefile
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/dts/Makefile
 | 
				
			||||||
 | 
					@@ -921,6 +921,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-clearfog.dtb \
 | 
				
			||||||
 | 
					 	armada-388-db.dtb \
 | 
				
			||||||
 | 
					 	armada-388-gp.dtb \
 | 
				
			||||||
							
								
								
									
										60
									
								
								target/linux/mvebu/patches-4.9/100-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								target/linux/mvebu/patches-4.9/100-find_active_root.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					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,
 | 
				
			||||||
 | 
					 				   const struct mtd_partition **pparts,
 | 
				
			||||||
 | 
					 				   struct mtd_part_parser_data *data)
 | 
				
			||||||
 | 
					@@ -33,6 +35,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;
 | 
				
			||||||
 | 
					@@ -109,9 +112,13 @@ static int parse_ofpart_partitions(struc
 | 
				
			||||||
 | 
					 		parts[i].offset = of_read_number(reg, a_cells);
 | 
				
			||||||
 | 
					 		parts[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);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 		parts[i].name = partname;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		if (of_get_property(pp, "read-only", &len))
 | 
				
			||||||
 | 
					@@ -212,6 +219,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);
 | 
				
			||||||
							
								
								
									
										15
									
								
								target/linux/mvebu/patches-4.9/102-revert_i2c_delay.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								target/linux/mvebu/patches-4.9/102-revert_i2c_delay.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					--- a/arch/arm/boot/dts/armada-xp.dtsi
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/dts/armada-xp.dtsi
 | 
				
			||||||
 | 
					@@ -85,12 +85,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>;
 | 
				
			||||||
 | 
					 			};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -727,7 +727,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 */
 | 
				
			||||||
@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					--- 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>;
 | 
				
			||||||
@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					--- 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 {
 | 
				
			||||||
 | 
					 			i2c@11000 {
 | 
				
			||||||
 | 
					@@ -88,6 +89,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;
 | 
				
			||||||
 | 
					@@ -97,6 +101,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;
 | 
				
			||||||
 | 
					@@ -107,6 +114,10 @@
 | 
				
			||||||
 | 
					 				status = "okay";
 | 
				
			||||||
 | 
					 			};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+			bm@c8000 {
 | 
				
			||||||
 | 
					+				status = "okay";
 | 
				
			||||||
 | 
					+			};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 			sata@a8000 {
 | 
				
			||||||
 | 
					 				status = "okay";
 | 
				
			||||||
 | 
					 			};
 | 
				
			||||||
 | 
					@@ -193,6 +204,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";
 | 
				
			||||||
 | 
					@@ -367,6 +378,10 @@
 | 
				
			||||||
 | 
					 				};
 | 
				
			||||||
 | 
					 			};
 | 
				
			||||||
 | 
					 		};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		bm-bppi {
 | 
				
			||||||
 | 
					+			status = "okay";
 | 
				
			||||||
 | 
					+		};
 | 
				
			||||||
 | 
					 	};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	gpio_keys {
 | 
				
			||||||
@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -791,24 +791,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;
 | 
				
			||||||
 | 
					@@ -850,8 +837,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) {
 | 
				
			||||||
 | 
					@@ -896,7 +882,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)
 | 
				
			||||||
 | 
					@@ -1856,9 +1842,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;
 | 
				
			||||||
@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -1719,8 +1719,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++) {
 | 
				
			||||||
 | 
					@@ -1728,6 +1730,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))
 | 
				
			||||||
 | 
					@@ -1738,6 +1745,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 */
 | 
				
			||||||
 | 
					@@ -1751,7 +1760,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -2358,6 +2367,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);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -2382,9 +2393,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;
 | 
				
			||||||
 | 
					@@ -2882,6 +2894,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)
 | 
				
			||||||
 | 
					@@ -2893,6 +2907,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;
 | 
				
			||||||
@@ -0,0 +1,433 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -319,6 +319,11 @@ config GPIO_MVEBU
 | 
				
			||||||
 | 
					 	depends on OF_GPIO
 | 
				
			||||||
 | 
					 	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
 | 
				
			||||||
 | 
					@@ -81,6 +81,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.
 | 
				
			||||||
 | 
					@@ -216,7 +199,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 = gpiochip_get_data(chip);
 | 
				
			||||||
 | 
					 	unsigned long flags;
 | 
				
			||||||
 | 
					@@ -596,6 +579,8 @@ static int mvebu_gpio_suspend(struct pla
 | 
				
			||||||
 | 
					 		BUG();
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	mvebu_pwm_suspend(mvchip);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -639,6 +624,8 @@ static int mvebu_gpio_resume(struct plat
 | 
				
			||||||
 | 
					 		BUG();
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	mvebu_pwm_resume(mvchip);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -650,7 +637,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;
 | 
				
			||||||
 | 
					 	bool have_irqs;
 | 
				
			||||||
 | 
					 	int soc_variant;
 | 
				
			||||||
 | 
					@@ -684,10 +670,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);
 | 
				
			||||||
 | 
					@@ -814,7 +800,8 @@ static int mvebu_gpio_probe(struct platf
 | 
				
			||||||
 | 
					 						 mvchip);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return 0;
 | 
				
			||||||
 | 
					+	/* Armada 370/XP has simple PWM support for gpio lines */
 | 
				
			||||||
 | 
					+	return mvebu_pwm_probe(pdev, mvchip, id);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 err_domain:
 | 
				
			||||||
 | 
					 	irq_domain_remove(mvchip->domain);
 | 
				
			||||||
 | 
					--- /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
 | 
				
			||||||
@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					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>;
 | 
				
			||||||
 | 
					+		};
 | 
				
			||||||
@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -144,24 +144,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 {
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -135,6 +135,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
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -416,13 +416,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 {
 | 
				
			||||||
@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					--- a/arch/arm/boot/dts/armada-388-rd.dts
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/dts/armada-388-rd.dts
 | 
				
			||||||
 | 
					@@ -140,6 +140,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>;
 | 
				
			||||||
 | 
					+		};
 | 
				
			||||||
 | 
					 	};
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -181,19 +181,19 @@
 | 
				
			||||||
 | 
					 					#size-cells = <1>;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 					partition@0 {
 | 
				
			||||||
 | 
					-						label = "U-Boot";
 | 
				
			||||||
 | 
					+						label = "u-boot";
 | 
				
			||||||
 | 
					 						reg = <0x00000000 0x00800000>;
 | 
				
			||||||
 | 
					 						read-only;
 | 
				
			||||||
 | 
					 					};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 					partition@800000 {
 | 
				
			||||||
 | 
					-						label = "uImage";
 | 
				
			||||||
 | 
					+						label = "kernel";
 | 
				
			||||||
 | 
					 						reg = <0x00800000 0x00400000>;
 | 
				
			||||||
 | 
					 						read-only;
 | 
				
			||||||
 | 
					 					};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 					partition@c00000 {
 | 
				
			||||||
 | 
					-						label = "Root";
 | 
				
			||||||
 | 
					+						label = "ubi";
 | 
				
			||||||
 | 
					 						reg = <0x00c00000 0x3f400000>;
 | 
				
			||||||
 | 
					 					};
 | 
				
			||||||
 | 
					 				};
 | 
				
			||||||
@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					--- a/arch/arm/boot/dts/armada-388-clearfog.dts
 | 
				
			||||||
 | 
					+++ b/arch/arm/boot/dts/armada-388-clearfog.dts
 | 
				
			||||||
 | 
					@@ -406,6 +406,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>;
 | 
				
			||||||
@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					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 */
 | 
				
			||||||
 | 
					@@ -350,6 +318,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>;
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -3835,6 +3835,16 @@ static int mvneta_ethtool_get_rxfh(struc
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+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,
 | 
				
			||||||
 | 
					@@ -3845,6 +3855,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 = {
 | 
				
			||||||
@@ -0,0 +1,177 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Sun, 12 Feb 2017 17:27:17 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -955,6 +955,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
 | 
				
			||||||
 | 
					@@ -996,8 +1006,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;
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -1009,9 +1018,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;
 | 
				
			||||||
 | 
					@@ -1036,8 +1043,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:
 | 
				
			||||||
 | 
					@@ -1047,13 +1053,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 and link changed
 | 
				
			||||||
 | 
					@@ -1076,14 +1081,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);
 | 
				
			||||||
 | 
					@@ -1091,8 +1094,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;
 | 
				
			||||||
 | 
					@@ -1112,11 +1114,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;
 | 
				
			||||||
 | 
					@@ -1128,11 +1130,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
 | 
				
			||||||
 | 
					@@ -645,6 +645,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
 | 
				
			||||||
 | 
					@@ -899,6 +912,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
 | 
				
			||||||
 | 
					@@ -426,6 +426,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(to_mdio_device(d), \
 | 
				
			||||||
@@ -0,0 +1,292 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Wed, 4 Jan 2017 10:46:43 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: move phy MMD accessors to phy-core.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Move the phy_(read|write)__mmd() helpers out of line, they will become
 | 
				
			||||||
 | 
					our main MMD accessor functions, and so will be a little more complex.
 | 
				
			||||||
 | 
					This complexity doesn't belong in an inline function.  Also move the
 | 
				
			||||||
 | 
					_indirect variants as well to keep like functionality together.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 create mode 100644 drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -1,6 +1,7 @@
 | 
				
			||||||
 | 
					 # Makefile for Linux PHY drivers and MDIO bus drivers
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-libphy-y			:= phy.o phy_device.o mdio_bus.o mdio_device.o
 | 
				
			||||||
 | 
					+libphy-y			:= phy.o phy_device.o mdio_bus.o mdio_device.o \
 | 
				
			||||||
 | 
					+				   phy-core.o
 | 
				
			||||||
 | 
					 libphy-$(CONFIG_SWPHY)		+= swphy.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_BOARDINFO)	+= mdio-boardinfo.o
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -1171,91 +1171,6 @@ void phy_mac_interrupt(struct phy_device
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_mac_interrupt);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
 | 
				
			||||||
 | 
					-				    int addr)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	/* Write the desired MMD Devad */
 | 
				
			||||||
 | 
					-	bus->write(bus, addr, MII_MMD_CTRL, devad);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	/* Write the desired MMD register address */
 | 
				
			||||||
 | 
					-	bus->write(bus, addr, MII_MMD_DATA, prtad);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	/* Select the Function : DATA with no post increment */
 | 
				
			||||||
 | 
					-	bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/**
 | 
				
			||||||
 | 
					- * phy_read_mmd_indirect - reads data from the MMD registers
 | 
				
			||||||
 | 
					- * @phydev: The PHY device bus
 | 
				
			||||||
 | 
					- * @prtad: MMD Address
 | 
				
			||||||
 | 
					- * @devad: MMD DEVAD
 | 
				
			||||||
 | 
					- *
 | 
				
			||||||
 | 
					- * Description: it reads data from the MMD registers (clause 22 to access to
 | 
				
			||||||
 | 
					- * clause 45) of the specified phy address.
 | 
				
			||||||
 | 
					- * To read these register we have:
 | 
				
			||||||
 | 
					- * 1) Write reg 13 // DEVAD
 | 
				
			||||||
 | 
					- * 2) Write reg 14 // MMD Address
 | 
				
			||||||
 | 
					- * 3) Write reg 13 // MMD Data Command for MMD DEVAD
 | 
				
			||||||
 | 
					- * 3) Read  reg 14 // Read MMD data
 | 
				
			||||||
 | 
					- */
 | 
				
			||||||
 | 
					-int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	struct phy_driver *phydrv = phydev->drv;
 | 
				
			||||||
 | 
					-	int addr = phydev->mdio.addr;
 | 
				
			||||||
 | 
					-	int value = -1;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (!phydrv->read_mmd_indirect) {
 | 
				
			||||||
 | 
					-		struct mii_bus *bus = phydev->mdio.bus;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		mutex_lock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					-		mmd_phy_indirect(bus, prtad, devad, addr);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		/* Read the content of the MMD's selected register */
 | 
				
			||||||
 | 
					-		value = bus->read(bus, addr, MII_MMD_DATA);
 | 
				
			||||||
 | 
					-		mutex_unlock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					-	} else {
 | 
				
			||||||
 | 
					-		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-	return value;
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-EXPORT_SYMBOL(phy_read_mmd_indirect);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/**
 | 
				
			||||||
 | 
					- * phy_write_mmd_indirect - writes data to the MMD registers
 | 
				
			||||||
 | 
					- * @phydev: The PHY device
 | 
				
			||||||
 | 
					- * @prtad: MMD Address
 | 
				
			||||||
 | 
					- * @devad: MMD DEVAD
 | 
				
			||||||
 | 
					- * @data: data to write in the MMD register
 | 
				
			||||||
 | 
					- *
 | 
				
			||||||
 | 
					- * Description: Write data from the MMD registers of the specified
 | 
				
			||||||
 | 
					- * phy address.
 | 
				
			||||||
 | 
					- * To write these register we have:
 | 
				
			||||||
 | 
					- * 1) Write reg 13 // DEVAD
 | 
				
			||||||
 | 
					- * 2) Write reg 14 // MMD Address
 | 
				
			||||||
 | 
					- * 3) Write reg 13 // MMD Data Command for MMD DEVAD
 | 
				
			||||||
 | 
					- * 3) Write reg 14 // Write MMD data
 | 
				
			||||||
 | 
					- */
 | 
				
			||||||
 | 
					-void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
 | 
				
			||||||
 | 
					-				   int devad, u32 data)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	struct phy_driver *phydrv = phydev->drv;
 | 
				
			||||||
 | 
					-	int addr = phydev->mdio.addr;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (!phydrv->write_mmd_indirect) {
 | 
				
			||||||
 | 
					-		struct mii_bus *bus = phydev->mdio.bus;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		mutex_lock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					-		mmd_phy_indirect(bus, prtad, devad, addr);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		/* Write the data into MMD's selected register */
 | 
				
			||||||
 | 
					-		bus->write(bus, addr, MII_MMD_DATA, data);
 | 
				
			||||||
 | 
					-		mutex_unlock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					-	} else {
 | 
				
			||||||
 | 
					-		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-EXPORT_SYMBOL(phy_write_mmd_indirect);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_init_eee - init and check the EEE feature
 | 
				
			||||||
 | 
					  * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,135 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Core PHY library, taken from phy.c
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * 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/phy.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
 | 
				
			||||||
 | 
					+				    int addr)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	/* Write the desired MMD Devad */
 | 
				
			||||||
 | 
					+	bus->write(bus, addr, MII_MMD_CTRL, devad);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Write the desired MMD register address */
 | 
				
			||||||
 | 
					+	bus->write(bus, addr, MII_MMD_DATA, prtad);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Select the Function : DATA with no post increment */
 | 
				
			||||||
 | 
					+	bus->write(bus, addr, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR));
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_read_mmd_indirect - reads data from the MMD registers
 | 
				
			||||||
 | 
					+ * @phydev: The PHY device bus
 | 
				
			||||||
 | 
					+ * @prtad: MMD Address
 | 
				
			||||||
 | 
					+ * @devad: MMD DEVAD
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Description: it reads data from the MMD registers (clause 22 to access to
 | 
				
			||||||
 | 
					+ * clause 45) of the specified phy address.
 | 
				
			||||||
 | 
					+ * To read these register we have:
 | 
				
			||||||
 | 
					+ * 1) Write reg 13 // DEVAD
 | 
				
			||||||
 | 
					+ * 2) Write reg 14 // MMD Address
 | 
				
			||||||
 | 
					+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
 | 
				
			||||||
 | 
					+ * 3) Read  reg 14 // Read MMD data
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct phy_driver *phydrv = phydev->drv;
 | 
				
			||||||
 | 
					+	int addr = phydev->mdio.addr;
 | 
				
			||||||
 | 
					+	int value = -1;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!phydrv->read_mmd_indirect) {
 | 
				
			||||||
 | 
					+		struct mii_bus *bus = phydev->mdio.bus;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		mutex_lock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					+		mmd_phy_indirect(bus, prtad, devad, addr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Read the content of the MMD's selected register */
 | 
				
			||||||
 | 
					+		value = bus->read(bus, addr, MII_MMD_DATA);
 | 
				
			||||||
 | 
					+		mutex_unlock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	return value;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_read_mmd_indirect);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_read_mmd - Convenience function for reading a register
 | 
				
			||||||
 | 
					+ * from an MMD on a given PHY.
 | 
				
			||||||
 | 
					+ * @phydev: The phy_device struct
 | 
				
			||||||
 | 
					+ * @devad: The MMD to read from
 | 
				
			||||||
 | 
					+ * @regnum: The register on the MMD to read
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Same rules as for phy_read();
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					+		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
 | 
				
			||||||
 | 
					+			    MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff));
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_read_mmd);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_write_mmd_indirect - writes data to the MMD registers
 | 
				
			||||||
 | 
					+ * @phydev: The PHY device
 | 
				
			||||||
 | 
					+ * @prtad: MMD Address
 | 
				
			||||||
 | 
					+ * @devad: MMD DEVAD
 | 
				
			||||||
 | 
					+ * @data: data to write in the MMD register
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Description: Write data from the MMD registers of the specified
 | 
				
			||||||
 | 
					+ * phy address.
 | 
				
			||||||
 | 
					+ * To write these register we have:
 | 
				
			||||||
 | 
					+ * 1) Write reg 13 // DEVAD
 | 
				
			||||||
 | 
					+ * 2) Write reg 14 // MMD Address
 | 
				
			||||||
 | 
					+ * 3) Write reg 13 // MMD Data Command for MMD DEVAD
 | 
				
			||||||
 | 
					+ * 3) Write reg 14 // Write MMD data
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+void phy_write_mmd_indirect(struct phy_device *phydev, int prtad,
 | 
				
			||||||
 | 
					+				   int devad, u32 data)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct phy_driver *phydrv = phydev->drv;
 | 
				
			||||||
 | 
					+	int addr = phydev->mdio.addr;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!phydrv->write_mmd_indirect) {
 | 
				
			||||||
 | 
					+		struct mii_bus *bus = phydev->mdio.bus;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		mutex_lock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					+		mmd_phy_indirect(bus, prtad, devad, addr);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Write the data into MMD's selected register */
 | 
				
			||||||
 | 
					+		bus->write(bus, addr, MII_MMD_DATA, data);
 | 
				
			||||||
 | 
					+		mutex_unlock(&bus->mdio_lock);
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_write_mmd_indirect);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_write_mmd - Convenience function for writing a register
 | 
				
			||||||
 | 
					+ * on an MMD on a given PHY.
 | 
				
			||||||
 | 
					+ * @phydev: The phy_device struct
 | 
				
			||||||
 | 
					+ * @devad: The MMD to read from
 | 
				
			||||||
 | 
					+ * @regnum: The register on the MMD to read
 | 
				
			||||||
 | 
					+ * @val: value to write to @regnum
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Same rules as for phy_write();
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					+		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	regnum = MII_ADDR_C45 | ((devad & 0x1f) << 16) | (regnum & 0xffff);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, regnum, val);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_write_mmd);
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -627,14 +627,7 @@ struct phy_fixup {
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Same rules as for phy_read();
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					-static inline int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					-		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
 | 
				
			||||||
 | 
					-			    MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff));
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					+int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_read_mmd_indirect - reads data from the MMD registers
 | 
				
			||||||
 | 
					@@ -728,16 +721,7 @@ static inline bool phy_is_pseudo_fixed_l
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Same rules as for phy_write();
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					-static inline int phy_write_mmd(struct phy_device *phydev, int devad,
 | 
				
			||||||
 | 
					-				u32 regnum, u16 val)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					-		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	regnum = MII_ADDR_C45 | ((devad & 0x1f) << 16) | (regnum & 0xffff);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, regnum, val);
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					+int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_write_mmd_indirect - writes data to the MMD registers
 | 
				
			||||||
@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Wed, 4 Jan 2017 19:20:21 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: make phy_(read|write)_mmd() generic MMD
 | 
				
			||||||
 | 
					 accessors
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Make phy_(read|write)_mmd() generic 802.3 clause 45 register accessors
 | 
				
			||||||
 | 
					for both Clause 22 and Clause 45 PHYs, using either the direct register
 | 
				
			||||||
 | 
					reading for Clause 45, or the indirect method for Clause 22 PHYs.
 | 
				
			||||||
 | 
					Allow this behaviour to be overriden by PHY drivers where necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					@@ -69,11 +69,18 @@ EXPORT_SYMBOL(phy_read_mmd_indirect);
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					-		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+	if (regnum > (u16)~0 || devad > 32)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr,
 | 
				
			||||||
 | 
					-			    MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff));
 | 
				
			||||||
 | 
					+	if (phydev->drv->read_mmd)
 | 
				
			||||||
 | 
					+		return phydev->drv->read_mmd(phydev, devad, regnum);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (phydev->is_c45) {
 | 
				
			||||||
 | 
					+		u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
 | 
				
			||||||
 | 
					+		return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, addr);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_read_mmd_indirect(phydev, regnum, devad);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_read_mmd);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -125,11 +132,21 @@ EXPORT_SYMBOL(phy_write_mmd_indirect);
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	if (!phydev->is_c45)
 | 
				
			||||||
 | 
					-		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+	if (regnum > (u16)~0 || devad > 32)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (phydev->drv->read_mmd)
 | 
				
			||||||
 | 
					+		return phydev->drv->write_mmd(phydev, devad, regnum, val);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (phydev->is_c45) {
 | 
				
			||||||
 | 
					+		u32 addr = MII_ADDR_C45 | (devad << 16) | (regnum & 0xffff);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr,
 | 
				
			||||||
 | 
					+				     addr, val);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	regnum = MII_ADDR_C45 | ((devad & 0x1f) << 16) | (regnum & 0xffff);
 | 
				
			||||||
 | 
					+	phy_write_mmd_indirect(phydev, regnum, devad, val);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, regnum, val);
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_write_mmd);
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -570,6 +570,30 @@ struct phy_driver {
 | 
				
			||||||
 | 
					 	 */
 | 
				
			||||||
 | 
					 	void (*link_change_notify)(struct phy_device *dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/*
 | 
				
			||||||
 | 
					+	 * Phy specific driver override for reading a MMD register.
 | 
				
			||||||
 | 
					+	 * This function is optional for PHY specific drivers.  When
 | 
				
			||||||
 | 
					+	 * not provided, the default MMD read function will be used
 | 
				
			||||||
 | 
					+	 * by phy_read_mmd(), which will use either a direct read for
 | 
				
			||||||
 | 
					+	 * Clause 45 PHYs or an indirect read for Clause 22 PHYs.
 | 
				
			||||||
 | 
					+	 *  devnum is the MMD device number within the PHY device,
 | 
				
			||||||
 | 
					+	 *  regnum is the register within the selected MMD device.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	int (*read_mmd)(struct phy_device *dev, int devnum, u16 regnum);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/*
 | 
				
			||||||
 | 
					+	 * Phy specific driver override for writing a MMD register.
 | 
				
			||||||
 | 
					+	 * This function is optional for PHY specific drivers.  When
 | 
				
			||||||
 | 
					+	 * not provided, the default MMD write function will be used
 | 
				
			||||||
 | 
					+	 * by phy_write_mmd(), which will use either a direct write for
 | 
				
			||||||
 | 
					+	 * Clause 45 PHYs, or an indirect write for Clause 22 PHYs.
 | 
				
			||||||
 | 
					+	 *  devnum is the MMD device number within the PHY device,
 | 
				
			||||||
 | 
					+	 *  regnum is the register within the selected MMD device.
 | 
				
			||||||
 | 
					+	 *  val is the value to be written.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	int (*write_mmd)(struct phy_device *dev, int devnum, u16 regnum,
 | 
				
			||||||
 | 
					+			 u16 val);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	/* A function provided by a phy specific driver to override the
 | 
				
			||||||
 | 
					 	 * the PHY driver framework support for reading a MMD register
 | 
				
			||||||
 | 
					 	 * from the PHY. If not supported, return -1. This function is
 | 
				
			||||||
@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Wed, 4 Jan 2017 21:00:51 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: avoid setting unsupported EEE advertisments
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We currently allow userspace to set any EEE advertisments it desires,
 | 
				
			||||||
 | 
					whether or not the PHY supports them.  For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 # ethtool --set-eee eth1 advertise 0xffffffff
 | 
				
			||||||
 | 
					 # ethtool --show-eee eth1
 | 
				
			||||||
 | 
					 EEE Settings for eth1:
 | 
				
			||||||
 | 
					        EEE status: disabled
 | 
				
			||||||
 | 
					        Tx LPI: disabled
 | 
				
			||||||
 | 
					        Supported EEE link modes:  100baseT/Full
 | 
				
			||||||
 | 
					                                   1000baseT/Full
 | 
				
			||||||
 | 
					                                   10000baseT/Full
 | 
				
			||||||
 | 
					        Advertised EEE link modes:  100baseT/Full
 | 
				
			||||||
 | 
					                                    1000baseT/Full
 | 
				
			||||||
 | 
					                                    1000baseKX/Full
 | 
				
			||||||
 | 
					                                    10000baseT/Full
 | 
				
			||||||
 | 
					                                    10000baseKX4/Full
 | 
				
			||||||
 | 
					                                    10000baseKR/Full
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Clearly, this is not sane, we should only allow link modes that are
 | 
				
			||||||
 | 
					supported to be advertised (as we do elsewhere.)  Ensure that we mask
 | 
				
			||||||
 | 
					the MDIO_AN_EEE_ADV value with the capabilities retrieved from the
 | 
				
			||||||
 | 
					MDIO_PCS_EEE_ABLE register.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -1307,11 +1307,16 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
 | 
				
			||||||
 | 
					+	int cap, adv;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, val);
 | 
				
			||||||
 | 
					+	/* Get Supported EEE */
 | 
				
			||||||
 | 
					+	cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
 | 
				
			||||||
 | 
					+	if (cap < 0)
 | 
				
			||||||
 | 
					+		return cap;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return 0;
 | 
				
			||||||
 | 
					+	adv = ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_ethtool_set_eee);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 12:21:09 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: restart phy autonegotiation after EEE
 | 
				
			||||||
 | 
					 advertisment change
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When the EEE advertisment is changed, we should restart autonegotiation
 | 
				
			||||||
 | 
					to update the link partner with the new EEE settings.  Add this trigger
 | 
				
			||||||
 | 
					but only if the advertisment has changed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -1307,16 +1307,33 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	int cap, adv;
 | 
				
			||||||
 | 
					+	int cap, old_adv, adv, ret;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Get Supported EEE */
 | 
				
			||||||
 | 
					 	cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
 | 
				
			||||||
 | 
					 	if (cap < 0)
 | 
				
			||||||
 | 
					 		return cap;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
 | 
				
			||||||
 | 
					+	if (old_adv < 0)
 | 
				
			||||||
 | 
					+		return old_adv;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	adv = ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
 | 
				
			||||||
 | 
					+	if (old_adv != adv) {
 | 
				
			||||||
 | 
					+		ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
 | 
				
			||||||
 | 
					+		if (ret < 0)
 | 
				
			||||||
 | 
					+			return ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Restart autonegotiation so the new modes get sent to the
 | 
				
			||||||
 | 
					+		 * link partner.
 | 
				
			||||||
 | 
					+		 */
 | 
				
			||||||
 | 
					+		ret = phy_restart_aneg(phydev);
 | 
				
			||||||
 | 
					+		if (ret < 0)
 | 
				
			||||||
 | 
					+			return ret;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_ethtool_set_eee);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 09:34:42 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: allow EEE with SGMII interface modes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As EEE is able to work in SGMII mode as well, add it to the list of
 | 
				
			||||||
 | 
					permissable EEE modes that phy_init_eee() will accept.  This is
 | 
				
			||||||
 | 
					necessary so that EEE can work with an 88E1512 connected in SGMII mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -1191,6 +1191,7 @@ int phy_init_eee(struct phy_device *phyd
 | 
				
			||||||
 | 
					 	if ((phydev->duplex == DUPLEX_FULL) &&
 | 
				
			||||||
 | 
					 	    ((phydev->interface == PHY_INTERFACE_MODE_MII) ||
 | 
				
			||||||
 | 
					 	    (phydev->interface == PHY_INTERFACE_MODE_GMII) ||
 | 
				
			||||||
 | 
					+	     phydev->interface == PHY_INTERFACE_MODE_SGMII ||
 | 
				
			||||||
 | 
					 	     phy_interface_is_rgmii(phydev) ||
 | 
				
			||||||
 | 
					 	     phy_is_internal(phydev))) {
 | 
				
			||||||
 | 
					 		int eee_lp, eee_cap, eee_adv;
 | 
				
			||||||
@@ -0,0 +1,199 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 16:32:14 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: improve phylib correctness for non-autoneg
 | 
				
			||||||
 | 
					 settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					phylib has some undesirable behaviour when forcing a link mode through
 | 
				
			||||||
 | 
					ethtool.  phylib uses this code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
 | 
				
			||||||
 | 
								features);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					to find an index in the settings table.  phy_find_setting() starts at
 | 
				
			||||||
 | 
					index 0, and scans upwards looking for an exact speed and duplex match.
 | 
				
			||||||
 | 
					When it doesn't find it, it returns MAX_NUM_SETTINGS - 1, which is
 | 
				
			||||||
 | 
					10baseT-Half duplex.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					phy_find_valid() then scans from the point (and effectively only checks
 | 
				
			||||||
 | 
					one entry) before bailing out, returning MAX_NUM_SETTINGS - 1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					phy_sanitize_settings() then sets ->speed to SPEED_10 and ->duplex to
 | 
				
			||||||
 | 
					DUPLEX_HALF whether or not 10baseT-Half is supported or not.  This goes
 | 
				
			||||||
 | 
					against all the comments against these functions, and 10baseT-Half may
 | 
				
			||||||
 | 
					not even be supported by the hardware.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Rework these functions, introducing a new method of scanning the table.
 | 
				
			||||||
 | 
					There are two modes of lookup that phylib wants: exact, and inexact.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- in exact mode, we return either an exact match or failure
 | 
				
			||||||
 | 
					- in inexact mode, we return an exact match if it exists, a match at
 | 
				
			||||||
 | 
					  the highest speed that is not greater than the requested speed
 | 
				
			||||||
 | 
					  (ignoring duplex), or failing that, the lowest supported speed, or
 | 
				
			||||||
 | 
					  failure.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The biggest difference is that we always check whether the entry is
 | 
				
			||||||
 | 
					supported before further consideration, so all unsupported entries are
 | 
				
			||||||
 | 
					not considered as candidates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This results in arguably saner behaviour, better matches the comments,
 | 
				
			||||||
 | 
					and is probably what users would expect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This becomes important as ethernet speeds increase, PHYs exist which do
 | 
				
			||||||
 | 
					not support the 10Mbit speeds, and half-duplex is likely to become
 | 
				
			||||||
 | 
					obsolete - it's already not even an option on 10Gbit and faster links.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -160,7 +160,9 @@ struct phy_setting {
 | 
				
			||||||
 | 
					 	u32 setting;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-/* A mapping of all SUPPORTED settings to speed/duplex */
 | 
				
			||||||
 | 
					+/* A mapping of all SUPPORTED settings to speed/duplex.  This table
 | 
				
			||||||
 | 
					+ * must be grouped by speed and sorted in descending match priority
 | 
				
			||||||
 | 
					+ * - iow, descending speed. */
 | 
				
			||||||
 | 
					 static const struct phy_setting settings[] = {
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					@@ -219,45 +221,70 @@ static const struct phy_setting settings
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-#define MAX_NUM_SETTINGS ARRAY_SIZE(settings)
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					- * phy_find_setting - find a PHY settings array entry that matches speed & duplex
 | 
				
			||||||
 | 
					+ * phy_lookup_setting - lookup a PHY setting
 | 
				
			||||||
 | 
					  * @speed: speed to match
 | 
				
			||||||
 | 
					  * @duplex: duplex to match
 | 
				
			||||||
 | 
					+ * @feature: allowed link modes
 | 
				
			||||||
 | 
					+ * @exact: an exact match is required
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Search the settings array for a setting that matches the speed and
 | 
				
			||||||
 | 
					+ * duplex, and which is supported.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * If @exact is unset, either an exact match or %NULL for no match will
 | 
				
			||||||
 | 
					+ * be returned.
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					- * Description: Searches the settings array for the setting which
 | 
				
			||||||
 | 
					- *   matches the desired speed and duplex, and returns the index
 | 
				
			||||||
 | 
					- *   of that setting.  Returns the index of the last setting if
 | 
				
			||||||
 | 
					- *   none of the others match.
 | 
				
			||||||
 | 
					+ * If @exact is set, an exact match, the fastest supported setting at
 | 
				
			||||||
 | 
					+ * or below the specified speed, the slowest supported setting, or if
 | 
				
			||||||
 | 
					+ * they all fail, %NULL will be returned.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					-static inline unsigned int phy_find_setting(int speed, int duplex)
 | 
				
			||||||
 | 
					+static const struct phy_setting *
 | 
				
			||||||
 | 
					+phy_lookup_setting(int speed, int duplex, u32 features, bool exact)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	unsigned int idx = 0;
 | 
				
			||||||
 | 
					+	const struct phy_setting *p, *match = NULL, *last = NULL;
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	while (idx < ARRAY_SIZE(settings) &&
 | 
				
			||||||
 | 
					-	       (settings[idx].speed != speed || settings[idx].duplex != duplex))
 | 
				
			||||||
 | 
					-		idx++;
 | 
				
			||||||
 | 
					+	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
 | 
				
			||||||
 | 
					+		if (p->setting & features) {
 | 
				
			||||||
 | 
					+			last = p;
 | 
				
			||||||
 | 
					+			if (p->speed == speed && p->duplex == duplex) {
 | 
				
			||||||
 | 
					+				/* Exact match for speed and duplex */
 | 
				
			||||||
 | 
					+				match = p;
 | 
				
			||||||
 | 
					+				break;
 | 
				
			||||||
 | 
					+			} else if (!exact) {
 | 
				
			||||||
 | 
					+				if (!match && p->speed <= speed)
 | 
				
			||||||
 | 
					+					/* Candidate */
 | 
				
			||||||
 | 
					+					match = p;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				if (p->speed < speed)
 | 
				
			||||||
 | 
					+					break;
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
 | 
				
			||||||
 | 
					+	if (!match && !exact)
 | 
				
			||||||
 | 
					+		match = last;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return match;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					- * phy_find_valid - find a PHY setting that matches the requested features mask
 | 
				
			||||||
 | 
					- * @idx: The first index in settings[] to search
 | 
				
			||||||
 | 
					- * @features: A mask of the valid settings
 | 
				
			||||||
 | 
					+ * phy_find_valid - find a PHY setting that matches the requested parameters
 | 
				
			||||||
 | 
					+ * @speed: desired speed
 | 
				
			||||||
 | 
					+ * @duplex: desired duplex
 | 
				
			||||||
 | 
					+ * @supported: mask of supported link modes
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					- * Description: Returns the index of the first valid setting less
 | 
				
			||||||
 | 
					- *   than or equal to the one pointed to by idx, as determined by
 | 
				
			||||||
 | 
					- *   the mask in features.  Returns the index of the last setting
 | 
				
			||||||
 | 
					- *   if nothing else matches.
 | 
				
			||||||
 | 
					+ * Locate a supported phy setting that is, in priority order:
 | 
				
			||||||
 | 
					+ * - an exact match for the specified speed and duplex mode
 | 
				
			||||||
 | 
					+ * - a match for the specified speed, or slower speed
 | 
				
			||||||
 | 
					+ * - the slowest supported speed
 | 
				
			||||||
 | 
					+ * Returns the matched phy_setting entry, or %NULL if no supported phy
 | 
				
			||||||
 | 
					+ * settings were found.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					-static inline unsigned int phy_find_valid(unsigned int idx, u32 features)
 | 
				
			||||||
 | 
					+static const struct phy_setting *
 | 
				
			||||||
 | 
					+phy_find_valid(int speed, int duplex, u32 supported)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features))
 | 
				
			||||||
 | 
					-		idx++;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return idx < MAX_NUM_SETTINGS ? idx : MAX_NUM_SETTINGS - 1;
 | 
				
			||||||
 | 
					+	return phy_lookup_setting(speed, duplex, supported, false);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					@@ -271,12 +298,7 @@ static inline unsigned int phy_find_vali
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 static inline bool phy_check_valid(int speed, int duplex, u32 features)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	unsigned int idx;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	idx = phy_find_valid(phy_find_setting(speed, duplex), features);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return settings[idx].speed == speed && settings[idx].duplex == duplex &&
 | 
				
			||||||
 | 
					-		(settings[idx].setting & features);
 | 
				
			||||||
 | 
					+	return !!phy_lookup_setting(speed, duplex, features, true);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					@@ -289,18 +311,22 @@ static inline bool phy_check_valid(int s
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 static void phy_sanitize_settings(struct phy_device *phydev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+	const struct phy_setting *setting;
 | 
				
			||||||
 | 
					 	u32 features = phydev->supported;
 | 
				
			||||||
 | 
					-	unsigned int idx;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Sanitize settings based on PHY capabilities */
 | 
				
			||||||
 | 
					 	if ((features & SUPPORTED_Autoneg) == 0)
 | 
				
			||||||
 | 
					 		phydev->autoneg = AUTONEG_DISABLE;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	idx = phy_find_valid(phy_find_setting(phydev->speed, phydev->duplex),
 | 
				
			||||||
 | 
					-			features);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	phydev->speed = settings[idx].speed;
 | 
				
			||||||
 | 
					-	phydev->duplex = settings[idx].duplex;
 | 
				
			||||||
 | 
					+	setting = phy_find_valid(phydev->speed, phydev->duplex, features);
 | 
				
			||||||
 | 
					+	if (setting) {
 | 
				
			||||||
 | 
					+		phydev->speed = setting->speed;
 | 
				
			||||||
 | 
					+		phydev->duplex = setting->duplex;
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		/* We failed to find anything (no supported speeds?) */
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					+		phydev->duplex = DUPLEX_UNKNOWN;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
@@ -0,0 +1,323 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 29 Dec 2016 11:03:09 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: add 802.3 clause 45 support to phylib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Add generic helpers for 802.3 clause 45 PHYs for >= 10Gbps support.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 create mode 100644 drivers/net/phy/phy-c45.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -1,7 +1,7 @@
 | 
				
			||||||
 | 
					 # Makefile for Linux PHY drivers and MDIO bus drivers
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 libphy-y			:= phy.o phy_device.o mdio_bus.o mdio_device.o \
 | 
				
			||||||
 | 
					-				   phy-core.o
 | 
				
			||||||
 | 
					+				   phy-c45.o phy-core.o
 | 
				
			||||||
 | 
					 libphy-$(CONFIG_SWPHY)		+= swphy.o
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_BOARDINFO)	+= mdio-boardinfo.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-c45.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,234 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * Clause 45 PHY support
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#include <linux/ethtool.h>
 | 
				
			||||||
 | 
					+#include <linux/export.h>
 | 
				
			||||||
 | 
					+#include <linux/mdio.h>
 | 
				
			||||||
 | 
					+#include <linux/mii.h>
 | 
				
			||||||
 | 
					+#include <linux/phy.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_setup_forced - configures a forced speed
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_pma_setup_forced(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int ctrl1, ctrl2, ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Half duplex is not supported */
 | 
				
			||||||
 | 
					+	if (phydev->duplex != DUPLEX_FULL)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
 | 
				
			||||||
 | 
					+	if (ctrl1 < 0)
 | 
				
			||||||
 | 
					+		return ctrl1;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
 | 
				
			||||||
 | 
					+	if (ctrl2 < 0)
 | 
				
			||||||
 | 
					+		return ctrl2;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
 | 
				
			||||||
 | 
					+	/* PMA/PMD type selection is 1.7.5:0 not 1.7.3:0.  See 45.2.1.6.1. */
 | 
				
			||||||
 | 
					+	ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	switch (phydev->speed) {
 | 
				
			||||||
 | 
					+	case SPEED_10:
 | 
				
			||||||
 | 
					+		ctrl2 |= MDIO_PMA_CTRL2_10BT;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPEED_100:
 | 
				
			||||||
 | 
					+		ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
 | 
				
			||||||
 | 
					+		ctrl2 |= MDIO_PMA_CTRL2_100BTX;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPEED_1000:
 | 
				
			||||||
 | 
					+		ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
 | 
				
			||||||
 | 
					+		/* Assume 1000base-T */
 | 
				
			||||||
 | 
					+		ctrl2 |= MDIO_PMA_CTRL2_1000BT;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case SPEED_10000:
 | 
				
			||||||
 | 
					+		ctrl1 |= MDIO_CTRL1_SPEED10G;
 | 
				
			||||||
 | 
					+		/* Assume 10Gbase-T */
 | 
				
			||||||
 | 
					+		ctrl2 |= MDIO_PMA_CTRL2_10GBT;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
 | 
				
			||||||
 | 
					+	if (ret < 0)
 | 
				
			||||||
 | 
					+		return ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_an_disable_aneg - disable auto-negotiation
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Disable auto-negotiation in the Clause 45 PHY. The link parameters
 | 
				
			||||||
 | 
					+ * parameters are controlled through the PMA/PMD MMD registers.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Returns zero on success, negative errno code on failure.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_an_disable_aneg(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
 | 
				
			||||||
 | 
					+	if (val < 0)
 | 
				
			||||||
 | 
					+		return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	val &= ~(MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_restart_aneg - Enable and restart auto-negotiation
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This assumes that the auto-negotiation MMD is present.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Enable and restart auto-negotiation.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_restart_aneg(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
 | 
				
			||||||
 | 
					+	if (val < 0)
 | 
				
			||||||
 | 
					+		return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_aneg_done - return auto-negotiation complete status
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * This assumes that the auto-negotiation MMD is present.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Reads the status register from the auto-negotiation MMD, returning:
 | 
				
			||||||
 | 
					+ * - positive if auto-negotiation is complete
 | 
				
			||||||
 | 
					+ * - negative errno code on error
 | 
				
			||||||
 | 
					+ * - zero otherwise
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_aneg_done(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_read_link - read the overall link status from the MMDs
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ * @mmd_mask: MMDs to read status from
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Read the link status from the specified MMDs, and if they all indicate
 | 
				
			||||||
 | 
					+ * that the link is up, return positive.  If an error is encountered,
 | 
				
			||||||
 | 
					+ * a negative errno will be returned, otherwise zero.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val, devad;
 | 
				
			||||||
 | 
					+	bool link = true;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	while (mmd_mask) {
 | 
				
			||||||
 | 
					+		devad = __ffs(mmd_mask);
 | 
				
			||||||
 | 
					+		mmd_mask &= ~BIT(devad);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					+		if (val < 0)
 | 
				
			||||||
 | 
					+			return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		/* Read twice because link state is latched and a
 | 
				
			||||||
 | 
					+		 * read moves the current state into the register
 | 
				
			||||||
 | 
					+		 */
 | 
				
			||||||
 | 
					+		val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					+		if (val < 0)
 | 
				
			||||||
 | 
					+			return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (!(val & MDIO_STAT1_LSTATUS))
 | 
				
			||||||
 | 
					+			link = false;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return link;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_read_link);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_read_lpa - read the link partner advertisment and pause
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
 | 
				
			||||||
 | 
					+ * filling in the link partner advertisment, pause and asym_pause members
 | 
				
			||||||
 | 
					+ * in @phydev.  This assumes that the auto-negotiation MMD is present, and
 | 
				
			||||||
 | 
					+ * the backplane bit (7.48.0) is clear.  Clause 45 PHY drivers are expected
 | 
				
			||||||
 | 
					+ * to fill in the remainder of the link partner advert from vendor registers.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_read_lpa(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Read the link partner's base page advertisment */
 | 
				
			||||||
 | 
					+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
 | 
				
			||||||
 | 
					+	if (val < 0)
 | 
				
			||||||
 | 
					+		return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	phydev->lp_advertising = mii_lpa_to_ethtool_lpa_t(val);
 | 
				
			||||||
 | 
					+	phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
 | 
				
			||||||
 | 
					+	phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Read the link partner's 10G advertisment */
 | 
				
			||||||
 | 
					+	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
 | 
				
			||||||
 | 
					+	if (val < 0)
 | 
				
			||||||
 | 
					+		return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (val & MDIO_AN_10GBT_STAT_LP10G)
 | 
				
			||||||
 | 
					+		phydev->lp_advertising |= ADVERTISED_10000baseT_Full;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * genphy_c45_read_pma - read link speed etc from PMA
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+int genphy_c45_read_pma(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
 | 
				
			||||||
 | 
					+	if (val < 0)
 | 
				
			||||||
 | 
					+		return val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	switch (val & MDIO_CTRL1_SPEEDSEL) {
 | 
				
			||||||
 | 
					+	case 0:
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_10;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case MDIO_PMA_CTRL1_SPEED100:
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_100;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case MDIO_PMA_CTRL1_SPEED1000:
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_1000;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	case MDIO_CTRL1_SPEED10G:
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_10000;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		phydev->speed = SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					+		break;
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	phydev->duplex = DUPLEX_FULL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return 0;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy_device.c
 | 
				
			||||||
 | 
					@@ -1390,27 +1390,19 @@ EXPORT_SYMBOL(genphy_read_status);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int gen10g_read_status(struct phy_device *phydev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	int devad, reg;
 | 
				
			||||||
 | 
					 	u32 mmd_mask = phydev->c45_ids.devices_in_package;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	phydev->link = 1;
 | 
				
			||||||
 | 
					+	int ret;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* For now just lie and say it's 10G all the time */
 | 
				
			||||||
 | 
					 	phydev->speed = SPEED_10000;
 | 
				
			||||||
 | 
					 	phydev->duplex = DUPLEX_FULL;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
 | 
				
			||||||
 | 
					-		if (!(mmd_mask & 1))
 | 
				
			||||||
 | 
					-			continue;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		/* Read twice because link state is latched and a
 | 
				
			||||||
 | 
					-		 * read moves the current state into the register
 | 
				
			||||||
 | 
					-		 */
 | 
				
			||||||
 | 
					-		phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					-		reg = phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					-		if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
 | 
				
			||||||
 | 
					-			phydev->link = 0;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					+	/* Avoid reading the vendor MMDs */
 | 
				
			||||||
 | 
					+	mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2));
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	ret = genphy_c45_read_link(phydev, mmd_mask);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	phydev->link = ret > 0 ? 1 : 0;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -807,6 +807,8 @@ static inline const char *phydev_name(co
 | 
				
			||||||
 | 
					 void phy_attached_print(struct phy_device *phydev, const char *fmt, ...)
 | 
				
			||||||
 | 
					 	__printf(2, 3);
 | 
				
			||||||
 | 
					 void phy_attached_info(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* Clause 22 PHY */
 | 
				
			||||||
 | 
					 int genphy_config_init(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 int genphy_setup_forced(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 int genphy_restart_aneg(struct phy_device *phydev);
 | 
				
			||||||
 | 
					@@ -817,6 +819,16 @@ int genphy_read_status(struct phy_device
 | 
				
			||||||
 | 
					 int genphy_suspend(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 int genphy_resume(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 int genphy_soft_reset(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/* Clause 45 PHY */
 | 
				
			||||||
 | 
					+int genphy_c45_restart_aneg(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+int genphy_c45_aneg_done(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+int genphy_c45_read_link(struct phy_device *phydev, u32 mmd_mask);
 | 
				
			||||||
 | 
					+int genphy_c45_read_lpa(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+int genphy_c45_read_pma(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+int genphy_c45_pma_setup_forced(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+int genphy_c45_an_disable_aneg(struct phy_device *phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 void phy_driver_unregister(struct phy_driver *drv);
 | 
				
			||||||
 | 
					 void phy_drivers_unregister(struct phy_driver *drv, int n);
 | 
				
			||||||
 | 
					 int phy_driver_register(struct phy_driver *new_driver, struct module *owner);
 | 
				
			||||||
@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Fri, 13 Jan 2017 11:17:30 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: hook up clause 45 autonegotiation restart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					genphy_restart_aneg() can only restart autonegotiation on clause 22
 | 
				
			||||||
 | 
					PHYs.  Add a phy_restart_aneg() function which selects between the
 | 
				
			||||||
 | 
					clause 22 and clause 45 restart functionality depending on the PHY
 | 
				
			||||||
 | 
					type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -134,6 +134,24 @@ static int phy_config_interrupt(struct p
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_restart_aneg - restart auto-negotiation
 | 
				
			||||||
 | 
					+ * @phydev: target phy_device struct
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Restart the autonegotiation on @phydev.  Returns >= 0 on success or
 | 
				
			||||||
 | 
					+ * negative errno on error.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+static int phy_restart_aneg(struct phy_device *phydev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	int ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (phydev->is_c45)
 | 
				
			||||||
 | 
					+		ret = genphy_c45_restart_aneg(phydev);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		ret = genphy_restart_aneg(phydev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return ret;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_aneg_done - return auto-negotiation status
 | 
				
			||||||
 | 
					@@ -1403,3 +1421,14 @@ int phy_ethtool_set_link_ksettings(struc
 | 
				
			||||||
 | 
					 	return phy_ethtool_ksettings_set(phydev, cmd);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL(phy_ethtool_set_link_ksettings);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int phy_ethtool_nway_reset(struct net_device *ndev)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct phy_device *phydev = ndev->phydev;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!phydev)
 | 
				
			||||||
 | 
					+		return -ENODEV;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_restart_aneg(phydev);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL(phy_ethtool_nway_reset);
 | 
				
			||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 00:23:40 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: don't double-read clause 45 status register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					One of the design decisions behind the link status bit in the status
 | 
				
			||||||
 | 
					register is that it latches low on link loss.  This is so that link loss
 | 
				
			||||||
 | 
					events are not missed.  Double-reading the status register means that we
 | 
				
			||||||
 | 
					always read the current state of the link, clearing any link loss event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can cause problems - for example, if the link has negotiated a
 | 
				
			||||||
 | 
					different set of operating parameters, these will not be communicated
 | 
				
			||||||
 | 
					to the MAC as the PHY state machine will still think that the link has
 | 
				
			||||||
 | 
					remained active.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy-c45.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-c45.c
 | 
				
			||||||
 | 
					@@ -143,12 +143,9 @@ int genphy_c45_read_link(struct phy_devi
 | 
				
			||||||
 | 
					 		devad = __ffs(mmd_mask);
 | 
				
			||||||
 | 
					 		mmd_mask &= ~BIT(devad);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					-		if (val < 0)
 | 
				
			||||||
 | 
					-			return val;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		/* Read twice because link state is latched and a
 | 
				
			||||||
 | 
					-		 * read moves the current state into the register
 | 
				
			||||||
 | 
					+		/* The link state is latched low so that momentary link
 | 
				
			||||||
 | 
					+		 * drops can be detected.  Do not double-read the status
 | 
				
			||||||
 | 
					+		 * register if the link is down.
 | 
				
			||||||
 | 
					 		 */
 | 
				
			||||||
 | 
					 		val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 | 
				
			||||||
 | 
					 		if (val < 0)
 | 
				
			||||||
@@ -0,0 +1,142 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 16:32:14 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: allow settings table to support more than 32
 | 
				
			||||||
 | 
					 link modes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Allow the phy settings table to support more than 32 link modes by
 | 
				
			||||||
 | 
					switching to the ethtool link mode bit number representation, rather
 | 
				
			||||||
 | 
					than storing the mask.  This will allow phylink and other ethtool
 | 
				
			||||||
 | 
					code to share the settings table to look up settings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -175,7 +175,7 @@ static inline int phy_aneg_done(struct p
 | 
				
			||||||
 | 
					 struct phy_setting {
 | 
				
			||||||
 | 
					 	int speed;
 | 
				
			||||||
 | 
					 	int duplex;
 | 
				
			||||||
 | 
					-	u32 setting;
 | 
				
			||||||
 | 
					+	int bit;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* A mapping of all SUPPORTED settings to speed/duplex.  This table
 | 
				
			||||||
 | 
					@@ -185,57 +185,57 @@ static const struct phy_setting settings
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_10000baseKR_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_10000baseKX4_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_10000baseT_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_2500,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_2500baseX_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_1000baseKX_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_1000baseT_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_1000baseT_Half,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_100,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_100baseT_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_100,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_100baseT_Half,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_10baseT_Full,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 	{
 | 
				
			||||||
 | 
					 		.speed = SPEED_10,
 | 
				
			||||||
 | 
					 		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.setting = SUPPORTED_10baseT_Half,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
 | 
				
			||||||
 | 
					 	},
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -243,7 +243,8 @@ static const struct phy_setting settings
 | 
				
			||||||
 | 
					  * phy_lookup_setting - lookup a PHY setting
 | 
				
			||||||
 | 
					  * @speed: speed to match
 | 
				
			||||||
 | 
					  * @duplex: duplex to match
 | 
				
			||||||
 | 
					- * @feature: allowed link modes
 | 
				
			||||||
 | 
					+ * @mask: allowed link modes
 | 
				
			||||||
 | 
					+ * @maxbit: bit size of link modes
 | 
				
			||||||
 | 
					  * @exact: an exact match is required
 | 
				
			||||||
 | 
					  *
 | 
				
			||||||
 | 
					  * Search the settings array for a setting that matches the speed and
 | 
				
			||||||
 | 
					@@ -257,13 +258,14 @@ static const struct phy_setting settings
 | 
				
			||||||
 | 
					  * they all fail, %NULL will be returned.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 static const struct phy_setting *
 | 
				
			||||||
 | 
					-phy_lookup_setting(int speed, int duplex, u32 features, bool exact)
 | 
				
			||||||
 | 
					+phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 | 
				
			||||||
 | 
					+		   size_t maxbit, bool exact)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	const struct phy_setting *p, *match = NULL, *last = NULL;
 | 
				
			||||||
 | 
					 	int i;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
 | 
				
			||||||
 | 
					-		if (p->setting & features) {
 | 
				
			||||||
 | 
					+		if (p->bit < maxbit && test_bit(p->bit, mask)) {
 | 
				
			||||||
 | 
					 			last = p;
 | 
				
			||||||
 | 
					 			if (p->speed == speed && p->duplex == duplex) {
 | 
				
			||||||
 | 
					 				/* Exact match for speed and duplex */
 | 
				
			||||||
 | 
					@@ -302,7 +304,9 @@ phy_lookup_setting(int speed, int duplex
 | 
				
			||||||
 | 
					 static const struct phy_setting *
 | 
				
			||||||
 | 
					 phy_find_valid(int speed, int duplex, u32 supported)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	return phy_lookup_setting(speed, duplex, supported, false);
 | 
				
			||||||
 | 
					+	unsigned long mask = supported;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_lookup_setting(speed, duplex, &mask, BITS_PER_LONG, false);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					@@ -316,7 +320,9 @@ phy_find_valid(int speed, int duplex, u3
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					 static inline bool phy_check_valid(int speed, int duplex, u32 features)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	return !!phy_lookup_setting(speed, duplex, features, true);
 | 
				
			||||||
 | 
					+	unsigned long mask = features;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return !!phy_lookup_setting(speed, duplex, &mask, BITS_PER_LONG, true);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Mon, 2 Jan 2017 17:52:18 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: split out PHY speed and duplex string
 | 
				
			||||||
 | 
					 generation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Other code would like to make use of this, so make the speed and duplex
 | 
				
			||||||
 | 
					string generation visible, and place it in a separate file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -38,26 +38,6 @@
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 #include <asm/irq.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static const char *phy_speed_to_str(int speed)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	switch (speed) {
 | 
				
			||||||
 | 
					-	case SPEED_10:
 | 
				
			||||||
 | 
					-		return "10Mbps";
 | 
				
			||||||
 | 
					-	case SPEED_100:
 | 
				
			||||||
 | 
					-		return "100Mbps";
 | 
				
			||||||
 | 
					-	case SPEED_1000:
 | 
				
			||||||
 | 
					-		return "1Gbps";
 | 
				
			||||||
 | 
					-	case SPEED_2500:
 | 
				
			||||||
 | 
					-		return "2.5Gbps";
 | 
				
			||||||
 | 
					-	case SPEED_10000:
 | 
				
			||||||
 | 
					-		return "10Gbps";
 | 
				
			||||||
 | 
					-	case SPEED_UNKNOWN:
 | 
				
			||||||
 | 
					-		return "Unknown";
 | 
				
			||||||
 | 
					-	default:
 | 
				
			||||||
 | 
					-		return "Unsupported (update phy.c)";
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 #define PHY_STATE_STR(_state)			\
 | 
				
			||||||
 | 
					 	case PHY_##_state:			\
 | 
				
			||||||
 | 
					 		return __stringify(_state);	\
 | 
				
			||||||
 | 
					@@ -93,7 +73,7 @@ void phy_print_status(struct phy_device
 | 
				
			||||||
 | 
					 		netdev_info(phydev->attached_dev,
 | 
				
			||||||
 | 
					 			"Link is Up - %s/%s - flow control %s\n",
 | 
				
			||||||
 | 
					 			phy_speed_to_str(phydev->speed),
 | 
				
			||||||
 | 
					-			DUPLEX_FULL == phydev->duplex ? "Full" : "Half",
 | 
				
			||||||
 | 
					+			phy_duplex_to_str(phydev->duplex),
 | 
				
			||||||
 | 
					 			phydev->pause ? "rx/tx" : "off");
 | 
				
			||||||
 | 
					 	} else	{
 | 
				
			||||||
 | 
					 		netdev_info(phydev->attached_dev, "Link is Down\n");
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					@@ -9,6 +9,39 @@
 | 
				
			||||||
 | 
					 #include <linux/export.h>
 | 
				
			||||||
 | 
					 #include <linux/phy.h>
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+const char *phy_speed_to_str(int speed)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	switch (speed) {
 | 
				
			||||||
 | 
					+	case SPEED_10:
 | 
				
			||||||
 | 
					+		return "10Mbps";
 | 
				
			||||||
 | 
					+	case SPEED_100:
 | 
				
			||||||
 | 
					+		return "100Mbps";
 | 
				
			||||||
 | 
					+	case SPEED_1000:
 | 
				
			||||||
 | 
					+		return "1Gbps";
 | 
				
			||||||
 | 
					+	case SPEED_2500:
 | 
				
			||||||
 | 
					+		return "2.5Gbps";
 | 
				
			||||||
 | 
					+	case SPEED_10000:
 | 
				
			||||||
 | 
					+		return "10Gbps";
 | 
				
			||||||
 | 
					+	case SPEED_UNKNOWN:
 | 
				
			||||||
 | 
					+		return "Unknown";
 | 
				
			||||||
 | 
					+	default:
 | 
				
			||||||
 | 
					+		return "Unsupported (update phy-core.c)";
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(phy_speed_to_str);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+const char *phy_duplex_to_str(unsigned int duplex)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	if (duplex == DUPLEX_HALF)
 | 
				
			||||||
 | 
					+		return "Half";
 | 
				
			||||||
 | 
					+	if (duplex == DUPLEX_FULL)
 | 
				
			||||||
 | 
					+		return "Full";
 | 
				
			||||||
 | 
					+	if (duplex == DUPLEX_UNKNOWN)
 | 
				
			||||||
 | 
					+		return "Unknown";
 | 
				
			||||||
 | 
					+	return "Unsupported (update phy-core.c)";
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(phy_duplex_to_str);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
 | 
				
			||||||
 | 
					 				    int addr)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -642,6 +642,9 @@ struct phy_fixup {
 | 
				
			||||||
 | 
					 	int (*run)(struct phy_device *phydev);
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+const char *phy_speed_to_str(int speed);
 | 
				
			||||||
 | 
					+const char *phy_duplex_to_str(unsigned int duplex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_read_mmd - Convenience function for reading a register
 | 
				
			||||||
 | 
					  * from an MMD on a given PHY.
 | 
				
			||||||
@@ -0,0 +1,329 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 5 Jan 2017 16:47:39 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: move phy_lookup_setting() and guts of
 | 
				
			||||||
 | 
					 phy_supported_speeds() to phy-core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					phy_lookup_setting() provides useful functionality in ethtool code
 | 
				
			||||||
 | 
					outside phylib.  Move it to phy-core and allow it to be re-used (eg,
 | 
				
			||||||
 | 
					in phylink) rather than duplicated elsewhere.  Note that this supports
 | 
				
			||||||
 | 
					the larger linkmode space.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As we move the phy settings table, we also need to move the guts of
 | 
				
			||||||
 | 
					phy_supported_speeds() as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -149,125 +149,6 @@ static inline int phy_aneg_done(struct p
 | 
				
			||||||
 | 
					 	return genphy_aneg_done(phydev);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-/* A structure for mapping a particular speed and duplex
 | 
				
			||||||
 | 
					- * combination to a particular SUPPORTED and ADVERTISED value
 | 
				
			||||||
 | 
					- */
 | 
				
			||||||
 | 
					-struct phy_setting {
 | 
				
			||||||
 | 
					-	int speed;
 | 
				
			||||||
 | 
					-	int duplex;
 | 
				
			||||||
 | 
					-	int bit;
 | 
				
			||||||
 | 
					-};
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/* A mapping of all SUPPORTED settings to speed/duplex.  This table
 | 
				
			||||||
 | 
					- * must be grouped by speed and sorted in descending match priority
 | 
				
			||||||
 | 
					- * - iow, descending speed. */
 | 
				
			||||||
 | 
					-static const struct phy_setting settings[] = {
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_2500,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_100,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_100,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_10,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-	{
 | 
				
			||||||
 | 
					-		.speed = SPEED_10,
 | 
				
			||||||
 | 
					-		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					-		.bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
 | 
				
			||||||
 | 
					-	},
 | 
				
			||||||
 | 
					-};
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-/**
 | 
				
			||||||
 | 
					- * phy_lookup_setting - lookup a PHY setting
 | 
				
			||||||
 | 
					- * @speed: speed to match
 | 
				
			||||||
 | 
					- * @duplex: duplex to match
 | 
				
			||||||
 | 
					- * @mask: allowed link modes
 | 
				
			||||||
 | 
					- * @maxbit: bit size of link modes
 | 
				
			||||||
 | 
					- * @exact: an exact match is required
 | 
				
			||||||
 | 
					- *
 | 
				
			||||||
 | 
					- * Search the settings array for a setting that matches the speed and
 | 
				
			||||||
 | 
					- * duplex, and which is supported.
 | 
				
			||||||
 | 
					- *
 | 
				
			||||||
 | 
					- * If @exact is unset, either an exact match or %NULL for no match will
 | 
				
			||||||
 | 
					- * be returned.
 | 
				
			||||||
 | 
					- *
 | 
				
			||||||
 | 
					- * If @exact is set, an exact match, the fastest supported setting at
 | 
				
			||||||
 | 
					- * or below the specified speed, the slowest supported setting, or if
 | 
				
			||||||
 | 
					- * they all fail, %NULL will be returned.
 | 
				
			||||||
 | 
					- */
 | 
				
			||||||
 | 
					-static const struct phy_setting *
 | 
				
			||||||
 | 
					-phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 | 
				
			||||||
 | 
					-		   size_t maxbit, bool exact)
 | 
				
			||||||
 | 
					-{
 | 
				
			||||||
 | 
					-	const struct phy_setting *p, *match = NULL, *last = NULL;
 | 
				
			||||||
 | 
					-	int i;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
 | 
				
			||||||
 | 
					-		if (p->bit < maxbit && test_bit(p->bit, mask)) {
 | 
				
			||||||
 | 
					-			last = p;
 | 
				
			||||||
 | 
					-			if (p->speed == speed && p->duplex == duplex) {
 | 
				
			||||||
 | 
					-				/* Exact match for speed and duplex */
 | 
				
			||||||
 | 
					-				match = p;
 | 
				
			||||||
 | 
					-				break;
 | 
				
			||||||
 | 
					-			} else if (!exact) {
 | 
				
			||||||
 | 
					-				if (!match && p->speed <= speed)
 | 
				
			||||||
 | 
					-					/* Candidate */
 | 
				
			||||||
 | 
					-					match = p;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-				if (p->speed < speed)
 | 
				
			||||||
 | 
					-					break;
 | 
				
			||||||
 | 
					-			}
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (!match && !exact)
 | 
				
			||||||
 | 
					-		match = last;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	return match;
 | 
				
			||||||
 | 
					-}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_find_valid - find a PHY setting that matches the requested parameters
 | 
				
			||||||
 | 
					  * @speed: desired speed
 | 
				
			||||||
 | 
					@@ -290,6 +171,25 @@ phy_find_valid(int speed, int duplex, u3
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					+ * phy_supported_speeds - return all speeds currently supported by a phy device
 | 
				
			||||||
 | 
					+ * @phy: The phy device to return supported speeds of.
 | 
				
			||||||
 | 
					+ * @speeds: buffer to store supported speeds in.
 | 
				
			||||||
 | 
					+ * @size:   size of speeds buffer.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Description: Returns the number of supported speeds, and fills the speeds
 | 
				
			||||||
 | 
					+ * buffer with the supported speeds. If speeds buffer is too small to contain
 | 
				
			||||||
 | 
					+ * all currently supported speeds, will return as many speeds as can fit.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+unsigned int phy_supported_speeds(struct phy_device *phy,
 | 
				
			||||||
 | 
					+				  unsigned int *speeds,
 | 
				
			||||||
 | 
					+				  unsigned int size)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	unsigned long supported = phy->supported;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return phy_speeds(speeds, size, &supported, BITS_PER_LONG);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					  * phy_check_valid - check if there is a valid PHY setting which matches
 | 
				
			||||||
 | 
					  *		     speed, duplex, and feature mask
 | 
				
			||||||
 | 
					  * @speed: speed to match
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy-core.c
 | 
				
			||||||
 | 
					@@ -42,6 +42,132 @@ const char *phy_duplex_to_str(unsigned i
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL_GPL(phy_duplex_to_str);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/* A mapping of all SUPPORTED settings to speed/duplex.  This table
 | 
				
			||||||
 | 
					+ * must be grouped by speed and sorted in descending match priority
 | 
				
			||||||
 | 
					+ * - iow, descending speed. */
 | 
				
			||||||
 | 
					+static const struct phy_setting settings[] = {
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_10000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_2500,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_1000,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_100,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_100,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_100baseT_Half_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_10,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_FULL,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10baseT_Full_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+	{
 | 
				
			||||||
 | 
					+		.speed = SPEED_10,
 | 
				
			||||||
 | 
					+		.duplex = DUPLEX_HALF,
 | 
				
			||||||
 | 
					+		.bit = ETHTOOL_LINK_MODE_10baseT_Half_BIT,
 | 
				
			||||||
 | 
					+	},
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/**
 | 
				
			||||||
 | 
					+ * phy_lookup_setting - lookup a PHY setting
 | 
				
			||||||
 | 
					+ * @speed: speed to match
 | 
				
			||||||
 | 
					+ * @duplex: duplex to match
 | 
				
			||||||
 | 
					+ * @mask: allowed link modes
 | 
				
			||||||
 | 
					+ * @maxbit: bit size of link modes
 | 
				
			||||||
 | 
					+ * @exact: an exact match is required
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Search the settings array for a setting that matches the speed and
 | 
				
			||||||
 | 
					+ * duplex, and which is supported.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * If @exact is unset, either an exact match or %NULL for no match will
 | 
				
			||||||
 | 
					+ * be returned.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * If @exact is set, an exact match, the fastest supported setting at
 | 
				
			||||||
 | 
					+ * or below the specified speed, the slowest supported setting, or if
 | 
				
			||||||
 | 
					+ * they all fail, %NULL will be returned.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+const struct phy_setting *
 | 
				
			||||||
 | 
					+phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 | 
				
			||||||
 | 
					+		   size_t maxbit, bool exact)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	const struct phy_setting *p, *match = NULL, *last = NULL;
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {
 | 
				
			||||||
 | 
					+		if (p->bit < maxbit && test_bit(p->bit, mask)) {
 | 
				
			||||||
 | 
					+			last = p;
 | 
				
			||||||
 | 
					+			if (p->speed == speed && p->duplex == duplex) {
 | 
				
			||||||
 | 
					+				/* Exact match for speed and duplex */
 | 
				
			||||||
 | 
					+				match = p;
 | 
				
			||||||
 | 
					+				break;
 | 
				
			||||||
 | 
					+			} else if (!exact) {
 | 
				
			||||||
 | 
					+				if (!match && p->speed <= speed)
 | 
				
			||||||
 | 
					+					/* Candidate */
 | 
				
			||||||
 | 
					+					match = p;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				if (p->speed < speed)
 | 
				
			||||||
 | 
					+					break;
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!match && !exact)
 | 
				
			||||||
 | 
					+		match = last;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return match;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(phy_lookup_setting);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+size_t phy_speeds(unsigned int *speeds, size_t size,
 | 
				
			||||||
 | 
					+		  unsigned long *mask, size_t maxbit)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	size_t count;
 | 
				
			||||||
 | 
					+	int i;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)
 | 
				
			||||||
 | 
					+		if (settings[i].bit < maxbit &&
 | 
				
			||||||
 | 
					+		    test_bit(settings[i].bit, mask) &&
 | 
				
			||||||
 | 
					+		    (count == 0 || speeds[count - 1] != settings[i].speed))
 | 
				
			||||||
 | 
					+			speeds[count++] = settings[i].speed;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return count;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
 | 
				
			||||||
 | 
					 				    int addr)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					--- a/include/linux/phy.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phy.h
 | 
				
			||||||
 | 
					@@ -645,6 +645,21 @@ struct phy_fixup {
 | 
				
			||||||
 | 
					 const char *phy_speed_to_str(int speed);
 | 
				
			||||||
 | 
					 const char *phy_duplex_to_str(unsigned int duplex);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+/* A structure for mapping a particular speed and duplex
 | 
				
			||||||
 | 
					+ * combination to a particular SUPPORTED and ADVERTISED value
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+struct phy_setting {
 | 
				
			||||||
 | 
					+	u32 speed;
 | 
				
			||||||
 | 
					+	u8 duplex;
 | 
				
			||||||
 | 
					+	u8 bit;
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+const struct phy_setting *
 | 
				
			||||||
 | 
					+phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 | 
				
			||||||
 | 
					+		   size_t maxbit, bool exact);
 | 
				
			||||||
 | 
					+size_t phy_speeds(unsigned int *speeds, size_t size,
 | 
				
			||||||
 | 
					+		  unsigned long *mask, size_t maxbit);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 /**
 | 
				
			||||||
 | 
					  * phy_read_mmd - Convenience function for reading a register
 | 
				
			||||||
 | 
					  * from an MMD on a given PHY.
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Fri, 16 Oct 2015 12:18:41 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phy.c
 | 
				
			||||||
 | 
					@@ -580,6 +580,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_trigger_machine - trigger the state machine to run
 | 
				
			||||||
							
								
								
									
										180
									
								
								target/linux/mvebu/patches-4.9/414-phy-add-I2C-mdio-bus.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								target/linux/mvebu/patches-4.9/414-phy-add-I2C-mdio-bus.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Fri, 25 Sep 2015 17:43:52 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since PHYs appear at I2C bus address 0x40..0x5f, and 0x50/0x51 are
 | 
				
			||||||
 | 
					reserved for SFP EEPROMs/diagnostics, we must not allow the MDIO bus
 | 
				
			||||||
 | 
					to access these I2C addresses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					 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
 | 
				
			||||||
 | 
					@@ -105,6 +105,16 @@ config MDIO_HISI_FEMAC
 | 
				
			||||||
 | 
					 	  This module provides a driver for the MDIO busses found in the
 | 
				
			||||||
 | 
					 	  Hisilicon SoC that have an Fast Ethernet MAC.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+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_MOXART
 | 
				
			||||||
 | 
					         tristate "MOXA ART MDIO interface support"
 | 
				
			||||||
 | 
					         depends on ARCH_MOXART
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/Makefile
 | 
				
			||||||
 | 
					@@ -33,6 +33,7 @@ obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += md
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_CAVIUM)	+= mdio-cavium.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_HISI_FEMAC)	+= mdio-hisi-femac.o
 | 
				
			||||||
 | 
					+obj-$(CONFIG_MDIO_I2C)		+= mdio-i2c.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_MOXART)	+= mdio-moxart.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_OCTEON)	+= mdio-octeon.o
 | 
				
			||||||
 | 
					 obj-$(CONFIG_MDIO_SUN4I)	+= mdio-sun4i.o
 | 
				
			||||||
 | 
					--- /dev/null
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/mdio-i2c.c
 | 
				
			||||||
 | 
					@@ -0,0 +1,109 @@
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * MDIO I2C bridge
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Copyright (C) 2015-2016 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.
 | 
				
			||||||
 | 
					+ *
 | 
				
			||||||
 | 
					+ * Network PHYs can appear on I2C buses when they are part of SFP module.
 | 
				
			||||||
 | 
					+ * This driver exposes these PHYs to the networking PHY code, allowing
 | 
				
			||||||
 | 
					+ * our PHY drivers access to these PHYs, and so allowing configuration
 | 
				
			||||||
 | 
					+ * of their settings.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+#include <linux/i2c.h>
 | 
				
			||||||
 | 
					+#include <linux/phy.h>
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+#include "mdio-i2c.h"
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+/*
 | 
				
			||||||
 | 
					+ * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
 | 
				
			||||||
 | 
					+ * specified to be present in SFP modules.  These correspond with PHY
 | 
				
			||||||
 | 
					+ * addresses 16 and 17.  Disallow access to these "phy" addresses.
 | 
				
			||||||
 | 
					+ */
 | 
				
			||||||
 | 
					+static bool i2c_mii_valid_phy_id(int phy_id)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return phy_id != 0x10 && phy_id != 0x11;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+static unsigned int i2c_mii_phy_addr(int phy_id)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	return phy_id + 0x40;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+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;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!i2c_mii_valid_phy_id(phy_id))
 | 
				
			||||||
 | 
					+		return 0xffff;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	bus_addr = i2c_mii_phy_addr(phy_id);
 | 
				
			||||||
 | 
					+	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 ret;
 | 
				
			||||||
 | 
					+	u8 data[3];
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!i2c_mii_valid_phy_id(phy_id))
 | 
				
			||||||
 | 
					+		return 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	data[0] = reg;
 | 
				
			||||||
 | 
					+	data[1] = val >> 8;
 | 
				
			||||||
 | 
					+	data[2] = val;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	msg.addr = i2c_mii_phy_addr(phy_id);
 | 
				
			||||||
 | 
					+	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
											
										
									
								
							@@ -0,0 +1,177 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 24 Sep 2015 11:01:13 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- rework phylink_set_link_*(), combining into a single function.
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- 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;
 | 
				
			||||||
 | 
					@@ -375,12 +381,20 @@ struct phylink *phylink_create(struct ne
 | 
				
			||||||
 | 
					 	phylink_init_advert(pl, pl->link_an_mode, pl->supported,
 | 
				
			||||||
 | 
					 			    pl->link_config.advertising);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	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);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					@@ -900,4 +914,93 @@ 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);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
 | 
					+		     const unsigned long *support)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask);
 | 
				
			||||||
 | 
					+	int ret = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	netdev_dbg(pl->netdev, "requesting link mode %s with support %*pb\n",
 | 
				
			||||||
 | 
					+		   phylink_an_mode_str(mode),
 | 
				
			||||||
 | 
					+		   __ETHTOOL_LINK_MODE_MASK_NBITS, support);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (mode == MLO_AN_FIXED)
 | 
				
			||||||
 | 
					+		return -EINVAL;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	linkmode_copy(mask, support);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Ignore errors if we're expecting a PHY to attach later */
 | 
				
			||||||
 | 
					+	ret = phylink_validate_support(pl, mode, mask);
 | 
				
			||||||
 | 
					+	if (ret && mode != MLO_AN_PHY)
 | 
				
			||||||
 | 
					+		return ret;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	mutex_lock(&pl->config_mutex);
 | 
				
			||||||
 | 
					+	if (mode == MLO_AN_8023Z && pl->phydev) {
 | 
				
			||||||
 | 
					+		ret = -EINVAL;
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		bool changed = !bitmap_equal(pl->supported, mask,
 | 
				
			||||||
 | 
					+					     __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
				
			||||||
 | 
					+		if (changed) {
 | 
				
			||||||
 | 
					+			linkmode_copy(pl->supported, mask);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			phylink_init_advert(pl, mode, mask,
 | 
				
			||||||
 | 
					+					    pl->link_config.advertising);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (pl->link_an_mode != mode) {
 | 
				
			||||||
 | 
					+			pl->link_an_mode = mode;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			changed = true;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+			netdev_info(pl->netdev, "switched to %s link mode\n",
 | 
				
			||||||
 | 
					+				    phylink_an_mode_str(mode));
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		pl->link_port = port;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (changed && !test_bit(PHYLINK_DISABLE_STOPPED,
 | 
				
			||||||
 | 
					+					 &pl->phylink_disable_state))
 | 
				
			||||||
 | 
					+			phylink_mac_config(pl, &pl->link_config);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+	mutex_unlock(&pl->config_mutex);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	return ret;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+EXPORT_SYMBOL_GPL(phylink_set_link);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+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
 | 
				
			||||||
 | 
					@@ -88,6 +88,12 @@ int phylink_ethtool_ksettings_set(struct
 | 
				
			||||||
 | 
					 				  const struct ethtool_link_ksettings *);
 | 
				
			||||||
 | 
					 int phylink_mii_ioctl(struct phylink *, struct ifreq *, int);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
 | 
					+		     const unsigned long *support);
 | 
				
			||||||
 | 
					+void phylink_disable(struct phylink *pl);
 | 
				
			||||||
 | 
					+void phylink_enable(struct phylink *pl);
 | 
				
			||||||
 | 
					+struct phylink *phylink_lookup_by_netdev(struct net_device *ndev);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 #define phylink_zero(bm) \
 | 
				
			||||||
 | 
					 	bitmap_zero(bm, __ETHTOOL_LINK_MODE_MASK_NBITS)
 | 
				
			||||||
 | 
					 #define __phylink_do_bit(op, bm, mode) \
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -0,0 +1,280 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Sun, 13 Sep 2015 01:06:31 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] sfp: display SFP module information
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/sfp.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/sfp.c
 | 
				
			||||||
 | 
					@@ -251,6 +251,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)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -428,6 +604,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -471,10 +648,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 ||
 | 
				
			||||||
@@ -0,0 +1,743 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Wed, 16 Sep 2015 21:27:10 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/Kconfig
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/Kconfig
 | 
				
			||||||
 | 
					@@ -57,7 +57,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)
 | 
				
			||||||
 | 
					@@ -399,14 +407,9 @@ struct mvneta_port {
 | 
				
			||||||
 | 
					 	u16 tx_ring_size;
 | 
				
			||||||
 | 
					 	u16 rx_ring_size;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	struct mii_bus *mii_bus;
 | 
				
			||||||
 | 
					-	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;
 | 
				
			||||||
 | 
					@@ -1240,44 +1243,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;
 | 
				
			||||||
 | 
					@@ -1425,7 +1390,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);
 | 
				
			||||||
 | 
					@@ -2630,26 +2594,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
 | 
				
			||||||
 | 
					@@ -2665,7 +2614,6 @@ static int mvneta_poll(struct napi_struc
 | 
				
			||||||
 | 
					 	u32 cause_rx_tx;
 | 
				
			||||||
 | 
					 	int rx_queue;
 | 
				
			||||||
 | 
					 	struct mvneta_port *pp = netdev_priv(napi->dev);
 | 
				
			||||||
 | 
					-	struct net_device *ndev = pp->dev;
 | 
				
			||||||
 | 
					 	struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (!netif_running(pp->dev)) {
 | 
				
			||||||
 | 
					@@ -2679,12 +2627,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, ndev->phydev);
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
 | 
				
			||||||
 | 
					+				  MVNETA_CAUSE_LINK_CHANGE |
 | 
				
			||||||
 | 
					+				  MVNETA_CAUSE_PSC_SYNC_CHANGE))
 | 
				
			||||||
 | 
					+			mvneta_link_change(pp);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Release Tx descriptors */
 | 
				
			||||||
 | 
					@@ -2982,7 +2929,6 @@ static int mvneta_setup_txqs(struct mvne
 | 
				
			||||||
 | 
					 static void mvneta_start_dev(struct mvneta_port *pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	int cpu;
 | 
				
			||||||
 | 
					-	struct net_device *ndev = pp->dev;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mvneta_max_rx_size_set(pp, pp->pkt_size);
 | 
				
			||||||
 | 
					 	mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
 | 
				
			||||||
 | 
					@@ -3005,16 +2951,15 @@ static void mvneta_start_dev(struct mvne
 | 
				
			||||||
 | 
					 		    MVNETA_CAUSE_LINK_CHANGE |
 | 
				
			||||||
 | 
					 		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	phy_start(ndev->phydev);
 | 
				
			||||||
 | 
					+	phylink_start(pp->phylink);
 | 
				
			||||||
 | 
					 	netif_tx_start_all_queues(pp->dev);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static void mvneta_stop_dev(struct mvneta_port *pp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	unsigned int cpu;
 | 
				
			||||||
 | 
					-	struct net_device *ndev = pp->dev;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	phy_stop(ndev->phydev);
 | 
				
			||||||
 | 
					+	phylink_stop(pp->phylink);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	for_each_online_cpu(cpu) {
 | 
				
			||||||
 | 
					 		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 | 
				
			||||||
 | 
					@@ -3184,99 +3129,210 @@ static int mvneta_set_mac_addr(struct ne
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static void mvneta_adjust_link(struct net_device *ndev)
 | 
				
			||||||
 | 
					+static void mvneta_validate_support(struct net_device *ndev, unsigned int mode,
 | 
				
			||||||
 | 
					+				    unsigned long *support)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Allow all the expected bits */
 | 
				
			||||||
 | 
					+	phylink_set(mask, Autoneg);
 | 
				
			||||||
 | 
					+	phylink_set(mask, TP);
 | 
				
			||||||
 | 
					+	phylink_set(mask, AUI);
 | 
				
			||||||
 | 
					+	phylink_set(mask, MII);
 | 
				
			||||||
 | 
					+	phylink_set(mask, FIBRE);
 | 
				
			||||||
 | 
					+	phylink_set(mask, BNC);
 | 
				
			||||||
 | 
					+	phylink_set(mask, Backplane);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	/* Half-duplex at speeds higher than 100Mbit is unsupported */
 | 
				
			||||||
 | 
					+	phylink_set(mask, 1000baseT_Full);
 | 
				
			||||||
 | 
					+	phylink_set(mask, 1000baseX_Full);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (mode != MLO_AN_8023Z) {
 | 
				
			||||||
 | 
					+		/* 10M and 100M are only supported in non-802.3z mode */
 | 
				
			||||||
 | 
					+		phylink_set(mask, 10baseT_Half);
 | 
				
			||||||
 | 
					+		phylink_set(mask, 10baseT_Full);
 | 
				
			||||||
 | 
					+		phylink_set(mask, 100baseT_Half);
 | 
				
			||||||
 | 
					+		phylink_set(mask, 100baseT_Full);
 | 
				
			||||||
 | 
					+	} else {
 | 
				
			||||||
 | 
					+		phylink_set(mask, Pause);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	bitmap_and(support, support, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+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 = ndev->phydev;
 | 
				
			||||||
 | 
					-	int status_change = 0;
 | 
				
			||||||
 | 
					+	u32 gmac_stat;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	gmac_stat = mvreg_read(pp, MVNETA_GMAC_STATUS);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	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;
 | 
				
			||||||
 | 
					+	state->an_complete = !!(gmac_stat & MVNETA_GMAC_AN_COMPLETE);
 | 
				
			||||||
 | 
					+	state->link = !!(gmac_stat & MVNETA_GMAC_LINK_UP);
 | 
				
			||||||
 | 
					+	state->duplex = !!(gmac_stat & MVNETA_GMAC_FULL_DUPLEX);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-			mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
 | 
				
			||||||
 | 
					+	return 1;
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-			pp->duplex = phydev->duplex;
 | 
				
			||||||
 | 
					-			pp->speed  = phydev->speed;
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					+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 (phylink_test(state->advertising, 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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		pp->link = phydev->link;
 | 
				
			||||||
 | 
					-		status_change = 1;
 | 
				
			||||||
 | 
					+	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;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	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_dev;
 | 
				
			||||||
 | 
					+	struct mvneta_port *pp = netdev_priv(ndev);
 | 
				
			||||||
 | 
					+	u32 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;
 | 
				
			||||||
 | 
					+	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->supported &= PHY_GBIT_FEATURES;
 | 
				
			||||||
 | 
					-	phy_dev->advertising = phy_dev->supported;
 | 
				
			||||||
 | 
					+	mvneta_port_up(pp);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	pp->link    = 0;
 | 
				
			||||||
 | 
					-	pp->duplex  = 0;
 | 
				
			||||||
 | 
					-	pp->speed   = 0;
 | 
				
			||||||
 | 
					+static const struct phylink_mac_ops mvneta_phylink_ops = {
 | 
				
			||||||
 | 
					+	.validate_support = mvneta_validate_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,
 | 
				
			||||||
 | 
					+};
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return 0;
 | 
				
			||||||
 | 
					+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)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	struct net_device *ndev = pp->dev;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	phy_disconnect(ndev->phydev);
 | 
				
			||||||
 | 
					+	phylink_disconnect_phy(pp->phylink);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Electing a CPU must be done in an atomic way: it should be done
 | 
				
			||||||
 | 
					@@ -3534,10 +3590,9 @@ static int mvneta_stop(struct net_device
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int mvneta_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-	if (!dev->phydev)
 | 
				
			||||||
 | 
					-		return -ENOTSUPP;
 | 
				
			||||||
 | 
					+	struct mvneta_port *pp = netdev_priv(dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return phy_mii_ioctl(dev->phydev, ifr, cmd);
 | 
				
			||||||
 | 
					+	return phylink_mii_ioctl(pp->phylink, ifr, cmd);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Ethtool methods */
 | 
				
			||||||
 | 
					@@ -3548,44 +3603,18 @@ mvneta_ethtool_set_link_ksettings(struct
 | 
				
			||||||
 | 
					 				  const struct ethtool_link_ksettings *cmd)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct mvneta_port *pp = netdev_priv(ndev);
 | 
				
			||||||
 | 
					-	struct phy_device *phydev = ndev->phydev;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-	if (!phydev)
 | 
				
			||||||
 | 
					-		return -ENODEV;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if ((cmd->base.autoneg == AUTONEG_ENABLE) != pp->use_inband_status) {
 | 
				
			||||||
 | 
					-		u32 val;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		mvneta_set_autoneg(pp, cmd->base.autoneg == AUTONEG_ENABLE);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		if (cmd->base.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);
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					+	return phylink_ethtool_ksettings_set(pp->phylink, cmd);
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		pp->use_inband_status = (cmd->base.autoneg == AUTONEG_ENABLE);
 | 
				
			||||||
 | 
					-		netdev_info(pp->dev, "autoneg status set to %i\n",
 | 
				
			||||||
 | 
					-			    pp->use_inband_status);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-		if (netif_running(ndev)) {
 | 
				
			||||||
 | 
					-			mvneta_port_down(pp);
 | 
				
			||||||
 | 
					-			mvneta_port_up(pp);
 | 
				
			||||||
 | 
					-		}
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					+/* Get link ksettings for ethtools */
 | 
				
			||||||
 | 
					+static int
 | 
				
			||||||
 | 
					+mvneta_ethtool_get_link_ksettings(struct net_device *ndev,
 | 
				
			||||||
 | 
					+				  struct ethtool_link_ksettings *cmd)
 | 
				
			||||||
 | 
					+{
 | 
				
			||||||
 | 
					+	struct mvneta_port *pp = netdev_priv(ndev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	return phy_ethtool_ksettings_set(ndev->phydev, cmd);
 | 
				
			||||||
 | 
					+	return phylink_ethtool_ksettings_get(pp->phylink, cmd);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Set interrupt coalescing for ethtools */
 | 
				
			||||||
 | 
					@@ -3693,26 +3722,28 @@ static void mvneta_ethtool_update_stats(
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	const struct mvneta_statistic *s;
 | 
				
			||||||
 | 
					 	void __iomem *base = pp->base;
 | 
				
			||||||
 | 
					-	u32 high, low, val;
 | 
				
			||||||
 | 
					-	u64 val64;
 | 
				
			||||||
 | 
					+	u32 high, low;
 | 
				
			||||||
 | 
					+	u64 val;
 | 
				
			||||||
 | 
					 	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);
 | 
				
			||||||
 | 
					-			val64 = (u64)high << 32 | low;
 | 
				
			||||||
 | 
					-			pp->ethtool_stats[i] += val64;
 | 
				
			||||||
 | 
					+			val = (u64)high << 32 | low;
 | 
				
			||||||
 | 
					 			break;
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+		pp->ethtool_stats[i] += val;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3872,7 +3903,7 @@ 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_link_ksettings = phy_ethtool_get_link_ksettings,
 | 
				
			||||||
 | 
					+	.get_link_ksettings = mvneta_ethtool_get_link_ksettings,
 | 
				
			||||||
 | 
					 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3999,14 +4030,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;
 | 
				
			||||||
 | 
					@@ -4022,31 +4052,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;
 | 
				
			||||||
 | 
					@@ -4057,12 +4067,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->rxq_def = rxq_def;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -4073,7 +4078,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);
 | 
				
			||||||
 | 
					@@ -4181,6 +4186,14 @@ static int mvneta_probe(struct platform_
 | 
				
			||||||
 | 
					 	dev->priv_flags |= 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");
 | 
				
			||||||
 | 
					@@ -4192,14 +4205,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->mdio.dev);
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 err_netdev:
 | 
				
			||||||
 | 
					@@ -4210,16 +4215,14 @@ 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_bus);
 | 
				
			||||||
 | 
					 	clk_disable_unprepare(pp->clk);
 | 
				
			||||||
 | 
					-err_put_phy_node:
 | 
				
			||||||
 | 
					-	of_node_put(phy_node);
 | 
				
			||||||
 | 
					-	if (of_phy_is_fixed_link(dn))
 | 
				
			||||||
 | 
					-		of_phy_deregister_fixed_link(dn);
 | 
				
			||||||
 | 
					 err_free_irq:
 | 
				
			||||||
 | 
					 	irq_dispose_mapping(dev->irq);
 | 
				
			||||||
 | 
					 err_free_netdev:
 | 
				
			||||||
 | 
					@@ -4231,7 +4234,6 @@ err_free_netdev:
 | 
				
			||||||
 | 
					 static int mvneta_remove(struct platform_device *pdev)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct net_device  *dev = platform_get_drvdata(pdev);
 | 
				
			||||||
 | 
					-	struct device_node *dn = pdev->dev.of_node;
 | 
				
			||||||
 | 
					 	struct mvneta_port *pp = netdev_priv(dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	unregister_netdev(dev);
 | 
				
			||||||
 | 
					@@ -4239,10 +4241,8 @@ static int mvneta_remove(struct platform
 | 
				
			||||||
 | 
					 	clk_disable_unprepare(pp->clk);
 | 
				
			||||||
 | 
					 	free_percpu(pp->ports);
 | 
				
			||||||
 | 
					 	free_percpu(pp->stats);
 | 
				
			||||||
 | 
					-	if (of_phy_is_fixed_link(dn))
 | 
				
			||||||
 | 
					-		of_phy_deregister_fixed_link(dn);
 | 
				
			||||||
 | 
					 	irq_dispose_mapping(dev->irq);
 | 
				
			||||||
 | 
					-	of_node_put(pp->phy_node);
 | 
				
			||||||
 | 
					+	phylink_destroy(pp->phylink);
 | 
				
			||||||
 | 
					 	free_netdev(dev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (pp->bm_priv) {
 | 
				
			||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Sat, 24 Dec 2016 10:27:08 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: mvneta: disable MVNETA_CAUSE_PSC_SYNC_CHANGE
 | 
				
			||||||
 | 
					 interrupt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The PSC sync change interrupt can fire multiple times while the link is
 | 
				
			||||||
 | 
					down.  As this isn't information we make use of, it's pointless having
 | 
				
			||||||
 | 
					the interrupt enabled, so let's disable this interrupt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -2629,9 +2629,11 @@ static int mvneta_poll(struct napi_struc
 | 
				
			||||||
 | 
					 		mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		if (cause_misc & (MVNETA_CAUSE_PHY_STATUS_CHANGE |
 | 
				
			||||||
 | 
					-				  MVNETA_CAUSE_LINK_CHANGE |
 | 
				
			||||||
 | 
					-				  MVNETA_CAUSE_PSC_SYNC_CHANGE))
 | 
				
			||||||
 | 
					+				  MVNETA_CAUSE_LINK_CHANGE)) {
 | 
				
			||||||
 | 
					+			printk(KERN_DEBUG "%s: cause 0x%08x:0x%08x\n",
 | 
				
			||||||
 | 
					+				__func__, cause_rx_tx, cause_misc);
 | 
				
			||||||
 | 
					 			mvneta_link_change(pp);
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	/* Release Tx descriptors */
 | 
				
			||||||
 | 
					@@ -2948,8 +2950,7 @@ static void mvneta_start_dev(struct mvne
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mvreg_write(pp, MVNETA_INTR_MISC_MASK,
 | 
				
			||||||
 | 
					 		    MVNETA_CAUSE_PHY_STATUS_CHANGE |
 | 
				
			||||||
 | 
					-		    MVNETA_CAUSE_LINK_CHANGE |
 | 
				
			||||||
 | 
					-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
 | 
				
			||||||
 | 
					+		    MVNETA_CAUSE_LINK_CHANGE);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	phylink_start(pp->phylink);
 | 
				
			||||||
 | 
					 	netif_tx_start_all_queues(pp->dev);
 | 
				
			||||||
 | 
					@@ -3440,8 +3441,7 @@ static int mvneta_cpu_online(unsigned in
 | 
				
			||||||
 | 
					 	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 |
 | 
				
			||||||
 | 
					-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
 | 
				
			||||||
 | 
					+		    MVNETA_CAUSE_LINK_CHANGE);
 | 
				
			||||||
 | 
					 	netif_tx_start_all_queues(pp->dev);
 | 
				
			||||||
 | 
					 	spin_unlock(&pp->lock);
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					@@ -3482,8 +3482,7 @@ static int mvneta_cpu_dead(unsigned int
 | 
				
			||||||
 | 
					 	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 |
 | 
				
			||||||
 | 
					-		    MVNETA_CAUSE_PSC_SYNC_CHANGE);
 | 
				
			||||||
 | 
					+		    MVNETA_CAUSE_LINK_CHANGE);
 | 
				
			||||||
 | 
					 	netif_tx_start_all_queues(pp->dev);
 | 
				
			||||||
 | 
					 	return 0;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 20:27:19 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -783,6 +783,20 @@ int phylink_ethtool_ksettings_set(struct
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_set);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+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
 | 
				
			||||||
 | 
					@@ -86,6 +86,7 @@ int phylink_ethtool_ksettings_get(struct
 | 
				
			||||||
 | 
					 				  struct ethtool_link_ksettings *);
 | 
				
			||||||
 | 
					 int phylink_ethtool_ksettings_set(struct phylink *,
 | 
				
			||||||
 | 
					 				  const struct ethtool_link_ksettings *);
 | 
				
			||||||
 | 
					+int phylink_ethtool_nway_reset(struct phylink *);
 | 
				
			||||||
 | 
					 int phylink_mii_ioctl(struct phylink *, struct ifreq *, int);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 19:40:31 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3616,6 +3616,13 @@ mvneta_ethtool_get_link_ksettings(struct
 | 
				
			||||||
 | 
					 	return phylink_ethtool_ksettings_get(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)
 | 
				
			||||||
 | 
					@@ -3889,6 +3896,7 @@ static const struct net_device_ops mvnet
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 const struct ethtool_ops mvneta_eth_tool_ops = {
 | 
				
			||||||
 | 
					+	.nway_reset	= mvneta_ethtool_nway_reset,
 | 
				
			||||||
 | 
					 	.get_link       = ethtool_op_get_link,
 | 
				
			||||||
 | 
					 	.set_coalesce   = mvneta_ethtool_set_coalesce,
 | 
				
			||||||
 | 
					 	.get_coalesce   = mvneta_ethtool_get_coalesce,
 | 
				
			||||||
@@ -0,0 +1,232 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 20:32:07 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -132,6 +132,9 @@ static int phylink_parse_fixedlink(struc
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		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"))
 | 
				
			||||||
 | 
					@@ -277,6 +280,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 (phylink_test(pl->link_config.advertising, Pause))
 | 
				
			||||||
 | 
					+			pause |= MLO_PAUSE_SYM;
 | 
				
			||||||
 | 
					+		if (phylink_test(pl->link_config.advertising, 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";
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					+}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 static void phylink_resolve(struct work_struct *w)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct phylink *pl = container_of(w, struct phylink, resolve);
 | 
				
			||||||
 | 
					@@ -290,6 +343,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:
 | 
				
			||||||
 | 
					@@ -298,9 +352,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:
 | 
				
			||||||
 | 
					@@ -330,7 +387,7 @@ static void phylink_resolve(struct work_
 | 
				
			||||||
 | 
					 				    "Link is Up - %s/%s - flow control %s\n",
 | 
				
			||||||
 | 
					 				    phy_speed_to_str(link_state.speed),
 | 
				
			||||||
 | 
					 				    phy_duplex_to_str(link_state.duplex),
 | 
				
			||||||
 | 
					-				    link_state.pause ? "rx/tx" : "off");
 | 
				
			||||||
 | 
					+				    phylink_pause_to_str(link_state.pause));
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 	mutex_unlock(&pl->state_mutex);
 | 
				
			||||||
 | 
					@@ -358,6 +415,7 @@ struct phylink *phylink_create(struct ne
 | 
				
			||||||
 | 
					 	pl->netdev = ndev;
 | 
				
			||||||
 | 
					 	pl->link_interface = iface;
 | 
				
			||||||
 | 
					 	pl->link_port = PORT_MII;
 | 
				
			||||||
 | 
					+	pl->link_config.pause = MLO_PAUSE_AN;
 | 
				
			||||||
 | 
					 	pl->link_config.speed = SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					 	pl->link_config.duplex = DUPLEX_UNKNOWN;
 | 
				
			||||||
 | 
					 	pl->ops = ops;
 | 
				
			||||||
 | 
					@@ -580,6 +638,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);
 | 
				
			||||||
 | 
					@@ -797,6 +856,79 @@ 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 (!phylink_test(pl->supported, Pause) &&
 | 
				
			||||||
 | 
					+	    !phylink_test(pl->supported, Asym_Pause))
 | 
				
			||||||
 | 
					+		return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!phylink_test(pl->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;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
 | 
				
			||||||
 | 
					+		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,
 | 
				
			||||||
 | 
					@@ -87,6 +91,10 @@ int phylink_ethtool_ksettings_get(struct
 | 
				
			||||||
 | 
					 int phylink_ethtool_ksettings_set(struct phylink *,
 | 
				
			||||||
 | 
					 				  const struct ethtool_link_ksettings *);
 | 
				
			||||||
 | 
					 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);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 17:41:44 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3180,6 +3180,12 @@ static int mvneta_mac_link_state(struct
 | 
				
			||||||
 | 
					 	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;
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3222,6 +3228,8 @@ static void mvneta_mac_config(struct net
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (phylink_test(state->advertising, 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:
 | 
				
			||||||
 | 
					@@ -3246,7 +3254,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -3712,6 +3720,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)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -3903,6 +3927,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,
 | 
				
			||||||
@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 00:34:08 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3154,10 +3154,11 @@ static void mvneta_validate_support(stru
 | 
				
			||||||
 | 
					 		phylink_set(mask, 10baseT_Full);
 | 
				
			||||||
 | 
					 		phylink_set(mask, 100baseT_Half);
 | 
				
			||||||
 | 
					 		phylink_set(mask, 100baseT_Full);
 | 
				
			||||||
 | 
					-	} else {
 | 
				
			||||||
 | 
					-		phylink_set(mask, Pause);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	if (mode != MLO_AN_FIXED)
 | 
				
			||||||
 | 
					+		phylink_set(mask, Pause);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	bitmap_and(support, support, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Tue, 12 Jul 2016 00:04:13 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3144,6 +3144,8 @@ static void mvneta_validate_support(stru
 | 
				
			||||||
 | 
					 	phylink_set(mask, BNC);
 | 
				
			||||||
 | 
					 	phylink_set(mask, Backplane);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	/* Asymmetric pause is unsupported */
 | 
				
			||||||
 | 
					+	phylink_set(mask, Pause);
 | 
				
			||||||
 | 
					 	/* Half-duplex at speeds higher than 100Mbit is unsupported */
 | 
				
			||||||
 | 
					 	phylink_set(mask, 1000baseT_Full);
 | 
				
			||||||
 | 
					 	phylink_set(mask, 1000baseX_Full);
 | 
				
			||||||
 | 
					@@ -3156,9 +3158,6 @@ static void mvneta_validate_support(stru
 | 
				
			||||||
 | 
					 		phylink_set(mask, 100baseT_Full);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (mode != MLO_AN_FIXED)
 | 
				
			||||||
 | 
					-		phylink_set(mask, Pause);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 	bitmap_and(support, support, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
							
								
								
									
										116
									
								
								target/linux/mvebu/patches-4.9/427-phylink-add-EEE-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								target/linux/mvebu/patches-4.9/427-phylink-add-EEE-support.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 21:19:53 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3306,7 +3306,8 @@ static void mvneta_mac_link_down(struct
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode)
 | 
				
			||||||
 | 
					+static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
 | 
				
			||||||
 | 
					+			       struct phy_device *phy)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	struct mvneta_port *pp = netdev_priv(ndev);
 | 
				
			||||||
 | 
					 	u32 val;
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -379,7 +379,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);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -929,6 +930,58 @@ 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);
 | 
				
			||||||
 | 
					+	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
 | 
				
			||||||
 | 
					@@ -70,7 +70,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 *,
 | 
				
			||||||
 | 
					@@ -95,6 +96,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);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Tue, 29 Sep 2015 15:17:39 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- 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 {
 | 
				
			||||||
 | 
					@@ -416,6 +429,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];
 | 
				
			||||||
 | 
					@@ -3291,6 +3308,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);
 | 
				
			||||||
 | 
					@@ -3304,6 +3333,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,
 | 
				
			||||||
 | 
					@@ -3320,6 +3352,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 = {
 | 
				
			||||||
 | 
					@@ -3772,6 +3809,13 @@ static void mvneta_ethtool_update_stats(
 | 
				
			||||||
 | 
					 			high = readl_relaxed(base + s->offset + 4);
 | 
				
			||||||
 | 
					 			val = (u64)high << 32 | low;
 | 
				
			||||||
 | 
					 			break;
 | 
				
			||||||
 | 
					+		case T_SW:
 | 
				
			||||||
 | 
					+			switch (s->offset) {
 | 
				
			||||||
 | 
					+			case ETHTOOL_STAT_EEE_WAKEUP:
 | 
				
			||||||
 | 
					+				val = phylink_get_eee_err(pp->phylink);
 | 
				
			||||||
 | 
					+				break;
 | 
				
			||||||
 | 
					+			}
 | 
				
			||||||
 | 
					+			break;
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		pp->ethtool_stats[i] += val;
 | 
				
			||||||
 | 
					@@ -3907,6 +3951,47 @@ static u16 mvneta_select_queue(struct ne
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+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,
 | 
				
			||||||
 | 
					@@ -3939,6 +4024,8 @@ const struct ethtool_ops mvneta_eth_tool
 | 
				
			||||||
 | 
					 	.set_rxfh	= mvneta_ethtool_set_rxfh,
 | 
				
			||||||
 | 
					 	.get_link_ksettings = mvneta_ethtool_get_link_ksettings,
 | 
				
			||||||
 | 
					 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
 | 
				
			||||||
 | 
					+	.get_eee	= mvneta_ethtool_get_eee,
 | 
				
			||||||
 | 
					+	.set_eee	= mvneta_ethtool_set_eee,
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 /* Initialize hw */
 | 
				
			||||||
@@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 23:10:05 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -930,6 +930,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;
 | 
				
			||||||
 | 
					@@ -1115,6 +1145,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
 | 
				
			||||||
 | 
					@@ -74,6 +74,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 *);
 | 
				
			||||||
 | 
					@@ -96,12 +101,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 *);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
 | 
				
			||||||
 | 
					 		     const unsigned long *support);
 | 
				
			||||||
 | 
					 void phylink_disable(struct phylink *pl);
 | 
				
			||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 23:32:39 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] net: mvneta: add module EEPROM reading support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/ethernet/marvell/mvneta.c
 | 
				
			||||||
 | 
					@@ -3951,6 +3951,22 @@ static u16 mvneta_select_queue(struct ne
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+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)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -4024,6 +4040,8 @@ const struct ethtool_ops mvneta_eth_tool
 | 
				
			||||||
 | 
					 	.set_rxfh	= mvneta_ethtool_set_rxfh,
 | 
				
			||||||
 | 
					 	.get_link_ksettings = mvneta_ethtool_get_link_ksettings,
 | 
				
			||||||
 | 
					 	.set_link_ksettings = mvneta_ethtool_set_link_ksettings,
 | 
				
			||||||
 | 
					+	.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,
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 8 Oct 2015 23:49:47 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] sfp/phylink: hook up eeprom functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/sfp.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/sfp.c
 | 
				
			||||||
 | 
					@@ -985,11 +985,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 */
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -1003,10 +1001,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;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -1037,7 +1034,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)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					@@ -1113,6 +1114,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;
 | 
				
			||||||
 | 
					@@ -1230,6 +1232,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);
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@arm.linux.org.uk>
 | 
				
			||||||
 | 
					Date: Thu, 1 Oct 2015 00:34:08 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] 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>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					@@ -1671,7 +1671,8 @@ 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 | SUPPORTED_FIBRE,
 | 
				
			||||||
 | 
					+		.features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE |
 | 
				
			||||||
 | 
					+				SUPPORTED_Pause,
 | 
				
			||||||
 | 
					 		.flags = PHY_HAS_INTERRUPT,
 | 
				
			||||||
 | 
					 		.probe = marvell_probe,
 | 
				
			||||||
 | 
					 		.config_init = &m88e1510_config_init,
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Tue, 12 Jul 2016 16:45:43 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] phy: marvell: 88E1111: 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					@@ -1523,7 +1523,7 @@ static struct phy_driver marvell_drivers
 | 
				
			||||||
 | 
					 		.phy_id = MARVELL_PHY_ID_88E1111,
 | 
				
			||||||
 | 
					 		.phy_id_mask = MARVELL_PHY_ID_MASK,
 | 
				
			||||||
 | 
					 		.name = "Marvell 88E1111",
 | 
				
			||||||
 | 
					-		.features = PHY_GBIT_FEATURES,
 | 
				
			||||||
 | 
					+		.features = PHY_GBIT_FEATURES | SUPPORTED_Pause,
 | 
				
			||||||
 | 
					 		.flags = PHY_HAS_INTERRUPT,
 | 
				
			||||||
 | 
					 		.probe = marvell_probe,
 | 
				
			||||||
 | 
					 		.config_init = &m88e1111_config_init,
 | 
				
			||||||
@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Tue, 12 Jul 2016 16:45:43 +0100
 | 
				
			||||||
 | 
					Subject: [PATCH] phy: marvell: 88E1540: 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					@@ -1691,7 +1691,7 @@ static struct phy_driver marvell_drivers
 | 
				
			||||||
 | 
					 		.phy_id = MARVELL_PHY_ID_88E1540,
 | 
				
			||||||
 | 
					 		.phy_id_mask = MARVELL_PHY_ID_MASK,
 | 
				
			||||||
 | 
					 		.name = "Marvell 88E1540",
 | 
				
			||||||
 | 
					-		.features = PHY_GBIT_FEATURES,
 | 
				
			||||||
 | 
					+		.features = PHY_GBIT_FEATURES | SUPPORTED_Pause,
 | 
				
			||||||
 | 
					 		.flags = PHY_HAS_INTERRUPT,
 | 
				
			||||||
 | 
					 		.probe = marvell_probe,
 | 
				
			||||||
 | 
					 		.config_init = &marvell_config_init,
 | 
				
			||||||
@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Fri, 23 Dec 2016 18:54:01 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] net: phy: fix marvell phy status reading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Marvell driver incorrectly provides phydev->lp_advertising as the
 | 
				
			||||||
 | 
					logical and of the link partner's advert and our advert.  This is
 | 
				
			||||||
 | 
					incorrect - this field is supposed to store the link parter's unmodified
 | 
				
			||||||
 | 
					advertisment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This allows ethtool to report the correct link partner auto-negotiation
 | 
				
			||||||
 | 
					status.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/marvell.c
 | 
				
			||||||
 | 
					@@ -1106,8 +1106,6 @@ static int marvell_read_status_page(stru
 | 
				
			||||||
 | 
					 		if (adv < 0)
 | 
				
			||||||
 | 
					 			return adv;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-		lpa &= adv;
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 		if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
 | 
				
			||||||
 | 
					 			phydev->duplex = DUPLEX_FULL;
 | 
				
			||||||
 | 
					 		else
 | 
				
			||||||
@@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Tue, 3 Jan 2017 18:34:17 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] phylink: propagate PHY interface mode to MAC driver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some 10Gigabit PHYs automatically switch the mode of their host
 | 
				
			||||||
 | 
					interface depending on their negotiated speed.  We need to communicate
 | 
				
			||||||
 | 
					this to the MAC driver so the MAC can switch its host interface to
 | 
				
			||||||
 | 
					match the PHYs new operating mode.  Provide the current PHY interface
 | 
				
			||||||
 | 
					mode to the MAC driver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -242,8 +242,9 @@ static void phylink_mac_config(struct ph
 | 
				
			||||||
 | 
					 			       const struct phylink_link_state *state)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					 	netdev_dbg(pl->netdev,
 | 
				
			||||||
 | 
					-		   "%s: mode=%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
 | 
				
			||||||
 | 
					+		   "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n",
 | 
				
			||||||
 | 
					 		   __func__, phylink_an_mode_str(pl->link_an_mode),
 | 
				
			||||||
 | 
					+		   phy_modes(state->interface),
 | 
				
			||||||
 | 
					 		   phy_speed_to_str(state->speed),
 | 
				
			||||||
 | 
					 		   phy_duplex_to_str(state->duplex),
 | 
				
			||||||
 | 
					 		   __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
 | 
				
			||||||
 | 
					@@ -264,6 +265,7 @@ static int phylink_get_mac_state(struct
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	linkmode_copy(state->advertising, pl->link_config.advertising);
 | 
				
			||||||
 | 
					 	linkmode_zero(state->lp_advertising);
 | 
				
			||||||
 | 
					+	state->interface = pl->link_config.interface;
 | 
				
			||||||
 | 
					 	state->an_enabled = pl->link_config.an_enabled;
 | 
				
			||||||
 | 
					 	state->link = 1;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -344,19 +346,38 @@ static void phylink_resolve(struct work_
 | 
				
			||||||
 | 
					 		case MLO_AN_PHY:
 | 
				
			||||||
 | 
					 			link_state = pl->phy_state;
 | 
				
			||||||
 | 
					 			phylink_resolve_flow(pl, &link_state);
 | 
				
			||||||
 | 
					+			phylink_mac_config(pl, &link_state);
 | 
				
			||||||
 | 
					 			break;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		case MLO_AN_FIXED:
 | 
				
			||||||
 | 
					 			phylink_get_fixed_state(pl, &link_state);
 | 
				
			||||||
 | 
					+			phylink_mac_config(pl, &link_state);
 | 
				
			||||||
 | 
					 			break;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 		case MLO_AN_SGMII:
 | 
				
			||||||
 | 
					 			phylink_get_mac_state(pl, &link_state);
 | 
				
			||||||
 | 
					 			if (pl->phydev) {
 | 
				
			||||||
 | 
					+				bool changed = false;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 				link_state.link = link_state.link &&
 | 
				
			||||||
 | 
					 						  pl->phy_state.link;
 | 
				
			||||||
 | 
					-				link_state.pause |= pl->phy_state.pause;
 | 
				
			||||||
 | 
					-				phylink_resolve_flow(pl, &link_state);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				if (pl->phy_state.interface !=
 | 
				
			||||||
 | 
					+				    link_state.interface) {
 | 
				
			||||||
 | 
					+					link_state.interface = pl->phy_state.interface;
 | 
				
			||||||
 | 
					+					changed = true;
 | 
				
			||||||
 | 
					+				}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+				/* Propagate the flow control from the PHY
 | 
				
			||||||
 | 
					+				 * to the MAC. Also propagate the interface
 | 
				
			||||||
 | 
					+				 * if changed.
 | 
				
			||||||
 | 
					+				 */
 | 
				
			||||||
 | 
					+				if (pl->phy_state.link || changed) {
 | 
				
			||||||
 | 
					+					link_state.pause |= pl->phy_state.pause;
 | 
				
			||||||
 | 
					+					phylink_resolve_flow(pl, &link_state);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+					phylink_mac_config(pl, &link_state);
 | 
				
			||||||
 | 
					+				}
 | 
				
			||||||
 | 
					 			}
 | 
				
			||||||
 | 
					 			break;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -372,13 +393,6 @@ static void phylink_resolve(struct work_
 | 
				
			||||||
 | 
					 			pl->ops->mac_link_down(ndev, pl->link_an_mode);
 | 
				
			||||||
 | 
					 			netdev_info(ndev, "Link is Down\n");
 | 
				
			||||||
 | 
					 		} else {
 | 
				
			||||||
 | 
					-			/* If we have a PHY, we need the MAC updated with
 | 
				
			||||||
 | 
					-			 * the current link parameters (eg, in SGMII mode,
 | 
				
			||||||
 | 
					-			 * with flow control status.)
 | 
				
			||||||
 | 
					-			 */
 | 
				
			||||||
 | 
					-			if (pl->phydev)
 | 
				
			||||||
 | 
					-				phylink_mac_config(pl, &link_state);
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					 			pl->ops->mac_link_up(ndev, pl->link_an_mode,
 | 
				
			||||||
 | 
					 					     pl->phydev);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -414,8 +428,10 @@ struct phylink *phylink_create(struct ne
 | 
				
			||||||
 | 
					 	mutex_init(&pl->config_mutex);
 | 
				
			||||||
 | 
					 	INIT_WORK(&pl->resolve, phylink_resolve);
 | 
				
			||||||
 | 
					 	pl->netdev = ndev;
 | 
				
			||||||
 | 
					+	pl->phy_state.interface = iface;
 | 
				
			||||||
 | 
					 	pl->link_interface = iface;
 | 
				
			||||||
 | 
					 	pl->link_port = PORT_MII;
 | 
				
			||||||
 | 
					+	pl->link_config.interface = iface;
 | 
				
			||||||
 | 
					 	pl->link_config.pause = MLO_PAUSE_AN;
 | 
				
			||||||
 | 
					 	pl->link_config.speed = SPEED_UNKNOWN;
 | 
				
			||||||
 | 
					 	pl->link_config.duplex = DUPLEX_UNKNOWN;
 | 
				
			||||||
 | 
					@@ -471,12 +487,14 @@ void phylink_phy_change(struct phy_devic
 | 
				
			||||||
 | 
					 		pl->phy_state.pause |= MLO_PAUSE_SYM;
 | 
				
			||||||
 | 
					 	if (phydev->asym_pause)
 | 
				
			||||||
 | 
					 		pl->phy_state.pause |= MLO_PAUSE_ASYM;
 | 
				
			||||||
 | 
					+	pl->phy_state.interface = phydev->interface;
 | 
				
			||||||
 | 
					 	pl->phy_state.link = up;
 | 
				
			||||||
 | 
					 	mutex_unlock(&pl->state_mutex);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	phylink_run_resolve(pl);
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	netdev_dbg(pl->netdev, "phy link %s %s/%s\n", up ? "up" : "down",
 | 
				
			||||||
 | 
					+	netdev_dbg(pl->netdev, "phy link %s %s/%s/%s\n", up ? "up" : "down",
 | 
				
			||||||
 | 
					+	           phy_modes(phydev->interface),
 | 
				
			||||||
 | 
					 		   phy_speed_to_str(phydev->speed),
 | 
				
			||||||
 | 
					 		   phy_duplex_to_str(phydev->duplex));
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					--- a/include/linux/phylink.h
 | 
				
			||||||
 | 
					+++ b/include/linux/phylink.h
 | 
				
			||||||
 | 
					@@ -27,6 +27,7 @@ enum {
 | 
				
			||||||
 | 
					 struct phylink_link_state {
 | 
				
			||||||
 | 
					 	__ETHTOOL_DECLARE_LINK_MODE_MASK(advertising);
 | 
				
			||||||
 | 
					 	__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
 | 
				
			||||||
 | 
					+	phy_interface_t interface;	/* PHY_INTERFACE_xxx */
 | 
				
			||||||
 | 
					 	int speed;
 | 
				
			||||||
 | 
					 	int duplex;
 | 
				
			||||||
 | 
					 	int pause;
 | 
				
			||||||
@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					Date: Mon, 19 Dec 2016 12:17:57 +0000
 | 
				
			||||||
 | 
					Subject: [PATCH] phylink: ensure link drops are reported
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When the MAC reports a link failure, it can be momentary.  Ensure
 | 
				
			||||||
 | 
					that the event is reported by latching the loss of link, so that the
 | 
				
			||||||
 | 
					worker reports link down.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--- a/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					+++ b/drivers/net/phy/phylink.c
 | 
				
			||||||
 | 
					@@ -60,6 +60,8 @@ struct phylink {
 | 
				
			||||||
 | 
					 	struct phylink_link_state phy_state;
 | 
				
			||||||
 | 
					 	struct work_struct resolve;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					+	bool mac_link_dropped;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	const struct phylink_module_ops *module_ops;
 | 
				
			||||||
 | 
					 	void *module_data;
 | 
				
			||||||
 | 
					 };
 | 
				
			||||||
 | 
					@@ -340,6 +342,9 @@ static void phylink_resolve(struct work_
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	mutex_lock(&pl->state_mutex);
 | 
				
			||||||
 | 
					 	if (pl->phylink_disable_state) {
 | 
				
			||||||
 | 
					+		pl->mac_link_dropped = false;
 | 
				
			||||||
 | 
					+		link_state.link = false;
 | 
				
			||||||
 | 
					+	} else if (pl->mac_link_dropped) {
 | 
				
			||||||
 | 
					 		link_state.link = false;
 | 
				
			||||||
 | 
					 	} else {
 | 
				
			||||||
 | 
					 		switch (pl->link_an_mode) {
 | 
				
			||||||
 | 
					@@ -405,6 +410,10 @@ static void phylink_resolve(struct work_
 | 
				
			||||||
 | 
					 				    phylink_pause_to_str(link_state.pause));
 | 
				
			||||||
 | 
					 		}
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+	if (!link_state.link && pl->mac_link_dropped) {
 | 
				
			||||||
 | 
					+		pl->mac_link_dropped = false;
 | 
				
			||||||
 | 
					+		queue_work(system_power_efficient_wq, &pl->resolve);
 | 
				
			||||||
 | 
					+	}
 | 
				
			||||||
 | 
					 	mutex_unlock(&pl->state_mutex);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -641,6 +650,8 @@ EXPORT_SYMBOL_GPL(phylink_disconnect_phy
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void phylink_mac_change(struct phylink *pl, bool up)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+	if (!up)
 | 
				
			||||||
 | 
					+		pl->mac_link_dropped = true;
 | 
				
			||||||
 | 
					 	phylink_run_resolve(pl);
 | 
				
			||||||
 | 
					 	netdev_dbg(pl->netdev, "mac link %s\n", up ? "up" : "down");
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
							
								
								
									
										119
									
								
								target/linux/mvebu/patches-4.9/450-reprobe_sfp_phy.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								target/linux/mvebu/patches-4.9/450-reprobe_sfp_phy.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					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
 | 
				
			||||||
 | 
					@@ -491,7 +491,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;
 | 
				
			||||||
 | 
					@@ -500,12 +500,12 @@ static void sfp_sm_probe_phy(struct sfp
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR);
 | 
				
			||||||
 | 
					 	if (IS_ERR(phy)) {
 | 
				
			||||||
 | 
					+		if (PTR_ERR(phy) == -ENODEV) {
 | 
				
			||||||
 | 
					+			dev_dbg(sfp->dev, "no PHY detected\n");
 | 
				
			||||||
 | 
					+			return -EAGAIN;
 | 
				
			||||||
 | 
					+		}
 | 
				
			||||||
 | 
					 		dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy));
 | 
				
			||||||
 | 
					-		return;
 | 
				
			||||||
 | 
					-	}
 | 
				
			||||||
 | 
					-	if (!phy) {
 | 
				
			||||||
 | 
					-		dev_info(sfp->dev, "no PHY detected\n");
 | 
				
			||||||
 | 
					-		return;
 | 
				
			||||||
 | 
					+		return PTR_ERR(phy);
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 	if (sfp->phylink) {
 | 
				
			||||||
 | 
					@@ -515,12 +515,14 @@ static void sfp_sm_probe_phy(struct sfp
 | 
				
			||||||
 | 
					 			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)
 | 
				
			||||||
 | 
					@@ -569,30 +571,41 @@ static void sfp_sm_fault(struct sfp *sfp
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static void sfp_sm_mod_init(struct sfp *sfp)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+	int ret = 0;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					 	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)
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-	if (sfp->phylink) {
 | 
				
			||||||
 | 
					-		/* Setting the serdes link mode is guesswork: there's no
 | 
				
			||||||
 | 
					-		 * field in the EEPROM which indicates what mode should
 | 
				
			||||||
 | 
					-		 * be used.
 | 
				
			||||||
 | 
					-		 *
 | 
				
			||||||
 | 
					-		 * If it's a gigabit-only fiber module, it probably does
 | 
				
			||||||
 | 
					-		 * not have a PHY, so switch to 802.3z negotiation mode.
 | 
				
			||||||
 | 
					-		 * Otherwise, switch to SGMII mode (which is required to
 | 
				
			||||||
 | 
					-		 * support non-gigabit speeds) and probe for a PHY.
 | 
				
			||||||
 | 
					+	/* Setting the serdes link mode is guesswork: there's no
 | 
				
			||||||
 | 
					+	 * field in the EEPROM which indicates what mode should
 | 
				
			||||||
 | 
					+	 * be used.
 | 
				
			||||||
 | 
					+	 *
 | 
				
			||||||
 | 
					+	 * If it's a gigabit-only fiber module, it probably does
 | 
				
			||||||
 | 
					+	 * not have a PHY, so switch to 802.3z negotiation mode.
 | 
				
			||||||
 | 
					+	 * Otherwise, switch to SGMII mode (which is required to
 | 
				
			||||||
 | 
					+	 * support non-gigabit speeds) and probe for a PHY.
 | 
				
			||||||
 | 
					+	 */
 | 
				
			||||||
 | 
					+	if (sfp->id.base.e1000_base_t ||
 | 
				
			||||||
 | 
					+	    sfp->id.base.e100_base_lx ||
 | 
				
			||||||
 | 
					+	    sfp->id.base.e100_base_fx)
 | 
				
			||||||
 | 
					+		ret = sfp_sm_probe_phy(sfp);
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (!ret) {
 | 
				
			||||||
 | 
					+		/* Wait t_init before indicating that the link is up, provided
 | 
				
			||||||
 | 
					+		 * the current state indicates no TX_FAULT.  If TX_FAULT clears
 | 
				
			||||||
 | 
					+		 * this time, that's fine too.
 | 
				
			||||||
 | 
					 		 */
 | 
				
			||||||
 | 
					-		if (sfp->id.base.e1000_base_t ||
 | 
				
			||||||
 | 
					-		    sfp->id.base.e100_base_lx ||
 | 
				
			||||||
 | 
					-		    sfp->id.base.e100_base_fx)
 | 
				
			||||||
 | 
					-			sfp_sm_probe_phy(sfp);
 | 
				
			||||||
 | 
					+		sfp_sm_next(sfp, SFP_S_INIT, T_INIT_JIFFIES);
 | 
				
			||||||
 | 
					+		sfp->sm_retries = 5;
 | 
				
			||||||
 | 
					+		return;
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+	if (ret == -EAGAIN)
 | 
				
			||||||
 | 
					+		sfp_sm_set_timer(sfp, T_PROBE_RETRY);
 | 
				
			||||||
 | 
					+	else
 | 
				
			||||||
 | 
					+		sfp_sm_next(sfp, SFP_S_TX_DISABLE, 0);
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 static int sfp_sm_mod_probe(struct sfp *sfp)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user