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:
Felix Fietkau 2017-02-06 11:46:48 +01:00
parent 2374549916
commit 2bf9ea6a31
62 changed files with 9799 additions and 1 deletions

View file

@ -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

View file

@ -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
} }

View 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

View 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 {

View 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 {

View 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 \

View 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);

View 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>;
};

View file

@ -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 */

View file

@ -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>;

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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>;
+ };

View file

@ -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 {

View file

@ -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

View file

@ -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 {

View file

@ -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>;
+ };
};
};

View file

@ -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>;
};
};

View file

@ -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>;

View file

@ -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 = <&eth2>;
+ tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>;
+ };
+
dsa@0 {
compatible = "marvell,dsa";
dsa,ethernet = <&eth1>;

View file

@ -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 = {

View file

@ -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), \

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;
+ }
}
/**

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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);
}
/**

View file

@ -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.

View file

@ -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.

View file

@ -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

View 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

View file

@ -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

View file

@ -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 ||

View file

@ -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) {

View file

@ -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;
}

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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);
}

View file

@ -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);
}

View 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,

View file

@ -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 */

View file

@ -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);

View file

@ -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,
};

View file

@ -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);

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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");
}

View 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)