imx6: drop 3.14

Signed-off-by: Luka Perkov <luka@openwrt.org>

SVN-Revision: 45371
v19.07.3_mercusys_ac12_duma
Luka Perkov 9 years ago
parent 912a6371f8
commit d21b92af8e

@ -1,362 +0,0 @@
CONFIG_AHCI_IMX=y
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
CONFIG_ARCH_HAS_CPUFREQ=y
CONFIG_ARCH_HAS_OPP=y
CONFIG_ARCH_HAS_RESET_CONTROLLER=y
CONFIG_ARCH_HAS_TICK_BROADCAST=y
CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=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_MXC=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_ARM=y
# CONFIG_ARM_CPU_SUSPEND is not set
CONFIG_ARM_ERRATA_754322=y
CONFIG_ARM_ERRATA_764369=y
CONFIG_ARM_ERRATA_775420=y
CONFIG_ARM_GIC=y
CONFIG_ARM_IMX6Q_CPUFREQ=y
# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
# CONFIG_ARM_LPAE is not set
CONFIG_ARM_NR_BANKS=8
CONFIG_ARM_PATCH_PHYS_VIRT=y
CONFIG_ARM_THUMB=y
# CONFIG_ARM_THUMBEE is not set
CONFIG_ARM_VIRT_EXT=y
CONFIG_ATA=y
CONFIG_ATAGS=y
# CONFIG_ATA_SFF is not set
CONFIG_AUTO_ZRELADDR=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_CLKDEV_LOOKUP=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLKSRC_OF=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
CONFIG_CPU_32v6K=y
CONFIG_CPU_32v7=y
CONFIG_CPU_ABRT_EV7=y
# 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_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_GOV_COMMON=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
CONFIG_CPU_HAS_ASID=y
# CONFIG_CPU_ICACHE_DISABLE is not set
CONFIG_CPU_PABRT_V7=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_TLB_V7=y
CONFIG_CPU_V7=y
CONFIG_CRC16=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_XZ=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_IMX_UART_PORT=1
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
# CONFIG_DEBUG_UART_8250 is not set
# CONFIG_DEBUG_UART_PL01X is not set
# CONFIG_DEBUG_USER is not set
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DMADEVICES=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DTC=y
# CONFIG_DW_DMAC_CORE is not set
# CONFIG_DW_DMAC_PCI is not set
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_FEC=y
CONFIG_FRAME_POINTER=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_GENERIC_CPUFREQ_CPU0 is not set
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IO=y
CONFIG_GENERIC_IRQ_CHIP=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_DEVRES=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_MXC=y
CONFIG_GPIO_SYSFS=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_PFN_VALID=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_ARM_SCU=y
CONFIG_HAVE_ARM_TWD=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_HAVE_BPF_JIT=y
CONFIG_HAVE_CC_STACKPROTECTOR=y
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_HAVE_CONTEXT_TRACKING=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_HAVE_DEBUG_KMEMLEAK=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_IDE=y
CONFIG_HAVE_IMX_ANATOP=y
CONFIG_HAVE_IMX_GPC=y
CONFIG_HAVE_IMX_MMDC=y
CONFIG_HAVE_IMX_SRC=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_NET_DSA=y
CONFIG_HAVE_OPROFILE=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_HZ_FIXED=0
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_IMX=y
CONFIG_IMX2_WDT=y
CONFIG_IMX_DMA=y
CONFIG_IMX_SDMA=y
# CONFIG_IMX_WEIM is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IOMMU_HELPER=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_JBD=y
CONFIG_JBD2=y
CONFIG_KTIME_SCALAR=y
# CONFIG_LEDS_REGULATOR is not set
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
# CONFIG_MACH_EUKREA_CPUIMX51SD is not set
# CONFIG_MACH_IMX51_DT is not set
# CONFIG_MACH_MX51_BABBAGE is not set
CONFIG_MDIO_BOARDINFO=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_MIGHT_HAVE_PCI=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
# CONFIG_MMC_MXC is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ESDHC_IMX=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
# CONFIG_MMC_SDHCI_PCI is not set
CONFIG_MMC_SDHCI_PLTFM=y
# CONFIG_MMC_TIFM_SD is not set
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_GPMI_NAND=y
# CONFIG_MTD_PHYSMAP_OF is not set
# CONFIG_MTD_SM_COMMON is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
# CONFIG_MTD_UBI_BLOCK is not set
# 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_MX3_IPU is not set
# CONFIG_MXC_DEBUG_BOARD is not set
CONFIG_MXS_DMA=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEON=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NO_BOOTMEM=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_MDIO=y
CONFIG_OF_MTD=y
CONFIG_OF_NET=y
CONFIG_OF_PCI=y
CONFIG_OF_PCI_IRQ=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_PAGE_OFFSET=0x80000000
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_IMX6=y
CONFIG_PERF_EVENTS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PHYLIB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_IMX=y
CONFIG_PINCTRL_IMX6Q=y
CONFIG_PINCTRL_IMX6SL=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PM_OPP=y
CONFIG_PPS=y
# CONFIG_PREEMPT_RCU is not set
CONFIG_PROC_DEVICETREE=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_RATIONAL=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RD_BZIP2=y
CONFIG_RD_GZIP=y
CONFIG_RD_LZO=y
CONFIG_RD_XZ=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_SPI=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_ANATOP=y
# CONFIG_REGULATOR_DEBUG is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PFUZE100=y
# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
# CONFIG_RFKILL_REGULATOR is not set
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_IMXDI is not set
# CONFIG_RTC_DRV_MXC is not set
CONFIG_SATA_AHCI_PLATFORM=y
CONFIG_SCHED_HRTICK=y
CONFIG_SCSI=y
CONFIG_SERIAL_IMX=y
CONFIG_SERIAL_IMX_CONSOLE=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
CONFIG_SOC_BUS=y
# CONFIG_SOC_IMX50 is not set
# CONFIG_SOC_IMX53 is not set
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
# CONFIG_SOC_VF610 is not set
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_IMX=y
CONFIG_SPI_MASTER=y
CONFIG_STMP_DEVICE=y
CONFIG_STOP_MACHINE=y
CONFIG_SWIOTLB=y
# CONFIG_SWP_EMULATE is not set
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_THUMB2_KERNEL is not set
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TREE_RCU=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_XZ=y
CONFIG_UBIFS_FS_ZLIB=y
CONFIG_UID16=y
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
# CONFIG_USB_MXS_PHY is not set
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_VFP=y
CONFIG_VFPv3=y
CONFIG_VMSPLIT_2G=y
# CONFIG_VMSPLIT_3G is not set
# CONFIG_XEN is not set
CONFIG_XPS=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA_FLAG=0

@ -1,19 +0,0 @@
/*
* Copyright 2014 Gateworks Corporation
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
#include "imx6dl.dtsi"
#include "imx6qdl-gw552x.dtsi"
/ {
model = "Gateworks Ventana i.MX6 DualLite/Solo GW552X";
compatible = "gw,imx6dl-gw552x", "gw,ventana", "fsl,imx6dl";
};

@ -1,23 +0,0 @@
/*
* Copyright 2014 Gateworks Corporation
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/dts-v1/;
#include "imx6q.dtsi"
#include "imx6qdl-gw552x.dtsi"
/ {
model = "Gateworks Ventana i.MX6 Dual/Quad GW552X";
compatible = "gw,imx6q-gw552x", "gw,ventana", "fsl,imx6q";
};
&sata {
status = "okay";
};

@ -1,313 +0,0 @@
/*
* Copyright 2014 Gateworks Corporation
*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/ {
/* these are used by bootloader for disabling nodes */
aliases {
led0 = &led0;
led1 = &led1;
led2 = &led2;
nand = &gpmi;
usb0 = &usbh1;
};
chosen {
bootargs = "console=ttymxc1,115200";
};
leds {
compatible = "gpio-leds";
led0: user1 {
label = "user1";
gpios = <&gpio4 6 0>; /* 102 -> MX6_PANLEDG */
default-state = "on";
linux,default-trigger = "heartbeat";
};
led1: user2 {
label = "user2";
gpios = <&gpio4 7 0>; /* 103 -> MX6_PANLEDR */
default-state = "off";
};
led2: user3 {
label = "user3";
gpios = <&gpio4 15 1>; /* 111 - MX6_LOCLED# */
default-state = "off";
};
};
memory {
reg = <0x10000000 0x20000000>;
};
regulators {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
reg_1p0v: regulator@0 {
compatible = "regulator-fixed";
reg = <0>;
regulator-name = "1P0V";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-always-on;
};
reg_3p3v: regulator@2 {
compatible = "regulator-fixed";
reg = <2>;
regulator-name = "3P3V";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
reg_5p0v: regulator@3 {
compatible = "regulator-fixed";
reg = <3>;
regulator-name = "5P0V";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
};
};
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
status = "okay";
};
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
eeprom1: eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
};
eeprom2: eeprom@51 {
compatible = "atmel,24c02";
reg = <0x51>;
pagesize = <16>;
};
eeprom3: eeprom@52 {
compatible = "atmel,24c02";
reg = <0x52>;
pagesize = <16>;
};
eeprom4: eeprom@53 {
compatible = "atmel,24c02";
reg = <0x53>;
pagesize = <16>;
};
gpio: pca9555@23 {
compatible = "nxp,pca9555";
reg = <0x23>;
gpio-controller;
#gpio-cells = <2>;
};
hwmon: gsc@29 {
compatible = "gw,gsp";
reg = <0x29>;
};
rtc: ds1672@68 {
compatible = "dallas,ds1672";
reg = <0x68>;
};
};
&i2c2 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2>;
status = "okay";
pciswitch: pex8609@3f {
compatible = "plx,pex8609";
reg = <0x3f>;
};
pmic: ltc3676@3c {
compatible = "ltc,ltc3676";
reg = <0x3c>;
regulators {
sw1_reg: ltc3676__sw1 {
regulator-min-microvolt = <1175000>;
regulator-max-microvolt = <1175000>;
regulator-boot-on;
regulator-always-on;
};
sw2_reg: ltc3676__sw2 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
sw3_reg: ltc3676__sw3 {
regulator-min-microvolt = <1175000>;
regulator-max-microvolt = <1175000>;
regulator-boot-on;
regulator-always-on;
};
sw4_reg: ltc3676__sw4 {
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: ltc3676__ldo2 {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
regulator-boot-on;
regulator-always-on;
};
ldo4_reg: ltc3676__ldo4 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
};
};
};
};
&i2c3 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
status = "okay";
};
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
imx6qdl-gw52xx {
pinctrl_hog: hoggrp {
fsl,pins = <
MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 /* PCIE_RST# */
MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x80000000 /* USBHUB_RST# */
MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* PCIESKT_WDIS# */
MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x80000000 /* user1 led */
MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x80000000 /* user2 led */
MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000 /* user3 led */
>;
};
pinctrl_gpmi_nand: gpminandgrp {
fsl,pins = <
MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
>;
};
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
>;
};
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
>;
};
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
>;
};
pinctrl_uart2: uart2grp {
fsl,pins = <
MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
>;
};
pinctrl_uart3: uart3grp {
fsl,pins = <
MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
>;
};
pinctrl_uart5: uart5grp {
fsl,pins = <
MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
>;
};
};
};
&pcie {
reset-gpio = <&gpio1 29 0>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "okay";
};
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart3>;
status = "okay";
};
&uart5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart5>;
status = "okay";
};
&usbh1 {
status = "okay";
};

