socfpga ethernet/MMC support for 3.8

Dinh Nguyen dinguyen at altera.com
Mon Mar 4 16:31:21 EST 2013


Hi Pavel,

On Mon, 2013-03-04 at 21:43 +0100, ZY - pavel wrote:
> Hi!
> 
> Below are changes that get MMC/ethernet working for me. Probably not
> everything is strictly neccessary, I'll try to prune them some more.
> 
> Strange thing is that enh_desc.c (disabling checksumming AFAICT) seems
> to be neccessary for NFS to work.
> 
> In the meantime... does it make sense to split simple changes and
> submit them upstream?
> 
> arch/arm/boot/dts/Makefile -- dtb files should be build, this can be
> probably considered bugfix.
> 
> socfpga.c: socfpga_cyclone5_restart() -- this is self-contained reset
> function marked with "TODO".

Alot of these changes have already been pull for 3.9. I have patches
queued up for restart, hotplug and some other misc function for SOCFPGA.

I am close to having a patch that enables SD/MMC, but that should go to
Seungwon Jeon and Jaehoon Chung.

Can you please coordinate with myself before sending such patches to the
mailing list?

Thanks,
Dinh
> 
> (patches are originally from Altera).
> Signed-off-by: Pavel Machek <pavel at denx.de>
> (but not for merge for now).
> 
> Thanks,
> 								Pavel
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 5ebb44f..d675c986 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -124,6 +124,9 @@ dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
>  	r8a7740-armadillo800eva.dtb \
>  	sh73a0-kzm9g.dtb \
>  	sh7372-mackerel.dtb
> +dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5.dtb\
> +	socfpga_ice.dtb\
> +	socfpga_vt.dtb
>  dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
>  	spear1340-evb.dtb
>  dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
> diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
> index 19aec42..c59ca7d 100644
> --- a/arch/arm/boot/dts/socfpga.dtsi
> +++ b/arch/arm/boot/dts/socfpga.dtsi
> @@ -23,8 +23,13 @@
>  
>  	aliases {
>  		ethernet0 = &gmac0;
> +		ethernet1 = &gmac1;
>  		serial0 = &uart0;
>  		serial1 = &uart1;
> +		timer0 = &timer0;
> +		timer1 = &timer1;
> +		timer2 = &timer2;
> +		timer3 = &timer3;
>  	};
>  
>  	cpus {
> @@ -61,6 +66,21 @@
>  		interrupt-parent = <&intc>;
>  		ranges;
>  
> +		agpio0: gpio at 0xc0000000 {
> +			compatible = "altr,pio-1.0";
> +			/* Register base 0xff200000 is for a light-weight bridge */
> +			reg = <0xff200000 0x10>;
> +			width = <32>;
> +			/* There are 64 interrupts from the FPGA start at 72, so 45 has to be wrong */
> +			interrupts = <0 45 4>;
> +			interrupt-controller;
> +			#interrupt-cells = <1>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +			level_trigger = <0>;
> +		};
> +
> +
>  		amba {
>  			compatible = "arm,amba-bus";
>  			#address-cells = <1>;
> @@ -74,13 +94,62 @@
>  			};
>  		};
>  
> -		gmac0: stmmac at ff700000 {
> +		clkmgr at ffd04000 {
> +				compatible = "altr,clk-mgr";
> +				reg = <0xffd04000 0x1000>;
> +			};
> +
> +
> +		gmac0: ethernet at ff700000 {
>  			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
>  			reg = <0xff700000 0x2000>;
>  			interrupts = <0 115 4>;
>  			interrupt-names = "macirq";
>  			mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
> -			phy-mode = "gmii";
> +		};
> +
> +		gmac1: ethernet at ff702000 {
> +			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
> +			reg = <0xff702000 0x2000>;
> +			interrupts = <0 120 4>;
> +			interrupt-names = "macirq";
> +			mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
> +		};
> +
> +		gpio0: gpio at ff708000 {
> +			compatible = "snps,dw-gpio";
> +			reg = <0xff708000 0x1000>;
> +			interrupts = <0 164 4>;
> +			width = <29>;
> +			virtual_irq_start = <257>;
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpio1: gpio at ff709000 {
> +			compatible = "snps,dw-gpio";
> +			reg = <0xff709000 0x1000>;
> +			interrupts = <0 165 4>;
> +			width = <29>;
> +			virtual_irq_start = <286>;
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
> +		};
> +
> +		gpio2: gpio at ff70a000 {
> +			compatible = "snps,dw-gpio";
> +			reg = <0xff70a000 0x1000>;
> +			interrupts = <0 166 4>;
> +			width = <27>;
> +			virtual_irq_start = <315>;
> +			interrupt-controller;
> +			#interrupt-cells = <2>;
> +			gpio-controller;
> +			#gpio-cells = <2>;
>  		};
>  
>  		L2: l2-cache at fffef000 {
> @@ -89,6 +158,83 @@
>  			interrupts = <0 38 0x04>;
>  			cache-unified;
>  			cache-level = <2>;
> +			arm,tag-latency = <1 1 1>;
> +			arm,data-latency = <2 1 1>;
> +		};
> +
> +		mmc: dwmmc0 at ff704000 {
> +			compatible = "snps,dw-mshc";
> +			reg = <0xff704000 0x1000>;
> +			interrupts = <0 139 4>;
> +			bus-hz = <12500000>; /*12.5 MHz*/
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			num-slots = <1>;
> +			supports-highspeed;
> +			broken-cd;
> +			fifo-depth = <0x400>;
> +			slot at 0 {
> +				reg = <0>;
> +				bus-width = <4>;
> +			};
> +		};
> +
> +		nand: nand at ff900000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "denali,denali-nand-dt";
> +			reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
> +			reg-names = "nand_data", "denali_reg";
> +			interrupts = <0 144 4>;
> +			dma-mask = <0xffffffff>;
> +			};
> +
> +		rstmgr at ffd05000 {
> +			compatible = "altr,rst-mgr";
> +			reg = <0xffd05000 0x1000>;
> +		};
> +
> +		spi0: spi at fff00000 {
> +			compatible = "snps,dw-spi-mmio";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <0xfff00000 0x1000>;
> +			interrupts = <0 154 4>;
> +			num-chipselect = <4>;
> +			bus-num = <0>;
> +			tx-dma-channel = <&pdma 16>;
> +			rx-dma-channel = <&pdma 17>;
> +
> +			spidev at 0 {
> +				compatible = "spidev";
> +				reg = <0>;	/* chip select */
> +				spi-max-frequency = <100000000>;
> +				enable-dma = <1>;
> +			};
> +		};
> +
> +		spi1: spi at fff01000 {
> +			compatible = "snps,dw-spi-mmio";
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <0xfff01000 0x1000>;
> +			interrupts = <0 156 4>;
> +			num-chipselect = <4>;
> +			bus-num = <1>;
> +			tx-dma-channel = <&pdma 20>;
> +			rx-dma-channel = <&pdma 21>;
> +
> +			spidev at 0 {
> +				compatible = "spidev";
> +				reg = <0>;
> +				spi-max-frequency = <100000000>;
> +				enable-dma = <1>;
> +			};
> +		};
> +		
> +		sysmgr at ffd08000 {
> +			compatible = "altr,sys-mgr";
> +			reg = <0xffd08000 0x4000>;
>  		};
>  
>  		/* Local timer */
> @@ -98,60 +244,44 @@
>  			interrupts = <1 13 0xf04>;
>  		};
>  
> -		timer0: timer at ffc08000 {
> +		timer0: timer0 at ffc08000 {
>  			compatible = "snps,dw-apb-timer-sp";
>  			interrupts = <0 167 4>;
> -			clock-frequency = <200000000>;
>  			reg = <0xffc08000 0x1000>;
>  		};
>  
> -		timer1: timer at ffc09000 {
> +		timer1: timer1 at ffc09000 {
>  			compatible = "snps,dw-apb-timer-sp";
>  			interrupts = <0 168 4>;
> -			clock-frequency = <200000000>;
>  			reg = <0xffc09000 0x1000>;
>  		};
>  
> -		timer2: timer at ffd00000 {
> +		timer2: timer2 at ffd00000 {
>  			compatible = "snps,dw-apb-timer-osc";
>  			interrupts = <0 169 4>;
> -			clock-frequency = <200000000>;
>  			reg = <0xffd00000 0x1000>;
>  		};
>  
> -		timer3: timer at ffd01000 {
> +		timer3: timer3 at ffd01000 {
>  			compatible = "snps,dw-apb-timer-osc";
>  			interrupts = <0 170 4>;
> -			clock-frequency = <200000000>;
>  			reg = <0xffd01000 0x1000>;
>  		};
>  
> -		uart0: uart at ffc02000 {
> +		uart0: serial0 at ffc02000 {
>  			compatible = "snps,dw-apb-uart";
>  			reg = <0xffc02000 0x1000>;
> -			clock-frequency = <7372800>;
>  			interrupts = <0 162 4>;
>  			reg-shift = <2>;
>  			reg-io-width = <4>;
>  		};
>  
> -		uart1: uart at ffc03000 {
> +		uart1: serial1 at ffc03000 {
>  			compatible = "snps,dw-apb-uart";
>  			reg = <0xffc03000 0x1000>;
> -			clock-frequency = <7372800>;
>  			interrupts = <0 163 4>;
>  			reg-shift = <2>;
>  			reg-io-width = <4>;
>  		};
> -
> -		rstmgr at ffd05000 {
> -				compatible = "altr,rst-mgr";
> -				reg = <0xffd05000 0x1000>;
> -			};
> -
> -		sysmgr at ffd08000 {
> -				compatible = "altr,sys-mgr";
> -				reg = <0xffd08000 0x4000>;
> -			};
>  	};
>  };
> diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dts
> index ab7e4a9..d29addc 100644
> --- a/arch/arm/boot/dts/socfpga_cyclone5.dts
> +++ b/arch/arm/boot/dts/socfpga_cyclone5.dts
> @@ -26,9 +26,169 @@
>  		bootargs = "console=ttyS0,57600";
>  	};
>  
> -	memory {
> -		name = "memory";
> -		device_type = "memory";
> -		reg = <0x0 0x10000000>; /* 256MB */
> +	aliases {
> +		/* this allow the ethaddr uboot environmnet variable contents
> +		 * to be added to the gmac1 device tree blob.
> +		 */
> +		ethernet0 = &gmac1;
> +	};
> +
> +	soc {
> +		ethernet at ff700000 {
> +			status = "disabled";
> +		};
> +
> +		ethernet at ff702000 {
> +			phy-mode = "rgmii";
> +			phy-addr = <0xffffffff>; /* probe for phy addr */
> +		};
> +
> +		qspi: spi at ff705000 {
> +				compatible = "cadence,qspi";
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				reg = <0xff705000 0x1000>,
> +					<0xffa00000 0x1000>;
> +				interrupts = <0 151 4>;
> +				master-ref-clk = <400000000>;
> +				ext-decoder = <0>;  /* external decoder */
> +				num-chipselect = <4>;
> +				fifo-depth = <128>;
> +				bus-num = <2>;
> +
> +				flash0: n25q128 at 0 {
> +					#address-cells = <1>;
> +					#size-cells = <1>;
> +					compatible = "n25q128";
> +					reg = <0>;	/* chip select */
> +					spi-max-frequency = <100000000>;
> +					page-size = <256>;
> +					block-size = <16>; /* 2^16, 64KB */
> +					quad = <1>;	   /* 1-support quad */
> +					tshsl-ns = <200>;
> +					tsd2d-ns = <255>;
> +					tchsh-ns = <20>;
> +					tslch-ns = <20>;
> +
> +					partition at 0 {
> +						/* 8MB for raw data. */
> +						label = "Flash 0 Raw Data";
> +						reg = <0x0 0x800000>;
> +					};
> +					partition at 800000 {
> +						/* 8MB for jffs2 data. */
> +						label = "Flash 0 jffs2 Filesystem";
> +						reg = <0x800000 0x800000>;
> +					};
> +				};
> +
> +				flash1: n25q128 at 1 {
> +					#address-cells = <1>;
> +					#size-cells = <1>;
> +					compatible = "n25q128";
> +					reg = <1>;	/* chip select */
> +					spi-max-frequency = <100000000>;
> +					page-size = <256>;
> +					block-size = <16>; /* 2^16, 64KB */
> +					quad = <1>;
> +					tshsl-ns = <200>;
> +					tsd2d-ns = <255>;
> +					tchsh-ns = <20>;
> +					tslch-ns = <20>;
> +
> +					partition at 0 {
> +						/* 16MB for user data. */
> +						label = "Flash 1 User Data";
> +						reg = <0x0 0x1000000>;
> +					};
> +				};
> +			};
> +
> +		timer0 at ffc08000 {
> +			clock-frequency = <100000000>;
> +		};
> +
> +		timer1 at ffc09000 {
> +			clock-frequency = <100000000>;
> +		};
> +
> +		timer2 at ffd00000 {
> +			clock-frequency = <25000000>;
> +		};
> +
> +		timer3 at ffd01000 {
> +			clock-frequency = <25000000>;
> +		};
> +
> +		serial0 at ffc02000 {
> +			clock-frequency = <100000000>;
> +		};
> +
> +		serial1 at ffc03000 {
> +			clock-frequency = <100000000>;
> +		};
> +
> +		i2c0: i2c at ffc04000 {
> +			speed-mode = <0>;
> +		};
> +
> +		leds {
> +			compatible = "gpio-leds";
> +			fpga0 {
> +				label = "fpga_led0";
> +				gpios = <&agpio0 0 1>;
> +			};
> +
> +			fpga1 {
> +				label = "fpga_led1";
> +				gpios = <&agpio0 1 1>;
> +			};
> +
> +			fpga2 {
> +				label = "fpga_led2";
> +				gpios = <&agpio0 2 1>;
> +			};
> +
> +			fpga3 {
> +				label = "fpga_led3";
> +				gpios = <&agpio0 3 1>;
> +			};
> +
> +			hps0 {
> +				label = "hps_led0";
> +				gpios = <&gpio1 15 1>;
> +			};
> +
> +			hps1 {
> +				label = "hps_led1";
> +				gpios = <&gpio1 14 1>;
> +			};
> +
> +			hps2 {
> +				label = "hps_led2";
> +				gpios = <&gpio1 13 1>;
> +			};
> +
> +			hps3 {
> +				label = "hps_led3";
> +				gpios = <&gpio1 12 1>;
> +			};
> +		};
> +	};
> +};
> +
> +&i2c0 {
> +	lcd: lcd at 28 {
> +		compatible = "newhaven,nhd-0216k3z-nsw-bbw";
> +		reg = <0x28>;
> +		height = <2>;
> +		width = <16>;
> +		brightness = <8>;
> +	};
> +
> +	eeprom at 51 {
> +		compatible = "atmel,24c32";
> +		reg = <0x51>;
> +		pagesize = <32>;
>  	};
>  };
> diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h
> index 9941caa..e297307 100644
> --- a/arch/arm/mach-socfpga/core.h
> +++ b/arch/arm/mach-socfpga/core.h
> @@ -24,11 +24,34 @@ extern void secondary_startup(void);
>  extern void __iomem *socfpga_scu_base_addr;
>  
>  extern void socfpga_init_clocks(void);
> -extern void socfpga_sysmgr_init(void);
> +//extern void socfpga_sysmgr_init(void);
>  
>  extern struct smp_operations socfpga_smp_ops;
>  extern char secondary_trampoline, secondary_trampoline_end;
>  
>  #define SOCFPGA_SCU_VIRT_BASE   0xfffec000
>  
> +
> +#define SOCFPGA_RSTMGR_CTRL	0x04
> +#define SOCFPGA_RSTMGR_MODPERRST	0x14
> +#define SOCFPGA_RSTMGR_BRGMODRST	0x1c
> +
> +/* System Manager bits */
> +#define RSTMGR_CTRL_SWCOLDRSTREQ	0x1	/* Cold Reset */
> +#define RSTMGR_CTRL_SWWARMRSTREQ	0x2	/* Warm Reset */
> +/*MPU Module Reset Register */
> + #define RSTMGR_MPUMODRST_CPU0	0x1	/*CPU0 Reset*/
> + #define RSTMGR_MPUMODRST_CPU1	0x2	/*CPU1 Reset*/
> + #define RSTMGR_MPUMODRST_WDS		0x4	/*Watchdog Reset*/
> + #define RSTMGR_MPUMODRST_SCUPER	0x8	/*SCU and periphs reset*/
> + #define RSTMGR_MPUMODRST_L2		0x10	/*L2 Cache reset*/
> +
> +#define SYSMGR_EMACGRP_CTRL_OFFSET 0x60
> +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
> +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
> +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
> +#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2
> +
> +#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
> +
>  #endif
> diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
> index 6732924..4d41642 100644
> --- a/arch/arm/mach-socfpga/socfpga.c
> +++ b/arch/arm/mach-socfpga/socfpga.c
> @@ -17,12 +17,19 @@
>  #include <linux/dw_apb_timer.h>
>  #include <linux/of_address.h>
>  #include <linux/of_irq.h>
> +#include <linux/of_address.h>
>  #include <linux/of_platform.h>
> +#include <linux/of_net.h>
> +#include <linux/stmmac.h>
> +#include <linux/phy.h>
> +#include <linux/micrel_phy.h>
> +
>  
>  #include <asm/hardware/cache-l2x0.h>
>  #include <asm/hardware/gic.h>
>  #include <asm/mach/arch.h>
>  #include <asm/mach/map.h>
> +#include <asm/smp_twd.h>
>  
>  #include "core.h"
>  
> @@ -30,6 +37,29 @@ void __iomem *socfpga_scu_base_addr = ((void __iomem *)(SOCFPGA_SCU_VIRT_BASE));
>  void __iomem *sys_manager_base_addr;
>  void __iomem *rst_manager_base_addr;
>  
> +static int socfpga_phy_reset_mii(struct mii_bus *bus, int phyaddr);
> +static int stmmac_plat_init(struct platform_device *pdev);
> +
> +static struct stmmac_mdio_bus_data stmmacenet_mdio_bus_data = {
> +	.phy_reset_mii = socfpga_phy_reset_mii,
> +};
> +
> +static struct plat_stmmacenet_data stmmacenet0_data = {
> +	.mdio_bus_data = &stmmacenet_mdio_bus_data,
> +	.init = &stmmac_plat_init,
> +};
> +
> +static struct plat_stmmacenet_data stmmacenet1_data = {
> +	.mdio_bus_data = &stmmacenet_mdio_bus_data,
> +	.init = &stmmac_plat_init,
> +};
> +
> +static const struct of_dev_auxdata socfpga_auxdata_lookup[] __initconst = {
> +	OF_DEV_AUXDATA("snps,dwmac-3.70a", 0xff700000, NULL, &stmmacenet0_data),
> +	OF_DEV_AUXDATA("snps,dwmac-3.70a", 0xff702000, NULL, &stmmacenet1_data),
> +	{ /* sentinel */ }
> +};
> + 
>  static struct map_desc scu_io_desc __initdata = {
>  	.virtual	= SOCFPGA_SCU_VIRT_BASE,
>  	.pfn		= 0, /* run-time */
> @@ -55,19 +85,126 @@ static void __init socfpga_scu_map_io(void)
>  	iotable_init(&scu_io_desc, 1);
>  }
>  
> -static void __init socfpga_map_io(void)
> +static void __init enable_periphs(void)
>  {
> -	socfpga_scu_map_io();
> -	iotable_init(&uart_io_desc, 1);
> -	early_printk("Early printk initialized\n");
> +	/* Release all peripherals from reset.*/
> +	__raw_writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_MODPERRST);
> +
> +	/* Release all FPGA bridges from reset.*/
> +	__raw_writel(0, rst_manager_base_addr + SOCFPGA_RSTMGR_BRGMODRST);
>  }
>  
> -const static struct of_device_id irq_match[] = {
> -	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> -	{}
> -};
> +static int stmmac_mdio_write_null(struct mii_bus *bus, int phyaddr, int phyreg,
> +			     u16 phydata)
> +{
> +	return 0;
> +}
> +
> +#define MICREL_KSZ9021_EXTREG_CTRL 11
> +#define MICREL_KSZ9021_EXTREG_DATA_WRITE 12
> +#define MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW 260
> +#define MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW 261
>  
> -void __init socfpga_sysmgr_init(void)
> +static int stmmac_emdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
> +			     u16 phydata)
> +{
> +	int ret = (bus->write)(bus, phyaddr,
> +		MICREL_KSZ9021_EXTREG_CTRL, 0x8000|phyreg);
> +	if (ret) {
> +		pr_warn("stmmac_emdio_write write1 failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	ret = (bus->write)(bus, phyaddr,
> +		MICREL_KSZ9021_EXTREG_DATA_WRITE, phydata);
> +	if (ret) {
> +		pr_warn("stmmac_emdio_write write2 failed %d\n", ret);
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
> +static int socfpga_phy_reset_mii(struct mii_bus *bus, int phyaddr)
> +{
> +	struct phy_device *phydev;
> +
> +	if (of_machine_is_compatible("altr,socfpga-vt"))
> +		return 0;
> +
> +	phydev = bus->phy_map[phyaddr];
> +
> +	if (NULL == phydev) {
> +		pr_err("%s no phydev found\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	if (PHY_ID_KSZ9021RLRN != phydev->phy_id) {
> +		pr_err("%s unexpected PHY ID %08x\n", __func__, phydev->phy_id);
> +		return -EINVAL;
> +	}
> +
> +	pr_info("%s writing extended registers to phyaddr %d\n",
> +		__func__, phyaddr);
> +
> +	/* add 2 ns of RXC PAD Skew and 2.6 ns of TXC PAD Skew */
> +	stmmac_emdio_write(bus, phyaddr,
> +		MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW, 0xa0d0);
> +
> +	/* set no PAD skew for data */
> +	stmmac_emdio_write(bus, phyaddr,
> +		MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW, 0x0000);
> +
> +	bus->write = &stmmac_mdio_write_null;
> +	return 0;
> +}
> +
> +static int stmmac_plat_init(struct platform_device *pdev)
> +{
> +	u32 ctrl, val, shift;
> +	int phymode;
> +
> +	if (of_machine_is_compatible("altr,socfpga-vt"))
> +		return 0;
> +
> +	phymode = of_get_phy_mode(pdev->dev.of_node);
> +
> +	switch (phymode) {
> +	case PHY_INTERFACE_MODE_RGMII:
> +		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
> +		break;
> +	case PHY_INTERFACE_MODE_MII:
> +	case PHY_INTERFACE_MODE_GMII:
> +		val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
> +		break;
> +	default:
> +		pr_err("%s bad phy mode %d", __func__, phymode);
> +		return -EINVAL;
> +	}
> +
> +	if (&stmmacenet1_data == pdev->dev.platform_data)
> +		shift = SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH;
> +	else if (&stmmacenet0_data == pdev->dev.platform_data)
> +		shift = 0;
> +	else {
> +		pr_err("%s unexpected platform data pointer\n", __func__);
> +		return -EINVAL;
> +	}
> +
> +	ctrl =  __raw_readl(sys_manager_base_addr +
> +		SYSMGR_EMACGRP_CTRL_OFFSET);
> +
> +	ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << shift);
> +
> +	ctrl |= (val << shift);
> +
> +	__raw_writel(ctrl, (sys_manager_base_addr +
> +		SYSMGR_EMACGRP_CTRL_OFFSET));
> +
> +	return 0;
> +}
> +
> +static void __init socfpga_sysmgr_init(void)
>  {
>  	struct device_node *np;
>  
> @@ -78,27 +215,58 @@ void __init socfpga_sysmgr_init(void)
>  	rst_manager_base_addr = of_iomap(np, 0);
>  }
>  
> +static void __init socfpga_map_io(void)
> +{
> +	socfpga_scu_map_io();
> +	iotable_init(&uart_io_desc, 1);
> +	early_printk("Early printk initialized\n");
> +}
> +
> +const static struct of_device_id irq_match[] = {
> +	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
> +	{}
> +};
> +
>  static void __init gic_init_irq(void)
>  {
>  	of_irq_init(irq_match);
>  	socfpga_sysmgr_init();
> +	socfpga_init_clocks();
> +	twd_local_timer_of_register();
>  }
>  
>  static void socfpga_cyclone5_restart(char mode, const char *cmd)
>  {
> -	/* TODO: */
> +	u32 temp;
> +
> +	temp = __raw_readl(rst_manager_base_addr + SOCFPGA_RSTMGR_CTRL);
> +
> +	if (mode == 'h')
> +		temp |= RSTMGR_CTRL_SWCOLDRSTREQ;
> +	else
> +		temp |= RSTMGR_CTRL_SWWARMRSTREQ;
> +	__raw_writel(temp, rst_manager_base_addr + SOCFPGA_RSTMGR_CTRL);
>  }
>  
>  static void __init socfpga_cyclone5_init(void)
>  {
> -	l2x0_of_init(0, ~0UL);
> -	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> -	socfpga_init_clocks();
> +#ifdef CONFIG_CACHE_L2X0
> +	u32 aux_ctrl = 0;
> +	aux_ctrl |= (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
> +			(1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT);
> +	l2x0_of_init(aux_ctrl, ~0UL);
> +#endif
> +	of_platform_populate(NULL, of_default_bus_match_table,
> +		socfpga_auxdata_lookup, NULL);
> +
> +	enable_periphs();
>  }
>  
>  static const char *altera_dt_match[] = {
>  	"altr,socfpga",
>  	"altr,socfpga-cyclone5",
> +	"altr,socfpga-vt",
> +	"altr,socfpga-ice",
>  	NULL
>  };
>  
> diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
> index 2c855a6..30c76c4 100644
> --- a/drivers/clk/socfpga/clk.c
> +++ b/drivers/clk/socfpga/clk.c
> @@ -17,6 +17,11 @@
>  #include <linux/clk.h>
>  #include <linux/clkdev.h>
>  #include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +static DEFINE_SPINLOCK(_lock);
>  
>  #define SOCFPGA_OSC1_CLK	10000000
>  #define SOCFPGA_MPU_CLK		800000000
> @@ -24,28 +29,124 @@
>  #define SOCFPGA_MAIN_NAND_SDMMC_CLK	250000000
>  #define SOCFPGA_S2F_USR_CLK		125000000
>  
> +#define SOCFPGA_MAIN_PLL_CLK		1200000000
> +#define SOCFPGA_PER_PLL_CLK		900000000
> +#define SOCFPGA_SDRAM_PLL_CLK		800000000
> +
> +#define CLKMGR_PERPLLGRP_EN	0xA0
> +
> +#define CLKMGR_QSPI_CLK_EN				11
> +#define CLKMGR_NAND_CLK_EN				10
> +#define CLKMGR_NAND_X_CLK_EN			9
> +#define CLKMGR_SDMMC_CLK_EN			8
> +#define CLKMGR_S2FUSR_CLK_EN			7
> +#define CLKMGR_GPIO_CLK_EN				6
> +#define CLKMGR_CAN1_CLK_EN				5
> +#define CLKMGR_CAN0_CLK_EN				4
> +#define CLKMGR_SPI_M_CLK_EN			3
> +#define CLKMGR_USB_MP_CLK_EN			2
> +#define CLKMGR_EMAC1_CLK_EN			1
> +#define CLKMGR_EMAC0_CLK_EN			0
> +
> +void __iomem *clk_mgr_base_addr;
> +
>  void __init socfpga_init_clocks(void)
>  {
>  	struct clk *clk;
> +	struct device_node *np;
>  
> -	clk = clk_register_fixed_rate(NULL, "osc1_clk", NULL, CLK_IS_ROOT, SOCFPGA_OSC1_CLK);
> +	np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
> +	clk_mgr_base_addr = of_iomap(np, 0);
> +
> +	clk = clk_register_fixed_rate(NULL, "main_pll_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MAIN_PLL_CLK);
> +	clk_register_clkdev(clk, "main_pll_clk", NULL);
> +
> +	clk = clk_register_fixed_rate(NULL, "per_pll_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_PER_PLL_CLK);
> +	clk_register_clkdev(clk, "per_pll_clk", NULL);
> +
> +	clk = clk_register_fixed_rate(NULL, "sdram_pll_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_SDRAM_PLL_CLK);
> +	clk_register_clkdev(clk, "sdram_pll_clk", NULL);
> +
> +	clk = clk_register_fixed_rate(NULL, "osc1_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_OSC1_CLK);
>  	clk_register_clkdev(clk, "osc1_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "mpu_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK);
> +	clk = clk_register_fixed_rate(NULL, "mpu_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MPU_CLK);
>  	clk_register_clkdev(clk, "mpu_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "main_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
> +	clk = clk_register_fixed_rate(NULL, "main_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MPU_CLK/2);
>  	clk_register_clkdev(clk, "main_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "dbg_base_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
> +	clk = clk_register_fixed_rate(NULL, "dbg_base_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MPU_CLK/2);
>  	clk_register_clkdev(clk, "dbg_base_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "main_qspi_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_QSPI_CLK);
> +	clk = clk_register_fixed_rate(NULL, "smp_twd", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MPU_CLK/4);
> +	clk_register_clkdev(clk, NULL, "smp_twd");
> +
> +	clk = clk_register_fixed_rate(NULL, "main_qspi_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_MAIN_QSPI_CLK);
>  	clk_register_clkdev(clk, "main_qspi_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "main_nand_sdmmc_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_NAND_SDMMC_CLK);
> +	clk = clk_register_fixed_rate(NULL, "main_nand_sdmmc_clk", NULL,
> +			CLK_IS_ROOT, SOCFPGA_MAIN_NAND_SDMMC_CLK);
>  	clk_register_clkdev(clk, "main_nand_sdmmc_clk", NULL);
>  
> -	clk = clk_register_fixed_rate(NULL, "s2f_usr_clk", NULL, CLK_IS_ROOT, SOCFPGA_S2F_USR_CLK);
> +	clk = clk_register_fixed_rate(NULL, "s2f_usr_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_S2F_USR_CLK);
>  	clk_register_clkdev(clk, "s2f_usr_clk", NULL);
> +
> +	clk = clk_register_fixed_rate(NULL, "i2c0_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_PER_PLL_CLK);
> +	clk_register_clkdev(clk, NULL, "ffc04000.i2c");
> +
> +	clk = clk_register_fixed_rate(NULL, "i2c1_clk", NULL, CLK_IS_ROOT,
> +			SOCFPGA_PER_PLL_CLK);
> +	clk_register_clkdev(clk, NULL, "ffc05000.i2c");
> +
> +	clk = clk_register_gate(NULL, "gmac0_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_EMAC0_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff700000.ethernet");
> +
> +	clk = clk_register_gate(NULL, "gmac1_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_EMAC1_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff702000.ethernet");
> +
> +	clk = clk_register_gate(NULL, "spi0_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_SPI_M_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "fff00000.spi");
> +
> +	clk = clk_register_gate(NULL, "spi1_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_SPI_M_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "fff01000.spi");
> +
> +	clk = clk_register_gate(NULL, "gpio0_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_GPIO_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff708000.gpio");
> +
> +	clk = clk_register_gate(NULL, "gpio1_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_GPIO_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff709000.gpio");
> +
> +	clk = clk_register_gate(NULL, "gpio2_clk", "per_pll_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_GPIO_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff70a000.gpio");
> +
> +	clk = clk_register_gate(NULL, "nand_clk", "main_nand_sdmmc_clk", 0,
> +			clk_mgr_base_addr + CLKMGR_PERPLLGRP_EN,
> +			CLKMGR_NAND_CLK_EN, 0, &_lock);
> +	clk_register_clkdev(clk, NULL, "ff900000.nand");
>  }
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 323c502..c199847 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -38,9 +38,14 @@
>  #include "dw_mmc.h"
>  
>  /* Common flag combinations */
> -#define DW_MCI_DATA_ERROR_FLAGS	(SDMMC_INT_DTO | SDMMC_INT_DCRC | \
> -				 SDMMC_INT_HTO | SDMMC_INT_SBE  | \
> -				 SDMMC_INT_EBE)
> +
> +/* According to Synopsys, the data starvation interrupt (HTO) should not treat
> + * as error. Software should continue the data transfer. We have verified this
> + * in Virtual Target. The same is applied to FIFO under/overrun (FRUN) as well.
> + */
> +#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \
> +				 SDMMC_INT_HTO | SDMMC_INT_FRUN | SDMMC_INT_SBE | SDMMC_INT_EBE)
> +
>  #define DW_MCI_CMD_ERROR_FLAGS	(SDMMC_INT_RTO | SDMMC_INT_RCRC | \
>  				 SDMMC_INT_RESP_ERR)
>  #define DW_MCI_ERROR_FLAGS	(DW_MCI_DATA_ERROR_FLAGS | \
> @@ -265,6 +270,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>  	if (drv_data && drv_data->prepare_command)
>  		drv_data->prepare_command(slot->host, &cmdr);
>  
> +	if (slot->host->use_hold_reg)
> +		cmdr |= SDMMC_CMD_USE_HOLD_REG;
> +
>  	return cmdr;
>  }
>  
> @@ -2047,6 +2055,16 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
> +	if (of_property_read_u32(dev->of_node, "bus-hz", &pdata->bus_hz)) {
> +		dev_err(dev, "couldn't determine bus-hz\n");
> +		pdata->bus_hz = 50000000;
> +	}
> +
> +	if (of_property_read_u32(dev->of_node, "pwr-en", &pdata->pwr_en)) {
> +		dev_info(dev, "couldn't determine pwr-en, assuming pwr-en = 0\n");
> +		pdata->pwr_en = 0;
> +	}
> +
>  	/* find out number of slots supported */
>  	if (of_property_read_u32(dev->of_node, "num-slots",
>  				&pdata->num_slots)) {
> @@ -2183,6 +2201,9 @@ int dw_mci_probe(struct dw_mci *host)
>  		host->data_shift = 2;
>  	}
>  
> +	/* Get the USE_HOLD_REG */
> +	host->use_hold_reg = mci_readl(host, CMD) & SDMMC_CMD_USE_HOLD_REG;
> +
>  	/* Reset all blocks */
>  	if (!mci_wait_reset(host->dev, host))
>  		return -ENODEV;
> @@ -2194,6 +2215,9 @@ int dw_mci_probe(struct dw_mci *host)
>  	mci_writel(host, RINTSTS, 0xFFFFFFFF);
>  	mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
>  
> +	/* Set PWREN bit */
> +	mci_writel(host, PWREN, host->pdata->pwr_en);
> +
>  	/* Put in max timeout */
>  	mci_writel(host, TMOUT, 0xFFFFFFFF);
>  
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 53b8fd9..6172900 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -111,6 +111,7 @@
>  #define SDMMC_INT_ERROR			0xbfc2
>  /* Command register defines */
>  #define SDMMC_CMD_START			BIT(31)
> +#define SDMMC_CMD_USE_HOLD_REG		BIT(29)
>  #define SDMMC_CMD_CCS_EXP		BIT(23)
>  #define SDMMC_CMD_CEATA_RD		BIT(22)
>  #define SDMMC_CMD_UPD_CLK		BIT(21)
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> index 7ad56af..03846dc 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
> @@ -228,6 +228,9 @@ enum rtc_control {
>  #define GMAC_MMC_CTRL      0x100
>  #define GMAC_MMC_RX_INTR   0x104
>  #define GMAC_MMC_TX_INTR   0x108
> +#define GMAC_MMC_INTR_MASK_RX		  0x10C
> +#define GMAC_MMC_INTR_MASK_TX		  0x110
> +#define GMAC_MMC_IPC_INTR_MASK_RX  0x200
>  #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
>  
>  extern const struct stmmac_dma_ops dwmac1000_dma_ops;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> index bfe0226..ade7bfb 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
> @@ -40,6 +40,11 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
>  	/* Mask GMAC interrupts */
>  	writel(0x207, ioaddr + GMAC_INT_MASK);
>  
> +	/* mask out interrupts because we don't handle them yet */
> +	writel(~0UL, ioaddr + GMAC_MMC_INTR_MASK_RX);
> +	writel(~0UL, ioaddr + GMAC_MMC_INTR_MASK_TX);
> +	writel(~0UL, ioaddr + GMAC_MMC_IPC_INTR_MASK_RX);
> +
>  #ifdef STMMAC_VLAN_TAG_USED
>  	/* Tag detection without filtering */
>  	writel(0x0, ioaddr + GMAC_VLAN_TAG);
> @@ -198,6 +203,7 @@ static int dwmac1000_irq_status(void __iomem *ioaddr)
>  {
>  	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
>  	int status = 0;
> +	u32 value;
>  
>  	/* Not used events (e.g. MMC interrupts) are not handled. */
>  	if ((intr_status & mmc_tx_irq)) {
> @@ -222,6 +228,11 @@ static int dwmac1000_irq_status(void __iomem *ioaddr)
>  		readl(ioaddr + GMAC_PMT);
>  		status |= core_irq_receive_pmt_irq;
>  	}
> +	if (unlikely(intr_status & rgmii_irq)) {
> +		CHIP_DBG(KERN_INFO "GMAC: Interrupt Status\n");
> +		/* clear this link change interrupt because we are not handling it yet. */
> +		value = readl(ioaddr + GMAC_GMII_STATUS);
> +	}
>  	/* MAC trx/rx EEE LPI entry/exit interrupts */
>  	if (intr_status & lpiis_irq) {
>  		/* Clean LPI interrupt by reading the Reg 12 */
> diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> index 2fc8ef9..6996b2e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c
> @@ -145,7 +145,11 @@ static int enh_desc_coe_rdes0(int ipc_err, int type, int payload_err)
>  		ret = discard_frame;
>  	} else if (status == 0x3) {
>  		CHIP_DBG(KERN_ERR "RX Des0 status: No IPv4, IPv6 frame.\n");
> +#ifdef CONFIG_ARCH_SOCFPGA
> +		ret = csum_none;
> +#else
>  		ret = discard_frame;
> +#endif
>  	}
>  	return ret;
>  }
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> index 0b9829f..294060e 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
> @@ -242,6 +242,11 @@ int stmmac_mdio_register(struct net_device *ndev)
>  		return -ENODEV;
>  	}
>  
> +	if (priv->plat->mdio_bus_data->phy_reset_mii) {
> +		priv->plat->mdio_bus_data->phy_reset_mii(new_bus,
> +			priv->plat->phy_addr);
> +	}
> +
>  	priv->mii = new_bus;
>  
>  	return 0;
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> index b43d68b..e7b455a 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
> @@ -34,15 +34,18 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
>  				  const char **mac)
>  {
>  	struct device_node *np = pdev->dev.of_node;
> +	u32 phyaddr;
>  
>  	if (!np)
>  		return -ENODEV;
>  
>  	*mac = of_get_mac_address(np);
>  	plat->interface = of_get_phy_mode(np);
> -	plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
> +	if (NULL == plat->mdio_bus_data) {
> +		plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
>  					   sizeof(struct stmmac_mdio_bus_data),
>  					   GFP_KERNEL);
> +	}
>  
>  	/*
>  	 * Currently only the properties needed on SPEAr600
> @@ -56,6 +59,17 @@ static int stmmac_probe_config_dt(struct platform_device *pdev,
>  		plat->pmt = 1;
>  	}
>  
> +	if (0 == of_property_read_u32(np, "phy-addr", &phyaddr)) {
> +		if ((-1 == phyaddr) ||
> +			((phyaddr >= 0) && (phyaddr < PHY_MAX_ADDR))) {
> +			plat->phy_addr = phyaddr;
> +		} else {
> +			pr_err("%s: ERROR: bad phy address: %d\n",
> +				__func__, phyaddr);
> +			return -EINVAL;
> +		}
> +	}
> +
>  	return 0;
>  }
>  #else
> @@ -94,10 +108,14 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
>  		return -ENOMEM;
>  	}
>  
> +	plat_dat = pdev->dev.platform_data;
> +
>  	if (pdev->dev.of_node) {
> -		plat_dat = devm_kzalloc(&pdev->dev,
> +		if (NULL == plat_dat) {
> +			plat_dat = devm_kzalloc(&pdev->dev,
>  					sizeof(struct plat_stmmacenet_data),
>  					GFP_KERNEL);
> +		}
>  		if (!plat_dat) {
>  			pr_err("%s: ERROR: no memory", __func__);
>  			return  -ENOMEM;
> @@ -108,8 +126,6 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
>  			pr_err("%s: main dt probe failed", __func__);
>  			return ret;
>  		}
> -	} else {
> -		plat_dat = pdev->dev.platform_data;
>  	}
>  
>  	/* Custom initialisation (if needed)*/
> diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
> index adfe8c0..f699596 100644
> --- a/include/linux/micrel_phy.h
> +++ b/include/linux/micrel_phy.h
> @@ -17,6 +17,7 @@
>  
>  #define PHY_ID_KSZ8873MLL	0x000e7237
>  #define PHY_ID_KSZ9021		0x00221610
> +#define PHY_ID_KSZ9021RLRN	0x00221611
>  #define PHY_ID_KS8737		0x00221720
>  #define PHY_ID_KSZ8021		0x00221555
>  #define PHY_ID_KSZ8041		0x00221510
> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> index 34be4f4..cf22d32 100644
> --- a/include/linux/mmc/dw_mmc.h
> +++ b/include/linux/mmc/dw_mmc.h
> @@ -187,6 +187,11 @@ struct dw_mci {
>  	struct regulator	*vmmc;	/* Power regulator */
>  	unsigned long		irq_flags; /* IRQ flags */
>  	int			irq;
> +
> +	/* Set to one for SDR12 and SDR25 */
> +	unsigned int use_hold_reg;
> +	/*Card needs power enable bit */
> +	u32 pwr_en;
>  };
>  
>  /* DMA ops for Internal/External DMAC interface */
> @@ -228,6 +233,8 @@ struct dw_mci_board {
>  
>  	u32 quirks; /* Workaround / Quirk flags */
>  	unsigned int bus_hz; /* Clock speed at the cclk_in pad */
> +	/*Card needs power enable bit */
> +	u32 pwr_en;
>  
>  	u32 caps;	/* Capabilities */
>  	u32 caps2;	/* More capabilities */
> diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
> index c1b3ed3..3666be2 100644
> --- a/include/linux/stmmac.h
> +++ b/include/linux/stmmac.h
> @@ -27,6 +27,8 @@
>  #define __STMMAC_PLATFORM_DATA
>  
>  #include <linux/platform_device.h>
> +#include <linux/mii.h>
> +#include <linux/phy.h>
>  
>  #define STMMAC_RX_COE_NONE	0
>  #define STMMAC_RX_COE_TYPE1	1
> @@ -77,6 +79,7 @@
>  
>  struct stmmac_mdio_bus_data {
>  	int (*phy_reset)(void *priv);
> +	int (*phy_reset_mii)(struct mii_bus *bus, int phyaddr);
>  	unsigned int phy_mask;
>  	int *irqs;
>  	int probed_phy_irq;
> 






More information about the linux-arm-kernel mailing list