This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359: AM3359 Eth1 is not working on Uboot

Part Number: AM3359

Tool/software:

Hi

I’m currently working with U-Boot (u-boot-2019.01+gitAUTOINC+333c3e72d3-g333c3e72d3) on AM3359 board, and I’m encountering an issue where the ethernet1 interface is not functioning as expected.

I am attaching the DTS snippet and using the CPSW driver . 

Note : When i am connecting eth1 and eth2 , only in that case ping is successful. but i required eth1 to be working independently. 

Pls suggest for Eth1 !!!

in uboot/arch/arm/dts/am33xx.dtsi

mac: ethernet@4a100000 {
compatible = "ti,cpsw";
ti,hwmods = "cpgmac0";
clocks = <&cpsw_125mhz_gclk>, <&cpsw_cpts_rft_clk>;
clock-names = "fck", "cpts";
cpdma_channels = <8>;
ale_entries = <1024>;
bd_ram_size = <0x2000>;
no_bd_ram = <0>;
rx_descs = <64>;
mac_control = <0x20>;
//slaves = <2>;
slaves = <1>;
active_slave = <0>;
cpts_clock_mult = <0x80000000>;
cpts_clock_shift = <29>;
reg = <0x4a100000 0x800
0x4a101200 0x100>;
#address-cells = <1>;
#size-cells = <1>;
/*
* c0_rx_thresh_pend
* c0_rx_pend
* c0_tx_pend
* c0_misc_pend
*/
interrupts = <40 41 42 43>;
ranges;
syscon = <&scm_conf>;
status = "disabled";

davinci_mdio: mdio@4a101000 {
compatible = "ti,davinci_mdio";
#address-cells = <1>;
#size-cells = <0>;
ti,hwmods = "davinci_mdio";
bus_freq = <1000000>;

reg = <0x4a101000 0x100>;
status = "disabled";
};

cpsw_emac0: slave@4a100200 {
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};

cpsw_emac1: slave@4a100300 {
/* Filled in by U-Boot */
mac-address = [ 00 00 00 00 00 00 ];
};

phy_sel: cpsw-phy-sel@44e10650 {
compatible = "ti,am3352-cpsw-phy-sel";
reg= <0x44e10650 0x4>;
reg-names = "gmii-sel";
};
};

in u-boot/arch/arm/dts/am335x-icev2.dts

&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
slaves = <2>;
active_slave = <1>; //added
dual_emac; //commented
status = "okay";
};

&davinci_mdio {
pinctrl-names = "default", "sleep";
compatible = "ti,cpsw-mdio","ti,davinci_mdio";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
reset-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
//reset-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>, <&gpio3 21 GPIO_ACTIVE_HIGH>;
//reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
reset-delay-us = <2>;

};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <1>;
};

&cpsw_emac1 {
phy_id = <&davinci_mdio>, <3>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
};

in uboot/board/ti/am335x/board.c

static struct cpsw_slave_data cpsw_slaves[] = {
{
.slave_reg_ofs = 0x208,
.sliver_reg_ofs = 0xd80,
.phy_addr = 0,
.phy_if = PHY_INTERFACE_MODE_RGMII,
},
{
.slave_reg_ofs = 0x308,
.sliver_reg_ofs = 0xdc0,
.phy_addr = 3,
.phy_if = PHY_INTERFACE_MODE_RGMII,
},
};

static struct cpsw_platform_data cpsw_data = {
.mdio_base = CPSW_MDIO_BASE,
.cpsw_base = CPSW_BASE,
.mdio_div = 0xff,
.channels = 8,
.cpdma_reg_ofs = 0x800,
.slaves = 1, //LFT
.slave_data = cpsw_slaves,
.ale_reg_ofs = 0xd00,
.ale_entries = 1024,
.host_port_reg_ofs = 0x108,
.hw_stats_reg_ofs = 0x900,
.bd_ram_ofs = 0x2000,
.mac_control = (1 << 5),
.control = cpsw_control,
.host_port_num = 0,
.version = CPSW_CTRL_VERSION_2,
};

cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */

AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
/*AM33XX_IOPAD(0xA34, PIN_INPUT_PULLUP | MUX_MODE7) /* (F15) USB1_DRVVBUS.gpio3[13] */

/*pinmux for max24288*/
AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
>;
};

cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J16) gmii1_txen.rgmii1_tctl */
AM33XX_IOPAD(0x918, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J17) gmii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x92c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K18) gmii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x930, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L18) gmii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K17) gmii1_txd0.rgmii1_td0 */
AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K16) gmii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x920, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K15) gmii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x91c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J18) gmii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (M16) gmii1_rxd0.rgmii1_rd0 */
AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L15) gmii1_rxd1.rgmii1_rd1 */
AM33XX_IOPAD(0x938, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L16) gmii1_rxd2.rgmii1_rd2 */
AM33XX_IOPAD(0x934, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L17) gmii1_rxd3.rgmii1_rd3 */
/*AM33XX_IOPAD(0xA34, PIN_OUTPUT_PULLDOWN | MUX_MODE7)*/
/* Slave 2 reset value*/
AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)

>;
};

davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0)) /* mdio_clk.mdio_clk */

/* AM33XX_IOPAD(0x88C, (PIN_OUTPUT_PULLUP | MUX_MODE5) ) /* (V12) gpmc_clk.pr1_mdio_mdclk */
/* AM33XX_IOPAD(0x888, (PIN_INPUT_PULLUP | MUX_MODE5) ) /* (T13) gpmc_csn3.pr1_mdio_data*/

>;
};

davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7))
AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
>;
};

  • /*
     * board.c
     *
     * Board functions for TI AM335X based boards
     *
     * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    
    #include <common.h>
    #include <dm.h>
    #include <errno.h>
    #include <spl.h>
    #include <serial.h>
    #include <asm/arch/cpu.h>
    #include <asm/arch/hardware.h>
    #include <asm/arch/omap.h>
    #include <asm/arch/ddr_defs.h>
    #include <asm/arch/clock.h>
    #include <asm/arch/clk_synthesizer.h>
    #include <asm/arch/gpio.h>
    #include <asm/arch/mmc_host_def.h>
    #include <asm/arch/sys_proto.h>
    #include <asm/arch/mem.h>
    #include <asm/io.h>
    #include <asm/emif.h>
    #include <asm/gpio.h>
    #include <asm/omap_common.h>
    #include <asm/omap_sec_common.h>
    #include <asm/omap_mmc.h>
    #include <i2c.h>
    #include <miiphy.h>
    #include <cpsw.h>
    #include <power/tps65217.h>
    #include <power/tps65910.h>
    #include <environment.h>
    #include <watchdog.h>
    #include <environment.h>
    #include "../common/board_detect.h"
    #include "board.h"
    
    DECLARE_GLOBAL_DATA_PTR;
    
    /* GPIO that controls power to DDR on EVM-SK */
    #define GPIO_TO_PIN(bank, gpio)		(32 * (bank) + (gpio))
    #define GPIO_DDR_VTT_EN		GPIO_TO_PIN(0, 7)
    #define ICE_GPIO_DDR_VTT_EN	GPIO_TO_PIN(0, 18)
    #define GPIO_PR1_MII_CTRL	GPIO_TO_PIN(3, 4)
    #define GPIO_MUX_MII_CTRL	GPIO_TO_PIN(3, 10)
    #define GPIO_FET_SWITCH_CTRL	GPIO_TO_PIN(0, 7)
    /* #define GPIO_PHY_RESET		GPIO_TO_PIN(2, 5) */
    #define GPIO_VSC8531		GPIO_TO_PIN(3, 21)                         //added for vsc8531 phy
    #define GPIO_PROCESSOR_DONE	GPIO_TO_PIN(2, 26)                         //added for vsc8531 phy
    #define GPIO_ETH0_MODE		GPIO_TO_PIN(0, 11)
    #define GPIO_ETH1_MODE		GPIO_TO_PIN(1, 26)
    
    //#define GPIO_FLASH_CTRL		GPIO_TO_PIN(3, 18)
    static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE;
    
    #define GPIO0_RISINGDETECT	(AM33XX_GPIO0_BASE + OMAP_GPIO_RISINGDETECT)
    #define GPIO1_RISINGDETECT	(AM33XX_GPIO1_BASE + OMAP_GPIO_RISINGDETECT)
    
    #define GPIO0_IRQSTATUS1	(AM33XX_GPIO0_BASE + OMAP_GPIO_IRQSTATUS1)
    #define GPIO1_IRQSTATUS1	(AM33XX_GPIO1_BASE + OMAP_GPIO_IRQSTATUS1)
    
    #define GPIO0_IRQSTATUSRAW	(AM33XX_GPIO0_BASE + 0x024)
    #define GPIO1_IRQSTATUSRAW	(AM33XX_GPIO1_BASE + 0x024)
    
    /*
     * Read header information from EEPROM into global structure.
     */
    #ifdef CONFIG_TI_I2C_BOARD_DETECT
    #if 1 
    void do_board_detect(void)
    {
    	enable_i2c0_pin_mux();
    	i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED, CONFIG_SYS_OMAP24_I2C_SLAVE);
    
    	if (ti_i2c_eeprom_am_get(CONFIG_EEPROM_BUS_ADDRESS,
    				CONFIG_EEPROM_CHIP_ADDRESS))
    		printf("ti_i2c_eeprom_init failed\n");
    	else
    		printf("ti-i2c initialized....board detected..............>>>>>>>>>>>>>>>>>>>>>>\n");
    
    	/*two lines commented*/
    	//gpio_request(GPIO_VSC8531, "phy_reset_vsc8531");
    	//gpio_direction_output(GPIO_VSC8531, 1);
    
    	//gpio_set_value(GPIO_VSC8531,1);
    }
    #endif
    #endif
    
    #ifndef CONFIG_DM_SERIAL
    struct serial_device *default_serial_console(void)
    {
    	if (board_is_icev2())
    		return &eserial4_device;
    	else
    		return &eserial1_device;
    }
    #endif
    
    #ifndef CONFIG_SKIP_LOWLEVEL_INIT
    static const struct ddr_data ddr2_data = {
    	.datardsratio0 = MT47H128M16RT25E_RD_DQS,
    	.datafwsratio0 = MT47H128M16RT25E_PHY_FIFO_WE,
    	.datawrsratio0 = MT47H128M16RT25E_PHY_WR_DATA,
    };
    
    static const struct cmd_control ddr2_cmd_ctrl_data = {
    	.cmd0csratio = MT47H128M16RT25E_RATIO,
    
    	.cmd1csratio = MT47H128M16RT25E_RATIO,
    
    	.cmd2csratio = MT47H128M16RT25E_RATIO,
    };
    
    static const struct emif_regs ddr2_emif_reg_data = {
    	.sdram_config = MT47H128M16RT25E_EMIF_SDCFG,
    	.ref_ctrl = MT47H128M16RT25E_EMIF_SDREF,
    	.sdram_tim1 = MT47H128M16RT25E_EMIF_TIM1,
    	.sdram_tim2 = MT47H128M16RT25E_EMIF_TIM2,
    	.sdram_tim3 = MT47H128M16RT25E_EMIF_TIM3,
    	.emif_ddr_phy_ctlr_1 = MT47H128M16RT25E_EMIF_READ_LATENCY,
    };
    
    static const struct emif_regs ddr2_evm_emif_reg_data = {
    	.sdram_config = MT47H128M16RT25E_EMIF_SDCFG,
    	.ref_ctrl = MT47H128M16RT25E_EMIF_SDREF,
    	.sdram_tim1 = MT47H128M16RT25E_EMIF_TIM1,
    	.sdram_tim2 = MT47H128M16RT25E_EMIF_TIM2,
    	.sdram_tim3 = MT47H128M16RT25E_EMIF_TIM3,
    	.ocp_config = EMIF_OCP_CONFIG_AM335X_EVM,
    	.emif_ddr_phy_ctlr_1 = MT47H128M16RT25E_EMIF_READ_LATENCY,
    };
    
    static const struct ddr_data ddr3_data = {
    	.datardsratio0 = MT41J128MJT125_RD_DQS,
    	.datawdsratio0 = MT41J128MJT125_WR_DQS,
    	.datafwsratio0 = MT41J128MJT125_PHY_FIFO_WE,
    	.datawrsratio0 = MT41J128MJT125_PHY_WR_DATA,
    };
    
    static const struct ddr_data ddr3_beagleblack_data = {
    	.datardsratio0 = MT41K256M16HA125E_RD_DQS,
    	.datawdsratio0 = MT41K256M16HA125E_WR_DQS,
    	.datafwsratio0 = MT41K256M16HA125E_PHY_FIFO_WE,
    	.datawrsratio0 = MT41K256M16HA125E_PHY_WR_DATA,
    };
    
    static const struct ddr_data ddr3_evm_data = {
    	.datardsratio0 = MT41J512M8RH125_RD_DQS,
    	.datawdsratio0 = MT41J512M8RH125_WR_DQS,
    	.datafwsratio0 = MT41J512M8RH125_PHY_FIFO_WE,
    	.datawrsratio0 = MT41J512M8RH125_PHY_WR_DATA,
    };
    
    static const struct ddr_data ddr3_icev2_data = {
    	.datardsratio0 = MT41J128MJT125_RD_DQS_400MHz,
    	.datawdsratio0 = MT41J128MJT125_WR_DQS_400MHz,
    	.datafwsratio0 = MT41J128MJT125_PHY_FIFO_WE_400MHz,
    	.datawrsratio0 = MT41J128MJT125_PHY_WR_DATA_400MHz,
    };
    
    static const struct cmd_control ddr3_cmd_ctrl_data = {
    	.cmd0csratio = MT41J128MJT125_RATIO,
    	.cmd0iclkout = MT41J128MJT125_INVERT_CLKOUT,
    
    	.cmd1csratio = MT41J128MJT125_RATIO,
    	.cmd1iclkout = MT41J128MJT125_INVERT_CLKOUT,
    
    	.cmd2csratio = MT41J128MJT125_RATIO,
    	.cmd2iclkout = MT41J128MJT125_INVERT_CLKOUT,
    };
    
    static const struct cmd_control ddr3_beagleblack_cmd_ctrl_data = {
    	.cmd0csratio = MT41K256M16HA125E_RATIO,
    	.cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
    
    	.cmd1csratio = MT41K256M16HA125E_RATIO,
    	.cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
    
    	.cmd2csratio = MT41K256M16HA125E_RATIO,
    	.cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT,
    };
    
    static const struct cmd_control ddr3_evm_cmd_ctrl_data = {
    	.cmd0csratio = MT41J512M8RH125_RATIO,
    	.cmd0iclkout = MT41J512M8RH125_INVERT_CLKOUT,
    
    	.cmd1csratio = MT41J512M8RH125_RATIO,
    	.cmd1iclkout = MT41J512M8RH125_INVERT_CLKOUT,
    
    	.cmd2csratio = MT41J512M8RH125_RATIO,
    	.cmd2iclkout = MT41J512M8RH125_INVERT_CLKOUT,
    };
    
    static const struct cmd_control ddr3_icev2_cmd_ctrl_data = {
    	.cmd0csratio = MT41J128MJT125_RATIO_400MHz,
    	.cmd0iclkout = MT41J128MJT125_INVERT_CLKOUT_400MHz,
    
    	.cmd1csratio = MT41J128MJT125_RATIO_400MHz,
    	.cmd1iclkout = MT41J128MJT125_INVERT_CLKOUT_400MHz,
    
    	.cmd2csratio = MT41J128MJT125_RATIO_400MHz,
    	.cmd2iclkout = MT41J128MJT125_INVERT_CLKOUT_400MHz,
    };
    
    static struct emif_regs ddr3_emif_reg_data = {
    	.sdram_config = MT41J128MJT125_EMIF_SDCFG,
    	.ref_ctrl = MT41J128MJT125_EMIF_SDREF,
    	.sdram_tim1 = MT41J128MJT125_EMIF_TIM1,
    	.sdram_tim2 = MT41J128MJT125_EMIF_TIM2,
    	.sdram_tim3 = MT41J128MJT125_EMIF_TIM3,
    	.zq_config = MT41J128MJT125_ZQ_CFG,
    	.emif_ddr_phy_ctlr_1 = MT41J128MJT125_EMIF_READ_LATENCY |
    		PHY_EN_DYN_PWRDN,
    };
    
    static struct emif_regs ddr3_beagleblack_emif_reg_data = {
    	.sdram_config = MT41K256M16HA125E_EMIF_SDCFG,
    	.ref_ctrl = MT41K256M16HA125E_EMIF_SDREF,
    	.sdram_tim1 = MT41K256M16HA125E_EMIF_TIM1,
    	.sdram_tim2 = MT41K256M16HA125E_EMIF_TIM2,
    	.sdram_tim3 = MT41K256M16HA125E_EMIF_TIM3,
    	.ocp_config = EMIF_OCP_CONFIG_BEAGLEBONE_BLACK,
    	.zq_config = MT41K256M16HA125E_ZQ_CFG,
    	.emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY,
    };
    
    static struct emif_regs ddr3_evm_emif_reg_data = {
    	.sdram_config = MT41J512M8RH125_EMIF_SDCFG,
    	.ref_ctrl = MT41J512M8RH125_EMIF_SDREF,
    	.sdram_tim1 = MT41J512M8RH125_EMIF_TIM1,
    	.sdram_tim2 = MT41J512M8RH125_EMIF_TIM2,
    	.sdram_tim3 = MT41J512M8RH125_EMIF_TIM3,
    	.ocp_config = EMIF_OCP_CONFIG_AM335X_EVM,
    	.zq_config = MT41J512M8RH125_ZQ_CFG,
    	.emif_ddr_phy_ctlr_1 = MT41J512M8RH125_EMIF_READ_LATENCY |
    		PHY_EN_DYN_PWRDN,
    };
    
    static struct emif_regs ddr3_icev2_emif_reg_data = {
    	.sdram_config = MT41J128MJT125_EMIF_SDCFG_400MHz,
    	.ref_ctrl = MT41J128MJT125_EMIF_SDREF_400MHz,
    	.sdram_tim1 = MT41J128MJT125_EMIF_TIM1_400MHz,
    	.sdram_tim2 = MT41J128MJT125_EMIF_TIM2_400MHz,
    	.sdram_tim3 = MT41J128MJT125_EMIF_TIM3_400MHz,
    	.zq_config = MT41J128MJT125_ZQ_CFG_400MHz,
    	.emif_ddr_phy_ctlr_1 = MT41J128MJT125_EMIF_READ_LATENCY_400MHz |
    		PHY_EN_DYN_PWRDN,
    };
    
    #ifdef CONFIG_SPL_OS_BOOT
    int spl_start_uboot(void)
    {
    	/* break into full u-boot on 'c' */
    	if (serial_tstc() && serial_getc() == 'c')
    		return 1;
    
    #ifdef CONFIG_SPL_ENV_SUPPORT
    	env_init();
    	env_load();
    	if (env_get_yesno("boot_os") != 1)
    		return 1;
    #endif
    
    	return 0;
    }
    #endif
    
    const struct dpll_params *get_dpll_ddr_params(void)
    {
    	int ind = get_sys_clk_index();
    
    	if (board_is_evm_sk())
    		return &dpll_ddr3_303MHz[ind];
    	else if (board_is_bone_lt() || board_is_icev2())
    		return &dpll_ddr3_400MHz[ind];
    	else if (board_is_evm_15_or_later())
    		return &dpll_ddr3_303MHz[ind];
    	else
    		return &dpll_ddr2_266MHz[ind];
    }
    
    static u8 bone_not_connected_to_ac_power(void)
    {
    	if (board_is_bone()) {
    		uchar pmic_status_reg;
    		if (tps65217_reg_read(TPS65217_STATUS,
    					&pmic_status_reg))
    			return 1;
    		if (!(pmic_status_reg & TPS65217_PWR_SRC_AC_BITMASK)) {
    			puts("No AC power, switching to default OPP\n");
    			return 1;
    		}
    	}
    	return 0;
    }
    
    const struct dpll_params *get_dpll_mpu_params(void)
    {
    	int ind = get_sys_clk_index();
    	int freq = am335x_get_efuse_mpu_max_freq(cdev);
    
    	if (bone_not_connected_to_ac_power())
    		freq = MPUPLL_M_600;
    
    	if (board_is_bone_lt())
    		freq = MPUPLL_M_1000;
    
    	switch (freq) {
    		case MPUPLL_M_1000:
    			return &dpll_mpu_opp[ind][5];
    		case MPUPLL_M_800:
    			return &dpll_mpu_opp[ind][4];
    		case MPUPLL_M_720:
    			return &dpll_mpu_opp[ind][3];
    		case MPUPLL_M_600:
    			return &dpll_mpu_opp[ind][2];
    		case MPUPLL_M_500:
    			return &dpll_mpu_opp100;
    		case MPUPLL_M_300:
    			return &dpll_mpu_opp[ind][0];
    	}
    
    	return &dpll_mpu_opp[ind][0];
    }
    
    static void scale_vcores_bone(int freq)
    {
    	int usb_cur_lim, mpu_vdd;
    
    	/*
    	 * Only perform PMIC configurations if board rev > A1
    	 * on Beaglebone White
    	 */
    	if (board_is_bone() && !strncmp(board_ti_get_rev(), "00A1", 4))
    		return;
    
    	if (i2c_probe(TPS65217_CHIP_PM))
    		return;
    
    	/*
    	 * On Beaglebone White we need to ensure we have AC power
    	 * before increasing the frequency.
    	 */
    	if (bone_not_connected_to_ac_power())
    		freq = MPUPLL_M_600;
    
    	/*
    	 * Override what we have detected since we know if we have
    	 * a Beaglebone Black it supports 1GHz.
    	 */
    	if (board_is_bone_lt())
    		freq = MPUPLL_M_1000;
    
    	switch (freq) {
    		case MPUPLL_M_1000:
    			mpu_vdd = TPS65217_DCDC_VOLT_SEL_1325MV;
    			usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1800MA;
    			break;
    		case MPUPLL_M_800:
    			mpu_vdd = TPS65217_DCDC_VOLT_SEL_1275MV;
    			usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA;
    			break;
    		case MPUPLL_M_720:
    			mpu_vdd = TPS65217_DCDC_VOLT_SEL_1200MV;
    			usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA;
    			break;
    		case MPUPLL_M_600:
    		case MPUPLL_M_500:
    		case MPUPLL_M_300:
    		default:
    			mpu_vdd = TPS65217_DCDC_VOLT_SEL_1100MV;
    			usb_cur_lim = TPS65217_USB_INPUT_CUR_LIMIT_1300MA;
    			break;
    	}
    
    	if (tps65217_reg_write(TPS65217_PROT_LEVEL_NONE,
    				TPS65217_POWER_PATH,
    				usb_cur_lim,
    				TPS65217_USB_INPUT_CUR_LIMIT_MASK))
    		puts("tps65217_reg_write failure\n");
    
    	/* Set DCDC3 (CORE) voltage to 1.10V */
    	if (tps65217_voltage_update(TPS65217_DEFDCDC3,
    				TPS65217_DCDC_VOLT_SEL_1100MV)) {
    		puts("tps65217_voltage_update failure\n");
    		return;
    	}
    
    	/* Set DCDC2 (MPU) voltage */
    	if (tps65217_voltage_update(TPS65217_DEFDCDC2, mpu_vdd)) {
    		puts("tps65217_voltage_update failure\n");
    		return;
    	}
    
    	/*
    	 * Set LDO3, LDO4 output voltage to 3.3V for Beaglebone.
    	 * Set LDO3 to 1.8V and LDO4 to 3.3V for Beaglebone Black.
    	 */
    	if (board_is_bone()) {
    		if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
    					TPS65217_DEFLS1,
    					TPS65217_LDO_VOLTAGE_OUT_3_3,
    					TPS65217_LDO_MASK))
    			puts("tps65217_reg_write failure\n");
    	} else {
    		if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
    					TPS65217_DEFLS1,
    					TPS65217_LDO_VOLTAGE_OUT_1_8,
    					TPS65217_LDO_MASK))
    			puts("tps65217_reg_write failure\n");
    	}
    
    	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2,
    				TPS65217_DEFLS2,
    				TPS65217_LDO_VOLTAGE_OUT_3_3,
    				TPS65217_LDO_MASK))
    		puts("tps65217_reg_write failure\n");
    }
    
    void scale_vcores_generic(int freq)
    {
    	int sil_rev, mpu_vdd;
    
    	/*
    	 * The GP EVM, IDK and EVM SK use a TPS65910 PMIC.  For all
    	 * MPU frequencies we support we use a CORE voltage of
    	 * 1.10V.  For MPU voltage we need to switch based on
    	 * the frequency we are running at.
    	 */
    	if (i2c_probe(TPS65910_CTRL_I2C_ADDR))
    		return;
    
    	/*
    	 * Depending on MPU clock and PG we will need a different
    	 * VDD to drive at that speed.
    	 */
    	sil_rev = readl(&cdev->deviceid) >> 28;
    	mpu_vdd = am335x_get_tps65910_mpu_vdd(sil_rev, freq);
    
    	/* Tell the TPS65910 to use i2c */
    	tps65910_set_i2c_control();
    
    	/* First update MPU voltage. */
    	if (tps65910_voltage_update(MPU, mpu_vdd))
    		return;
    
    	/* Second, update the CORE voltage. */
    	if (tps65910_voltage_update(CORE, TPS65910_OP_REG_SEL_1_1_0))
    	{
    		//gpio_request(GPIO_FLASH_CTRL, "flash_ctrl_en");
    		//gpio_direction_output(GPIO_FLASH_CTRL, 0);
    
    
    		return;
    	}
    
    }
    
    void gpi2c_init(void)
    {
    	/* When needed to be invoked prior to BSS initialization */
    	static bool first_time = true;
    
    	if (first_time) {
    		enable_i2c0_pin_mux();
    		i2c_init(CONFIG_SYS_OMAP24_I2C_SPEED,
    				CONFIG_SYS_OMAP24_I2C_SLAVE);
    		first_time = false;
    	}
    
    	//gpio_direction_output(GPIO_VSC8531, 0);                         //commented
    }
    
    void scale_vcores(void)
    {
    	int freq;
    
    	gpi2c_init();
    	freq = am335x_get_efuse_mpu_max_freq(cdev);
    
    	if (board_is_beaglebonex())
    		scale_vcores_bone(freq);
    	else
    		scale_vcores_generic(freq);
    }
    
    void set_uart_mux_conf(void)
    {
    #if CONFIG_CONS_INDEX == 1
    	enable_uart0_pin_mux();
    #elif CONFIG_CONS_INDEX == 2
    	enable_uart1_pin_mux();
    #elif CONFIG_CONS_INDEX == 3
    	enable_uart2_pin_mux();
    #elif CONFIG_CONS_INDEX == 4
    	enable_uart3_pin_mux();
    #elif CONFIG_CONS_INDEX == 5
    	enable_uart4_pin_mux();
    #elif CONFIG_CONS_INDEX == 6
    	enable_uart5_pin_mux();
    #endif
    }
    
    void set_mux_conf_regs(void)
    {
    	enable_board_pin_mux();
    }
    
    const struct ctrl_ioregs ioregs_evmsk = {
    	.cm0ioctl		= MT41J128MJT125_IOCTRL_VALUE,
    	.cm1ioctl		= MT41J128MJT125_IOCTRL_VALUE,
    	.cm2ioctl		= MT41J128MJT125_IOCTRL_VALUE,
    	.dt0ioctl		= MT41J128MJT125_IOCTRL_VALUE,
    	.dt1ioctl		= MT41J128MJT125_IOCTRL_VALUE,
    };
    
    const struct ctrl_ioregs ioregs_bonelt = {
    	.cm0ioctl		= MT41K256M16HA125E_IOCTRL_VALUE,
    	.cm1ioctl		= MT41K256M16HA125E_IOCTRL_VALUE,
    	.cm2ioctl		= MT41K256M16HA125E_IOCTRL_VALUE,
    	.dt0ioctl		= MT41K256M16HA125E_IOCTRL_VALUE,
    	.dt1ioctl		= MT41K256M16HA125E_IOCTRL_VALUE,
    };
    
    const struct ctrl_ioregs ioregs_evm15 = {
    	.cm0ioctl		= MT41J512M8RH125_IOCTRL_VALUE,
    	.cm1ioctl		= MT41J512M8RH125_IOCTRL_VALUE,
    	.cm2ioctl		= MT41J512M8RH125_IOCTRL_VALUE,
    	.dt0ioctl		= MT41J512M8RH125_IOCTRL_VALUE,
    	.dt1ioctl		= MT41J512M8RH125_IOCTRL_VALUE,
    };
    
    const struct ctrl_ioregs ioregs = {
    	.cm0ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
    	.cm1ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
    	.cm2ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
    	.dt0ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
    	.dt1ioctl		= MT47H128M16RT25E_IOCTRL_VALUE,
    };
    
    void sdram_init(void)
    {
    	if (board_is_evm_sk()) {
    		/*
    		 * EVM SK 1.2A and later use gpio0_7 to enable DDR3.
    		 * This is safe enough to do on older revs.
    		 */
    		gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en");
    		gpio_direction_output(GPIO_DDR_VTT_EN, 1);
    	}
    
    	if (board_is_icev2()) {
    		printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>board detected..............>>>>>>>>>>>>>>>>************>>>>>>>>>>>>>>>>>>>>>>\n");	
    		gpio_request(GPIO_PROCESSOR_DONE, "phy_reset_vsc8531");
    		gpio_direction_output(GPIO_PROCESSOR_DONE, 0);
    		gpio_request(GPIO_VSC8531, "phy_reset_vsc8531");
    		gpio_direction_output(GPIO_VSC8531, 1);
    		udelay(5000);		
    		//gpio_direction_output(GPIO_VSC8531, 0);
    		//udelay(5000);		
    		//gpio_direction_output(GPIO_VSC8531, 1);
    
    		//gpio_request(GPIO_FLASH_CTRL, "flash_ctrl_en");
    		//gpio_direction_output(GPIO_FLASH_CTRL, 0);
    		gpio_request(ICE_GPIO_DDR_VTT_EN, "ddr_vtt_en");
    		gpio_direction_output(ICE_GPIO_DDR_VTT_EN, 1);
    		//gpio_set_value(GPIO_VSC8531,1);
    
    
    	}
    
    	if (board_is_evm_sk())
    		config_ddr(303, &ioregs_evmsk, &ddr3_data,
    				&ddr3_cmd_ctrl_data, &ddr3_emif_reg_data, 0);
    	else if (board_is_bone_lt())
    		config_ddr(400, &ioregs_bonelt,
    				&ddr3_beagleblack_data,
    				&ddr3_beagleblack_cmd_ctrl_data,
    				&ddr3_beagleblack_emif_reg_data, 0);
    	else if (board_is_evm_15_or_later())
    		config_ddr(303, &ioregs_evm15, &ddr3_evm_data,
    				&ddr3_evm_cmd_ctrl_data, &ddr3_evm_emif_reg_data, 0);
    	else if (board_is_icev2())
    		config_ddr(400, &ioregs_evmsk, &ddr3_icev2_data,
    				&ddr3_icev2_cmd_ctrl_data, &ddr3_icev2_emif_reg_data,
    				0);
    	else if (board_is_gp_evm())
    		config_ddr(266, &ioregs, &ddr2_data,
    				&ddr2_cmd_ctrl_data, &ddr2_evm_emif_reg_data, 0);
    	else
    		config_ddr(266, &ioregs, &ddr2_data,
    				&ddr2_cmd_ctrl_data, &ddr2_emif_reg_data, 0);
    }
    #endif
    
    #if !defined(CONFIG_SPL_BUILD) || \
    	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
    static void request_and_set_gpio(int gpio, char *name, int val)
    {
    	int ret;
    
    	ret = gpio_request(gpio, name);
    	if (ret < 0) {
    		printf("%s: Unable to request %s\n", __func__, name);
    		return;
    	}
    
    	ret = gpio_direction_output(gpio, 0);
    	if (ret < 0) {
    		printf("%s: Unable to set %s  as output\n", __func__, name);
    		goto err_free_gpio;
    	}
    
    	gpio_set_value(gpio, val);
    
    	return;
    
    err_free_gpio:
    	gpio_free(gpio);
    }
    
    #define REQUEST_AND_SET_GPIO(N)	request_and_set_gpio(N, #N, 1);
    #define REQUEST_AND_CLR_GPIO(N)	request_and_set_gpio(N, #N, 0);
    
    /**
     * RMII mode on ICEv2 board needs 50MHz clock. Given the clock
     * synthesizer With a capacitor of 18pF, and 25MHz input clock cycle
     * PLL1 gives an output of 100MHz. So, configuring the div2/3 as 2 to
     * give 50MHz output for Eth0 and 1.
     */
    static struct clk_synth cdce913_data = {
    	.id = 0x81,
    	.capacitor = 0x90,
    	.mux = 0x6d,
    	.pdiv2 = 0x2,
    	.pdiv3 = 0x2,
    };
    #endif
    
    #if !defined(CONFIG_SPL_BUILD) || \
    	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
    static bool prueth_is_mii = true;
    #endif
    
    /*
     * Basic board specific setup.  Pinmux has been handled already.
     */
    int board_init(void)
    {
    	/*added by astra*/
    	REQUEST_AND_SET_GPIO(114)/*Added By RAM*/
    
    		/*Commented by RAM
    		  REQUEST_AND_CLR_GPIO(29)
    		  REQUEST_AND_SET_GPIO(89)
    		  REQUEST_AND_SET_GPIO(55)
    		  REQUEST_AND_SET_GPIO(56)
    		  */
    #if defined(CONFIG_HW_WATCHDOG)
    		hw_watchdog_init();
    #endif
    
    	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
    #if defined(CONFIG_NOR) || defined(CONFIG_NAND)
    	gpmc_init();
    #endif
    
    #if !defined(CONFIG_SPL_BUILD) || \
    	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
    	if (board_is_icev2()) {
    #if 0
    		int rv;
    		u32 reg;
    		bool eth0_is_mii = true;
    		bool eth1_is_mii = true;
    		REQUEST_AND_SET_GPIO(GPIO_PR1_MII_CTRL);
    		/* Make J19 status available on GPIO1_26 */
    		REQUEST_AND_CLR_GPIO(GPIO_MUX_MII_CTRL);
    
    		REQUEST_AND_SET_GPIO(GPIO_FET_SWITCH_CTRL);
    		/*
    		 * Both ports can be set as RMII-CPSW or MII-PRU-ETH using
    		 * jumpers near the port. Read the jumper value and set
    		 * the pinmux, external mux and PHY clock accordingly.
    		 * As jumper line is overridden by PHY RX_DV pin immediately
    		 * after bootstrap (power-up/reset), we need to sample
    		 * it during PHY reset using GPIO rising edge detection.
    		 */
    		REQUEST_AND_SET_GPIO(GPIO_PHY_RESET);
    		/* Enable rising edge IRQ on GPIO0_11 and GPIO 1_26 */
    		reg = readl(GPIO0_RISINGDETECT) | BIT(11);
    		writel(reg, GPIO0_RISINGDETECT);
    		reg = readl(GPIO1_RISINGDETECT) | BIT(26);
    		writel(reg, GPIO1_RISINGDETECT);
    		/* Reset PHYs to capture the Jumper setting */
    		gpio_set_value(GPIO_PHY_RESET, 0);
    		udelay(2);	/* PHY datasheet states 1uS min. */
    		gpio_set_value(GPIO_PHY_RESET, 1);
    
    		reg = readl(GPIO0_IRQSTATUSRAW) & BIT(11);
    		if (reg) {
    			writel(reg, GPIO0_IRQSTATUS1); /* clear irq */
    			/* RMII mode */
    			printf("ETH0, CPSW\n");
    			eth0_is_mii = false;
    		} else {
    			/* MII mode */
    			printf("ETH0, PRU\n");
    			cdce913_data.pdiv3 = 4;	/* 25MHz PHY clk */
    		}
    
    		reg = readl(GPIO1_IRQSTATUSRAW) & BIT(26);
    		if (reg) {
    			writel(reg, GPIO1_IRQSTATUS1); /* clear irq */
    			/* RMII mode */
    			printf("ETH1, CPSW\n");
    			gpio_set_value(GPIO_MUX_MII_CTRL, 1);
    			eth1_is_mii = false;
    		} else {
    			/* MII mode */
    			printf("ETH1, PRU\n");
    			cdce913_data.pdiv2 = 4;	/* 25MHz PHY clk */
    		}
    
    		if (eth0_is_mii != eth1_is_mii) {
    			printf("Unsupported Ethernet port configuration\n");
    			printf("Both ports must be set as RMII or MII\n");
    			hang();
    		}
    
    		prueth_is_mii = eth0_is_mii;
    
    		/* disable rising edge IRQs */
    		reg = readl(GPIO0_RISINGDETECT) & ~BIT(11);
    		writel(reg, GPIO0_RISINGDETECT);
    		reg = readl(GPIO1_RISINGDETECT) & ~BIT(26);
    		writel(reg, GPIO1_RISINGDETECT);
    		rv = setup_clock_synthesizer(&cdce913_data);
    		if (rv) {
    			printf("Clock synthesizer setup failed %d\n", rv);
    			return rv;
    		}
    
    		/* reset PHYs */
    		gpio_set_value(GPIO_PHY_RESET, 0);
    		udelay(2);	/* PHY datasheet states 1uS min. */
    		gpio_set_value(GPIO_PHY_RESET, 1);
    
    #endif
    	}
    #endif
    
    	return 0;
    }
    
    #ifdef CONFIG_BOARD_LATE_INIT
    int board_late_init(void)
    {
    #if !defined(CONFIG_SPL_BUILD)
    	uint8_t mac_addr[6];
    	uint32_t mac_hi, mac_lo;
    #endif
    
    #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
    	char *name = NULL;
    
    	if (board_is_bone_lt()) {
    		/* BeagleBoard.org BeagleBone Black Wireless: */
    		if (!strncmp(board_ti_get_rev(), "BWA", 3)) {
    			name = "BBBW";
    		}
    		/* SeeedStudio BeagleBone Green Wireless */
    		if (!strncmp(board_ti_get_rev(), "GW1", 3)) {
    			name = "BBGW";
    		}
    		/* BeagleBoard.org BeagleBone Blue */
    		if (!strncmp(board_ti_get_rev(), "BLA", 3)) {
    			name = "BBBL";
    		}
    	}
    
    	if (board_is_bbg1())
    		name = "BBG1";
    	set_board_info_env(name);
    
    	/*
    	 * Default FIT boot on HS devices. Non FIT images are not allowed
    	 * on HS devices.
    	 */
    	if (get_device_type() == HS_DEVICE)
    		env_set("boot_fit", "1");
    #endif
    
    #if !defined(CONFIG_SPL_BUILD)
    	/* try reading mac address from efuse */
    	mac_lo = readl(&cdev->macid0l);
    	mac_hi = readl(&cdev->macid0h);
    	mac_addr[0] = mac_hi & 0xFF;
    	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
    	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
    	mac_addr[4] = mac_lo & 0xFF;
    	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
    
    	if (!env_get("ethaddr")) {
    		printf("<ethaddr> not set. Validating first E-fuse MAC\n");
    
    		if (is_valid_ethaddr(mac_addr))
    			eth_env_set_enetaddr("ethaddr", mac_addr);
    	}
    
    	mac_lo = readl(&cdev->macid1l);
    	mac_hi = readl(&cdev->macid1h);
    	mac_addr[0] = mac_hi & 0xFF;
    	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
    	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
    	mac_addr[4] = mac_lo & 0xFF;
    	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
    
    	if (!env_get("eth1addr")) {
    		if (is_valid_ethaddr(mac_addr))
    			eth_env_set_enetaddr("eth1addr", mac_addr);
    	}
    
    	env_set("ice_mii", prueth_is_mii ? "mii" : "rmii");
    #endif
    
    	return 0;
    }
    #endif
    
    #ifndef CONFIG_DM_ETH
    
    #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
    	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
    static void cpsw_control(int enabled)
    {
    	/* VTP can be added here */
    
    	return;
    }
    
    static struct cpsw_slave_data cpsw_slaves[] = {
    	{
    		.slave_reg_ofs	= 0x208,
    		.sliver_reg_ofs	= 0xd80,
    		.phy_addr	= 0,
    		.phy_if		= PHY_INTERFACE_MODE_RGMII,
    	},
    	{
    		.slave_reg_ofs	= 0x308,
    		.sliver_reg_ofs	= 0xdc0,
    		.phy_addr	= 3,
    		.phy_if		= PHY_INTERFACE_MODE_RGMII,
    	},
    };
    
    static struct cpsw_platform_data cpsw_data = {
    	.mdio_base		= CPSW_MDIO_BASE,
    	.cpsw_base		= CPSW_BASE,
    	.mdio_div		= 0xff,
    	.channels		= 8,
    	.cpdma_reg_ofs		= 0x800,
    	.slaves			= 1,		//LFT
    	.slave_data		= cpsw_slaves,
    	.ale_reg_ofs		= 0xd00,
    	.ale_entries		= 1024,
    	.host_port_reg_ofs	= 0x108,
    	.hw_stats_reg_ofs	= 0x900,
    	.bd_ram_ofs		= 0x2000,
    	.mac_control		= (1 << 5),
    	.control		= cpsw_control,
    	.host_port_num		= 0,
    	.version		= CPSW_CTRL_VERSION_2,
    };
    #endif
    
    #if ((defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USBETH_SUPPORT)) &&\
    		defined(CONFIG_SPL_BUILD)) || \
    		((defined(CONFIG_DRIVER_TI_CPSW) || \
    		  defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) && \
    		  !defined(CONFIG_SPL_BUILD))
    
    /*
     * This function will:
     * Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr
     * in the environment
     * Perform fixups to the PHY present on certain boards.  We only need this
     * function in:
     * - SPL with either CPSW or USB ethernet support
     * - Full U-Boot, with either CPSW or USB ethernet
     * Build in only these cases to avoid warnings about unused variables
     * when we build an SPL that has neither option but full U-Boot will.
     */
    int board_eth_init(bd_t *bis)
    {
    	int rv, n = 0;
    #if defined(CONFIG_USB_ETHER) && \
    	(!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT))
    	uint8_t mac_addr[6];
    	uint32_t mac_hi, mac_lo;
    
    	/*
    	 * use efuse mac address for USB ethernet as we know that
    	 * both CPSW and USB ethernet will never be active at the same time
    	 */
    	mac_lo = readl(&cdev->macid0l);
    	mac_hi = readl(&cdev->macid0h);
    	mac_addr[0] = mac_hi & 0xFF;
    	mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    	mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
    	mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
    	mac_addr[4] = mac_lo & 0xFF;
    	mac_addr[5] = (mac_lo & 0xFF00) >> 8;
    #endif
    
    
    #if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \
    	(defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD))
    	/*if (!env_get("ethaddr")) {
    	  puts("<ethaddr> not set. Validating first E-fuse MAC\n");
    	  if (is_valid_ethaddr(mac_addr))
    	  eth_env_set_enetaddr("ethaddr", mac_addr);
    	  }*/
    
    #ifdef CONFIG_DRIVER_TI_CPSW
    	if (board_is_bone() || board_is_bone_lt() ||
    			board_is_idk()) {
    		writel(MII_MODE_ENABLE, &cdev->miisel);
    		cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
    			PHY_INTERFACE_MODE_MII;
    	} else if (board_is_icev2()) {
    		writel((RGMII_MODE_ENABLE | RGMII_INT_DELAY), &cdev->miisel);
    	/*	cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
    			PHY_INTERFACE_MODE_RGMII;
    	*/	
    
    	} else {
    		writel((RGMII_MODE_ENABLE | RGMII_INT_DELAY), &cdev->miisel);
    		cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if =
    			PHY_INTERFACE_MODE_RGMII;
    	}
    
    	rv = cpsw_register(&cpsw_data);
    	if (rv < 0)
    		printf("Error %d registering CPSW switch\n", rv);
    	else
    		n += rv;
    #endif
    
    	/*
    	 *
    	 * CPSW RGMII Internal Delay Mode is not supported in all PVT
    	 * operating points.  So we must set the TX clock delay feature
    	 * in the AR8051 PHY.  Since we only support a single ethernet
    	 * device in U-Boot, we only do this for the first instance.
    	 */
    #define AR8051_PHY_DEBUG_ADDR_REG	0x1d
    #define AR8051_PHY_DEBUG_DATA_REG	0x1e
    #define AR8051_DEBUG_RGMII_CLK_DLY_REG	0x5
    #define AR8051_RGMII_TX_CLK_DLY		0x100
    
    	if (board_is_evm_sk() || board_is_gp_evm()) {
    		const char *devname;
    		devname = miiphy_get_current_dev();
    
    		miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_ADDR_REG,
    				AR8051_DEBUG_RGMII_CLK_DLY_REG);
    		miiphy_write(devname, 0x0, AR8051_PHY_DEBUG_DATA_REG,
    				AR8051_RGMII_TX_CLK_DLY);
    	}
    #endif
    #if defined(CONFIG_USB_ETHER) && \
    	(!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT))
    	if (is_valid_ethaddr(mac_addr))
    		eth_env_set_enetaddr("usbnet_devaddr", mac_addr);
    
    	rv = usb_eth_initialize(bis);
    	if (rv < 0)
    		printf("Error %d registering USB_ETHER\n", rv);
    	else
    		n += rv;
    #endif
    	return n;
    }
    #endif
    
    #endif /* CONFIG_DM_ETH */
    
    #ifdef CONFIG_SPL_LOAD_FIT
    int board_fit_config_name_match(const char *name)
    {
    	if (board_is_gp_evm() && !strcmp(name, "am335x-evm"))
    		return 0;
    	else if (board_is_bone() && !strcmp(name, "am335x-bone"))
    		return 0;
    	else if (board_is_bone_lt() && !strcmp(name, "am335x-boneblack"))
    		return 0;
    	else if (board_is_evm_sk() && !strcmp(name, "am335x-evmsk"))
    		return 0;
    	else if (board_is_bbg1() && !strcmp(name, "am335x-bonegreen"))
    		return 0;
    	else if (board_is_icev2() && !strcmp(name, "am335x-icev2"))
    		return 0;
    	else
    		return -1;
    }
    #endif
    
    #ifdef CONFIG_TI_SECURE_DEVICE
    void board_fit_image_post_process(void **p_image, size_t *p_size)
    {
    	secure_boot_verify_image(p_image, p_size);
    }
    #endif
    
    #if !CONFIG_IS_ENABLED(OF_CONTROL)
    static const struct omap_hsmmc_plat am335x_mmc0_platdata = {
    	.base_addr = (struct hsmmc *)OMAP_HSMMC1_BASE,
    	.cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_4BIT,
    	.cfg.f_min = 400000,
    	.cfg.f_max = 52000000,
    	.cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
    	.cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
    };
    
    U_BOOT_DEVICE(am335x_mmc0) = {
    	.name = "omap_hsmmc",
    	.platdata = &am335x_mmc0_platdata,
    };
    
    static const struct omap_hsmmc_plat am335x_mmc1_platdata = {
    	.base_addr = (struct hsmmc *)OMAP_HSMMC2_BASE,
    	.cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT,
    	.cfg.f_min = 400000,
    	.cfg.f_max = 52000000,
    	.cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195,
    	.cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT,
    };
    
    U_BOOT_DEVICE(am335x_mmc1) = {
    	.name = "omap_hsmmc",
    	.platdata = &am335x_mmc1_platdata,
    };
    #endif
    
    /*
     * CPSW Ethernet Switch Driver
     *
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.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 version 2.
     *
     * This program is distributed "as is" WITHOUT ANY WARRANTY of any
     * kind, whether express or implied; without even the implied warranty
     * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     * GNU General Public License for more details.
     */
    
    #include <common.h>
    #include <command.h>
    #include <net.h>
    #include <miiphy.h>
    #include <malloc.h>
    #include <net.h>
    #include <netdev.h>
    #include <cpsw.h>
    #include <linux/errno.h>
    #include <asm/gpio.h>
    #include <asm/io.h>
    #include <phy.h>
    #include <asm/arch/cpu.h>
    #include <dm.h>
    #include <fdt_support.h>
    
    DECLARE_GLOBAL_DATA_PTR;
    
    #define BITMASK(bits)		(BIT(bits) - 1)
    #define PHY_REG_MASK		0x1f
    #define PHY_ID_MASK		0x1f
    #define NUM_DESCS		(PKTBUFSRX * 2)
    #define PKT_MIN			60
    #define PKT_MAX			(1500 + 14 + 4 + 4)
    #define CLEAR_BIT		1
    #define GIGABITEN		BIT(7)
    #define FULLDUPLEXEN		BIT(0)
    #define MIIEN			BIT(15)
    
    /* reg offset */
    #define CPSW_HOST_PORT_OFFSET	0x108
    #define CPSW_SLAVE0_OFFSET	0x208
    #define CPSW_SLAVE1_OFFSET	0x308
    #define CPSW_SLAVE_SIZE		0x100
    #define CPSW_CPDMA_OFFSET	0x800
    #define CPSW_HW_STATS		0x900
    #define CPSW_STATERAM_OFFSET	0xa00
    #define CPSW_CPTS_OFFSET	0xc00
    #define CPSW_ALE_OFFSET		0xd00
    #define CPSW_SLIVER0_OFFSET	0xd80
    #define CPSW_SLIVER1_OFFSET	0xdc0
    #define CPSW_BD_OFFSET		0x2000
    #define CPSW_MDIO_DIV		0xff
    
    #define AM335X_GMII_SEL_OFFSET	0x630
    
    /* DMA Registers */
    #define CPDMA_TXCONTROL		0x004
    #define CPDMA_RXCONTROL		0x014
    #define CPDMA_SOFTRESET		0x01c
    #define CPDMA_RXFREE		0x0e0
    #define CPDMA_TXHDP_VER1	0x100
    #define CPDMA_TXHDP_VER2	0x200
    #define CPDMA_RXHDP_VER1	0x120
    #define CPDMA_RXHDP_VER2	0x220
    #define CPDMA_TXCP_VER1		0x140
    #define CPDMA_TXCP_VER2		0x240
    #define CPDMA_RXCP_VER1		0x160
    #define CPDMA_RXCP_VER2		0x260
    
    /* Descriptor mode bits */
    #define CPDMA_DESC_SOP		BIT(31)
    #define CPDMA_DESC_EOP		BIT(30)
    #define CPDMA_DESC_OWNER	BIT(29)
    #define CPDMA_DESC_EOQ		BIT(28)
    
    /*
     * This timeout definition is a worst-case ultra defensive measure against
     * unexpected controller lock ups.  Ideally, we should never ever hit this
     * scenario in practice.
     */
    #define MDIO_TIMEOUT            100 /* msecs */
    #define CPDMA_TIMEOUT		100 /* msecs */
    
    struct cpsw_mdio_regs {
    	u32	version;
    	u32	control;
    #define CONTROL_IDLE		BIT(31)
    #define CONTROL_ENABLE		BIT(30)
    
    	u32	alive;
    	u32	link;
    	u32	linkintraw;
    	u32	linkintmasked;
    	u32	__reserved_0[2];
    	u32	userintraw;
    	u32	userintmasked;
    	u32	userintmaskset;
    	u32	userintmaskclr;
    	u32	__reserved_1[20];
    
    	struct {
    		u32		access;
    		u32		physel;
    #define USERACCESS_GO		BIT(31)
    #define USERACCESS_WRITE	BIT(30)
    #define USERACCESS_ACK		BIT(29)
    #define USERACCESS_READ		(0)
    #define USERACCESS_DATA		(0xffff)
    	} user[0];
    };
    
    struct cpsw_regs {
    	u32	id_ver;
    	u32	control;
    	u32	soft_reset;
    	u32	stat_port_en;
    	u32	ptype;
    };
    
    struct cpsw_slave_regs {
    	u32	max_blks;
    	u32	blk_cnt;
    	u32	flow_thresh;
    	u32	port_vlan;
    	u32	tx_pri_map;
    #ifdef CONFIG_AM33XX
    	u32	gap_thresh;
    #elif defined(CONFIG_TI814X)
    	u32	ts_ctl;
    	u32	ts_seq_ltype;
    	u32	ts_vlan;
    #endif
    	u32	sa_lo;
    	u32	sa_hi;
    };
    
    struct cpsw_host_regs {
    	u32	max_blks;
    	u32	blk_cnt;
    	u32	flow_thresh;
    	u32	port_vlan;
    	u32	tx_pri_map;
    	u32	cpdma_tx_pri_map;
    	u32	cpdma_rx_chan_map;
    };
    
    struct cpsw_sliver_regs {
    	u32	id_ver;
    	u32	mac_control;
    	u32	mac_status;
    	u32	soft_reset;
    	u32	rx_maxlen;
    	u32	__reserved_0;
    	u32	rx_pause;
    	u32	tx_pause;
    	u32	__reserved_1;
    	u32	rx_pri_map;
    };
    
    #define ALE_ENTRY_BITS		68
    #define ALE_ENTRY_WORDS		DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
    
    /* ALE Registers */
    #define ALE_CONTROL		0x08
    #define ALE_UNKNOWNVLAN		0x18
    #define ALE_TABLE_CONTROL	0x20
    #define ALE_TABLE		0x34
    #define ALE_PORTCTL		0x40
    
    #define ALE_TABLE_WRITE		BIT(31)
    
    #define ALE_TYPE_FREE			0
    #define ALE_TYPE_ADDR			1
    #define ALE_TYPE_VLAN			2
    #define ALE_TYPE_VLAN_ADDR		3
    
    #define ALE_UCAST_PERSISTANT		0
    #define ALE_UCAST_UNTOUCHED		1
    #define ALE_UCAST_OUI			2
    #define ALE_UCAST_TOUCHED		3
    
    #define ALE_MCAST_FWD			0
    #define ALE_MCAST_BLOCK_LEARN_FWD	1
    #define ALE_MCAST_FWD_LEARN		2
    #define ALE_MCAST_FWD_2			3
    
    enum cpsw_ale_port_state {
    	ALE_PORT_STATE_DISABLE	= 0x00,
    	ALE_PORT_STATE_BLOCK	= 0x01,
    	ALE_PORT_STATE_LEARN	= 0x02,
    	ALE_PORT_STATE_FORWARD	= 0x03,
    };
    
    /* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
    #define ALE_SECURE	1
    #define ALE_BLOCKED	2
    
    struct cpsw_slave {
    	struct cpsw_slave_regs		*regs;
    	struct cpsw_sliver_regs		*sliver;
    	int				slave_num;
    	u32				mac_control;
    	struct cpsw_slave_data		*data;
    };
    
    struct cpdma_desc {
    	/* hardware fields */
    	u32			hw_next;
    	u32			hw_buffer;
    	u32			hw_len;
    	u32			hw_mode;
    	/* software fields */
    	u32			sw_buffer;
    	u32			sw_len;
    };
    
    struct cpdma_chan {
    	struct cpdma_desc	*head, *tail;
    	void			*hdp, *cp, *rxfree;
    };
    
    /* AM33xx SoC specific definitions for the CONTROL port */
    #define AM33XX_GMII_SEL_MODE_MII	0
    #define AM33XX_GMII_SEL_MODE_RMII	1
    #define AM33XX_GMII_SEL_MODE_RGMII	2
    
    #define AM33XX_GMII_SEL_RGMII1_IDMODE	BIT(4)
    #define AM33XX_GMII_SEL_RGMII2_IDMODE	BIT(5)
    #define AM33XX_GMII_SEL_RMII1_IO_CLK_EN	BIT(6)
    #define AM33XX_GMII_SEL_RMII2_IO_CLK_EN	BIT(7)
    
    #define GMII_SEL_MODE_MASK		0x3
    
    #define desc_write(desc, fld, val)	__raw_writel((u32)(val), &(desc)->fld)
    #define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
    #define desc_read_ptr(desc, fld)	((void *)__raw_readl(&(desc)->fld))
    
    #define chan_write(chan, fld, val)	__raw_writel((u32)(val), (chan)->fld)
    #define chan_read(chan, fld)		__raw_readl((chan)->fld)
    #define chan_read_ptr(chan, fld)	((void *)__raw_readl((chan)->fld))
    
    #define for_active_slave(slave, priv) \
    	slave = (priv)->slaves + (priv)->data.active_slave; if (slave)
    #define for_each_slave(slave, priv) \
    	for (slave = (priv)->slaves; slave != (priv)->slaves + \
    				(priv)->data.slaves; slave++)
    
    struct cpsw_priv {
    #ifdef CONFIG_DM_ETH
    	struct udevice			*dev;
    #else
    	struct eth_device		*dev;
    #endif
    	struct cpsw_platform_data	data;
    	int				host_port;
    
    	struct cpsw_regs		*regs;
    	void				*dma_regs;
    	struct cpsw_host_regs		*host_port_regs;
    	void				*ale_regs;
    
    	struct cpdma_desc		*descs;
    	struct cpdma_desc		*desc_free;
    	struct cpdma_chan		rx_chan, tx_chan;
    
    	struct cpsw_slave		*slaves;
    	struct phy_device		*phydev;
    	struct mii_dev			*bus;
    
    	u32				phy_mask;
    };
    
    static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
    {
    	int idx;
    
    	idx    = start / 32;
    	start -= idx * 32;
    	idx    = 2 - idx; /* flip */
    	return (ale_entry[idx] >> start) & BITMASK(bits);
    }
    
    static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
    				      u32 value)
    {
    	int idx;
    
    	value &= BITMASK(bits);
    	idx    = start / 32;
    	start -= idx * 32;
    	idx    = 2 - idx; /* flip */
    	ale_entry[idx] &= ~(BITMASK(bits) << start);
    	ale_entry[idx] |=  (value << start);
    }
    
    #define DEFINE_ALE_FIELD(name, start, bits)				\
    static inline int cpsw_ale_get_##name(u32 *ale_entry)			\
    {									\
    	return cpsw_ale_get_field(ale_entry, start, bits);		\
    }									\
    static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)	\
    {									\
    	cpsw_ale_set_field(ale_entry, start, bits, value);		\
    }
    
    DEFINE_ALE_FIELD(entry_type,		60,	2)
    DEFINE_ALE_FIELD(mcast_state,		62,	2)
    DEFINE_ALE_FIELD(port_mask,		66,	3)
    DEFINE_ALE_FIELD(ucast_type,		62,	2)
    DEFINE_ALE_FIELD(port_num,		66,	2)
    DEFINE_ALE_FIELD(blocked,		65,	1)
    DEFINE_ALE_FIELD(secure,		64,	1)
    DEFINE_ALE_FIELD(mcast,			40,	1)
    
    /* The MAC address field in the ALE entry cannot be macroized as above */
    static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
    {
    	int i;
    
    	for (i = 0; i < 6; i++)
    		addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
    }
    
    static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
    {
    	int i;
    
    	for (i = 0; i < 6; i++)
    		cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
    }
    
    static int cpsw_ale_read(struct cpsw_priv *priv, int idx, u32 *ale_entry)
    {
    	int i;
    
    	__raw_writel(idx, priv->ale_regs + ALE_TABLE_CONTROL);
    
    	for (i = 0; i < ALE_ENTRY_WORDS; i++)
    		ale_entry[i] = __raw_readl(priv->ale_regs + ALE_TABLE + 4 * i);
    
    	return idx;
    }
    
    static int cpsw_ale_write(struct cpsw_priv *priv, int idx, u32 *ale_entry)
    {
    	int i;
    
    	for (i = 0; i < ALE_ENTRY_WORDS; i++)
    		__raw_writel(ale_entry[i], priv->ale_regs + ALE_TABLE + 4 * i);
    
    	__raw_writel(idx | ALE_TABLE_WRITE, priv->ale_regs + ALE_TABLE_CONTROL);
    
    	return idx;
    }
    
    static int cpsw_ale_match_addr(struct cpsw_priv *priv, const u8 *addr)
    {
    	u32 ale_entry[ALE_ENTRY_WORDS];
    	int type, idx;
    
    	for (idx = 0; idx < priv->data.ale_entries; idx++) {
    		u8 entry_addr[6];
    
    		cpsw_ale_read(priv, idx, ale_entry);
    		type = cpsw_ale_get_entry_type(ale_entry);
    		if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
    			continue;
    		cpsw_ale_get_addr(ale_entry, entry_addr);
    		if (memcmp(entry_addr, addr, 6) == 0)
    			return idx;
    	}
    	return -ENOENT;
    }
    
    static int cpsw_ale_match_free(struct cpsw_priv *priv)
    {
    	u32 ale_entry[ALE_ENTRY_WORDS];
    	int type, idx;
    
    	for (idx = 0; idx < priv->data.ale_entries; idx++) {
    		cpsw_ale_read(priv, idx, ale_entry);
    		type = cpsw_ale_get_entry_type(ale_entry);
    		if (type == ALE_TYPE_FREE)
    			return idx;
    	}
    	return -ENOENT;
    }
    
    static int cpsw_ale_find_ageable(struct cpsw_priv *priv)
    {
    	u32 ale_entry[ALE_ENTRY_WORDS];
    	int type, idx;
    
    	for (idx = 0; idx < priv->data.ale_entries; idx++) {
    		cpsw_ale_read(priv, idx, ale_entry);
    		type = cpsw_ale_get_entry_type(ale_entry);
    		if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
    			continue;
    		if (cpsw_ale_get_mcast(ale_entry))
    			continue;
    		type = cpsw_ale_get_ucast_type(ale_entry);
    		if (type != ALE_UCAST_PERSISTANT &&
    		    type != ALE_UCAST_OUI)
    			return idx;
    	}
    	return -ENOENT;
    }
    
    static int cpsw_ale_add_ucast(struct cpsw_priv *priv, const u8 *addr,
    			      int port, int flags)
    {
    	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
    	int idx;
    
    	cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
    	cpsw_ale_set_addr(ale_entry, addr);
    	cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
    	cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
    	cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
    	cpsw_ale_set_port_num(ale_entry, port);
    
    	idx = cpsw_ale_match_addr(priv, addr);
    	if (idx < 0)
    		idx = cpsw_ale_match_free(priv);
    	if (idx < 0)
    		idx = cpsw_ale_find_ageable(priv);
    	if (idx < 0)
    		return -ENOMEM;
    
    	cpsw_ale_write(priv, idx, ale_entry);
    	return 0;
    }
    
    static int cpsw_ale_add_mcast(struct cpsw_priv *priv, const u8 *addr,
    			      int port_mask)
    {
    	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
    	int idx, mask;
    
    	idx = cpsw_ale_match_addr(priv, addr);
    	if (idx >= 0)
    		cpsw_ale_read(priv, idx, ale_entry);
    
    	cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
    	cpsw_ale_set_addr(ale_entry, addr);
    	cpsw_ale_set_mcast_state(ale_entry, ALE_MCAST_FWD_2);
    
    	mask = cpsw_ale_get_port_mask(ale_entry);
    	port_mask |= mask;
    	cpsw_ale_set_port_mask(ale_entry, port_mask);
    
    	if (idx < 0)
    		idx = cpsw_ale_match_free(priv);
    	if (idx < 0)
    		idx = cpsw_ale_find_ageable(priv);
    	if (idx < 0)
    		return -ENOMEM;
    
    	cpsw_ale_write(priv, idx, ale_entry);
    	return 0;
    }
    
    static inline void cpsw_ale_control(struct cpsw_priv *priv, int bit, int val)
    {
    	u32 tmp, mask = BIT(bit);
    
    	tmp  = __raw_readl(priv->ale_regs + ALE_CONTROL);
    	tmp &= ~mask;
    	tmp |= val ? mask : 0;
    	__raw_writel(tmp, priv->ale_regs + ALE_CONTROL);
    }
    
    #define cpsw_ale_enable(priv, val)	cpsw_ale_control(priv, 31, val)
    #define cpsw_ale_clear(priv, val)	cpsw_ale_control(priv, 30, val)
    #define cpsw_ale_vlan_aware(priv, val)	cpsw_ale_control(priv,  2, val)
    
    static inline void cpsw_ale_port_state(struct cpsw_priv *priv, int port,
    				       int val)
    {
    	int offset = ALE_PORTCTL + 4 * port;
    	u32 tmp, mask = 0x3;
    
    	tmp  = __raw_readl(priv->ale_regs + offset);
    	tmp &= ~mask;
    	tmp |= val & mask;
    	__raw_writel(tmp, priv->ale_regs + offset);
    }
    
    static struct cpsw_mdio_regs *mdio_regs;
    
    /* wait until hardware is ready for another user access */
    static inline u32 wait_for_user_access(void)
    {
    	u32 reg = 0;
    	int timeout = MDIO_TIMEOUT;
    
    	while (timeout-- &&
    	((reg = __raw_readl(&mdio_regs->user[0].access)) & USERACCESS_GO))
    		udelay(10);
    
    	if (timeout == -1) {
    		printf("wait_for_user_access Timeout\n");
    		return -ETIMEDOUT;
    	}
    	return reg;
    }
    
    /* wait until hardware state machine is idle */
    static inline void wait_for_idle(void)
    {
    	int timeout = MDIO_TIMEOUT;
    
    	while (timeout-- &&
    		((__raw_readl(&mdio_regs->control) & CONTROL_IDLE) == 0))
    		udelay(10);
    
    	if (timeout == -1)
    		printf("wait_for_idle Timeout\n");
    }
    
    static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
    				int dev_addr, int phy_reg)
    {
    	int data;
    	u32 reg;
    
    	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
    		return -EINVAL;
    
    	wait_for_user_access();
    	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
    	       (phy_id << 16));
    	__raw_writel(reg, &mdio_regs->user[0].access);
    	reg = wait_for_user_access();
    
    	data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
    	return data;
    }
    
    static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
    				int phy_reg, u16 data)
    {
    	u32 reg;
    
    	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
    		return -EINVAL;
    
    	wait_for_user_access();
    	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
    		   (phy_id << 16) | (data & USERACCESS_DATA));
    	__raw_writel(reg, &mdio_regs->user[0].access);
    	wait_for_user_access();
    
    	return 0;
    }
    
    static void cpsw_mdio_init(const char *name, u32 mdio_base, u32 div)
    {
    	struct mii_dev *bus = mdio_alloc();
    
    	mdio_regs = (struct cpsw_mdio_regs *)mdio_base;
    
    	/* set enable and clock divider */
    	__raw_writel(div | CONTROL_ENABLE, &mdio_regs->control);
    
    	/*
    	 * wait for scan logic to settle:
    	 * the scan time consists of (a) a large fixed component, and (b) a
    	 * small component that varies with the mii bus frequency.  These
    	 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
    	 * silicon.  Since the effect of (b) was found to be largely
    	 * negligible, we keep things simple here.
    	 */
    	udelay(1000);
    
    	bus->read = cpsw_mdio_read;
    	bus->write = cpsw_mdio_write;
    	strcpy(bus->name, name);
    
    	mdio_register(bus);
    }
    
    /* Set a self-clearing bit in a register, and wait for it to clear */
    static inline void setbit_and_wait_for_clear32(void *addr)
    {
    	__raw_writel(CLEAR_BIT, addr);
    	while (__raw_readl(addr) & CLEAR_BIT)
    		;
    }
    
    #define mac_hi(mac)	(((mac)[0] << 0) | ((mac)[1] << 8) |	\
    			 ((mac)[2] << 16) | ((mac)[3] << 24))
    #define mac_lo(mac)	(((mac)[4] << 0) | ((mac)[5] << 8))
    
    static void cpsw_set_slave_mac(struct cpsw_slave *slave,
    			       struct cpsw_priv *priv)
    {
    #ifdef CONFIG_DM_ETH
    	struct eth_pdata *pdata = dev_get_platdata(priv->dev);
    
    	writel(mac_hi(pdata->enetaddr), &slave->regs->sa_hi);
    	writel(mac_lo(pdata->enetaddr), &slave->regs->sa_lo);
    #else
    	__raw_writel(mac_hi(priv->dev->enetaddr), &slave->regs->sa_hi);
    	__raw_writel(mac_lo(priv->dev->enetaddr), &slave->regs->sa_lo);
    #endif
    }
    
    static int cpsw_slave_update_link(struct cpsw_slave *slave,
    				   struct cpsw_priv *priv, int *link)
    {
    	struct phy_device *phy;
    	u32 mac_control = 0;
    	int ret = -ENODEV;
    
    	phy = priv->phydev;
    	if (!phy)
    		goto out;
    
    	ret = phy_startup(phy);
    	if (ret)
    		goto out;
    
    	if (link)
    		*link = phy->link;
    
    	if (phy->link) { /* link up */
    		mac_control = priv->data.mac_control;
    		if (phy->speed == 1000)
    			mac_control |= GIGABITEN;
    		if (phy->duplex == DUPLEX_FULL)
    			mac_control |= FULLDUPLEXEN;
    		if (phy->speed == 100)
    			mac_control |= MIIEN;
    	}
    
    	if (mac_control == slave->mac_control)
    		goto out;
    
    	if (mac_control) {
    		printf("link up on port %d, speed %d, %s duplex\n",
    				slave->slave_num, phy->speed,
    				(phy->duplex == DUPLEX_FULL) ? "full" : "half");
    	} else {
    		printf("link down on port %d\n", slave->slave_num);
    	}
    
    	__raw_writel(mac_control, &slave->sliver->mac_control);
    	slave->mac_control = mac_control;
    
    out:
    	return ret;
    }
    
    static int cpsw_update_link(struct cpsw_priv *priv)
    {
    	int ret = -ENODEV;
    	struct cpsw_slave *slave;
    
    	for_active_slave(slave, priv)
    		ret = cpsw_slave_update_link(slave, priv, NULL);
    
    	return ret;
    }
    
    static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
    {
    	if (priv->host_port == 0)
    		return slave_num + 1;
    	else
    		return slave_num;
    }
    
    static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
    {
    	u32     slave_port;
    
    	setbit_and_wait_for_clear32(&slave->sliver->soft_reset);
    
    	/* setup priority mapping */
    	__raw_writel(0x76543210, &slave->sliver->rx_pri_map);
    	__raw_writel(0x33221100, &slave->regs->tx_pri_map);
    
    	/* setup max packet size, and mac address */
    	__raw_writel(PKT_MAX, &slave->sliver->rx_maxlen);
    	cpsw_set_slave_mac(slave, priv);
    
    	slave->mac_control = 0;	/* no link yet */
    
    	/* enable forwarding */
    	slave_port = cpsw_get_slave_port(priv, slave->slave_num);
    	cpsw_ale_port_state(priv, slave_port, ALE_PORT_STATE_FORWARD);
    
    	cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << slave_port);
    
    	priv->phy_mask |= 1 << slave->data->phy_addr;
    }
    
    static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
    {
    	struct cpdma_desc *desc = priv->desc_free;
    
    	if (desc)
    		priv->desc_free = desc_read_ptr(desc, hw_next);
    	return desc;
    }
    
    static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc)
    {
    	if (desc) {
    		desc_write(desc, hw_next, priv->desc_free);
    		priv->desc_free = desc;
    	}
    }
    
    static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan,
    			void *buffer, int len)
    {
    	struct cpdma_desc *desc, *prev;
    	u32 mode;
    
    	desc = cpdma_desc_alloc(priv);
    	if (!desc)
    		return -ENOMEM;
    
    	if (len < PKT_MIN)
    		len = PKT_MIN;
    
    	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
    
    	desc_write(desc, hw_next,   0);
    	desc_write(desc, hw_buffer, buffer);
    	desc_write(desc, hw_len,    len);
    	desc_write(desc, hw_mode,   mode | len);
    	desc_write(desc, sw_buffer, buffer);
    	desc_write(desc, sw_len,    len);
    
    	if (!chan->head) {
    		/* simple case - first packet enqueued */
    		chan->head = desc;
    		chan->tail = desc;
    		chan_write(chan, hdp, desc);
    		goto done;
    	}
    
    	/* not the first packet - enqueue at the tail */
    	prev = chan->tail;
    	desc_write(prev, hw_next, desc);
    	chan->tail = desc;
    
    	/* next check if EOQ has been triggered already */
    	if (desc_read(prev, hw_mode) & CPDMA_DESC_EOQ)
    		chan_write(chan, hdp, desc);
    
    done:
    	if (chan->rxfree)
    		chan_write(chan, rxfree, 1);
    	return 0;
    }
    
    static int cpdma_process(struct cpsw_priv *priv, struct cpdma_chan *chan,
    			 void **buffer, int *len)
    {
    	struct cpdma_desc *desc = chan->head;
    	u32 status;
    
    	if (!desc)
    		return -ENOENT;
    
    	status = desc_read(desc, hw_mode);
    
    	if (len)
    		*len = status & 0x7ff;
    
    	if (buffer)
    		*buffer = desc_read_ptr(desc, sw_buffer);
    
    	if (status & CPDMA_DESC_OWNER) {
    		if (chan_read(chan, hdp) == 0) {
    			if (desc_read(desc, hw_mode) & CPDMA_DESC_OWNER)
    				chan_write(chan, hdp, desc);
    		}
    
    		return -EBUSY;
    	}
    
    	chan->head = desc_read_ptr(desc, hw_next);
    	chan_write(chan, cp, desc);
    
    	cpdma_desc_free(priv, desc);
    	return 0;
    }
    
    static int _cpsw_init(struct cpsw_priv *priv, u8 *enetaddr)
    {
    	struct cpsw_slave	*slave;
    	int i, ret;
    
    	/* soft reset the controller and initialize priv */
    	setbit_and_wait_for_clear32(&priv->regs->soft_reset);
    
    	/* initialize and reset the address lookup engine */
    	cpsw_ale_enable(priv, 1);
    	cpsw_ale_clear(priv, 1);
    	cpsw_ale_vlan_aware(priv, 0); /* vlan unaware mode */
    
    	/* setup host port priority mapping */
    	__raw_writel(0x76543210, &priv->host_port_regs->cpdma_tx_pri_map);
    	__raw_writel(0, &priv->host_port_regs->cpdma_rx_chan_map);
    
    	/* disable priority elevation and enable statistics on all ports */
    	__raw_writel(0, &priv->regs->ptype);
    
    	/* enable statistics collection only on the host port */
    	__raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
    	__raw_writel(0x7, &priv->regs->stat_port_en);
    
    	cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
    
    	cpsw_ale_add_ucast(priv, enetaddr, priv->host_port, ALE_SECURE);
    	cpsw_ale_add_mcast(priv, net_bcast_ethaddr, 1 << priv->host_port);
    
    	for_active_slave(slave, priv)
    		cpsw_slave_init(slave, priv);
    
    	ret = cpsw_update_link(priv);
    	if (ret)
    		goto out;
    
    	/* init descriptor pool */
    	for (i = 0; i < NUM_DESCS; i++) {
    		desc_write(&priv->descs[i], hw_next,
    			   (i == (NUM_DESCS - 1)) ? 0 : &priv->descs[i+1]);
    	}
    	priv->desc_free = &priv->descs[0];
    
    	/* initialize channels */
    	if (priv->data.version == CPSW_CTRL_VERSION_2) {
    		memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
    		priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER2;
    		priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER2;
    		priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
    
    		memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
    		priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER2;
    		priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER2;
    	} else {
    		memset(&priv->rx_chan, 0, sizeof(struct cpdma_chan));
    		priv->rx_chan.hdp       = priv->dma_regs + CPDMA_RXHDP_VER1;
    		priv->rx_chan.cp        = priv->dma_regs + CPDMA_RXCP_VER1;
    		priv->rx_chan.rxfree    = priv->dma_regs + CPDMA_RXFREE;
    
    		memset(&priv->tx_chan, 0, sizeof(struct cpdma_chan));
    		priv->tx_chan.hdp       = priv->dma_regs + CPDMA_TXHDP_VER1;
    		priv->tx_chan.cp        = priv->dma_regs + CPDMA_TXCP_VER1;
    	}
    
    	/* clear dma state */
    	setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
    
    	if (priv->data.version == CPSW_CTRL_VERSION_2) {
    		for (i = 0; i < priv->data.channels; i++) {
    			__raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER2 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER2 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER2 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER2 + 4
    					* i);
    		}
    	} else {
    		for (i = 0; i < priv->data.channels; i++) {
    			__raw_writel(0, priv->dma_regs + CPDMA_RXHDP_VER1 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_RXFREE + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_RXCP_VER1 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_TXHDP_VER1 + 4
    					* i);
    			__raw_writel(0, priv->dma_regs + CPDMA_TXCP_VER1 + 4
    					* i);
    
    		}
    	}
    
    	__raw_writel(1, priv->dma_regs + CPDMA_TXCONTROL);
    	__raw_writel(1, priv->dma_regs + CPDMA_RXCONTROL);
    
    	/* submit rx descs */
    	for (i = 0; i < PKTBUFSRX; i++) {
    		ret = cpdma_submit(priv, &priv->rx_chan, net_rx_packets[i],
    				   PKTSIZE);
    		if (ret < 0) {
    			printf("error %d submitting rx desc\n", ret);
    			break;
    		}
    	}
    
    out:
    	return ret;
    }
    
    static void _cpsw_halt(struct cpsw_priv *priv)
    {
    	writel(0, priv->dma_regs + CPDMA_TXCONTROL);
    	writel(0, priv->dma_regs + CPDMA_RXCONTROL);
    
    	/* soft reset the controller and initialize priv */
    	setbit_and_wait_for_clear32(&priv->regs->soft_reset);
    
    	/* clear dma state */
    	setbit_and_wait_for_clear32(priv->dma_regs + CPDMA_SOFTRESET);
    
    }
    
    static int _cpsw_send(struct cpsw_priv *priv, void *packet, int length)
    {
    	void *buffer;
    	int len;
    	int timeout = CPDMA_TIMEOUT;
    
    	flush_dcache_range((unsigned long)packet,
    			   (unsigned long)packet + ALIGN(length, PKTALIGN));
    
    	/* first reap completed packets */
    	while (timeout-- &&
    		(cpdma_process(priv, &priv->tx_chan, &buffer, &len) >= 0))
    		;
    
    	if (timeout == -1) {
    		printf("cpdma_process timeout\n");
    		return -ETIMEDOUT;
    	}
    
    	return cpdma_submit(priv, &priv->tx_chan, packet, length);
    }
    
    static int _cpsw_recv(struct cpsw_priv *priv, uchar **pkt)
    {
    	void *buffer;
    	int len;
    	int ret = -EAGAIN;
    
    	ret = cpdma_process(priv, &priv->rx_chan, &buffer, &len);
    	if (ret < 0)
    		return ret;
    
    	invalidate_dcache_range((unsigned long)buffer,
    				(unsigned long)buffer + PKTSIZE_ALIGN);
    	*pkt = buffer;
    
    	return len;
    }
    
    static void cpsw_slave_setup(struct cpsw_slave *slave, int slave_num,
    			    struct cpsw_priv *priv)
    {
    	void			*regs = priv->regs;
    	struct cpsw_slave_data	*data = priv->data.slave_data + slave_num;
    	slave->slave_num = slave_num;
    	slave->data	= data;
    	slave->regs	= regs + data->slave_reg_ofs;
    	slave->sliver	= regs + data->sliver_reg_ofs;
    }
    
    static int cpsw_phy_init(struct cpsw_priv *priv, struct cpsw_slave *slave)
    {
    	struct phy_device *phydev;
    	u32 supported = PHY_GBIT_FEATURES;
    
    	phydev = phy_connect(priv->bus,
    			slave->data->phy_addr,
    			priv->dev,
    			slave->data->phy_if);
    
    	if (!phydev)
    		return -1;
    
    	phydev->supported &= supported;
    	phydev->advertising = phydev->supported;
    
    #ifdef CONFIG_DM_ETH
    	if (slave->data->phy_of_handle)
    		dev_set_of_offset(phydev->dev, slave->data->phy_of_handle);
    #endif
    
    	priv->phydev = phydev;
    	phy_config(phydev);
    	return 1;
    }
    
    int _cpsw_register(struct cpsw_priv *priv)
    {
    	struct cpsw_slave	*slave;
    	struct cpsw_platform_data *data = &priv->data;
    	void			*regs = (void *)data->cpsw_base;
    
    	priv->slaves = malloc(sizeof(struct cpsw_slave) * data->slaves);
    	if (!priv->slaves) {
    		return -ENOMEM;
    	}
    
    	priv->host_port		= data->host_port_num;
    	priv->regs		= regs;
    	priv->host_port_regs	= regs + data->host_port_reg_ofs;
    	priv->dma_regs		= regs + data->cpdma_reg_ofs;
    	priv->ale_regs		= regs + data->ale_reg_ofs;
    	priv->descs		= (void *)regs + data->bd_ram_ofs;
    
    	int idx = 0;
    
    	for_each_slave(slave, priv) {
    		cpsw_slave_setup(slave, idx, priv);
    		idx = idx + 1;
    	}
    
    	cpsw_mdio_init(priv->dev->name, data->mdio_base, data->mdio_div);
    	priv->bus = miiphy_get_dev_by_name(priv->dev->name);
    	for_active_slave(slave, priv)
    		cpsw_phy_init(priv, slave);
    
    	return 0;
    }
    
    #ifndef CONFIG_DM_ETH
    static int cpsw_init(struct eth_device *dev, bd_t *bis)
    {
    	struct cpsw_priv	*priv = dev->priv;
    
    	return _cpsw_init(priv, dev->enetaddr);
    }
    
    static void cpsw_halt(struct eth_device *dev)
    {
    	struct cpsw_priv *priv = dev->priv;
    
    	return _cpsw_halt(priv);
    }
    
    static int cpsw_send(struct eth_device *dev, void *packet, int length)
    {
    	struct cpsw_priv	*priv = dev->priv;
    
    	return _cpsw_send(priv, packet, length);
    }
    
    static int cpsw_recv(struct eth_device *dev)
    {
    	struct cpsw_priv *priv = dev->priv;
    	uchar *pkt = NULL;
    	int len;
    
    	len = _cpsw_recv(priv, &pkt);
    
    	if (len > 0) {
    		net_process_received_packet(pkt, len);
    		cpdma_submit(priv, &priv->rx_chan, pkt, PKTSIZE);
    	}
    
    	return len;
    }
    
    int cpsw_register(struct cpsw_platform_data *data)
    {
    	struct cpsw_priv	*priv;
    	struct eth_device	*dev;
    	int ret;
    
    	dev = calloc(sizeof(*dev), 1);
    	if (!dev)
    		return -ENOMEM;
    
    	priv = calloc(sizeof(*priv), 1);
    	if (!priv) {
    		free(dev);
    		return -ENOMEM;
    	}
    
    	priv->dev = dev;
    	priv->data = *data;
    
    	strcpy(dev->name, "cpsw");
    	dev->iobase	= 0;
    	dev->init	= cpsw_init;
    	dev->halt	= cpsw_halt;
    	dev->send	= cpsw_send;
    	dev->recv	= cpsw_recv;
    	dev->priv	= priv;
    
    	eth_register(dev);
    
    	ret = _cpsw_register(priv);
    	if (ret < 0) {
    		eth_unregister(dev);
    		free(dev);
    		free(priv);
    		return ret;
    	}
    
    	return 1;
    }
    #else
    static int cpsw_eth_start(struct udevice *dev)
    {
    	struct eth_pdata *pdata = dev_get_platdata(dev);
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	return _cpsw_init(priv, pdata->enetaddr);
    }
    
    static int cpsw_eth_send(struct udevice *dev, void *packet, int length)
    {
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	return _cpsw_send(priv, packet, length);
    }
    
    static int cpsw_eth_recv(struct udevice *dev, int flags, uchar **packetp)
    {
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	return _cpsw_recv(priv, packetp);
    }
    
    static int cpsw_eth_free_pkt(struct udevice *dev, uchar *packet,
    				   int length)
    {
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	return cpdma_submit(priv, &priv->rx_chan, packet, PKTSIZE);
    }
    
    static void cpsw_eth_stop(struct udevice *dev)
    {
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	return _cpsw_halt(priv);
    }
    
    
    static int cpsw_eth_probe(struct udevice *dev)
    {
    	struct cpsw_priv *priv = dev_get_priv(dev);
    
    	priv->dev = dev;
    
    	return _cpsw_register(priv);
    }
    
    static const struct eth_ops cpsw_eth_ops = {
    	.start		= cpsw_eth_start,
    	.send		= cpsw_eth_send,
    	.recv		= cpsw_eth_recv,
    	.free_pkt	= cpsw_eth_free_pkt,
    	.stop		= cpsw_eth_stop,
    };
    
    static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
    {
    	return fdtdec_get_addr_size_auto_noparent(fdt, node, "reg", 0, NULL,
    						  false);
    }
    
    static void cpsw_gmii_sel_am3352(struct cpsw_priv *priv,
    				 phy_interface_t phy_mode)
    {
    	u32 reg;
    	u32 mask;
    	u32 mode = 0;
    	bool rgmii_id = false;
    	int slave = priv->data.active_slave;
    
    	reg = readl(priv->data.gmii_sel);
    
    	switch (phy_mode) {
    	case PHY_INTERFACE_MODE_RMII:
    		mode = AM33XX_GMII_SEL_MODE_RMII;
    		break;
    
    	case PHY_INTERFACE_MODE_RGMII:
    		mode = AM33XX_GMII_SEL_MODE_RGMII;
    		break;
    	case PHY_INTERFACE_MODE_RGMII_ID:
    	case PHY_INTERFACE_MODE_RGMII_RXID:
    	case PHY_INTERFACE_MODE_RGMII_TXID:
    		mode = AM33XX_GMII_SEL_MODE_RGMII;
    		rgmii_id = true;
    		break;
    
    	case PHY_INTERFACE_MODE_MII:
    	default:
    		mode = AM33XX_GMII_SEL_MODE_MII;
    		break;
    	};
    
    	mask = GMII_SEL_MODE_MASK << (slave * 2) | BIT(slave + 6);
    	mode <<= slave * 2;
    
    	if (priv->data.rmii_clock_external) {
    		if (slave == 0)
    			mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
    		else
    			mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
    	}
    
    	if (rgmii_id) {
    		if (slave == 0)
    			mode |= AM33XX_GMII_SEL_RGMII1_IDMODE;
    		else
    			mode |= AM33XX_GMII_SEL_RGMII2_IDMODE;
    	}
    
    	reg &= ~mask;
    	reg |= mode;
    
    	writel(reg, priv->data.gmii_sel);
    }
    
    static void cpsw_gmii_sel_dra7xx(struct cpsw_priv *priv,
    				 phy_interface_t phy_mode)
    {
    	u32 reg;
    	u32 mask;
    	u32 mode = 0;
    	int slave = priv->data.active_slave;
    
    	reg = readl(priv->data.gmii_sel);
    
    	switch (phy_mode) {
    	case PHY_INTERFACE_MODE_RMII:
    		mode = AM33XX_GMII_SEL_MODE_RMII;
    		break;
    
    	case PHY_INTERFACE_MODE_RGMII:
    	case PHY_INTERFACE_MODE_RGMII_ID:
    	case PHY_INTERFACE_MODE_RGMII_RXID:
    	case PHY_INTERFACE_MODE_RGMII_TXID:
    		mode = AM33XX_GMII_SEL_MODE_RGMII;
    		break;
    
    	case PHY_INTERFACE_MODE_MII:
    	default:
    		mode = AM33XX_GMII_SEL_MODE_MII;
    		break;
    	};
    
    	switch (slave) {
    	case 0:
    		mask = GMII_SEL_MODE_MASK;
    		break;
    	case 1:
    		mask = GMII_SEL_MODE_MASK << 4;
    		mode <<= 4;
    		break;
    	default:
    		dev_err(priv->dev, "invalid slave number...\n");
    		return;
    	}
    
    	if (priv->data.rmii_clock_external)
    		dev_err(priv->dev, "RMII External clock is not supported\n");
    
    	reg &= ~mask;
    	reg |= mode;
    
    	writel(reg, priv->data.gmii_sel);
    }
    
    static void cpsw_phy_sel(struct cpsw_priv *priv, const char *compat,
    			 phy_interface_t phy_mode)
    {
    	if (!strcmp(compat, "ti,am3352-cpsw-phy-sel"))
    		cpsw_gmii_sel_am3352(priv, phy_mode);
    	if (!strcmp(compat, "ti,am43xx-cpsw-phy-sel"))
    		cpsw_gmii_sel_am3352(priv, phy_mode);
    	else if (!strcmp(compat, "ti,dra7xx-cpsw-phy-sel"))
    		cpsw_gmii_sel_dra7xx(priv, phy_mode);
    }
    
    static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
    {
    	struct eth_pdata *pdata = dev_get_platdata(dev);
    	struct cpsw_priv *priv = dev_get_priv(dev);
    	struct gpio_desc *mode_gpios;
    	const char *phy_mode;
    	const char *phy_sel_compat = NULL;
    	const void *fdt = gd->fdt_blob;
    	int node = dev_of_offset(dev);
    	int subnode;
    	int slave_index = 0;
    	int active_slave;
    	int num_mode_gpios;
    	int ret;
    
    	pdata->iobase = devfdt_get_addr(dev);
    	priv->data.version = CPSW_CTRL_VERSION_2;
    	priv->data.bd_ram_ofs = CPSW_BD_OFFSET;
    	priv->data.ale_reg_ofs = CPSW_ALE_OFFSET;
    	priv->data.cpdma_reg_ofs = CPSW_CPDMA_OFFSET;
    	priv->data.mdio_div = CPSW_MDIO_DIV;
    	priv->data.host_port_reg_ofs = CPSW_HOST_PORT_OFFSET,
    
    	pdata->phy_interface = -1;
    
    	priv->data.cpsw_base = pdata->iobase;
    	priv->data.channels = fdtdec_get_int(fdt, node, "cpdma_channels", -1);
    	if (priv->data.channels <= 0) {
    		printf("error: cpdma_channels not found in dt\n");
    		return -ENOENT;
    	}
    
    	priv->data.slaves = fdtdec_get_int(fdt, node, "slaves", -1);
    	if (priv->data.slaves <= 0) {
    		printf("error: slaves not found in dt\n");
    		return -ENOENT;
    	}
    	priv->data.slave_data = malloc(sizeof(struct cpsw_slave_data) *
    				       priv->data.slaves);
    
    	priv->data.ale_entries = fdtdec_get_int(fdt, node, "ale_entries", -1);
    	if (priv->data.ale_entries <= 0) {
    		printf("error: ale_entries not found in dt\n");
    		return -ENOENT;
    	}
    
    	priv->data.bd_ram_ofs = fdtdec_get_int(fdt, node, "bd_ram_size", -1);
    	if (priv->data.bd_ram_ofs <= 0) {
    		printf("error: bd_ram_size not found in dt\n");
    		return -ENOENT;
    	}
    
    	priv->data.mac_control = fdtdec_get_int(fdt, node, "mac_control", -1);
    	if (priv->data.mac_control <= 0) {
    		printf("error: ale_entries not found in dt\n");
    		return -ENOENT;
    	}
    
    	num_mode_gpios = gpio_get_list_count(dev, "mode-gpios");
    	if (num_mode_gpios > 0) {
    		mode_gpios = malloc(sizeof(struct gpio_desc) *
    				    num_mode_gpios);
    		gpio_request_list_by_name(dev, "mode-gpios", mode_gpios,
    					  num_mode_gpios, GPIOD_IS_OUT);
    		free(mode_gpios);
    	}
    
    	active_slave = fdtdec_get_int(fdt, node, "active_slave", 0);
    	priv->data.active_slave = active_slave;
    
    	fdt_for_each_subnode(subnode, fdt, node) {
    		int len;
    		const char *name;
    
    		name = fdt_get_name(fdt, subnode, &len);
    		if (!strncmp(name, "mdio", 4)) {
    			u32 mdio_base;
    
    			mdio_base = cpsw_get_addr_by_node(fdt, subnode);
    			if (mdio_base == FDT_ADDR_T_NONE) {
    				pr_err("Not able to get MDIO address space\n");
    				return -ENOENT;
    			}
    			priv->data.mdio_base = mdio_base;
    		}
    
    		if (!strncmp(name, "slave", 5)) {
    			u32 phy_id[2];
    
    			if (slave_index >= priv->data.slaves)
    				continue;
    			phy_mode = fdt_getprop(fdt, subnode, "phy-mode", NULL);
    			if (phy_mode)
    				priv->data.slave_data[slave_index].phy_if =
    					phy_get_interface_by_name(phy_mode);
    
    			priv->data.slave_data[slave_index].phy_of_handle =
    				fdtdec_lookup_phandle(fdt, subnode,
    						      "phy-handle");
    
    			if (priv->data.slave_data[slave_index].phy_of_handle >= 0) {
    				priv->data.slave_data[slave_index].phy_addr =
    						fdtdec_get_int(gd->fdt_blob,
    							       priv->data.slave_data[slave_index].phy_of_handle,
    							       "reg", -1);
    			} else {
    				fdtdec_get_int_array(fdt, subnode, "phy_id",
    						     phy_id, 2);
    				priv->data.slave_data[slave_index].phy_addr =
    						phy_id[1];
    			}
    			slave_index++;
    		}
    
    		if (!strncmp(name, "cpsw-phy-sel", 12)) {
    			priv->data.gmii_sel = cpsw_get_addr_by_node(fdt,
    								    subnode);
    
    			if (priv->data.gmii_sel == FDT_ADDR_T_NONE) {
    				pr_err("Not able to get gmii_sel reg address\n");
    				return -ENOENT;
    			}
    
    			if (fdt_get_property(fdt, subnode, "rmii-clock-ext",
    					     NULL))
    				priv->data.rmii_clock_external = true;
    
    			phy_sel_compat = fdt_getprop(fdt, subnode, "compatible",
    						     NULL);
    			if (!phy_sel_compat) {
    				pr_err("Not able to get gmii_sel compatible\n");
    				return -ENOENT;
    			}
    		}
    	}
    
    	priv->data.slave_data[0].slave_reg_ofs = CPSW_SLAVE0_OFFSET;
    	priv->data.slave_data[0].sliver_reg_ofs = CPSW_SLIVER0_OFFSET;
    
    	if (priv->data.slaves == 2) {
    		priv->data.slave_data[1].slave_reg_ofs = CPSW_SLAVE1_OFFSET;
    		priv->data.slave_data[1].sliver_reg_ofs = CPSW_SLIVER1_OFFSET;
    	}
    
    	ret = ti_cm_get_macid(dev, active_slave, pdata->enetaddr);
    	if (ret < 0) {
    		pr_err("cpsw read efuse mac failed\n");
    		return ret;
    	}
    
    	pdata->phy_interface = priv->data.slave_data[active_slave].phy_if;
    	if (pdata->phy_interface == -1) {
    		debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
    		return -EINVAL;
    	}
    
    	/* Select phy interface in control module */
    	cpsw_phy_sel(priv, phy_sel_compat, pdata->phy_interface);
    
    	return 0;
    }
    
    
    static const struct udevice_id cpsw_eth_ids[] = {
    	{ .compatible = "ti,cpsw" },
    	{ .compatible = "ti,am335x-cpsw" },
    	{ }
    };
    
    U_BOOT_DRIVER(eth_cpsw) = {
    	.name	= "eth_cpsw",
    	.id	= UCLASS_ETH,
    	.of_match = cpsw_eth_ids,
    	.ofdata_to_platdata = cpsw_eth_ofdata_to_platdata,
    	.probe	= cpsw_eth_probe,
    	.ops	= &cpsw_eth_ops,
    	.priv_auto_alloc_size = sizeof(struct cpsw_priv),
    	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
    	.flags = DM_FLAG_ALLOC_PRIV_DMA,
    };
    #endif /* CONFIG_DM_ETH */
    
    // SPDX-License-Identifier: MIT
    /*
     * Microsemi PHY drivers
     *
     *
     * Copyright (c) 2016 Microsemi Corporation
     *
     * Author: John Haechten
     *
     */
    #include <linux/ethtool.h>
    #include <miiphy.h>
    #include <bitfield.h>
    #include <time.h>
    #include <linux/delay.h>
    #include "Am335x_gpio.h"
    
    /* Microsemi PHY ID's */
    
    #define PHY_ID_VSC8502                  0x00070630
    
    #define PHY_ID_VSC8530                  0x00070560
    #define PHY_ID_VSC8531                  0x00070570
    #define PHY_ID_VSC8540                  0x00070760
    #define PHY_ID_VSC8541                  0x00070770
    
    /* Microsemi VSC85xx PHY Register Pages */
    #define MSCC_EXT_PAGE_ACCESS            31     /* Page Access Register */
    #define MSCC_PHY_PAGE_STD		0x0000 /* Standard registers */
    #define MSCC_PHY_PAGE_EXT1		0x0001 /* Extended registers - page 1 */
    #define MSCC_PHY_PAGE_EXT2		0x0002 /* Extended registers - page 2 */
    #define MSCC_PHY_PAGE_EXT3		0x0003 /* Extended registers - page 3 */
    #define MSCC_PHY_PAGE_EXT4		0x0004 /* Extended registers - page 4 */
    #define MSCC_PHY_PAGE_GPIO		0x0010 /* GPIO registers */
    #define MSCC_PHY_PAGE_TEST		0x2A30 /* TEST Page registers */
    #define MSCC_PHY_PAGE_TR		0x52B5 /* Token Ring Page registers */
    
    #define GPIO_TO_PIN(bank, gpio)         (32 * (bank) + (gpio))
    
    #define GPIO_FLASH_MUX_CTRL     GPIO_TO_PIN(2, 31)
    #define GPIO_PROGRAM_B          GPIO_TO_PIN(0, 29)
    #define GPIO_DONE_LED           GPIO_TO_PIN(3, 20)
    
    
    /* Std Page Register 18 */
    #define MSCC_PHY_BYPASS_CONTROL           18
    #define PARALLEL_DET_IGNORE_ADVERTISED    BIT(3)
    
    /* Std Page Register 22 */
    #define MSCC_PHY_EXT_CNTL_STATUS          22
    #define SMI_BROADCAST_WR_EN              BIT(0)
    
    /* Std Page Register 24 */
    #define MSCC_PHY_EXT_PHY_CNTL_2           24
    
    
    
    /* Std Page Register 28 - PHY AUX Control/Status */
    #define MIIM_AUX_CNTRL_STAT_REG		28
    #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO	(0x0004)
    #define MIIM_AUX_CNTRL_STAT_F_DUPLEX	(0x0020)
    #define MIIM_AUX_CNTRL_STAT_SPEED_MASK	(0x0018)
    #define MIIM_AUX_CNTRL_STAT_SPEED_POS	(3)
    #define MIIM_AUX_CNTRL_STAT_SPEED_10M	(0x0)
    #define MIIM_AUX_CNTRL_STAT_SPEED_100M	(0x1)
    #define MIIM_AUX_CNTRL_STAT_SPEED_1000M	(0x2)
    
    
    /* Std Page Register 23 - Extended PHY CTRL_1 */
    #define MSCC_PHY_EXT_PHY_CNTL_1_REG     23
    #define MAC_IF_SELECTION_MASK           (0x1800)
    #define MAC_IF_SELECTION_GMII           (0)
    #define MAC_IF_SELECTION_RMII           (1)
    #define MAC_IF_SELECTION_RGMII          (2)
    #define MAC_IF_SELECTION_POS            (11)
    #define MAC_IF_SELECTION_WIDTH          (2)
    #define VSC8584_MAC_IF_SELECTION_MASK     BIT(12)
    #define VSC8584_MAC_IF_SELECTION_SGMII    0
    #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
    #define VSC8584_MAC_IF_SELECTION_POS      12
    #define MEDIA_OP_MODE_MASK                GENMASK(10, 8)
    #define MEDIA_OP_MODE_COPPER              0
    #define MEDIA_OP_MODE_SERDES              1
    #define MEDIA_OP_MODE_1000BASEX           2
    #define MEDIA_OP_MODE_100BASEFX           3
    #define MEDIA_OP_MODE_AMS_COPPER_SERDES   5
    #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX      6
    #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX      7
    #define MEDIA_OP_MODE_POS                 8
    
    
    /* Std Page Register 23 - Extended PHY CTRL_1 */
    /*#define MSCC_PHY_EXT_PHY_CNTL_1_REG	23
    #define MAC_IF_SELECTION_MASK		(0x1800)
    #define MAC_IF_SELECTION_GMII		(0)
    #define MAC_IF_SELECTION_RMII		(1)
    #define MAC_IF_SELECTION_RGMII		(2)
    #define MAC_IF_SELECTION_POS		(11)
    #define MAC_IF_SELECTION_WIDTH		(2)
    */
    
    /* Extended Page 1 Register 20E1 */
    #define MSCC_PHY_ACTIPHY_CNTL             20
    #define PHY_ADDR_REVERSED                 BIT(9)
    
    /* Extended Page 1 Register 23E1 */
    
    #define MSCC_PHY_EXT_PHY_CNTL_4           23
    #define PHY_CNTL_4_ADDR_POS               11
    
    /* Extended Page 1 Register 25E1 */
    #define MSCC_PHY_VERIPHY_CNTL_2         25
    
    /* Extended Page 1 Register 26E1 */
    #define MSCC_PHY_VERIPHY_CNTL_3         26
    
    /* Extended Page 2 Register 16E2 */
    #define MSCC_PHY_CU_PMD_TX_CNTL         16
    
    
    
    /* Extended Page 2 Register 20E2 */
    #define MSCC_PHY_RGMII_CNTL_REG		20
    #define VSC_FAST_LINK_FAIL2_ENA_MASK	(0x8000)
    #define RX_CLK_OUT_MASK			(0x0800)
    #define RX_CLK_OUT_POS			(11)
    #define RX_CLK_OUT_WIDTH		(1)
    #define RX_CLK_OUT_NORMAL		(0)
    #define RX_CLK_OUT_DISABLE		(1)
    #define RGMII_RX_CLK_DELAY_POS		(4)
    #define RGMII_RX_CLK_DELAY_WIDTH	(3)
    #define RGMII_RX_CLK_DELAY_MASK		(0x0070)
    #define RGMII_TX_CLK_DELAY_POS		(0)
    #define RGMII_TX_CLK_DELAY_WIDTH	(3)
    #define RGMII_TX_CLK_DELAY_MASK		(0x0007)
    
    /* Extended Page 2 Register 27E2 */
    #define MSCC_PHY_WOL_MAC_CONTROL	27
    #define EDGE_RATE_CNTL_POS		(5)
    #define EDGE_RATE_CNTL_WIDTH		(3)
    #define EDGE_RATE_CNTL_MASK		(0x00E0)
    #define RMII_CLK_OUT_ENABLE_POS		(4)
    #define RMII_CLK_OUT_ENABLE_WIDTH	(1)
    #define RMII_CLK_OUT_ENABLE_MASK	(0x10)
    
    
    /* Extended Page 3 Register 22E3 */
    #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT  22
    
    /* Extended page GPIO register 00G */
    #define MSCC_DW8051_CNTL_STATUS         0
    #define MICRO_NSOFT_RESET               BIT(15)
    #define RUN_FROM_INT_ROM                BIT(14)
    #define AUTOINC_ADDR                    BIT(13)
    #define PATCH_RAM_CLK                   BIT(12)
    #define MICRO_PATCH_EN                  BIT(7)
    #define DW8051_CLK_EN                   BIT(4)
    #define MICRO_CLK_EN                    BIT(3)
    #define MICRO_CLK_DIVIDE(x)             ((x) >> 1)
    #define MSCC_DW8051_VLD_MASK            0xf1ff
    
    /* Extended page GPIO register 09G */
    #define MSCC_TRAP_ROM_ADDR(x)           ((x) * 2 + 1)
    #define MSCC_TRAP_ROM_ADDR_SERDES_INIT  0x3eb7
    
    /* Extended page GPIO register 10G */
    #define MSCC_PATCH_RAM_ADDR(x)          (((x) + 1) * 2)
    #define MSCC_PATCH_RAM_ADDR_SERDES_INIT 0x4012
    
    /* Extended page GPIO register 11G */
    #define MSCC_INT_MEM_ADDR               11
    
    /* Extended page GPIO register 12G */
    #define MSCC_INT_MEM_CNTL               12
    #define READ_SFR                        (BIT(14) | BIT(13))
    #define READ_PRAM                       BIT(14)
    #define READ_ROM                        BIT(13)
    #define READ_RAM                        (0x00 << 13)
    #define INT_MEM_WRITE_EN                BIT(12)
    #define EN_PATCH_RAM_TRAP_ADDR(x)       BIT((x) + 7)
    #define INT_MEM_DATA_M                  GENMASK(7, 0)
    #define INT_MEM_DATA(x)                 (INT_MEM_DATA_M & (x))
    
    /* Extended page GPIO register 18G */
    #define MSCC_PHY_PROC_CMD                 18
    #define PROC_CMD_NCOMPLETED               BIT(15)
    #define PROC_CMD_FAILED                   BIT(14)
    #define PROC_CMD_SGMII_PORT(x)            ((x) << 8)
    #define PROC_CMD_FIBER_PORT(x)            BIT(8 + (x) % 4)
    #define PROC_CMD_QSGMII_PORT              (BIT(11) | BIT(10))
    #define PROC_CMD_RST_CONF_PORT            BIT(7)
    #define PROC_CMD_RECONF_PORT              (0 << 7)
    #define PROC_CMD_READ_MOD_WRITE_PORT      BIT(6)
    #define PROC_CMD_WRITE                    BIT(6)
    #define PROC_CMD_READ                     (0 << 6)
    #define PROC_CMD_FIBER_DISABLE            BIT(5)
    #define PROC_CMD_FIBER_100BASE_FX         BIT(4)
    #define PROC_CMD_FIBER_1000BASE_X         (0 << 4)
    #define PROC_CMD_SGMII_MAC                (BIT(5) | BIT(4))
    #define PROC_CMD_QSGMII_MAC               BIT(5)
    #define PROC_CMD_NO_MAC_CONF              (0x00 << 4)
    #define PROC_CMD_1588_DEFAULT_INIT        BIT(4)
    #define PROC_CMD_NOP                      GENMASK(3, 0)
    #define PROC_CMD_PHY_INIT                 (BIT(3) | BIT(1))
    #define PROC_CMD_CRC16                    BIT(3)
    #define PROC_CMD_FIBER_MEDIA_CONF         BIT(0)
    #define PROC_CMD_MCB_ACCESS_MAC_CONF      (0x0000 << 0)
    #define PROC_CMD_NCOMPLETED_TIMEOUT_MS    500
    
    /* Extended page GPIO register 14G */
    #define MSCC_PHY_COMA_MODE                14
    #define GPIO_COMA_MODE_POS               (13)
    #define GPIO_COMA_MODE_WIDTH             (1)
    
    /* Extended page GPIO register 19G */
    #define MSCC_PHY_MAC_CFG_FASTLINK         19
    #define MAC_CFG_MASK                      GENMASK(15, 14)
    #define MAC_CFG_SGMII                     (0x00 << 14)
    #define MAC_CFG_QSGMII                    BIT(14)
    
    /* Test Registers */
    #define MSCC_PHY_TEST_PAGE_5            5
    
    #define MSCC_PHY_TEST_PAGE_8            8
    #define TR_CLK_DISABLE                  BIT(15)
    
    #define MSCC_PHY_TEST_PAGE_9            9
    #define MSCC_PHY_TEST_PAGE_20           20
    #define MSCC_PHY_TEST_PAGE_24           24
    
    
    
    /* Token Ring Page 0x52B5 Registers */
    #define MSCC_PHY_REG_TR_ADDR_16		16
    #define MSCC_PHY_REG_TR_DATA_17		17
    #define MSCC_PHY_REG_TR_DATA_18		18
    
    /* Token Ring - Read Value in */
    #define MSCC_PHY_TR_16_READ		(0xA000)
    /* Token Ring - Write Value out */
    #define MSCC_PHY_TR_16_WRITE		(0x8000)
    
    /* Token Ring Registers */
    #define MSCC_PHY_TR_LINKDETCTRL_POS	(3)
    #define MSCC_PHY_TR_LINKDETCTRL_WIDTH	(2)
    #define MSCC_PHY_TR_LINKDETCTRL_VAL	(3)
    #define MSCC_PHY_TR_LINKDETCTRL_MASK	(0x0018)
    #define MSCC_PHY_TR_LINKDETCTRL_ADDR	(0x07F8)
    
    #define MSCC_PHY_TR_VGATHRESH100_POS	(0)
    #define MSCC_PHY_TR_VGATHRESH100_WIDTH	(7)
    #define MSCC_PHY_TR_VGATHRESH100_VAL	(0x0018)
    #define MSCC_PHY_TR_VGATHRESH100_MASK	(0x007f)
    #define MSCC_PHY_TR_VGATHRESH100_ADDR	(0x0FA4)
    
    #define MSCC_PHY_TR_VGAGAIN10_U_POS	(0)
    #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH	(1)
    #define MSCC_PHY_TR_VGAGAIN10_U_MASK	(0x0001)
    #define MSCC_PHY_TR_VGAGAIN10_U_VAL	(0)
    
    #define MSCC_PHY_TR_VGAGAIN10_L_POS	(12)
    #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH	(4)
    #define MSCC_PHY_TR_VGAGAIN10_L_MASK	(0xf000)
    #define MSCC_PHY_TR_VGAGAIN10_L_VAL	(0x0001)
    #define MSCC_PHY_TR_VGAGAIN10_ADDR	(0x0F92)
    
    /* General Timeout Values */
    #define MSCC_PHY_RESET_TIMEOUT		(100)
    #define MSCC_PHY_MICRO_TIMEOUT		(500)
    
    #define VSC8584_REVB            0x0001
    #define MSCC_DEV_REV_MASK       GENMASK(3, 0)
    
    #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
    #define MSCC_VSC8574_REVB_INT8051_FW_CRC        0x29e8
    
    #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR 0xe800
    #define MSCC_VSC8584_REVB_INT8051_FW_CRC        0xfb48
    
    
    /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
    	VSC_PHY_RGMII_DELAY_200_PS,
    	VSC_PHY_RGMII_DELAY_800_PS,
    	VSC_PHY_RGMII_DELAY_1100_PS,
    	VSC_PHY_RGMII_DELAY_1700_PS,
    	VSC_PHY_RGMII_DELAY_2000_PS,
    	VSC_PHY_RGMII_DELAY_2300_PS,
    	VSC_PHY_RGMII_DELAY_2600_PS,
    	VSC_PHY_RGMII_DELAY_3400_PS,
    };
    
    /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2  */ enum
    vsc_phy_clk_slew {
    	VSC_PHY_CLK_SLEW_RATE_0,
    	VSC_PHY_CLK_SLEW_RATE_1,
    	VSC_PHY_CLK_SLEW_RATE_2,
    	VSC_PHY_CLK_SLEW_RATE_3,
    	VSC_PHY_CLK_SLEW_RATE_4,
    	VSC_PHY_CLK_SLEW_RATE_5,
    	VSC_PHY_CLK_SLEW_RATE_6,
    	VSC_PHY_CLK_SLEW_RATE_7,
    };
    
    
    static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
    {
    	u16	reg_val;
    
    	/* Set to Access Token Ring Registers */
    	phy_write(phydev, MDIO_DEVAD_NONE,
    			MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
    
    	/* Update LinkDetectCtrl default to optimized values */
    	/* Determined during Silicon Validation Testing */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
    	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
    			MSCC_PHY_TR_LINKDETCTRL_WIDTH,
    			MSCC_PHY_TR_LINKDETCTRL_VAL);
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
    
    	/* Update VgaThresh100 defaults to optimized values */
    	/* Determined during Silicon Validation Testing */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
    	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
    			MSCC_PHY_TR_VGATHRESH100_WIDTH,
    			MSCC_PHY_TR_VGATHRESH100_VAL);
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
    
    	/* Update VgaGain10 defaults to optimized values */
    	/* Determined during Silicon Validation Testing */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
    	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
    			MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
    			MSCC_PHY_TR_VGAGAIN10_U_VAL);
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
    	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
    			MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
    			MSCC_PHY_TR_VGAGAIN10_L_VAL);
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
    			(MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
    
    	/* Set back to Access Standard Page Registers */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_STD);
    
    	return 0;
    }
    
    static int mscc_parse_status(struct phy_device *phydev)
    {
    	u16 speed;
    	u16 mii_reg;
    
    	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
    
    	if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
    		phydev->duplex = DUPLEX_FULL;
    	else
    		phydev->duplex = DUPLEX_HALF;
    
    	speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
    	speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
    
    	switch (speed) {
    		case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
    			phydev->speed = SPEED_1000;
    			break;
    		case MIIM_AUX_CNTRL_STAT_SPEED_100M:
    			phydev->speed = SPEED_100;
    			break;
    		case MIIM_AUX_CNTRL_STAT_SPEED_10M:
    			phydev->speed = SPEED_10;
    			break;
    		default:
    			phydev->speed = SPEED_10;
    			break;
    	}
    
    	// printf("%s phy set speed :%d duples :%d\n", __func__, phydev->speed, phydev->duplex);
    	return 0;
    }
    
    static int mscc_startup(struct phy_device *phydev)
    {
    	int retval;
    
    	retval = genphy_update_link(phydev);
    
    	if (retval)
    	{
    		printf("%s ret :%d before parse status \n", __func__, retval);
    		return retval;
    	}
    	return mscc_parse_status(phydev);
    }
    
    static int mscc_phy_soft_reset(struct phy_device *phydev)
    {
    	int     retval = 0;
    	u16     timeout = MSCC_PHY_RESET_TIMEOUT;
    	u16     reg_val = 0;
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_STD);
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
    	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
    	udelay(1000);   /* 1 ms */		//LFT
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
    
    	while ((reg_val & BMCR_RESET) && (timeout > 0)) {
    		reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
    		timeout--;
    		udelay(1000);   /* 1 ms */
    	}
    
    	if (timeout == 0) {
    		printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
    				phydev->interface);
    		retval = -ETIME;
    	}
    
    	return retval;
    }
    
    static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
    {
    	u16	reg_val = 0;
    	u16	mac_if = 0;
    	u16	rx_clk_out = 0;
    
    	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
    	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
    	/* Setup MAC Configuration */
    	switch (phydev->interface) {
    		case PHY_INTERFACE_MODE_MII:
    		case PHY_INTERFACE_MODE_GMII:
    			/* Set Reg23.12:11=0 */
    			mac_if = MAC_IF_SELECTION_GMII;
    			/* Set Reg20E2.11=1 */
    			rx_clk_out = RX_CLK_OUT_DISABLE;
    			break;
    
    		case PHY_INTERFACE_MODE_RMII:
    			/* Set Reg23.12:11=1 */
    			mac_if = MAC_IF_SELECTION_RMII;
    			/* Set Reg20E2.11=0 */
    			rx_clk_out = RX_CLK_OUT_NORMAL;
    			break;
    
    		case PHY_INTERFACE_MODE_RGMII:
    			/* Set Reg23.12:11=2 */
    			mac_if = MAC_IF_SELECTION_RGMII;
    			/* Set Reg20E2.11=0 */
    			rx_clk_out = RX_CLK_OUT_NORMAL;
    			printf("\n********************UBOOT  MSCC.C vsc8531_MAC_config function************************* \n");
    			break;
    
    		default:
    			printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
    					phydev->interface);
    			return -EINVAL;
    	}
    
    	//Letting the PHY know that its going to communicate on RGMII with MAC
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_STD);
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
    			MSCC_PHY_EXT_PHY_CNTL_1_REG);
    	/* Set MAC i/f bits Reg23.12:11 */
    	reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
    			MAC_IF_SELECTION_WIDTH, mac_if);
    	/* Update Reg23.12:11 */
    	phy_write(phydev, MDIO_DEVAD_NONE,
    			MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
    
    	/* Setup ExtPg_2 Register Access */
    	phy_write(phydev, MDIO_DEVAD_NONE,
    			MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
    	/* Read Reg20E2 */
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
    			MSCC_PHY_RGMII_CNTL_REG);
    	reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
    			RX_CLK_OUT_WIDTH, rx_clk_out);
    	/* Update Reg20E2.11 */
    	phy_write(phydev, MDIO_DEVAD_NONE,
    			MSCC_PHY_RGMII_CNTL_REG, reg_val);
    	/* Before leaving - Change back to Std Page Register Access */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_STD);
    
    	return 0;
    }
    
    static int vsc8531_config(struct phy_device *phydev)
    {
    	unsigned int Ret=2;
    	long delay_cnt=0;	
    
    	gpio_request(GPIO_FLASH_MUX_CTRL, "flash_ctrl_en");
    	gpio_direction_output(GPIO_FLASH_MUX_CTRL, 0);
    	udelay(200000);
    
    	gpio_request(GPIO_PROGRAM_B, "Program_b");
    	gpio_direction_output(GPIO_PROGRAM_B, 0);
    	udelay(100000);
    
    	gpio_request(GPIO_PROGRAM_B, "Program_b");
    	gpio_direction_output(GPIO_PROGRAM_B, 1);
    	udelay(100000);
    
    
    	//udelay(8000000);
    	gpio_request(GPIO_DONE_LED, "gpio_done_led");
    	gpio_direction_input(GPIO_DONE_LED);
    	udelay(100000);
    
    	//gpio_request(GPIO_INIT_B, "gpio_init_b");
    	//gpio_direction_output(GPIO_INIT_B, 1);
    	//udelay(200000);
    	while(delay_cnt<400)
    	{
    		Ret = Gpio_get_value(GPIO_DONE_LED,"gpio_done_led");
    		if(Ret == 1) 
    		{
    			gpio_request(GPIO_FLASH_MUX_CTRL, "flash_ctrl_en");
    			gpio_direction_output(GPIO_FLASH_MUX_CTRL, 1);
    			udelay(200000);
    			break;
    		}
    		else
    		{
    			udelay(10000);
    			delay_cnt++;
    		}
    	}
    
    	int  retval = -EINVAL;
    	u16  reg_val;
    	u16  coma_mode_pin=0;
    	u16  rmii_clk_out;
    	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
    	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
    	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
    
    	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
    	mscc_vsc8531_vsc8541_init_scripts(phydev);
    
    	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
    	switch (phydev->interface) {
    		case PHY_INTERFACE_MODE_RMII:
    		case PHY_INTERFACE_MODE_RGMII:
    			retval = vsc8531_vsc8541_mac_config(phydev);
    			if (retval != 0)
    				return retval;
    
    			retval = mscc_phy_soft_reset(phydev);
    			if (retval != 0)
    				return retval;
    			break;
    		default:
    			printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
    					phydev->interface);
    			return -EINVAL;
    	}
    	/* Default RMII Clk Output to 0=OFF/1=ON  */
    	rmii_clk_out = 0;
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_EXT2);
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
    
    	/* Reg20E2 - Update RGMII RX_Clk Skews. */
    	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
    			RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
    	/* Reg20E2 - Update RGMII TX_Clk Skews. */
    	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
    			RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
    	/* Reg27E2 - Update Clk Slew Rate. */
    	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
    			EDGE_RATE_CNTL_WIDTH, edge_rate);
    	/* Reg27E2 - Update RMII Clk Out. */
    	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
    			RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
    	/* Update Reg27E2 */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
    
    	genphy_config_aneg(phydev);
    	mscc_phy_soft_reset(phydev);
    	return 0; 
    }
    
    static int vsc8541_config(struct phy_device *phydev)
    {
    	int  retval = -EINVAL;
    	u16  reg_val;
    	u16  rmii_clk_out;
    	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
    	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
    	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
    
    	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
    
    	//mscc_vsc8531_vsc8541_init_scripts(phydev);		
    
    	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
    	switch (phydev->interface) {
    		case PHY_INTERFACE_MODE_MII:
    		case PHY_INTERFACE_MODE_GMII:
    		case PHY_INTERFACE_MODE_RMII:
    		case PHY_INTERFACE_MODE_RGMII:
    			retval = vsc8531_vsc8541_mac_config(phydev);
    			if (retval != 0)
    				return retval;
    
    			retval = mscc_phy_soft_reset(phydev);
    			if (retval != 0)
    				return retval;
    			break;
    		default:
    			printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
    					phydev->interface);
    			return -EINVAL;
    	}
    	/* Default RMII Clk Output to 0=OFF/1=ON  */
    	rmii_clk_out = 0;
    
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_EXT2);
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
    	/* Reg20E2 - Update RGMII RX_Clk Skews. */
    	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
    			RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
    	/* Reg20E2 - Update RGMII TX_Clk Skews. */
    	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
    			RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
    
    	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
    	/* Reg27E2 - Update Clk Slew Rate. */
    	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
    			EDGE_RATE_CNTL_WIDTH, edge_rate);
    	/* Reg27E2 - Update RMII Clk Out. */
    	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
    			RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
    	/* Update Reg27E2 */
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
    	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
    			MSCC_PHY_PAGE_STD);
    
    	//return genphy_config_aneg(phydev);
    	genphy_config_aneg(phydev);
    	return 0;
    }
    
    static struct phy_driver VSC8530_driver = {
    	.name = "Microsemi VSC8530",
    	.uid = PHY_ID_VSC8530,
    	.mask = 0x000ffff0,
    	.features = PHY_BASIC_FEATURES,
    	.config = &vsc8531_config,
    	.startup = &mscc_startup,
    	.shutdown = &genphy_shutdown,
    };
    
    static struct phy_driver VSC8531_driver = {
    	.name = "Microsemi VSC8531",
    	.uid = PHY_ID_VSC8531,
    	.mask = 0x000ffff0,
    	.features = PHY_GBIT_FEATURES,
    	.config = &vsc8531_config,
    	.startup = &mscc_startup,
    	.shutdown = &genphy_shutdown,
    };
    
    static struct phy_driver VSC8540_driver = {
    	.name = "Microsemi VSC8540",
    	.uid = PHY_ID_VSC8540,
    	.mask = 0x000ffff0,
    	.features = PHY_BASIC_FEATURES,
    	.config = &vsc8541_config,
    	.startup = &mscc_startup,
    	.shutdown = &genphy_shutdown,
    };
    
    static struct phy_driver VSC8541_driver = {
    	.name = "Microsemi VSC8541",
    	.uid = PHY_ID_VSC8541,
    	.mask = 0x000ffff0,
    	.features = PHY_GBIT_FEATURES,
    	.config = &vsc8541_config,
    	.startup = &mscc_startup,
    	.shutdown = &genphy_shutdown,
    };
    
    int phy_mscc_init(void)
    {
    	phy_register(&VSC8530_driver);
    	phy_register(&VSC8531_driver);
    	phy_register(&VSC8540_driver);
    	phy_register(&VSC8541_driver);
    
    	return 0;
    }
    
    /*
     * Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     */
    
    /*
     * AM335x ICE V2 board
     * http://www.ti.com/tool/tmdsice3359
     */
    
    /dts-v1/;
    
    #include "am33xx.dtsi"
    #include <dt-bindings/interrupt-controller/irq.h>
    #include <dt-bindings/net/ti-dp83867.h>
    #include <dt-bindings/net/mscc-phy-vsc8531.h>
    
    
    / {
    	model = "TI AM3359 ICE-V2";
    	compatible = "ti,am3359-icev2", "ti,am33xx";
    
    	memory@80000000 {
    		device_type = "memory";
    		reg = <0x80000000 0x10000000>; /* 256 MB */
    	};
    
    	chosen {
    		stdout-path = &uart0;
    	};
    
    	vbat: fixedregulator0 {
    		compatible = "regulator-fixed";
    		regulator-name = "vbat";
    		regulator-min-microvolt = <5000000>;
    		regulator-max-microvolt = <5000000>;
    		regulator-boot-on;
    	};
    /*
    	vtt_fixed: fixedregulator1 {
    		compatible = "regulator-fixed";
    		regulator-name = "vtt";
    		regulator-min-microvolt = <1500000>;
    		regulator-max-microvolt = <1500000>;
    		gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>;
    		regulator-always-on;
    		regulator-boot-on;
    		enable-active-high;
    	};
    */
    /*
    	leds-iio {
    		status = "disabled";
    		compatible = "gpio-leds";
    		led-out0 {
    			label = "out0";
    			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out1 {
    			label = "out1";
    			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out2 {
    			label = "out2";
    			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out3 {
    			label = "out3";
    			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out4 {
    			label = "out4";
    			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out5 {
    			label = "out5";
    			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out6 {
    			label = "out6";
    			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    
    		led-out7 {
    			label = "out7";
    			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
    			default-state = "off";
    		};
    	};
    
    	
    	gpio-decoder {
    		compatible = "gpio-decoder";
    		gpios = <&pca9536 3 GPIO_ACTIVE_HIGH>,
    			<&pca9536 2 GPIO_ACTIVE_HIGH>,
    			<&pca9536 1 GPIO_ACTIVE_HIGH>,
    			<&pca9536 0 GPIO_ACTIVE_HIGH>;
    		linux,axis = <0>; // ABS_X
    		decoder-max-value = <9>;
    	};
    */
    	
    };
    
    &am33xx_pinmux {
    
    	i2c0_pins_default: i2c0_pins_default {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
    			AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
    		>;
    	};
    
    #if 0
    	/* Not used in MGCM*/
    	i2c2_pins_default: i2c2_pins_default {
                    pinctrl-single,pins = <
                            AM33XX_IOPAD(0x95C, PIN_INPUT | MUX_MODE3) /* (B16) I2C2_SDA.I2C2_SDA */
                            AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE3) /* (A16) I2C2_SCL.I2C2_SCL */
                    >;
            };
    
    	/* I2C 1 added in MGCM */
    	i2c1_pins_default: i2c1_pins_default {
                    pinctrl-single,pins = <
    			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (E18) uart0_ctsn.i2c1_sda*/ 
    			AM33XX_IOPAD(0x95C, PIN_OUTPUT_PULLUP | MUX_MODE0) /* (E17) uart0_rtsn.i2c1_scl */
                    >;
            };
    
    	gpio0_pins_default: gpio0_pins_default {
    		pinctrl-single,pins = <
    		>;
    	};
    	gpio1_pins_default: gpio1_pins_default {
    		pinctrl-single,pins = <
    			/*AM33XX_IOPAD(0x858, PIN_INPUT_PULLUP | MUX_MODE7)*/	/*GPIO1_22 U15*/
    		>;
    	};
    #endif
    
    	gpio2_pins_default: gpio2_pins_default {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0xa1c, PIN_INPUT_PULLUP | MUX_MODE7) /* (F16) M0 lcd_ac_bias_en.gpio2[25]*/ 
    			AM33XX_IOPAD(0x968, PIN_INPUT | MUX_MODE7) /* (G17) mmc0_dat0.gpio2[29] */
    			AM33XX_IOPAD(0x904, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (G18) mmc0_dat0.gpio2[29] */
    			/*AM33XX_IOPAD(0xa34, PIN_INPUT_PULLUP | MUX_MODE7) /* (F15) USB1_DRVVBUS.gpio3[13] */              /*added for vsc8531*/  
    		>;
    	};
    
    	gpio3_pins_default: gpio3_pins_default {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0xa34, PIN_INPUT_PULLUP | MUX_MODE7) /* (F15) USB1_DRVVBUS.gpio3[13] */              /*added for vsc8531*/  
    			AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE7) /* (F17) mmc0_dat3.gpio2[26] */
    			AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE7) /* (F18) mmc0_dat1.gpio2[28] */
    			AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE7) /* (G15) mmc0_dat0.gpio2[29] */
    			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (G16) mmc0_dat0.gpio2[29] */
    			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE7) /* (G17) mmc0_dat0.gpio2[29] */
    			/*AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE7)*/ /* (G18) mmc0_dat0.gpio2[29] */
    			AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (B12) mcasp0_aclkr.gpio3[18] */
    		>;
    	};
    
    #if 1 
    	spi0_pins_default: spi0_pins_default {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
    			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
    			/*AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0)*/ /* (B16) spi0_d1.spi0_d1 */
    			/*AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0)*/ /* (A16) spi0_cs0.spi0_cs0 */
    			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0) /* (C15) spi0_cs1.spi0_cs1 */
    			/*AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) *//* (B12) mcasp0_aclkr.gpio3[18] */
    		>;
    	};	
    	 spi1_pins_default: spi1_pins_default {
    		pinctrl-single,pins = <
    		AM33XX_IOPAD(0x990, PIN_INPUT_PULLUP | MUX_MODE3) /* (A13) mcasp0_aclkx.spi1_sclk */
    		AM33XX_IOPAD(0x994, PIN_INPUT_PULLUP | MUX_MODE3) /* (B13) mcasp0_fsx.spi1_d0 */
    		AM33XX_IOPAD(0x998, PIN_INPUT_PULLUP | MUX_MODE3) /* (D12) mcasp0_axr0.spi1_d1 */
    		AM33XX_IOPAD(0x99c, PIN_INPUT_PULLUP | MUX_MODE3) /* (C12) mcasp0_ahclkr.spi1_cs0 */
    		>;
    	};
    
    #endif
    	/*DEBUG UART*/
    	uart0_pins_default: uart0_pins_default {
    		pinctrl-single,pins = <
    			AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* (E15) uart0_rxd.uart0_rxd */
    			AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLUP | MUX_MODE0) /* (E16) uart0_txd.uart0_txd */
    		>;
    	};
    	
    	/*HSKP UART FROM GCM TO SGCM*/
    	uart1_pins_default: uart1_pins_default {
    	pinctrl-single,pins = <
    		AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* (D16) uart1_rxd.uart1_rxd */
    		AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLUP | MUX_MODE0) /* (D15) uart1_txd.uart1_txd */
    	>;
    	};
    
    	
    
    	cpsw_default: cpsw_default {
    		pinctrl-single,pins = <
    				/* Slave 1 */
    		AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
    		AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxdv.rgmii1_rctl */
    		AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd3.rgmii1_td3 */
    		AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd2.rgmii1_td2 */
    		AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txd1.rgmii1_td1 */
    		AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* mii1_txd0.rgmii1_td0 */		       
    
                    AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)	/* mii1_txclk.rgmii1_tclk */
    		AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxclk.rgmii1_rclk */
    		AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd3.rgmii1_rd3 */
    		AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd2.rgmii1_rd2 */
    		AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd1.rgmii1_rd1 */
    		AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)	/* mii1_rxd0.rgmii1_rd0 */
    		/*AM33XX_IOPAD(0xA34, PIN_INPUT_PULLUP | MUX_MODE7) /* (F15) USB1_DRVVBUS.gpio3[13] */
    
    		      /*pinmux for max24288*/                
          		AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a0.rgmii2_tctl */
                    AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a1.rgmii2_rctl */
                    AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a2.rgmii2_td3 */
                    AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a3.rgmii2_td2 */
                    AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a4.rgmii2_td1 */
                    AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a5.rgmii2_td0 */
                    AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2)    /* gpmc_a6.rgmii2_tclk */
                    AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a7.rgmii2_rclk */
                    AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a8.rgmii2_rd3 */
                    AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a9.rgmii2_rd2 */
                    AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a10.rgmii2_rd1 */
                    AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2)     /* gpmc_a11.rgmii2_rd0 */ 
    		>;
    	};
    
    	cpsw_sleep: cpsw_sleep {
    		pinctrl-single,pins = <
    		AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J16) gmii1_txen.rgmii1_tctl */
    		AM33XX_IOPAD(0x918, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J17) gmii1_rxdv.rgmii1_rctl */
    		AM33XX_IOPAD(0x92c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K18) gmii1_txclk.rgmii1_tclk */
    		AM33XX_IOPAD(0x930, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L18) gmii1_rxclk.rgmii1_rclk */
    		AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K17) gmii1_txd0.rgmii1_td0 */
    		AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K16) gmii1_txd1.rgmii1_td1 */
    		AM33XX_IOPAD(0x920, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (K15) gmii1_txd2.rgmii1_td2 */
    		AM33XX_IOPAD(0x91c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (J18) gmii1_txd3.rgmii1_td3 */
    		AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (M16) gmii1_rxd0.rgmii1_rd0 */
    		AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L15) gmii1_rxd1.rgmii1_rd1 */
    		AM33XX_IOPAD(0x938, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L16) gmii1_rxd2.rgmii1_rd2 */
    		AM33XX_IOPAD(0x934, (PIN_INPUT_PULLDOWN | MUX_MODE7) ) /* (L17) gmii1_rxd3.rgmii1_rd3 */
    		/*AM33XX_IOPAD(0xA34, PIN_OUTPUT_PULLDOWN | MUX_MODE7)*/
    		/* Slave 2 reset value*/
    	        AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
                    AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)	
    
    		>;
    	};
    
    	davinci_mdio_default: davinci_mdio_default {
    		pinctrl-single,pins = <
    			/* MDIO */
    			AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0))	/* mdio_data.mdio_data */
    			AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0))			/* mdio_clk.mdio_clk */
    
            /*                AM33XX_IOPAD(0x88C, (PIN_OUTPUT_PULLUP | MUX_MODE5) ) /* (V12) gpmc_clk.pr1_mdio_mdclk */
              /*              AM33XX_IOPAD(0x888, (PIN_INPUT_PULLUP | MUX_MODE5) ) /* (T13) gpmc_csn3.pr1_mdio_data*/
    	
    		>;
    	};
    
    	davinci_mdio_sleep: davinci_mdio_sleep {
    		pinctrl-single,pins = <
    			/* MDIO reset value */
    			AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7))
    			AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
    		>;
    	};
            
    	nandflash_pins_s0: nandflash_pins_s0 {
                    pinctrl-single,pins = <
                            AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad0.gpmc_ad0 */
                            AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad1.gpmc_ad1 */
                            AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad2.gpmc_ad2 */
                            AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad3.gpmc_ad3 */
                            AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad4.gpmc_ad4 */
                            AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad5.gpmc_ad5 */
                            AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad6.gpmc_ad6 */
                            AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)       /* gpmc_ad7.gpmc_ad7 */
    			AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad8.gpmc.ad8*/
    			AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad9.gpmc.ad9*/
    			AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad10.gpmc.ad10*/
    			AM33XX_IOPAD(0x82C, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad11.gpmc.ad11*/
    			AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad12.gpmc.ad12*/
    			AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad13.gpmc.ad13*/
    			AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad14.gpmc.ad14*/
    			AM33XX_IOPAD(0x83C, PIN_INPUT_PULLUP | MUX_MODE0)	/*gpmc_ad15.gpmc.ad15*/
    	
    			AM33XX_IOPAD(0x878, PIN_OUTPUT_PULLUP | MUX_MODE0)	/*gpmc_ben1*/
    			AM33XX_IOPAD(0x884, PIN_OUTPUT_PULLUP | MUX_MODE0)	/*gpmc_csn2*/
    			/*AM33XX_IOPAD(0x888, PIN_OUTPUT_PULLUP | MUX_MODE0)*/ 	/* (T13) gpmc_csn3.gpmc_csn3 */
    			AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP  | MUX_MODE0)	/*gpmc_csn1.gpmc_csn1*/
    	/*		AM33XX_IOPAD(0x88C, PIN_INPUT | MUX_MODE0)	*/	/*gpmc_clk.gpmc_clk*/
    
                            AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)      /* gpmc_wait0.gpmc_wait0 */
                            AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE0)      /* gpmc_wpn.gpio0_30 */
                            AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0)     /* gpmc_csn0.gpmc_csn0  */
                            AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0)     /* gpmc_advn_ale.gpmc_advn_ale */
                            AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0)     /* gpmc_oen_ren.gpmc_oen_ren */
                            AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0)     /* gpmc_wen.gpmc_wen */
                            AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0)     /* gpmc_be0n_cle.gpmc_be0n_cle */
    
                    >;
            };
    };
    
    
    &i2c0 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&i2c0_pins_default>;
    
    	status = "okay";
    	clock-frequency = <400000>;
    
    
    	tps: power-controller@2d {
    		reg = <0x2d>;
    	};
    /*
    	tpic2810: gpio@60 {
    		compatible = "ti,tpic2810";
    		reg = <0x60>;
    		gpio-controller;
    		#gpio-cells = <2>;
    	};
    
    	pca9536: gpio@41 {
    		compatible = "ti,pca9536";
    		reg = <0x41>;
    		gpio-controller;
    		#gpio-cells = <2>;
    	};
    */
    };
    #if 0
    &i2c1{
            pinctrl-names = "default";
    	pinctrl-0 = <&i2c1_pins_default>;
    
            compatible = "ti,omap4-i2c";
            #address-cells = <1>;
            #size-cells = <0>;
            ti,hwmods = "i2c2";
            reg = <0x4802a000 0x1000>;
            interrupts = <71>;
    
            status = "okay";
    	clock-frequency = <500000>;
    		ad7414@48 {
    			compatible = "analog,ad7414";
            		reg = <0x48>;
          		  	status = "okay";
        			};
          };
    
    /*I2C inteface b/w Processor and FPGA*/
    &i2c2{
            pinctrl-names = "default";
    	pinctrl-0 = <&i2c1_pins_default>;
    
    	status = "okay";
    	clock-frequency = <500000>; /*for 400KHz added by Chinmay*/ 
    		/*ad7414@4A {
    			compatible = "analog,ad7414";
            		reg = <0x4A>;
          		  	status = "okay";
        			};*/
    };
    #endif
    
    #if 0
    &i2c2{
            pinctrl-names = "default";
    	pinctrl-0 = <&i2c2_pins_default>;
    
    	status = "okay";
    		ad7414@48 {
    			compatible = "analog,ad7414";
            		reg = <0x48>;
          		  	status = "okay";
        			};
    };
    #endif
    
    //#if 0
    &spi0 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&spi0_pins_default>;
    
    	
    	sn65hvs882@1 {
    		compatible = "pisosr-gpio";
    		gpio-controller;
    		#gpio-cells = <2>;
    
    		load-gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
    
    		reg = <1>;
    		spi-max-frequency = <1000000>;
    		spi-cpol;
    	};
    	
    	/*spi_nor: flash@0 { */
    	spi_fpga@1 {
    		#address-cells = <1>;
    		#size-cells = <1>;
    		compatible = "linux,spidev";	
    		/*compatible = "winbond,w25q64", "jedec,spi-nor" , "linux,spidev";*/
    		spi-max-frequency = <20000000>;  /* 20 mhz */
    		m25p,fast-read;
    		reg = <1>;
    
    
    
    	};
    
    };
    //#endif
    &spi1 {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&spi1_pins_default>;
    	
    
    	spidev@0 {
    		#address-cells = <1>;
    		#size-cells = <1>;
    		compatible = "n25q256a","jedec,spi-nor";
    		//compatible = "mt25q256","jedec,spi-nor";
    		/*compatible = "linux,spidev";*/
    		spi-max-frequency = <2000000>;
    		m25p,fast-read;
    		reg = <0x0>;
    
    		partition@0 {
    			label = "spi1_partition";
    			reg = <0x0 0x2000000>;
    		};
    	};
    };
    
    /*
    &spi1
    {
        pinctrl-names = "default";
        pinctrl-0 = <&spi1_pins_default>;
        ti,pindir-d0-out-d1-in = <1>;
         status = "okay";
         spidev@0
            {
              #address-cells = <1>;
              #size-cells = <0>;
              compatible ="rohm,dh2228fv";
              spi-max-frequency = <48000000>;
              reg = <0x0>;
            };
    
    };
    
    #endif
    */
    &tscadc {
    	status = "okay";
    	adc {
    		ti,adc-channels = <1 2 3 4 5 6 7>;
    	};
    };
    
    #include "tps65910.dtsi"
    &tps {
    	vcc1-supply = <&vbat>;
    	vcc2-supply = <&vbat>;
    	vcc3-supply = <&vbat>;
    	vcc4-supply = <&vbat>;
    	vcc5-supply = <&vbat>;
    	vcc6-supply = <&vbat>;
    	vcc7-supply = <&vbat>;
    	vccio-supply = <&vbat>;
    
    	regulators {
    		vrtc_reg: regulator@0 {
    			regulator-always-on;
    		};
    
    		vio_reg: regulator@1 {
    			regulator-always-on;
    		};
    
    		vdd1_reg: regulator@2 {
    			regulator-name = "vdd_mpu";
    			regulator-min-microvolt = <912500>;
    			regulator-max-microvolt = <1326000>;
    			regulator-boot-on;
    			regulator-always-on;
    		};
    
    		vdd2_reg: regulator@3 {
    			regulator-name = "vdd_core";
    			regulator-min-microvolt = <912500>;
    			regulator-max-microvolt = <1144000>;
    			regulator-boot-on;
    			regulator-always-on;
    		};
    
    		vdd3_reg: regulator@4 {
    			regulator-always-on;
    		};
    
    		vdig1_reg: regulator@5 {
    			regulator-always-on;
    		};
    
    		vdig2_reg: regulator@6 {
    			regulator-always-on;
    		};
    
    		vpll_reg: regulator@7 {
    			regulator-always-on;
    		};
    
    		vdac_reg: regulator@8 {
    			regulator-always-on;
    		};
    
    		vaux1_reg: regulator@9 {
    			regulator-always-on;
    		};
    
    		vaux2_reg: regulator@10 {
    			regulator-always-on;
    		};
    
    		vaux33_reg: regulator@11 {
    			regulator-always-on;
    		};
    
    		vmmc_reg: regulator@12 {
    			regulator-min-microvolt = <1800000>;
    			regulator-max-microvolt = <3300000>;
    			regulator-always-on;
    		};
    	};
    };
    
    
    #if 0
    &gpio0 {
    	/* Do not idle the GPIO used for holding the VTT regulator */
    	ti,no-reset-on-init;
    	ti,no-idle-on-init;
    	pinctrl-names = "default";
    	pinctrl-0 = <&gpio0_pins_default>;
    	status = "okay";
    };
    
    &gpio1 {
    	/* Do not idle the GPIO used for holding the VTT regulator */
    	ti,no-reset-on-init;
    	ti,no-idle-on-init;
    	pinctrl-names = "default";
    	pinctrl-0 = <&gpio1_pins_default>;
    	status = "okay";
    };
    
    #endif
    
    &gpio2 {
    	/* Do not idle the GPIO used for holding the VTT regulator */
    	ti,no-reset-on-init;
    	ti,no-idle-on-init;
    	pinctrl-names = "default";
    	pinctrl-0 = <&gpio2_pins_default>;
    	status = "okay";
    
    };
    
    &gpio3 {
    	/* Do not idle the GPIO used for holding the VTT regulator */
    	ti,no-reset-on-init;
    	ti,no-idle-on-init;
    	pinctrl-names = "default";
    	pinctrl-0 = <&gpio3_pins_default>;
    	status = "okay";
    
    };
    
    
    /*DEBUG UART*/
    &uart0 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&uart0_pins_default>;
    	status = "okay";
    };
    
    /*HSKP UART*/
    &uart1 {
    	pinctrl-names = "default";
    	pinctrl-0 = <&uart1_pins_default>;
    	status = "okay";
    };
    
    
    &mac {
            pinctrl-names = "default", "sleep";
            pinctrl-0 = <&cpsw_default>;
            pinctrl-1 = <&cpsw_sleep>;
    	slaves = <2>;    
    	active_slave = <1>;                          //added
            dual_emac;                               //commented
            status = "okay";
    };
    
    
    &davinci_mdio {
            pinctrl-names = "default", "sleep";
            compatible = "ti,cpsw-mdio","ti,davinci_mdio";
    	pinctrl-0 = <&davinci_mdio_default>;
            pinctrl-1 = <&davinci_mdio_sleep>;
            status = "okay";
            reset-gpios                = <&gpio3 13 GPIO_ACTIVE_HIGH>;
            //reset-gpios                = <&gpio3 13 GPIO_ACTIVE_HIGH>, <&gpio3 21 GPIO_ACTIVE_HIGH>;
            //reset-gpios                = <&gpio3 13 GPIO_ACTIVE_LOW>;
    	reset-delay-us = <2>;
    /*
    #if 1 
    
    	ethphy3: ethernet-phy@3 {                                           //added block
            reg = <3>;
            compatible              = "ethernet-phy-id0007.0570";
            vsc8531,vddmac          = <3300>;
            vsc8531,edge-slowdown   = <7>;
            vsc8531,led-0-mode      = <VSC8531_LINK_1000_ACTIVITY>;
            vsc8531,led-1-mode      = <VSC8531_LINK_100_ACTIVITY>;
            reset-gpios                = <&gpio3 13 GPIO_ACTIVE_HIGH>;
            //reset-gpios                = <&gpio1 22 GPIO_ACTIVE_HIGH>;
            };
    	
    	ethphy0: ethernet-phy@0 {                                           //added block
            reg = <0>;
            compatible              = "ethernet-phy-id0007.0570";
            vsc8531,vddmac          = <3300>;
            vsc8531,edge-slowdown   = <7>;
            vsc8531,led-0-mode      = <VSC8531_LINK_1000_ACTIVITY>;
            vsc8531,led-1-mode      = <VSC8531_LINK_100_ACTIVITY>;
            reset-gpios                = <&gpio3 13 GPIO_ACTIVE_HIGH>;
            //reset-gpios                = <&gpio1 22 GPIO_ACTIVE_HIGH>;
            };
    #endif
    */
    
    };
    &cpsw_emac0 {
            phy_id = <&davinci_mdio>, <0>;
            phy-mode = "rgmii-txid"; 
            dual_emac_res_vlan = <1>;
    };
    
    &cpsw_emac1 {
            phy_id = <&davinci_mdio>, <3>;
            phy-mode = "rgmii-txid";
            dual_emac_res_vlan = <2>;
    };
    
    
    
    &elm{
    status = "okay"; 
    };
    
    &gpmc {
    	status = "okay";
    	pinctrl-names = "default";
    	pinctrl-0 = <&nandflash_pins_s0>;
    	ranges = <0 0 0x08000000 0x01000000>,	/*CSn0 for NAND*/
            	 <2 0 0x09000000 0x01000000>;   /*CSn2 for FPGA*/
    	nand@0,0 {
    		compatible = "ti,omap2-nand";
    		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
    		rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
    		ti,nand-xfer-type = "prefetch-dma";
    		ti,nand-ecc-opt = "bch8";
    		ti,elm-id = <&elm>;
    		nand-bus-width = <16>;
    		gpmc,device-width = <1>;
    		gpmc,sync-clk-ps = <0>;
    		gpmc,cs-on-ns = <0>;
    		gpmc,cs-rd-off-ns = <44>;
    		gpmc,cs-wr-off-ns = <44>;
    		gpmc,adv-on-ns = <6>;
    		gpmc,adv-rd-off-ns = <34>;
    		gpmc,adv-wr-off-ns = <44>;
    		gpmc,we-on-ns = <0>;
    		gpmc,we-off-ns = <40>;
    		gpmc,oe-on-ns = <0>;
    		gpmc,oe-off-ns = <54>;
    		gpmc,access-ns = <64>;
    		gpmc,rd-cycle-ns = <82>;
    		gpmc,wr-cycle-ns = <82>;
    		gpmc,bus-turnaround-ns = <0>;
    		gpmc,cycle2cycle-delay-ns = <0>;
    		gpmc,clk-activation-ns = <0>;
    		gpmc,wr-access-ns = <40>;
    		gpmc,wr-data-mux-bus-ns = <0>;
    		/* MTD partition table */
    		/* All SPL-* partitions are sized to minimal length
    		 * which can be independently programmable. For
    		 * NAND flash this is equal to size of erase-block */
    		#address-cells = <1>;
    		#size-cells = <1>;
    		partition@0 {
    			label = "NAND.SPL";
    			reg = <0x00000000 0x000020000>;
    		};
    		partition@1 {
    			label = "NAND.SPL.backup1";
    			reg = <0x00020000 0x00020000>;
    		};
    		partition@2 {
    			label = "NAND.SPL.backup2";
    			reg = <0x00040000 0x00020000>;
    		};
    		partition@3 {
    			label = "NAND.SPL.backup3";
    			reg = <0x00060000 0x00020000>;
    		};
    		partition@4 {
    			label = "NAND.u-boot-spl-os";
    			reg = <0x00080000 0x00040000>;
    		};
    		partition@5 {
    			label = "NAND.u-boot";
    			reg = <0x000C0000 0x00100000>;
    		};
    		partition@6 {
    			label = "NAND.u-boot-env";
    			reg = <0x001C0000 0x00020000>;
    		};
    		partition@7 {
    			label = "NAND.u-boot-env.backup1";
    			reg = <0x001E0000 0x00020000>;
    		};
    
    		partition@8 {
    			label = "NAND.kernel";
    			reg = <0x00200000 0x00800000>;
    		};
    		partition@9 {
    			label = "NAND.file-system";
    			reg = <0x00A00000 0x0F600000>;
     
    		};
    /*
    
    		partition@8 {
    			label = "NAND.kernel";
    			reg = <0x00200000 0x1000000>;
    		};
    		partition@9 {
    			label = "NAND.file-system";
    			reg = <0x00E00000 0x01200000>;
    		};
    */
    };
    
    
    	fpga@2,0{
    	     reg = <2 0 0x01000000>; /*CSn2*/
                 compatible = "cet,am335x-dma-test";
       	     #address-cells = <1>;
    	     #size-cells = <1>;
                 bank-width = <2>; /* GPMC_CONFIG1_DEVICESIZE(1) *//*16 bit wide*/
    	     interrupt-parent = <&gpmc>;
    	     interrupts = <0 0>, <1 0>;
                 /*gpmc,burst-write;*/
                 /*gpmc,burst-read;*/
                 /*gpmc,burst-wrap;*/
                 gpmc,sync-read; /* GPMC_CONFIG1_READTYPE_ASYNC */
                 gpmc,sync-write; /* GPMC_CONFIG1_WRITETYPE_ASYNC */
                 gpmc,clk-activation-ns = <0>; /* GPMC_CONFIG1_CLKACTIVATIONTIME(2) */
                 gpmc,burst-length = <16>; /* GPMC_CONFIG1_PAGE_LEN(2) */
                 gpmc,mux-add-data = <0>; /* GPMC_CONFIG1_MUXTYPE(2) */
    
                 gpmc,sync-clk-ps = <0>; /* CONFIG2 20000*/
    
                 gpmc,cs-on-ns = <10>;       /*10*/
                 gpmc,cs-rd-off-ns = <30>;  /*default 100*/
                 gpmc,cs-wr-off-ns = <0>;  /*10*/
    
                 gpmc,adv-on-ns = <0>; /* CONFIG3 */
                 gpmc,adv-rd-off-ns = <10>;
                 gpmc,adv-wr-off-ns = <0>; /*10*/
    
                 gpmc,we-on-ns = <0>; /*10*//* CONFIG4 */
                 gpmc,we-off-ns = <0>;/*10*/
                 gpmc,oe-on-ns = <10>;
                 gpmc,oe-off-ns = <30>;/*100*/
    
                 gpmc,page-burst-access-ns = <10>; /* CONFIG 5 */
                 gpmc,access-ns = <10>; /*80*/
                 gpmc,rd-cycle-ns = <20>;/*default 120*/
                 gpmc,wr-cycle-ns = <0>;/*60*/
                 gpmc,wr-access-ns = <10>; /* CONFIG 6 */
                 gpmc,wr-data-mux-bus-ns = <20>;
    
                 gpmc,bus-turnaround-ns = <40>; /* CONFIG6:3:0 = 4 */
                 gpmc,cycle2cycle-samecsen; /* CONFIG6:7 = 1 */
                 gpmc,cycle2cycle-delay-ns = <20>; /* CONFIG6:11:8 = 4 */
    
    /* not using dma engine yet, but we can get the channel number here */
              /*   dmas = <&edma 1>;*/
              /*   dma-names = "rxtx";*/
    	      };
    };