@ -1,949 +0,0 @@
/*
* drivers/net/phy/gw16083.c
*
* Driver for GW16083 Ventana Ethernet Expansion Mezzanine
*
* Author: Tim Harvey
*
* Copyright (c) 2014 Tim Harvey <tharvey@gateworks.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
/*
* The GW16083 interfaces with a Ventana baseboard via the PCIe bus, an i2c
* bus (i2c2), and a couple of GPIO's. On the PCIe bus is an i210 GigE with
* its MAC connected to Port4 of a Marvell MV88E6176 7-port GigE switch via
* MDIO and RGMII. Ports 0-3 are standard copper RJ45 but Ports 5 and 6
* connect to Marvell MV88E1111 dual-mode Copper/Fiber PHY's over SGMII and
* MDIO. The PHY's have both an RG45 for copper and an SFP module.
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/marvell_phy.h>
#include <linux/of_platform.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <linux/uaccess.h>
#include "gw16083.h"
#undef FAIL_ON_CHECKSUM_ERR /* fail to configure SFP if checksum bad */
#define PORT_POWER_CONTROL /* ports can be enabled/disabled via sysfs */
#define PORT_MODE_CONTROL /* ports 5/6 can have SFP/RJ45 mode forced */
MODULE_DESCRIPTION("GW16083 driver");
MODULE_AUTHOR("Tim Harvey");
MODULE_LICENSE("GPL");
struct mv88e1111_port_state {
int port;
bool present;
bool serdes;
bool sfp_signal;
bool sfp_present;
bool sfp_compat;
bool sfp_enabled;
char sfp_id[64];
};
struct mv88e1111_priv {
struct phy_device *phydev;
struct i2c_client *client;
struct mv88e1111_port_state port5;
struct mv88e1111_port_state port6;
struct kobject *sysfs_kobj;
};
enum {
mode_copper = 0,
mode_serdes = 1,
};
static struct i2c_client *gw16083_client = NULL;
static int gw16083_read_port_sfp(struct i2c_client *client,
struct mv88e1111_port_state *state);
/* read switch port register from port0-6 */
u16 read_switch_port(struct phy_device *pdev, int port, u8 regaddr)
{
return pdev->bus->read(pdev->bus, MV_BASE + port, regaddr);
}
/* write switch port register to port0-6 */
int write_switch_port(struct phy_device *pdev, int port, u8 regaddr, u16 val)
{
return pdev->bus->write(pdev->bus, MV_BASE + port, regaddr, val);
}
/*
* read_switch_port_phy - write a register for a specific port on 88E6176
* The 88E6176 PHY registers must be accessed thorugh the Global2 address
* using the SMI_PHY_COMMAND_REG and SMI_PHY_DATA_REG.
*/
int read_switch_port_phy(struct phy_device *pdev, int port, u8 regaddr)
{
u16 reg;
int i;
dev_dbg(&pdev->dev, "read_phy: port%d reg=0x%02x\n", port, regaddr);
reg = SMIBUSY | SMIMODE22 | SMIOP_READ;
reg |= port << DEVADDR;
reg |= regaddr << REGADDR;
pdev->bus->write(pdev->bus, MV_GLOBAL2, MV_SMI_PHY_COMMAND, reg);
for (i = 0; i < 10; i++) {
reg = pdev->bus->read(pdev->bus, MV_GLOBAL2,
MV_SMI_PHY_COMMAND);
if (!(reg & (1<<15)))
break;
mdelay(1);
}
/* timeout */
if (i == 10)
return 0xffff;
reg = pdev->bus->read(pdev->bus, MV_GLOBAL2, MV_SMI_PHY_DATA);
return reg;
}
/*
* write_switch_port_phy - write a register for a specific port on 88E6176
* The 88E6176 PHY registers must be accessed thorugh the Global2 address
* using the SMI_PHY_COMMAND_REG and SMI_PHY_DATA_REG.
*/
int write_switch_port_phy(struct phy_device *pdev, int port, u8 addr, u16 reg)
{
int i;
dev_dbg(&pdev->dev, "write_phy: port%d reg=0x%02x val=0x%04x\n", port,
addr, reg);
pdev->bus->write(pdev->bus, MV_GLOBAL2, MV_SMI_PHY_DATA, reg);
reg = SMIBUSY | SMIMODE22 | SMIOP_WRITE;
reg |= port << DEVADDR;
reg |= addr << REGADDR;
pdev->bus->write(pdev->bus, MV_GLOBAL2, MV_SMI_PHY_COMMAND, reg);
for (i = 0; i < 10; i++) {
reg = pdev->bus->read(pdev->bus, MV_GLOBAL2,
MV_SMI_PHY_COMMAND);
if (!(reg & (1<<15)))
break;
mdelay(1);
}
/* timeout */
if (i == 10)
return -ETIMEDOUT;
return 0;
}
/* read a scratch register from switch */
inline u8 read_switch_scratch(struct phy_device *pdev, u8 reg)
{
pdev->bus->write(pdev->bus, MV_GLOBAL2, MV_SCRATCH_MISC, (reg << 8));
return pdev->bus->read(pdev->bus, MV_GLOBAL2, MV_SCRATCH_MISC) & 0xff;
}
/* write a scratch register to switch */
inline void write_switch_scratch(struct phy_device *pdev, u8 reg, u8 val)
{
pdev->bus->write(pdev->bus, MV_GLOBAL2, MV_SCRATCH_MISC,
(1 << 15) | (reg << 8) | val);
}
/* enable or disable an SFP's TXEN signal */
static int enable_sfp_txen(struct phy_device *pdev, int port, bool enable)
{
u8 gpio;
int bit;
if (port != 5 && port != 6)
return -EINVAL;
/* GPIO[2:1] output low to enable TXEN */
bit = (port == 5) ? 1 : 2;
gpio = read_switch_scratch(pdev, MV_GPIO_DATA);
if (enable)
gpio |= (1 << bit);
else
gpio &= (1 << bit);
write_switch_scratch(pdev, MV_GPIO_DATA, gpio);
dev_info(&pdev->dev, "Port%d: SFP TX %s\n", port, enable ?
"enabled" : "disabled");
return 0;
}
/* configure mv88e1111 port for copper or serdes
* For Copper we set auto link/duplex/speed detection
* For SerDes/Fiber we force 1000mbps link up and auto-neg duplex
*/
static int config_mv88e1111_port_sfp(struct phy_device *pdev, int port,
bool sfp)
{
u16 reg;
if (port != 5 && port != 6)
return -EINVAL;
dev_dbg(&pdev->dev, "%s: Port%d %s\n", __func__, port,
sfp ? "SFP" : "copper");
if (sfp) {
enable_sfp_txen(pdev, port, 1);
/* configure MV88E6176 Physical Control Port Register */
dev_info(&pdev->dev,
"Port%d: SFP: force 1000mbps link up "
"(auto-negotiate duplex)\n",
port);
reg = read_switch_port(pdev, port, MV_PORT_PHYS_CONTROL);
reg &= ~0x3f; /* clear 5-0 */
reg |= (1 << 4) | (1 << 5); /* force link up */
reg |= 2; /* force 1000mbps */
write_switch_port(pdev, port, MV_PORT_PHYS_CONTROL, reg);
reg = read_switch_port(pdev, port, MV_PORT_PHYS_CONTROL);
}
/* copper */
else {
enable_sfp_txen(pdev, port, 0);
/* configure MV88E6176 Physical Control Port Register */
dev_info(&pdev->dev,
"Port%d: Copper: set auto-neg link/duplex/speed\n",
port);
reg = read_switch_port(pdev, port, MV_PORT_PHYS_CONTROL);
reg &= ~0x3f; /* clear 5-0 */
reg |= 3; /* speed not forced */
write_switch_port(pdev, port, MV_PORT_PHYS_CONTROL, reg);
reg = read_switch_port(pdev, port, MV_PORT_PHYS_CONTROL);
}
dev_dbg(&pdev->dev, "%s: Port%d %s PORT_PHYS_CONTROL=0x%04x\n",
__func__, port, sfp ? "SFP" : "copper",
read_switch_port(pdev, port, MV_PORT_PHYS_CONTROL));
return 0;
}
#if defined(PORT_POWER_CONTROL)
static int enable_switch_port(struct phy_device *pdev, int port, bool enable)
{
struct mv88e1111_priv *priv = dev_get_drvdata(&pdev->dev);
u16 reg;
/* power up port */
dev_info(&priv->client->dev, "Port%d: %s\n", port,
enable ? "normal operation" : "power down");
reg = read_switch_port_phy(pdev, port, MV_PHY_CONTROL);
if (enable)
reg &= ~(1 << 11); /* Normal Operation */
else
reg |= (1 << 11); /* power down */
write_switch_port_phy(pdev, port, MV_PHY_CONTROL, reg);
reg = read_switch_port_phy(pdev, port, MV_PHY_CONTROL1);
if (enable)
reg &= ~(1 << 2); /* Normal Operation */
else
reg |= (1 << 2); /* power down */
write_switch_port_phy(pdev, port, MV_PHY_CONTROL1, reg);
return 0;
}
#endif
/*
* Sysfs API
*/
struct mv88e1111_port_state *get_port_state(struct mv88e1111_priv *priv,
int port)
{
if (port == 5)
return &priv->port5;
if (port == 6)
return &priv->port6;
return NULL;
}
/*
* get MV88E6176 port number for a specific GW16083 port name
* The GW16083 ports as shown on the silkscreen are not mapped according to
* the MV88E6176 ports numbers.
*/
static int gw16083_get_port(const char* name)
{
int i;
int map[] = { 3, 2, 1, 0, 5, 6 };
if (strncasecmp(name, "ETHERNET", 8) != 0 || strlen(name) != 9)
return -1;
i = name[8] - '0';
if (i < 1 || i > 6)
return -1;
return map[i-1];
}
static ssize_t port_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mv88e1111_priv *priv = dev_get_drvdata(dev);
int port = -1;
u16 reg;
if (sscanf(attr->attr.name, "port%d", &port) != 1)
return 0;
if (port < 0 || port > 6)
return 0;
reg = read_switch_port_phy(priv->phydev, port, MV_PHY_CONTROL);
return sprintf(buf, "%s\n", (reg & (1 << 11)) ? "disabled" : "enabled");
}
#if defined(PORT_POWER_CONTROL)
static ssize_t port_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct mv88e1111_priv *priv = dev_get_drvdata(dev);
int port = -1;
int val;
port = gw16083_get_port(attr->attr.name);
if (port < 0)
return 0;
if (sscanf(buf, "%d", &val) != 1)
return 0;
enable_switch_port(priv->phydev, port, val ? 1 : 0);
return count;
}
static DEVICE_ATTR(ethernet1, S_IWUSR | S_IRUGO, port_show, port_store);
static DEVICE_ATTR(ethernet2, S_IWUSR | S_IRUGO, port_show, port_store);
static DEVICE_ATTR(ethernet3, S_IWUSR | S_IRUGO, port_show, port_store);
static DEVICE_ATTR(ethernet4, S_IWUSR | S_IRUGO, port_show, port_store);
static DEVICE_ATTR(ethernet5, S_IWUSR | S_IRUGO, port_show, port_store);
static DEVICE_ATTR(ethernet6, S_IWUSR | S_IRUGO, port_show, port_store);
#else
static DEVICE_ATTR(ethernet1, S_IRUGO, port_show, NULL);
static DEVICE_ATTR(ethernet2, S_IRUGO, port_show, NULL);
static DEVICE_ATTR(ethernet3, S_IRUGO, port_show, NULL);
static DEVICE_ATTR(ethernet4, S_IRUGO, port_show, NULL);
static DEVICE_ATTR(ethernet5, S_IRUGO, port_show, NULL);
static DEVICE_ATTR(ethernet6, S_IRUGO, port_show, NULL);
#endif
static ssize_t portsfp_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mv88e1111_priv *priv = dev_get_drvdata(dev);
struct mv88e1111_port_state *state;
state = get_port_state(priv, gw16083_get_port(attr->attr.name));
if (!state)
return 0;
if (!state->sfp_present)
return 0;
return sprintf(buf, "%s\n", state->sfp_id);
}
static ssize_t portmode_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct mv88e1111_priv *priv = dev_get_drvdata(dev);
struct mv88e1111_port_state *state;
state = get_port_state(priv, gw16083_get_port(attr->attr.name));
if (!state)
return 0;
return sprintf(buf, "%s\n", state->serdes ? "SFP" : "RJ45");
}
static DEVICE_ATTR(ethernet5_sfp, S_IRUGO, portsfp_show, NULL);
static DEVICE_ATTR(ethernet6_sfp, S_IRUGO, portsfp_show, NULL);
#ifdef PORT_MODE_CONTROL
static ssize_t portmode_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct mv88e1111_priv *priv = dev_get_drvdata(dev);
struct mv88e1111_port_state *state;
u16 reg;
int port;
port = gw16083_get_port(attr->attr.name);
state = get_port_state(priv, port);
if (!state)
return 0;
reg = read_switch_port_phy(priv->phydev, port, MII_M1111_PHY_EXT_SR);
if (strcasecmp(buf, "auto") == 0) {
reg &= ~(1<<15); /* enable auto-selection */
dev_info(&priv->client->dev, "Port%d: enable auto-selection\n",
port);
} else if (strcasecmp(buf, "RJ45") == 0) {
reg |= (1<<15); /* disable auto-selection */
reg |= 0xb; /* RGMII to Copper */
config_mv88e1111_port_sfp(priv->phydev, port, 0);
dev_info(&priv->client->dev, "Port%d: select RJ45\n", port);
} else if (strcasecmp(buf, "SFP") == 0) {
reg |= (1<<15); /* disable auto-selection */
reg |= 0x3; /* RGMII to Fiber */
config_mv88e1111_port_sfp(priv->phydev, port, 1);
dev_info(&priv->client->dev, "Port%d: select SFP\n", port);
}
write_switch_port_phy(priv->phydev, port, MII_M1111_PHY_EXT_SR, reg);
return count;
}
static DEVICE_ATTR(ethernet5_mode, S_IWUSR | S_IRUGO, portmode_show,
portmode_store);
static DEVICE_ATTR(ethernet6_mode, S_IWUSR | S_IRUGO, portmode_show,
portmode_store);
#else
static DEVICE_ATTR(ethernet5_mode, S_IRUGO, portmode_show, NULL);
static DEVICE_ATTR(ethernet6_mode, S_IRUGO, portmode_show, NULL);
#endif
/*
* PHY driver
*/
static int
mv88e6176_config_init(struct phy_device *pdev)
{
dev_dbg(&pdev->dev, "%s\n", __func__);
pdev->state = PHY_RUNNING;
return 0;
}
/* check MV88E1111 PHY status and MV88E6176 GPIO */
static int
mv88e6176_read_status(struct phy_device *pdev)
{
struct mv88e1111_priv *priv = dev_get_drvdata(&pdev->dev);
struct mv88e1111_port_state *state;
bool serdes, sfp_present, sfp_signal;
int port;
int ret = 0;
u16 gpio;
dev_dbg(&pdev->dev, "%s", __func__);
gpio = read_switch_scratch(pdev, MV_GPIO_DATA);
for (port = 5; port < 7; port++) {
serdes = (read_switch_port_phy(pdev, port, MII_M1111_PHY_EXT_SR)
& (1<<13)) ? 1 : 0;
dev_dbg(&pdev->dev, "%s: Port%d GPIO:0x%02x SerDes:%d\n",
__func__, port, gpio, serdes);
switch(port) {
case 5:
state = &priv->port5;
sfp_present = !((gpio >> 5) & 1);
sfp_signal = !((gpio >> 6) & 1);
break;
case 6:
state = &priv->port6;
sfp_present = !((gpio >> 3) & 1);
sfp_signal = !((gpio >> 4) & 1);
break;
}
/*
* on sfp_detect read/verify SFP MSA and set sfp_compat
* on sfp_signal issue link down?
* on serdes auto-select
*/
if (state->sfp_present != sfp_present) {
state->sfp_present = sfp_present;
dev_info(&pdev->dev, "Port%d: SFP %s\n",
port, sfp_present ? "inserted" : "removed");
if (state->sfp_present) {
if (gw16083_read_port_sfp(priv->client, state))
state->sfp_compat = false;
else
state->sfp_compat = true;
} else {
state->sfp_compat = false;
state->sfp_enabled = false;
}
}
if (state->sfp_signal != sfp_signal) {
state->sfp_signal = sfp_signal;
dev_info(&pdev->dev, "Port%d: SFP signal %s\n",
port, sfp_signal ? "detected" : "lost");
}
if (state->serdes != serdes) {
state->serdes = serdes;
dev_info(&pdev->dev, "Port%d: %s auto-selected\n",
port, serdes ? "SERDES" : "copper");
/*
* if auto-selection has switched to copper
* disable serdes
*/
if (!serdes) {
config_mv88e1111_port_sfp(pdev, port, 0);
state->sfp_enabled = false;
}
}
/*
* if serdes and compatible SFP module and not yet enabled
* then enable for serdes
*/
if (serdes && state->sfp_compat && state->sfp_signal &&
!state->sfp_enabled)
{
if (!config_mv88e1111_port_sfp(pdev, port, 1))
state->sfp_enabled = true;
}
}
return ret;
}
static int
mv88e6176_config_aneg(struct phy_device *pdev)
{
dev_dbg(&pdev->dev, "%s", __func__);
return 0;
}
static void
mv88e6176_remove(struct phy_device *pdev)
{
dev_dbg(&pdev->dev, "%s", __func__);
device_remove_file(&pdev->dev, &dev_attr_ethernet1);
device_remove_file(&pdev->dev, &dev_attr_ethernet2);
device_remove_file(&pdev->dev, &dev_attr_ethernet3);
device_remove_file(&pdev->dev, &dev_attr_ethernet4);
device_remove_file(&pdev->dev, &dev_attr_ethernet5);
device_remove_file(&pdev->dev, &dev_attr_ethernet6);
device_remove_file(&pdev->dev, &dev_attr_ethernet5_sfp);
device_remove_file(&pdev->dev, &dev_attr_ethernet6_sfp);
device_remove_file(&pdev->dev, &dev_attr_ethernet5_mode);
device_remove_file(&pdev->dev, &dev_attr_ethernet6_mode);
sysfs_remove_link(kernel_kobj, "gw16083");
}
static int
mv88e6176_probe(struct phy_device *pdev)
{
int port;
int ret = 0;
u32 id, reg;
struct mv88e1111_priv *priv;
dev_dbg(&pdev->dev, "%s: addr=0x%02x bus=%s:%s gw16083_client=%p\n",
__func__, pdev->addr, pdev->bus->name, pdev->bus->id,
gw16083_client);
/* In single-chip addressing mode the MV88E6176 shows up on 0x10-0x16 */
if (pdev->addr != MV_BASE)
return 0;
/* i2c driver needs to be loaded first */
if (!gw16083_client)
return 0;
/* gw16083 has MV88E1676 hanging off of i210 mdio bus */
if (strcmp(pdev->bus->name, "igb_enet_mii_bus") != 0)
return 0;
//dev_info(&pdev->dev, "Detected");
dev_info(&gw16083_client->dev, "%s: MV88E6176 7-port switch detected",
pdev->bus->id);
/*
* port5/6 config: MV88E1111 PHY
* Register 20: PHY Control Register
* R20_7: add delay to RX_CLK for RXD
* R20_1: add delay to TX_CLK for TXD
* Register 24: LED Control Register
* 0x4111:
* Pulse stretch 170 to 340 ms
* Register 0: Control Register
* R0_15: phy reset
*/
for (port = 5; port < 7; port++) {
#ifndef RGMII_DELAY_ON_PHY
write_switch_port(pdev, port, MV_PORT_PHYS_CONTROL, 0xC003);
#endif
id = read_switch_port_phy(pdev, port,
MII_M1111_PHY_IDENT0) << 16;
id |= read_switch_port_phy(pdev, port, MII_M1111_PHY_IDENT1);
if ((id & MII_M1111_PHY_ID_MASK) != MII_M1111_PHY_ID) {
dev_err(&gw16083_client->dev,
"Port%d: No MV88E1111 PHY detected", port);
return 0;
//continue;
}
#ifdef RGMII_DELAY_ON_PHY
/* phy rx/tx delay */
reg = read_switch_port_phy(pdev, port, MII_M1111_PHY_EXT_CR);
reg |= (1<<1) | (1<<7);
write_switch_port_phy(pdev, port, MII_M1111_PHY_EXT_CR, reg);
#endif
/* led config */
write_switch_port_phy(pdev, port, MII_M1111_PHY_LED_CONTROL,
MII_M1111_PHY_LED_PULSE_STR);
/* reset phy */
reg = read_switch_port_phy(pdev, port, MII_M1111_PHY_CONTROL);
reg |= MII_M1111_PHY_CONTROL_RESET;
write_switch_port_phy(pdev, port, MII_M1111_PHY_CONTROL, reg);
dev_info(&gw16083_client->dev,
"Port%d MV88E111 PHY configured\n", port);
}
/*
* GPIO Configuration:
* GPIO1: FIB5_TXEN# (output)
* GPIO2: FIB6_TXEN# (output)
* GPIO3: FIB6_PRES# (input)
* GPIO4: FIB6_LOS (input)
* GPIO5: FIB5_PRES# (input)
* GPIO6: FIB5_LOS (input)
*/
write_switch_scratch(pdev, MV_GPIO_DATA, 0x06); /* GPIO[2:1] out hi */
write_switch_scratch(pdev, MV_GPIO_DIR, 0x78); /* GPIO[6:3] inp */
pdev->irq = PHY_POLL;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
memset(priv, 0, sizeof(*priv));
priv->phydev = pdev;
priv->client = gw16083_client;
priv->port5.port = 5;
priv->port6.port = 6;
dev_set_drvdata(&pdev->dev, priv);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet1);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet2);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet3);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet4);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet5);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet6);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet5_sfp);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet6_sfp);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet5_mode);
ret |= device_create_file(&pdev->dev, &dev_attr_ethernet6_mode);
if (unlikely(ret))
dev_err(&pdev->dev, "Failed creating attrs\n");
/* Add a nice symlink to the real device */
ret = sysfs_create_link(kernel_kobj, &pdev->dev.kobj, "gw16083");
dev_dbg(&pdev->dev, "initial state: GPIO=0x%02x "
"Port5_serdes=%d Port6_serdes=%d\n",
read_switch_scratch(pdev, MV_GPIO_DATA),
(read_switch_port_phy(pdev, 5, MII_M1111_PHY_EXT_SR)
& (1<<13) ? 1:0),
(read_switch_port_phy(pdev, 6, MII_M1111_PHY_EXT_SR)
& (1<<13) ? 1:0));
return ret;
}
static struct phy_driver mv88e6176_phy_driver = {
.name = "MV88E6176",
.phy_id = MV_IDENT_VALUE,
.phy_id_mask = MV_IDENT_MASK,
.features = PHY_BASIC_FEATURES,
.probe = &mv88e6176_probe,
.remove = &mv88e6176_remove,
.config_init = &mv88e6176_config_init,
.config_aneg = &mv88e6176_config_aneg,
.read_status = &mv88e6176_read_status,
.driver = { .owner = THIS_MODULE },
};
/*
* I2C driver
*/
/* See SFF-8472 */
struct sfp_msa {
/* Basic ID fields */
u8 identifier;
u8 ext_identifier;
u8 connector;
u8 transceiver[8];
u8 encoding;
u8 br_nominal;
u8 rate_identifier;
u8 length_smf_km;
u8 length_smf;
u8 length_om2;
u8 length_om1;
u8 length_om4;
u8 length_om3;
u8 vendor_name[16];
u8 transceiver2;
u8 vendor_oui[3];
u8 vendor_pn[16];
u8 vendor_rev[4];
u8 wavelength[2];
u8 resv1;
u8 cc_base;
/* extended id fields */
u8 options[2];
u8 br_max;
u8 br_min;
u8 vendor_sn[16];
u8 date_code[8];
u8 diags_type;
u8 enhanced_options;
u8 sff8472_compliance;
u8 cc_ext;
/* Vendor specific ID fields */
u8 vendor_data[32];
u8 sff8079[128];
};
enum identifier {
UNKNOWN,
GBIC,
SFF,
SFP,
XBI,
XENPACK,
XFP,
XFF,
XFP_E,
XPAK,
X2,
DWDM_SFP,
QSFP,
MAX_ID,
};
const char* id_names[] = {
"UNKONWN",
"GBIC",
"SFF",
"SFP",
NULL,
};
/* Flags for SFP modules compatible with ETH up to 1Gb */
struct sfp_flags {
u8 e1000_base_sx:1;
u8 e1000_base_lx:1;
u8 e1000_base_cx:1;
u8 e1000_base_t:1;
u8 e100_base_lx:1;
u8 e100_base_fx:1;
u8 e10_base_bx10:1;
u8 e10_base_px:1;
};
#define STRING_APPEND(str, src) \
strncat(str, src, sizeof(src)); \
for (i = 1; i < sizeof(str); i++) \
if (str[i-1] == ' ' && str[i] == ' ') \
str[i] = 0;
static int gw16083_read_port_sfp(struct i2c_client *client,
struct mv88e1111_port_state *state)
{
int ret = 0;
u8 data[256];
struct sfp_flags *eth_flags;
u8 crc;
int i;
u8 *str;
struct sfp_msa *sfp_msa = (struct sfp_msa *)data;
int port = state->port;
union i2c_smbus_data d;
dev_dbg(&client->dev, "%s Port%d\n", __func__, port);
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_I2C_BLOCK))
return -ENODEV;
d.byte = (port == 5) ? 1 : 2;
if (i2c_smbus_xfer(client->adapter, GW16083_I2C_ADDR_PCA9543,
client->flags, I2C_SMBUS_WRITE, 0,
I2C_SMBUS_BYTE_DATA, &d) < 0)
{
dev_err(&client->dev,
"Port%d: failed writing PCA9543 register\n", port);
return ret;
}
/* read all 256 bytes of SFP EEPROM */
for (i = 0; i < sizeof(data); i += I2C_SMBUS_BLOCK_MAX) {
d.block[0] = I2C_SMBUS_BLOCK_MAX;
if (i2c_smbus_xfer(client->adapter, GW16083_I2C_ADDR_SFP1,
client->flags, I2C_SMBUS_READ, i,
I2C_SMBUS_I2C_BLOCK_DATA, &d) < 0)
{
dev_err(&client->dev,
"Port%d: failed reading SFP data\n", port);
return ret;
}
memcpy(data + i, d.block + 1, I2C_SMBUS_BLOCK_MAX);
}
/* Validate checksums */
for (crc = 0, i = 0; i < 63; i++)
crc += data[i];
if (crc != sfp_msa->cc_base) {
dev_err(&client->dev, "Port%d: "
"Checksum failure for Base ID fields: 0x%02x\n", port,
crc);
#ifdef FAIL_ON_CHECKSUM_ERR
return -EINVAL;
#endif
}
for (crc = 0, i = 64; i < 95; i++)
crc += data[i];
if (crc != sfp_msa->cc_ext) {
dev_err(&client->dev, "Port%d: "
"Checksum failure for Extended ID fields: 0x%02x\n",
port, crc);
#ifdef FAIL_ON_CHECKSUM_ERR
return -EINVAL;
#endif
}
state->sfp_id[0] = 0;
for (i = 0; id_names[i]; i++) {
if (sfp_msa->identifier == i) {
sprintf(state->sfp_id, "%s: ", id_names[i]);
break;
}
}
STRING_APPEND(state->sfp_id, sfp_msa->vendor_oui);
STRING_APPEND(state->sfp_id, sfp_msa->vendor_name);
STRING_APPEND(state->sfp_id, sfp_msa->vendor_pn);
STRING_APPEND(state->sfp_id, sfp_msa->vendor_rev);
STRING_APPEND(state->sfp_id, sfp_msa->vendor_sn);
dev_info(&client->dev, "Port%d: %s\n", port, state->sfp_id);
if ((sfp_msa->identifier != GBIC) &&
(sfp_msa->identifier != SFF) &&
(sfp_msa->identifier != SFP))
{
dev_err(&client->dev, "Port%d: Unknown module identifier: %d\n",
port, sfp_msa->identifier);
return -EINVAL;
}
str = "";
eth_flags = (struct sfp_flags *)(sfp_msa->transceiver + 3);
if (eth_flags->e1000_base_sx) {
str = "1000Base-SX (Fiber)";
} else if (eth_flags->e1000_base_lx) {
str = "1000Base-LX (Fiber)";
} else if (eth_flags->e1000_base_t) {
str = "1000Base-T (Copper)";
} else if (eth_flags->e100_base_fx) {
str = "100Base-FX (Fiber) - not supported";
ret = -EINVAL;
} else {
str = "Unknown/Unsupported media type";
ret = -EINVAL;
}
if (ret)
dev_err(&client->dev, "Port%d: %s (0x%02x)\n", port, str,
sfp_msa->transceiver[3]);
else
dev_info(&client->dev, "Port%d: %s (0x%02x)\n", port, str,
sfp_msa->transceiver[3]);
return ret;
}
static int gw16083_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
dev_info(&client->dev, "GW16083 Ethernet Expansion Mezzanine\n");
if (gw16083_client) {
dev_err(&client->dev, "client already registered\n");
return -EINVAL;
}
gw16083_client = client;
ret = phy_driver_register(&mv88e6176_phy_driver);
if (ret)
dev_err(&client->dev,
"failed to register mv88e6176 phy driver: %d\n", ret);
return ret;
}
static int gw16083_remove(struct i2c_client *client)
{
dev_dbg(&client->dev, "%s\n", __func__);
phy_driver_unregister(&mv88e6176_phy_driver);
gw16083_client = NULL;
return 0;
}
static const struct of_device_id gw16083_dt_ids[] = {
{ .compatible = "gateworks,gw16083", },
{ }
};
MODULE_DEVICE_TABLE(of, gw16083_dt_ids);
static const struct i2c_device_id gw16083_id[] = {
{ "gw16083", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, gw16083_id);
static struct i2c_driver gw16083_driver = {
.driver = {
.name = "gw16083",
.of_match_table = gw16083_dt_ids,
},
.probe = gw16083_probe,
.remove = gw16083_remove,
.id_table = gw16083_id,
};
static int __init mv88e6176_init(void)
{
return i2c_add_driver(&gw16083_driver);
}
static void __exit mv88e6176_exit(void)
{
i2c_del_driver(&gw16083_driver);
}
module_init(mv88e6176_init);
module_exit(mv88e6176_exit);

@ -1,123 +0,0 @@
/*
* drivers/net/phy/mv88e6176.h
*
* Driver for Marvell Switch
*
* Author: Tim Harvey
*
* Copyright (c) 2014 Tim Harvey <tharvey@gateworks.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifndef _GW16083_H_
#define _GW16083_H_
#define MII_MARVELL_PHY_PAGE 22
/*
* I2C Addresses
*/
#define GW16083_I2C_ADDR_SFP1 0x50
#define GW16083_I2C_ADDR_SFP2 0x51
#define GW16083_I2C_ADDR_EEPROM 0x52
#define GW16083_I2C_ADDR_PCA9543 0x70
/*
* MV88E1111 PHY Registers
*/
enum {
MII_M1111_PHY_CONTROL = 0,
MII_M1111_PHY_STATUS = 1,
MII_M1111_PHY_IDENT0 = 2,
MII_M1111_PHY_IDENT1 = 3,
MII_M1111_PHY_EXT_CR = 20,
MII_M1111_PHY_LED_CONTROL = 24,
MII_M1111_PHY_EXT_SR = 27,
};
#define MII_M1111_PHY_ID_MASK 0xfffffff0
#define MII_M1111_PHY_ID 0x01410cc0
#define MII_M1111_PHY_CONTROL_RESET (1 << 15)
#define MII_M1111_PHY_LED_DIRECT 0x4100
#define MII_M1111_PHY_LED_PULSE_STR 0x4111
#define MII_M1111_PHY_LED_COMBINE 0x411c
#define MII_M1111_RX_DELAY 0x80
#define MII_M1111_TX_DELAY 0x2
/*
* MV88E6176 Switch Registers
*/
/* PHY Addrs */
#define MV_BASE 0x10
#define MV_GLOBAL1 0x1b
#define MV_GLOBAL2 0x1c
#define MV_GLOBAL3 0x1d
/* Global2 Registers */
enum {
MV_SMI_PHY_COMMAND = 0x18,
MV_SMI_PHY_DATA = 0x19,
MV_SCRATCH_MISC = 0x1A,
};
/* Scratch And Misc Reg offsets */
enum {
MV_GPIO_MODE = 0x60,
MV_GPIO_DIR = 0x62,
MV_GPIO_DATA = 0x64,
MV_GPIO76_CNTL = 0x6B,
MV_GPIO54_CNTL = 0x6A,
MV_GPIO32_CNTL = 0x69,
MV_GPIO10_CNTL = 0x68,
MV_CONFIG0 = 0x70,
MV_CONFIG1 = 0x71,
MV_CONFIG2 = 0x72,
MV_CONFIG3 = 0x73,
};
/* PHY Registers */
enum {
MV_PHY_CONTROL = 0x00,
MV_PHY_STATUS = 0x01,
MV_PHY_IDENT0 = 0x02,
MV_PHY_IDENT1 = 0x03,
MV_PHY_ANEG = 0x04,
MV_PHY_LINK_ABILITY = 0x05,
MV_PHY_ANEG_EXPAND = 0x06,
MV_PHY_XMIT_NEXTP = 0x07,
MV_PHY_LINK_NEXTP = 0x08,
MV_PHY_CONTROL1 = 0x10,
MV_PHY_STATUS1 = 0x11,
MV_PHY_INTR_EN = 0x12,
};
/* Port Registers */
enum {
MV_PORT_STATUS = 0x00,
MV_PORT_PHYS_CONTROL = 0x01,
MV_PORT_IDENT = 0x03,
MV_PORT_CONTROL = 0x04,
MV_PORT_VLANMAP = 0x06,
MV_PORT_ASSOC = 0x0b,
MV_PORT_RXCOUNT = 0x10,
MV_PORT_TXCOUNT = 0x11,
};
#define SMIBUSY (1<<15)
#define SMIMODE22 (1<<12)
#define SMIOP_READ (2<<10)
#define SMIOP_WRITE (1<<10)
#define DEVADDR 5
#define REGADDR 0
#define MV_IDENT_MASK 0x0000fff0
#define MV_IDENT_VALUE 0x00001760
#endif /* _GW16083_H_ */

@ -1,31 +0,0 @@
From 1759b172f78263de7077a2743e11f3b718682849 Mon Sep 17 00:00:00 2001
From: Tim Harvey <tharvey@gateworks.com>
Date: Tue, 22 Oct 2013 21:51:27 -0700
Subject: [PATCH 1/3] ARM: dts: disable flexcan by default
Typically nodes are disabled by default and enabled when needed.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/boot/dts/imx6qdl.dtsi | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -331,6 +331,7 @@
interrupts = <0 110 0x04>;
clocks = <&clks 108>, <&clks 109>;
clock-names = "ipg", "per";
+ status = "disabled";
};
can2: flexcan@02094000 {
@@ -339,6 +340,7 @@
interrupts = <0 111 0x04>;
clocks = <&clks 110>, <&clks 111>;
clock-names = "ipg", "per";
+ status = "disabled";
};
gpt: gpt@02098000 {

@ -1,115 +0,0 @@
From 925467009cc6d92edb02b9e68710db022cd56f41 Mon Sep 17 00:00:00 2001
From: Tim Harvey <tharvey@gateworks.com>
Date: Tue, 22 Oct 2013 21:51:25 -0700
Subject: [PATCH 2/3] ARM: dts: added several new imx-pinmux groups
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/boot/dts/imx6qdl.dtsi | 60 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -639,6 +639,14 @@
MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x80000000
>;
};
+
+ pinctrl_audmux_4: audmux-4 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__AUD5_RXFS 0x80000000
+ MX6QDL_PAD_EIM_D25__AUD5_RXC 0x80000000
+ MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x80000000
+ >;
+ };
};
ecspi1 {
@@ -811,6 +819,28 @@
MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
>;
};
+
+ /* No Strobe */
+ pinctrl_gpmi_nand_2: gpmi-nand-2 {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ >;
+ };
};
hdmi_hdcp {
@@ -1058,6 +1088,13 @@
MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
>;
};
+
+ pinctrl_uart1_2: uart1grp-2 {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
};
uart2 {
@@ -1076,6 +1113,13 @@
MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
>;
};
+
+ pinctrl_uart2_3: uart2grp-3 {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA 0x1b0b1
+ >;
+ };
};
uart3 {
@@ -1096,6 +1140,13 @@
MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1
>;
};
+
+ pinctrl_uart3_3: uart3grp-3 {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
};
uart4 {
@@ -1106,6 +1157,15 @@
>;
};
};
+
+ uart5 {
+ pinctrl_uart5_1: uart5grp-1 {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA 0x1b0b1
+ >;
+ };
+ };
usbotg {
pinctrl_usbotg_1: usbotggrp-1 {

@ -1,42 +0,0 @@
From 978ed904c17cd39700a5e1f95ee29ef4fee08ce9 Mon Sep 17 00:00:00 2001
From: Anson Huang <b20788@freescale.com>
Date: Thu, 19 Dec 2013 10:02:10 -0500
Subject: [PATCH] ARM: dts: imx6dl: enable cpufreq support
This patch adds cpufreq dts for i.mx6dl to support cpufreq driver.
Signed-off-by: Anson Huang <b20788@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/boot/dts/imx6dl.dtsi | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -21,6 +21,26 @@
device_type = "cpu";
reg = <0>;
next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 996000 1275000
+ 792000 1175000
+ 396000 1075000
+ >;
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC-PU uV */
+ 996000 1175000
+ 792000 1175000
+ 396000 1175000
+ >;
+ clock-latency = <61036>; /* two CLK32 periods */
+ clocks = <&clks 104>, <&clks 6>, <&clks 16>,
+ <&clks 17>, <&clks 170>;
+ clock-names = "arm", "pll2_pfd2_396m", "step",
+ "pll1_sw", "pll1_sys";
+ arm-supply = <&reg_arm>;
+ pu-supply = <&reg_pu>;
+ soc-supply = <&reg_soc>;
};
cpu@1 {

@ -1,64 +0,0 @@
From 804f57b1a63c7435fe43b36942581cc6c79ebb5c Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Wed, 5 Mar 2014 14:25:51 +0100
Subject: [PATCH] PCI: designware: Use new OF interrupt mapping when possible
Use new OF interrupt mapping (of_irq_parse_and_map_pci()) when possible.
This is the recommended method of doing the IRQ mapping. For old
devicetrees we fall back to the previous practice.
This makes INTB, INTC, and INTD work on i.MX.
Tested-by: Tim Harvey <tharvey@gateworks.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Marek Vasut <marex@denx.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jingoo Han <jg1.han@samsung.com>
---
drivers/pci/host/pcie-designware.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pci_regs.h>
#include <linux/types.h>
@@ -492,7 +493,7 @@ int __init dw_pcie_host_init(struct pcie
dw_pci.nr_controllers = 1;
dw_pci.private_data = (void **)&pp;
- pci_common_init(&dw_pci);
+ pci_common_init_dev(pp->dev, &dw_pci);
pci_assign_unassigned_resources();
#ifdef CONFIG_PCI_DOMAINS
dw_pci.domain++;
@@ -725,7 +726,7 @@ static struct pci_bus *dw_pcie_scan_bus(
if (pp) {
pp->root_bus_nr = sys->busnr;
- bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops,
+ bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,
sys, &sys->resources);
} else {
bus = NULL;
@@ -738,8 +739,13 @@ static struct pci_bus *dw_pcie_scan_bus(
static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
+ int irq;
- return pp->irq;
+ irq = of_irq_parse_and_map_pci(dev, slot, pin);
+ if (!irq)
+ irq = pp->irq;
+
+ return irq;
}
static void dw_pcie_add_bus(struct pci_bus *bus)

@ -1,38 +0,0 @@
From 07134a365f1c4be6e840a00ae452d1593f15c5fc Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Wed, 5 Mar 2014 14:25:50 +0100
Subject: [PATCH] ARM: dts: imx6: add PCIe interrupt mapping properties
As defined by the common PCI bindings.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/boot/dts/imx6qdl.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -10,6 +10,8 @@
* http://www.gnu.org/copyleft/gpl.html
*/
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
#include "skeleton.dtsi"
/ {
@@ -127,6 +129,12 @@
0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
num-lanes = <1>;
interrupts = <0 123 0x04>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 189>, <&clks 187>, <&clks 206>, <&clks 144>;
clock-names = "pcie_ref_125m", "sata_ref_100m", "lvds_gate", "pcie_axi";
status = "disabled";

@ -1,42 +0,0 @@
From 54e8eaeec1227a024373e37315770cc79d69917b Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 28 Mar 2014 17:25:51 +0100
Subject: [PATCH] ARM: dts: imx: drop invalid size and address cells properties
Those two properties should have been set to zero, which
is the same as not specifying them.
Having address-cells set to 1 causes OF interrupt
mapping routines to add 1 to the interrupt-cells
property and as result fail because all calculations
are off by one.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
arch/arm/boot/dts/imx6qdl.dtsi | 2 --
arch/arm/boot/dts/imx6sl.dtsi | 2 --
2 files changed, 4 deletions(-)
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -40,8 +40,6 @@
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
reg = <0x00a01000 0x1000>,
<0x00a00100 0x100>;
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -44,8 +44,6 @@
intc: interrupt-controller@00a01000 {
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
- #address-cells = <1>;
- #size-cells = <1>;
interrupt-controller;
reg = <0x00a01000 0x1000>,
<0x00a00100 0x100>;

@ -1,76 +0,0 @@
From c962a0996335fae7f79e64677f47d4784b86f692 Mon Sep 17 00:00:00 2001
From: Anson Huang <b20788@freescale.com>
Date: Wed, 12 Feb 2014 17:57:03 +0800
Subject: [PATCH] ARM: imx: add speed grading check for i.mx6 soc
The fuse map of speed_grading[1:0] defines the max speed
of ARM, see below the definition:
2b'11: 1200000000Hz;
2b'10: 996000000Hz;
2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
2b'00: 792000000Hz;
Need to remove all illegal setpoints according to fuse
map.
Signed-off-by: Anson Huang <b20788@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
arch/arm/mach-imx/mach-imx6q.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -219,8 +219,10 @@ static void __init imx6q_init_machine(vo
#define OCOTP_CFG3 0x440
#define OCOTP_CFG3_SPEED_SHIFT 16
#define OCOTP_CFG3_SPEED_1P2GHZ 0x3
+#define OCOTP_CFG3_SPEED_996MHZ 0x2
+#define OCOTP_CFG3_SPEED_852MHZ 0x1
-static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
+static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
{
struct device_node *np;
void __iomem *base;
@@ -238,11 +240,29 @@ static void __init imx6q_opp_check_1p2gh
goto put_node;
}
+ /*
+ * SPEED_GRADING[1:0] defines the max speed of ARM:
+ * 2b'11: 1200000000Hz;
+ * 2b'10: 996000000Hz;
+ * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
+ * 2b'00: 792000000Hz;
+ * We need to set the max speed of ARM according to fuse map.
+ */
val = readl_relaxed(base + OCOTP_CFG3);
val >>= OCOTP_CFG3_SPEED_SHIFT;
- if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
+ val &= 0x3;
+
+ if (val != OCOTP_CFG3_SPEED_1P2GHZ)
if (dev_pm_opp_disable(cpu_dev, 1200000000))
pr_warn("failed to disable 1.2 GHz OPP\n");
+ if (val < OCOTP_CFG3_SPEED_996MHZ)
+ if (dev_pm_opp_disable(cpu_dev, 996000000))
+ pr_warn("failed to disable 996 MHz OPP\n");
+ if (cpu_is_imx6q()) {
+ if (val != OCOTP_CFG3_SPEED_852MHZ)
+ if (dev_pm_opp_disable(cpu_dev, 852000000))
+ pr_warn("failed to disable 852 MHz OPP\n");
+ }
put_node:
of_node_put(np);
@@ -268,7 +288,7 @@ static void __init imx6q_opp_init(void)
goto put_node;
}
- imx6q_opp_check_1p2ghz(cpu_dev);
+ imx6q_opp_check_speed_grading(cpu_dev);
put_node:
of_node_put(np);

@ -1,69 +0,0 @@
From: Tim Harvey <tharvey@gateworks.com>
Subject: [PATCH] sky2: allow mac to come from dt
The driver reads the mac address from the device registers which would
need to have been programmed by the bootloader. This patch adds
the ability to pull the mac from devicetree via the aliases/sky2 node.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
drivers/net/ethernet/marvell/sky2.c | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -44,6 +44,8 @@
#include <linux/prefetch.h>
#include <linux/debugfs.h>
#include <linux/mii.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
#include <asm/irq.h>
@@ -4748,6 +4750,7 @@ static struct net_device *sky2_init_netd
{
struct sky2_port *sky2;
struct net_device *dev = alloc_etherdev(sizeof(*sky2));
+ unsigned char *iap, tmpaddr[ETH_ALEN];
if (!dev)
return NULL;
@@ -4805,8 +4808,36 @@ static struct net_device *sky2_init_netd
dev->features |= dev->hw_features;
+ /*
+ * try to get mac address in the following order:
+ * 1) from device tree data
+ * 2) from internal registers set by bootloader
+ */
+ iap = NULL;
+ if (IS_ENABLED(CONFIG_OF)) {
+ struct device_node *np;
+ np = of_find_node_by_path("/aliases");
+ if (np) {
+ const char *path = of_get_property(np, "sky2", NULL);
+ if (path)
+ np = of_find_node_by_path(path);
+ if (np)
+ path = of_get_mac_address(np);
+ if (path)
+ iap = (unsigned char *) path;
+ }
+ }
+
+ /*
+ * 2) mac registers set by bootloader
+ */
+ if (!iap || !is_valid_ether_addr(iap)) {
+ memcpy_fromio(&tmpaddr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
+ iap = &tmpaddr[0];
+ }
+
/* read the mac address */
- memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port * 8, ETH_ALEN);
+ memcpy(dev->dev_addr, iap, ETH_ALEN);
return dev;
}

@ -1,86 +0,0 @@
This fixes a boot hang observed when the bootloader
already enabled the PCIe link for it's own use. The
fundamental problem is that Freescale forgot to wire
up the core reset, so software doesn't have a sane way
to get the core into a defined state.
According to the DW PCIe core reference manual configuration
of the core may only happen when the LTSSM is disabled, so
this is one of the first things we need to do. Apparently
this isn't safe to do when the LTSSM is in any other state
than "detect" as we observe an instant machine hang when
trying to do so while the link is already up.
As a workaround force LTSSM into detect state right before
hitting the disable switch.
Reported-by: Fabio Estevam <fabio.estevam <at> freescale.com>
Signed-off-by: Lucas Stach <l.stach <at> pengutronix.de>
Acked-by: Tim Harvey <tharvey <at> gateworks.com>
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -52,6 +52,9 @@ struct imx6_pcie {
/* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700
+#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
+#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
+#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
@@ -217,6 +220,31 @@ static int imx6q_pcie_abort_handler(unsi
static int imx6_pcie_assert_core_reset(struct pcie_port *pp)
{
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
+ u32 val, gpr1, gpr12;
+
+ /*
+ * If the bootloader already enabled the link we need some special
+ * handling to get the core back into a state where it is safe to
+ * touch it for configuration. As there is no dedicated reset signal
+ * wired up for MX6QDL, we need to manually force LTSSM into "detect"
+ * state before completely disabling LTSSM, which is a prerequisite
+ * for core configuration.
+ * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong
+ * indication that the bootloader activated the link.
+ */
+ regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
+ regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
+
+ if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
+ (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
+ val = readl(pp->dbi_base + PCIE_PL_PFLR);
+ val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
+ val |= PCIE_PL_PFLR_FORCE_LINK;
+ writel(val, pp->dbi_base + PCIE_PL_PFLR);
+
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+ IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+ }
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
@@ -627,6 +655,14 @@ static int __init imx6_pcie_probe(struct
return 0;
}
+static void imx6_pcie_shutdown(struct platform_device *pdev)
+{
+ struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
+
+ /* bring down link, so bootloader gets clean state in case of reboot */
+ imx6_pcie_assert_core_reset(&imx6_pcie->pp);
+}
+
static const struct of_device_id imx6_pcie_of_match[] = {
{ .compatible = "fsl,imx6q-pcie", },
{},
@@ -639,6 +675,7 @@ static struct platform_driver imx6_pcie_
.owner = THIS_MODULE,
.of_match_table = imx6_pcie_of_match,
},
+ .shutdown = imx6_pcie_shutdown,
};
/* Freescale PCIe driver does not allow module unload */

@ -1,38 +0,0 @@
PCI: imx6: fix occasional link failure
According to the IMX6 reference manuals, REF_SSP_EN (Reference clock enable
for SS function) must remain deasserted until the reference clock is running
at the appropriate frequency.
Without this patch we find a high link failure rate (>5%) on certain
IMX6 boards at various temperatures.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -262,11 +262,6 @@ static int imx6_pcie_deassert_core_reset
if (gpio_is_valid(imx6_pcie->power_on_gpio))
gpio_set_value(imx6_pcie->power_on_gpio, 1);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
-
ret = clk_prepare_enable(imx6_pcie->sata_ref_100m);
if (ret) {
dev_err(pp->dev, "unable to enable sata_ref_100m\n");
@@ -294,6 +289,12 @@ static int imx6_pcie_deassert_core_reset
/* allow the clocks to stabilize */
usleep_range(200, 500);
+ /* power up core phy and enable ref clock */
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
+ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
+ IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
+
/* Some boards don't have PCIe reset GPIO. */
if (gpio_is_valid(imx6_pcie->reset_gpio)) {
gpio_set_value(imx6_pcie->reset_gpio, 0);

@ -1,11 +0,0 @@
--- a/arch/arm/boot/dts/imx6dl-wandboard.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard.dts
@@ -19,4 +19,8 @@
memory {
reg = <0x10000000 0x40000000>;
};
+
+ chosen {
+ bootargs = "console=ttymxc0,115200";
+ };
};

@ -1,33 +0,0 @@
commit e84634dc6c7f3f6af9b8ef1fb36f0d85c476ab95
Author: Tim Harvey <tharvey@gateworks.com>
Date: Thu Feb 27 01:02:23 2014 -0800
PCI: designware: add ability for custom swizzle
Add the ability for a platform driver to provide a platform-specific
swizzle function.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -481,6 +481,9 @@ int __init dw_pcie_host_init(struct pcie
if (pp->ops->host_init)
pp->ops->host_init(pp);
+ if (pp->swizzle)
+ dw_pci.swizzle = pp->swizzle;
+
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
/* program correct class for RC */
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -53,6 +53,7 @@ struct pcie_port {
struct irq_domain *irq_domain;
unsigned long msi_data;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
+ u8 (*swizzle)(struct pci_dev *, u8 *);
};
struct pcie_host_ops {

@ -1,81 +0,0 @@
commit 2c0d0491438433a1f327f2e754c7b6b55fec51c4
Author: Tim Harvey <tharvey@gateworks.com>
Date: Thu Feb 27 00:59:53 2014 -0800
PCI: imx6: ventana: fixup for IRQ mismapping
The TI XIO2001 PCIe-to-PCI bridge used on several Ventana expansion boards
has its slot-to-bridge IRQ mapping reversed from the PCI specification:
INTA->INTD
INTB->INTC
INTC->INTB
INTD->INTA
Implement a custom swizzle function that does a fixup on the interrupt for
devices on a TI XIO2001 bridge.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -540,6 +540,39 @@ static int imx6_add_pcie_port(struct pci
return 0;
}
+/* TI XIO2001 PCIe-to-PCI bridge on GW16082 exp card has IRQs reversed */
+u8 ventana_swizzle(struct pci_dev *dev, u8 *pin)
+{
+ u8 i = 0;
+ struct pci_dev *pdev = dev;
+
+ /* count number of TI XIO2001 bridges on bus */
+ while (!pci_is_root_bus(pdev->bus)) {
+ if (pdev->bus && pdev->bus->self &&
+ (pdev->bus->self->vendor == PCI_VENDOR_ID_TI) &&
+ (pdev->bus->self->device == PCI_DEVICE_ID_TI_XIO2001)) {
+ i++;
+ }
+ pdev = pdev->bus->self;
+ }
+ while (!pci_is_root_bus(dev->bus)) {
+ /* if we are directly downstream from 1st TI XIO2001 bridge */
+ if (dev->bus && dev->bus->self &&
+ (dev->bus->self->vendor == PCI_VENDOR_ID_TI) &&
+ (dev->bus->self->device == PCI_DEVICE_ID_TI_XIO2001)) {
+ if (--i == 0) {
+ /* swap IRQs and swizzle backwards */
+ *pin = (15 - PCI_SLOT(dev->devfn)) + 1;
+ dev = dev->bus->self;
+ continue;
+ }
+ }
+ *pin = pci_swizzle_interrupt_pin(dev, *pin);
+ dev = dev->bus->self;
+ }
+ return PCI_SLOT(dev->devfn);
+}
+
static int __init imx6_pcie_probe(struct platform_device *pdev)
{
struct imx6_pcie *imx6_pcie;
@@ -648,6 +681,9 @@ static int __init imx6_pcie_probe(struct
return PTR_ERR(imx6_pcie->iomuxc_gpr);
}
+ if (of_machine_is_compatible("gw,ventana"))
+ pp->swizzle = ventana_swizzle;
+
ret = imx6_add_pcie_port(pp, pdev);
if (ret < 0)
return ret;
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -822,6 +822,7 @@
#define PCI_DEVICE_ID_TI_XX12 0x8039
#define PCI_DEVICE_ID_TI_XX12_FM 0x803b
#define PCI_DEVICE_ID_TI_XIO2000A 0x8231
+#define PCI_DEVICE_ID_TI_XIO2001 0x8240
#define PCI_DEVICE_ID_TI_1130 0xac12
#define PCI_DEVICE_ID_TI_1031 0xac13
#define PCI_DEVICE_ID_TI_1131 0xac15

@ -1,129 +0,0 @@
Author: Tim Harvey <tharvey@gateworks.com>
Date: Thu May 15 00:12:26 2014 -0700
net: igb: add i210/i211 support for phy read/write
The i210/i211 uses the MDICNFG register for the phy address instead of the
MDIC register.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -139,7 +139,7 @@ out:
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
{
struct e1000_phy_info *phy = &hw->phy;
- u32 i, mdic = 0;
+ u32 i, mdicnfg, mdic = 0;
s32 ret_val = 0;
if (offset > MAX_PHY_REG_ADDRESS) {
@@ -152,11 +152,25 @@ s32 igb_read_phy_reg_mdic(struct e1000_h
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
- mdic = ((offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_READ));
+ switch (hw->mac.type) {
+ case e1000_i210:
+ case e1000_i211:
+ mdicnfg = rd32(E1000_MDICNFG);
+ mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
+ mdicnfg |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
+ wr32(E1000_MDICNFG, mdicnfg);
+ mdic = ((offset << E1000_MDIC_REG_SHIFT) |
+ (E1000_MDIC_OP_READ));
+ break;
+ default:
+ mdic = ((offset << E1000_MDIC_REG_SHIFT) |
+ (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_READ));
+ break;
+ }
wr32(E1000_MDIC, mdic);
+ wrfl();
/* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
@@ -181,6 +195,18 @@ s32 igb_read_phy_reg_mdic(struct e1000_h
*data = (u16) mdic;
out:
+ switch (hw->mac.type) {
+ /* restore MDICNFG to have phy's addr */
+ case e1000_i210:
+ case e1000_i211:
+ mdicnfg = rd32(E1000_MDICNFG);
+ mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
+ mdicnfg |= (hw->phy.addr << E1000_MDICNFG_PHY_SHIFT);
+ wr32(E1000_MDICNFG, mdicnfg);
+ break;
+ default:
+ break;
+ }
return ret_val;
}
@@ -195,7 +221,7 @@ out:
s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
{
struct e1000_phy_info *phy = &hw->phy;
- u32 i, mdic = 0;
+ u32 i, mdicnfg, mdic = 0;
s32 ret_val = 0;
if (offset > MAX_PHY_REG_ADDRESS) {
@@ -208,12 +234,27 @@ s32 igb_write_phy_reg_mdic(struct e1000_
* Control register. The MAC will take care of interfacing with the
* PHY to retrieve the desired data.
*/
- mdic = (((u32)data) |
- (offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
- (E1000_MDIC_OP_WRITE));
+ switch (hw->mac.type) {
+ case e1000_i210:
+ case e1000_i211:
+ mdicnfg = rd32(E1000_MDICNFG);
+ mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
+ mdicnfg |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
+ wr32(E1000_MDICNFG, mdicnfg);
+ mdic = (((u32)data) |
+ (offset << E1000_MDIC_REG_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
+ break;
+ default:
+ mdic = (((u32)data) |
+ (offset << E1000_MDIC_REG_SHIFT) |
+ (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE));
+ break;
+ }
wr32(E1000_MDIC, mdic);
+ wrfl();
/* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
@@ -237,6 +278,18 @@ s32 igb_write_phy_reg_mdic(struct e1000_
}
out:
+ switch (hw->mac.type) {
+ /* restore MDICNFG to have phy's addr */
+ case e1000_i210:
+ case e1000_i211:
+ mdicnfg = rd32(E1000_MDICNFG);
+ mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
+ mdicnfg |= (hw->phy.addr << E1000_MDICNFG_PHY_SHIFT);
+ wr32(E1000_MDICNFG, mdicnfg);
+ break;
+ default:
+ break;
+ }
return ret_val;
}

@ -1,255 +0,0 @@
Author: Tim Harvey <tharvey@gateworks.com>
Date: Thu May 15 00:29:18 2014 -0700
net: igb: add phy read/write functions that accept phy addr
Add igb_write_reg_gs40g/igb_read_reg_gs40g that can be passed a phy address.
The existing igb_write_phy_reg_gs40g/igb_read_phy_reg_gs40g become wrappers
to this function.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -2142,7 +2142,7 @@ static s32 igb_read_phy_reg_82580(struct
if (ret_val)
goto out;
- ret_val = igb_read_phy_reg_mdic(hw, offset, data);
+ ret_val = igb_read_phy_reg_mdic(hw, hw->phy.addr, offset, data);
hw->phy.ops.release(hw);
@@ -2167,7 +2167,7 @@ static s32 igb_write_phy_reg_82580(struc
if (ret_val)
goto out;
- ret_val = igb_write_phy_reg_mdic(hw, offset, data);
+ ret_val = igb_write_phy_reg_mdic(hw, hw->phy.addr, offset, data);
hw->phy.ops.release(hw);
--- a/drivers/net/ethernet/intel/igb/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.c
@@ -136,9 +136,8 @@ out:
* Reads the MDI control regsiter in the PHY at offset and stores the
* information read to data.
**/
-s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u8 addr, u32 offset, u16 *data)
{
- struct e1000_phy_info *phy = &hw->phy;
u32 i, mdicnfg, mdic = 0;
s32 ret_val = 0;
@@ -157,14 +156,14 @@ s32 igb_read_phy_reg_mdic(struct e1000_h
case e1000_i211:
mdicnfg = rd32(E1000_MDICNFG);
mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
- mdicnfg |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
+ mdicnfg |= (addr << E1000_MDICNFG_PHY_SHIFT);
wr32(E1000_MDICNFG, mdicnfg);
mdic = ((offset << E1000_MDIC_REG_SHIFT) |
(E1000_MDIC_OP_READ));
break;
default:
mdic = ((offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_READ));
break;
}
@@ -218,9 +217,8 @@ out:
*
* Writes data to MDI control register in the PHY at offset.
**/
-s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u8 addr, u32 offset, u16 data)
{
- struct e1000_phy_info *phy = &hw->phy;
u32 i, mdicnfg, mdic = 0;
s32 ret_val = 0;
@@ -239,7 +237,7 @@ s32 igb_write_phy_reg_mdic(struct e1000_
case e1000_i211:
mdicnfg = rd32(E1000_MDICNFG);
mdicnfg &= ~(E1000_MDICNFG_PHY_MASK);
- mdicnfg |= (phy->addr << E1000_MDICNFG_PHY_SHIFT);
+ mdicnfg |= (addr << E1000_MDICNFG_PHY_SHIFT);
wr32(E1000_MDICNFG, mdicnfg);
mdic = (((u32)data) |
(offset << E1000_MDIC_REG_SHIFT) |
@@ -248,7 +246,7 @@ s32 igb_write_phy_reg_mdic(struct e1000_
default:
mdic = (((u32)data) |
(offset << E1000_MDIC_REG_SHIFT) |
- (phy->addr << E1000_MDIC_PHY_SHIFT) |
+ (addr << E1000_MDIC_PHY_SHIFT) |
(E1000_MDIC_OP_WRITE));
break;
}
@@ -539,7 +537,7 @@ s32 igb_read_phy_reg_igp(struct e1000_hw
goto out;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
- ret_val = igb_write_phy_reg_mdic(hw,
+ ret_val = igb_write_phy_reg_mdic(hw, hw->phy.addr,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
if (ret_val) {
@@ -548,8 +546,8 @@ s32 igb_read_phy_reg_igp(struct e1000_hw
}
}
- ret_val = igb_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ ret_val = igb_read_phy_reg_mdic(hw, hw->phy.addr,
+ MAX_PHY_REG_ADDRESS & offset, data);
hw->phy.ops.release(hw);
@@ -578,7 +576,7 @@ s32 igb_write_phy_reg_igp(struct e1000_h
goto out;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
- ret_val = igb_write_phy_reg_mdic(hw,
+ ret_val = igb_write_phy_reg_mdic(hw, hw->phy.addr,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
if (ret_val) {
@@ -587,8 +585,8 @@ s32 igb_write_phy_reg_igp(struct e1000_h
}
}
- ret_val = igb_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
+ ret_val = igb_write_phy_reg_mdic(hw, hw->phy.addr,
+ MAX_PHY_REG_ADDRESS & offset, data);
hw->phy.ops.release(hw);
@@ -2554,8 +2552,9 @@ out:
}
/**
- * igb_write_phy_reg_gs40g - Write GS40G PHY register
+ * igb_write_reg_gs40g - Write GS40G PHY register
* @hw: pointer to the HW structure
+ * @addr: phy address to write to
* @offset: lower half is register offset to write to
* upper half is page to use.
* @data: data to write at register offset
@@ -2563,7 +2562,7 @@ out:
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
**/
-s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+s32 igb_write_reg_gs40g(struct e1000_hw *hw, u8 addr, u32 offset, u16 data)
{
s32 ret_val;
u16 page = offset >> GS40G_PAGE_SHIFT;
@@ -2573,10 +2572,10 @@ s32 igb_write_phy_reg_gs40g(struct e1000
if (ret_val)
return ret_val;
- ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ ret_val = igb_write_phy_reg_mdic(hw, addr, GS40G_PAGE_SELECT, page);
if (ret_val)
goto release;
- ret_val = igb_write_phy_reg_mdic(hw, offset, data);
+ ret_val = igb_write_phy_reg_mdic(hw, addr, offset, data);
release:
hw->phy.ops.release(hw);
@@ -2584,8 +2583,24 @@ release:
}
/**
- * igb_read_phy_reg_gs40g - Read GS40G PHY register
+ * igb_write_phy_reg_gs40g - Write GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to write to
+ * upper half is page to use.
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore, if necessary, then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return igb_write_reg_gs40g(hw, hw->phy.addr, offset, data);
+}
+
+/**
+ * igb_read_reg_gs40g - Read GS40G PHY register
* @hw: pointer to the HW structure
+ * @addr: phy address to read from
* @offset: lower half is register offset to read to
* upper half is page to use.
* @data: data to read at register offset
@@ -2593,7 +2608,7 @@ release:
* Acquires semaphore, if necessary, then reads the data in the PHY register
* at the offset. Release any acquired semaphores before exiting.
**/
-s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+s32 igb_read_reg_gs40g(struct e1000_hw *hw, u8 addr, u32 offset, u16 *data)
{
s32 ret_val;
u16 page = offset >> GS40G_PAGE_SHIFT;
@@ -2603,10 +2618,10 @@ s32 igb_read_phy_reg_gs40g(struct e1000_
if (ret_val)
return ret_val;
- ret_val = igb_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
+ ret_val = igb_write_phy_reg_mdic(hw, addr, GS40G_PAGE_SELECT, page);
if (ret_val)
goto release;
- ret_val = igb_read_phy_reg_mdic(hw, offset, data);
+ ret_val = igb_read_phy_reg_mdic(hw, addr, offset, data);
release:
hw->phy.ops.release(hw);
@@ -2614,6 +2629,21 @@ release:
}
/**
+ * igb_read_phy_reg_gs40g - Read GS40G PHY register
+ * @hw: pointer to the HW structure
+ * @offset: lower half is register offset to read to
+ * upper half is page to use.
+ * @data: data to read at register offset
+ *
+ * Acquires semaphore, if necessary, then reads the data in the PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return igb_read_reg_gs40g(hw, hw->phy.addr, offset, data);
+}
+
+/**
* igb_set_master_slave_mode - Setup PHY for Master/slave mode
* @hw: pointer to the HW structure
*
--- a/drivers/net/ethernet/intel/igb/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igb/e1000_phy.h
@@ -65,8 +65,8 @@ s32 igb_phy_has_link(struct e1000_hw *h
void igb_power_up_phy_copper(struct e1000_hw *hw);
void igb_power_down_phy_copper(struct e1000_hw *hw);
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
-s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
-s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u8 addr, u32 offset, u16 *data);
+s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u8 addr, u32 offset, u16 data);
s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
@@ -77,6 +77,8 @@ s32 igb_phy_force_speed_duplex_82580(st
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
s32 igb_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data);
s32 igb_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data);
+s32 igb_read_reg_gs40g(struct e1000_hw *hw, u8 addr, u32 offset, u16 *data);
+s32 igb_write_reg_gs40g(struct e1000_hw *hw, u8 addr, u32 offset, u16 data);
s32 igb_check_polarity_m88(struct e1000_hw *hw);
/* IGP01E1000 Specific Registers */

@ -1,303 +0,0 @@
Author: Tim Harvey <tharvey@gateworks.com>
Date: Thu May 15 12:36:23 2014 -0700
net: igb: register mii_bus for SerDes w/ external phy
If an i210 is configured for 1000BASE-BX link_mode and has an external phy
specified, then register an mii bus using the external phy address as
a mask.
An i210 hooked to an external standard phy will be configured with a link_mo
of SGMII in which case phy ops will be configured and used internall in the
igb driver for link status. However, in certain cases one might be using a
backplane SerDes connection to something that talks on the mdio bus but is
not a standard phy, such as a switch. In this case by registering an mdio
bus a phy driver can manage the device.
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -606,13 +606,25 @@ static s32 igb_get_invariants_82575(stru
switch (link_mode) {
case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
hw->phy.media_type = e1000_media_type_internal_serdes;
+ if (igb_sgmii_uses_mdio_82575(hw)) {
+ u32 mdicnfg = rd32(E1000_MDICNFG);
+ mdicnfg &= E1000_MDICNFG_PHY_MASK;
+ hw->phy.addr = mdicnfg >> E1000_MDICNFG_PHY_SHIFT;
+ hw_dbg("1000BASE_KX w/ external MDIO device at 0x%x\n",
+ hw->phy.addr);
+ } else {
+ hw_dbg("1000BASE_KX");
+ }
break;
case E1000_CTRL_EXT_LINK_MODE_SGMII:
/* Get phy control interface type set (MDIO vs. I2C)*/
if (igb_sgmii_uses_mdio_82575(hw)) {
hw->phy.media_type = e1000_media_type_copper;
dev_spec->sgmii_active = true;
+ hw_dbg("SGMII with external MDIO PHY");
break;
+ } else {
+ hw_dbg("SGMII with external I2C PHY");
}
/* fall through for I2C based SGMII */
case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
@@ -629,8 +641,11 @@ static s32 igb_get_invariants_82575(stru
hw->phy.media_type = e1000_media_type_copper;
dev_spec->sgmii_active = true;
}
+ hw_dbg("SERDES with external SFP");
break;
+ } else {
+ hw_dbg("SERDES");
}
/* do not change link mode for 100BaseFX */
--- a/drivers/net/ethernet/intel/igb/e1000_hw.h
+++ b/drivers/net/ethernet/intel/igb/e1000_hw.h
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/netdevice.h>
+#include <linux/phy.h>
#include "e1000_regs.h"
#include "e1000_defines.h"
@@ -553,6 +554,12 @@ struct e1000_hw {
struct e1000_mbx_info mbx;
struct e1000_host_mng_dhcp_cookie mng_cookie;
+#ifdef CONFIG_PHYLIB
+ /* Phylib and MDIO interface */
+ struct mii_bus *mii_bus;
+ struct phy_device *phy_dev;
+ phy_interface_t phy_interface;
+#endif
union {
struct e1000_dev_spec_82575 _82575;
} dev_spec;
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -45,6 +45,7 @@
#include <linux/if_vlan.h>
#include <linux/pci.h>
#include <linux/pci-aspm.h>
+#include <linux/phy.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/ip.h>
@@ -2191,6 +2192,126 @@ static s32 igb_init_i2c(struct igb_adapt
return status;
}
+
+#ifdef CONFIG_PHYLIB
+/*
+ * MMIO/PHYdev support
+ */
+
+static int igb_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct e1000_hw *hw = bus->priv;
+ u16 out;
+ int err;
+
+ err = igb_read_reg_gs40g(hw, mii_id, regnum, &out);
+ if (err)
+ return err;
+ return out;
+}
+
+static int igb_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 val)
+{
+ struct e1000_hw *hw = bus->priv;
+
+ return igb_write_reg_gs40g(hw, mii_id, regnum, val);
+}
+
+static int igb_enet_mdio_reset(struct mii_bus *bus)
+{
+ udelay(300);
+ return 0;
+}
+
+static void igb_enet_mii_link(struct net_device *netdev)
+{
+}
+
+/* Probe the mdio bus for phys and connect them */
+static int igb_enet_mii_probe(struct net_device *netdev)
+{
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ struct phy_device *phy_dev = NULL;
+ int phy_id;
+
+ /* check for attached phy */
+ for (phy_id = 0; (phy_id < PHY_MAX_ADDR); phy_id++) {
+ if (hw->mii_bus->phy_map[phy_id]) {
+ phy_dev = hw->mii_bus->phy_map[phy_id];
+ break;
+ }
+ }
+ if (!phy_dev) {
+ netdev_err(netdev, "no PHY found\n");
+ return -ENODEV;
+ }
+
+ hw->phy_interface = PHY_INTERFACE_MODE_RGMII;
+ phy_dev = phy_connect(netdev, dev_name(&phy_dev->dev),
+ igb_enet_mii_link, hw->phy_interface);
+ if (IS_ERR(phy_dev)) {
+ netdev_err(netdev, "could not attach to PHY\n");
+ return PTR_ERR(phy_dev);
+ }
+
+ hw->phy_dev = phy_dev;
+ netdev_info(netdev, "igb PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+ hw->phy_dev->drv->name, dev_name(&hw->phy_dev->dev));
+
+ return 0;
+}
+
+/* Create and register mdio bus */
+static int igb_enet_mii_init(struct pci_dev *pdev)
+{
+ struct mii_bus *mii_bus;
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
+ int err;
+
+ mii_bus = mdiobus_alloc();
+ if (mii_bus == NULL) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ mii_bus->name = "igb_enet_mii_bus";
+ mii_bus->read = igb_enet_mdio_read;
+ mii_bus->write = igb_enet_mdio_write;
+ mii_bus->reset = igb_enet_mdio_reset;
+ snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ pci_name(pdev), hw->device_id + 1);
+ mii_bus->priv = hw;
+ mii_bus->parent = &pdev->dev;
+ mii_bus->phy_mask = ~(1 << hw->phy.addr);
+
+ err = mdiobus_register(mii_bus);
+ if (err) {
+ printk(KERN_ERR "failed to register mii_bus: %d\n", err);
+ goto err_out_free_mdiobus;
+ }
+ hw->mii_bus = mii_bus;
+
+ return 0;
+
+err_out_free_mdiobus:
+ mdiobus_free(mii_bus);
+err_out:
+ return err;
+}
+
+static void igb_enet_mii_remove(struct e1000_hw *hw)
+{
+ if (hw->mii_bus) {
+ mdiobus_unregister(hw->mii_bus);
+ mdiobus_free(hw->mii_bus);
+ }
+}
+#endif /* CONFIG_PHYLIB */
+
/**
* igb_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -2593,6 +2714,13 @@ static int igb_probe(struct pci_dev *pde
}
pm_runtime_put_noidle(&pdev->dev);
+
+#ifdef CONFIG_PHYLIB
+ /* create and register the mdio bus if using ext phy */
+ if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
+ igb_enet_mii_init(pdev);
+#endif
+
return 0;
err_register:
@@ -2736,6 +2864,10 @@ static void igb_remove(struct pci_dev *p
struct e1000_hw *hw = &adapter->hw;
pm_runtime_get_noresume(&pdev->dev);
+#ifdef CONFIG_PHYLIB
+ if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
+ igb_enet_mii_remove(hw);
+#endif
#ifdef CONFIG_IGB_HWMON
igb_sysfs_exit(adapter);
#endif
@@ -3040,6 +3172,12 @@ static int __igb_open(struct net_device
if (!resuming)
pm_runtime_put(&pdev->dev);
+#ifdef CONFIG_PHYLIB
+ /* Probe and connect to PHY if using ext phy */
+ if (rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO)
+ igb_enet_mii_probe(netdev);
+#endif
+
/* start the watchdog. */
hw->mac.get_link_status = 1;
schedule_work(&adapter->watchdog_task);
@@ -7095,21 +7233,41 @@ void igb_alloc_rx_buffers(struct igb_rin
static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
{
struct igb_adapter *adapter = netdev_priv(netdev);
+ struct e1000_hw *hw = &adapter->hw;
struct mii_ioctl_data *data = if_mii(ifr);
- if (adapter->hw.phy.media_type != e1000_media_type_copper)
+ if (adapter->hw.phy.media_type != e1000_media_type_copper &&
+ !(rd32(E1000_MDICNFG) & E1000_MDICNFG_EXT_MDIO))
return -EOPNOTSUPP;
switch (cmd) {
case SIOCGMIIPHY:
- data->phy_id = adapter->hw.phy.addr;
+ data->phy_id = hw->phy.addr;
break;
case SIOCGMIIREG:
- if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
- &data->val_out))
- return -EIO;
+ if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
+ if (igb_read_reg_gs40g(hw, data->phy_id,
+ data->reg_num & 0x1F,
+ &data->val_out))
+ return -EIO;
+ } else {
+ if (igb_read_phy_reg(hw, data->reg_num & 0x1F,
+ &data->val_out))
+ return -EIO;
+ }
break;
case SIOCSMIIREG:
+ if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
+ if (igb_write_reg_gs40g(hw, data->phy_id,
+ data->reg_num & 0x1F,
+ data->val_in))
+ return -EIO;
+ } else {
+ if (igb_write_phy_reg(hw, data->reg_num & 0x1F,
+ data->val_in))
+ return -EIO;
+ }
+ break;
default:
return -EOPNOTSUPP;
}

@ -1,27 +0,0 @@
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -273,6 +273,14 @@ endif # RTL8366_SMI
source "drivers/net/phy/b53/Kconfig"
+config GATEWORKS_GW16083
+ tristate "Gateworks GW16083 Ethernet Expansion Mezzanine"
+ ---help---
+ The Gateworks GW16083 Ethernet Expansion Mezzanine connects to a
+ Gateworks Ventana baseboard and provides a 7-port GbE managed
+ Ethernet switch with 4 dedicated GbE RJ45 ports, and 2 Gbe/SFP
+ ports"
+
endif # PHYLIB
config MICREL_KS8995MA
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
+obj-$(CONFIG_GATEWORKS_GW16083) += gw16083.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_AT803X_PHY) += at803x.o

@ -1,56 +0,0 @@
--- a/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
@@ -201,6 +201,11 @@
};
};
};
+
+ gw16083: gw16083@52 {
+ compatible = "gateworks,gw16083";
+ reg = <0x52>;
+ };
};
&i2c3 {
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -268,6 +268,11 @@
};
};
};
+
+ gw16083: gw16083@52 {
+ compatible = "gateworks,gw16083";
+ reg = <0x52>;
+ };
};
&i2c3 {
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -289,6 +289,11 @@
};
};
};
+
+ gw16083: gw16083@52 {
+ compatible = "gateworks,gw16083";
+ reg = <0x52>;
+ };
};
&i2c3 {
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -317,6 +317,11 @@
compatible = "sil,si52147";
reg = <0x6b>;
};
+
+ gw16083: gw16083@52 {
+ compatible = "gateworks,gw16083";
+ reg = <0x52>;
+ };
};
&i2c3 {

@ -1,58 +0,0 @@
This patch allows passing in the gpio output mask used for GPIO0-7 on the
PLX PCIe bridge. These GPIO's are used for PERST# on the downstream ports.
Allowing the kernel to override the default configuration allows for keeping
specific devices held in reset. One important use of this is to allow
temporarily disabling devices that may request too many resources such as
an unprogrammed i210 device.
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -84,6 +84,7 @@ static int ksz9031rn_phy_fixup(struct ph
* fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
* as they are used for slots1-7 PERST#
*/
+unsigned int ventana_plx_gpio = 0xfe;
static void ventana_pciesw_early_fixup(struct pci_dev *dev)
{
u32 dw;
@@ -95,19 +96,25 @@ static void ventana_pciesw_early_fixup(s
return;
pci_read_config_dword(dev, 0x62c, &dw);
+ dev_info(&dev->dev, "de-asserting downstream PERST# 0x%04x\n",
+ ventana_plx_gpio);
dw |= 0xaaa8; // GPIO1-7 outputs
pci_write_config_dword(dev, 0x62c, dw);
-
- pci_read_config_dword(dev, 0x644, &dw);
- dw |= 0xfe; // GPIO1-7 output high
- pci_write_config_dword(dev, 0x644, dw);
-
+ pci_write_config_dword(dev, 0x644, ventana_plx_gpio);
msleep(100);
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
+static int __init setup_ventana_plx_gpio(char *str)
+{
+ get_option(&str, &ventana_plx_gpio);
+
+ return 0;
+}
+early_param("plx_gpio", setup_ventana_plx_gpio);
+
static int ar8031_phy_fixup(struct phy_device *dev)
{
u16 val;
@@ -328,7 +335,7 @@ static void __init imx6q_init_irq(void)
irqchip_init();
}
-static const char *imx6q_dt_compat[] __initconst = {
+static const char *imx6q_dt_compat[] __initdata = {
"fsl,imx6dl",
"fsl,imx6q",
NULL,

@ -1,18 +0,0 @@
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -158,6 +158,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6dl-gw52xx.dtb \
imx6dl-gw53xx.dtb \
imx6dl-gw54xx.dtb \
+ imx6dl-gw552x.dtb \
imx6dl-hummingboard.dtb \
imx6dl-sabreauto.dtb \
imx6dl-sabresd.dtb \
@@ -169,6 +170,7 @@ dtb-$(CONFIG_ARCH_MXC) += \
imx6q-gw53xx.dtb \
imx6q-gw5400-a.dtb \
imx6q-gw54xx.dtb \
+ imx6q-gw552x.dtb \
imx6q-phytec-pbab01.dtb \
imx6q-sabreauto.dtb \
imx6q-sabrelite.dtb \
Loading…
Cancel
Save