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.

Phy GigaEthernet to replace AR8031 with KSZ9021 (micrel)

Hi,

I'm using AM335x MPU, i'm planing to use micrel KSZ9021RL gigabit PHY on AM335x.

is the ethernet device drive from AM335x EVM SDK is generic?

Thanks

Keldy

  • Keldy

    Ethernet driver is generic and doesn't depend on PHY. If the phy has no errata, then generic phy driver in the linux should work fine.

    with regards

    Mugunthan V N

  • Hi Mugunthan,

    the ethernet driver is generic in the linux, How about in u-boot ?

    Thanks & Regards

    Keldy

  • Keldy

    U-Boot CPSW driver is also generic.

    with regards

    Mugunthan V N

  • Hi Mugunthan,

    After I replace AR8031 phy with micrel KSZ9021RL phy,

    in u-boot, when i enter "dhcp",

    u-boot#dhcp

    link up on port 1, speed 100, full duplex

    BOOTP broadcast 1

    BOOTP broadcast 2

    BOOTP broadcast 3

    BOOTP broadcast 4

    .....until BOOTP broadcast 10 then repeat again

    seen like the ethernet can't work properly and can't get IP address.

    Why this will happen?

    Do i need to change something in u-boot code, like the phy device id, phyaddr or others thing else?

    Thanks & Regards

    Keldy

  • Keldy

    U-Boot Supports only EMAC 0 by default. From the logs it shows that Ethernet is connected to EMAC 1.

    Did you ported U-Boot to support EMAC 1 from the Porting guide Wiki.

    http://processors.wiki.ti.com/index.php/TI81xx_PSP_Porting_Guide#CPSW_EMAC_1_bringup_in_uboot

    If you have two eEthernet pinned out, can you try connecting with EMAC0.

    with regards

    Mugunthan V N

  • Hi Mugunthan,

    The Micrel KSZ9021RL phy is connected to EMAC 0.

    i think in u-boot,  the EMAC 0  refer as port 1, EMAC 1 refer as port 2. same as i2c0 refer as i2c-1.

    Thanks & Regards

    Keldy 

  • Hi,

    I'm using AM335x MPU, that have only one EMAC and two port, port 1 and port 2. The micrel KSZ9021RL phy was connected to the port 1.

    Port 1 previously connected to Atheros AR8031 phy which is working properly, when i change to micrel KSZ9021RL phy, the ethernet not working anymore.

    Any idea?

    Thanks & Regards

    Keldy

  • Keldy

    Can you confirm the connection in the Schematics, Because in U-Boot port 1 is referenced to EMAC 1 and not EMAC 0.

    Also check if RGMII internal delay is taken care.

    with regards

    Mugunthan V N

  • Hi Mugunthan,

    here is my connection,

    RGMII interface:

    Am335x Pin connect to Micrel PHY KSZ9021RL
    GMII1_TXCLK GTX_CLK
    GMII1_TXD0 TXD0
    GMII1_TXD1 TXD1
    GMII1_TXD2 TXD2
    GMII1_TXD3 TXD3
    GMII1_TXEN TXEN
    GMII1_RXCLK RX_CLK
    GMII1_RXD0 RXD0
    GMII1_RXD1 RXD1
    GMII1_RXD2 RXD2
    GMII1_RXD3 RXD3
    GMII1_RXDV RX_DV
    GMII1_MDIO_CLK MDC
    GMII1_MDIO_DATA MDIO

    For your info, I'm using AM335x EVM board and sdk. 

    How to check the internal delay?

    Thanks & Regards

    Keldy

  • Look at the gmii_sel register at 0x44e10650. Bits 1:0 select the mode for port1 (rgmii = 10) and bit 4 selects the internal delay. See the Control Module chapter of the TRM.

    Steve K.

  • Hi,

    will the internal delay cause my micrel KSZ9021RL phy fail working?

    how to verify the RGMII interface is working?

    is it the micrel phy not compatible with AM335x ?

    Thanks & Regards

    Keldy 

  • Keldy

    In U-Boot EMAC 0 is attached to Port 0 in software, but it is showing Port 1is connected.

    Can you check the phy address is populated in the devices structure properly. You can look for phy_id in the following location

    board/ti/am335x/evm.c:struct cpsw_slave_data cpsw_slaves[] - phy_id

    with regards

    Mugunthan V N

  • Hi,

    What do you mean check the phy address is populated in the devices structure properly ?

    do you mean to use the mdio line to access the register in ethernet phy, and get the phy address?

    Thanks & Regards

    Keldy 

  • Hi, after i change my phy addr to 0x00, now link up on port 0.

    in u-boot, when i type "dhcp":

    U-boot#dhcp

    link up on port 0, speed 100, full duplex

    BOOTP broadcast 1

    BOOTP broadcast 2

    ......until BOOTP broadcast 10 and repeat again

    seem like the micrel phy still not working properly. Any idea?

    Thanks & Regards

    Keldy

  • Keldy

    Can you disable the RGMII internal delay by enabling the bits in gmii_sel

    with regards

    Mugunthan V N

  • As mentioned in your other E2E forum post titled “Ethernet PHY connection and configuration“, the KSZ9021 has different default timing for the RGMII signals. 

    You must configure the KSZ9021 to meet the timing requirements defined in the AM335x data sheet.

    The receive data is transferred with respect to the receive clock and the transmit data is transferred with respect to the transmit clock. You need to insure all timing parameters of both devices are within the specified operating range.  This may require timing adjustments via the KSZ9021RL RGMII Clock and Control Pad Skew and RGMII RX Data Pad Skew registers.

    Note: The AM335x has the internal delay mode enabled by default and this is not supported so you must disable the internal delay mode in AM335x and adjust RGMII timing using the timing adjustment features in KSZ9021.

    Regards,
    Paul

  • Hi,

    I had disable the internal delay by changing file in "ti-sdk-am335x-evm-05.03.00.00/board-support/u-boot-2011.09-psp04.06.00.02/board/ti/am335x/evm.c"  

    int board_init(void)
    {
     __raw_writel(0x00111010, gmii_sel); --------------------disable internal delay, enable RGMII

    In adjustment of RGMII timing of KSZ9021 micrel phy, i have no idea how to do it. Any tutorial that i can refer ?

    Thanks & Regards

    Keldy

  • To change the phy timings you use the MDIO interface to modify phy registers. In u-boot, you would use the miiphy_read() and mmiphy_write() routines. In u-boot, look in evm.c for the evm_phy_init() routine. You can see where code reads registers MII_PHYSID1 and MII_PHYSID2 to determine which phy is used. You would want to add code to test for your phy and, if found, program the RGMII Clock and Control Pad Skew register (address 260) and the RTMII RX Data Pad Skew register (address 261). I found these addresses in the Micrel datasheet.

    I asked Paul for more information about these registers and he said:

    He needs to check the timing of each RGMII signal.  This calculation is done by using the minimum setup/hold time input requirements, the min/max output characteristics, and PCB propagation delays of each signal to determine how to configure these registers. 

    For example, the RX data to RX clock output characteristics of the KSZ9021 is +/-500ps and the AM335x input requires a minimum 1ns setup and hold time to operate properly.  If the PCB propagation time of RX data and RX clock are equal, the RX clock would need to be delayed in the KSZ9021 about 1.5ns - 2ns to center the clock edge in the valid data window.

    Steve K.

  • Hi,

    Thanks for reply.

    I know nothing about RGMII calculation and RGMII signal tunning. I'll try study some RGMII document to learn.

    Please continue to support me in this issue.

    Thanks & Regards

    Keldy

  • Hi,

    base on ksz9021 datasheet, the TskewT min/max is +/- 500ps, TskewR max is 2.6ns, AM335x setup/hold time min is 1ns, assume PCB propagation delay is same.

    RXC skew delay about 1.5ns(500ps + 1ns) to 3.1ns(500ps + 2.6ns) 

    TXC skew delay about 1.5ns(500ps + 1ns) to 3.1ns(500ps + 2.6ns)

    RXCTL, TXCTL, RXD[0-3] skew delay set to 0ns

    ksz9021 phy, register 260: 

    default value     default delay     new value     new delay
    RXC PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     1000     0.2 x 8 = 1.6ns
    RX_CTL PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns
    TXC PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     1000     0.2 x 8 = 1.6ns
    TX_CTL PAD Skew(0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns

    register 261

    default value     default delay     new value     new delay
    RXD3 PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns
    RXD2 PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns
    RXD1 PAD Skew (0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns
    RXD0 PAD Skew(0.2ns/step) 0111     0.2 x 7 = 1.4ns     0000     0.2 x 0 = 0ns

     Am i correct with the register new configuration? 

    Thanks & Regards

    Keldy

  • Hello Keldy,

    After reviewing the Micrel datasheet, I agree that you are moving in the right direction, but I would suggest trying to center the data a bit more by setting 0x104 [15:0] to 0x9797. This would set the new delay for TXC and RXC to 1.8ns while leaving RX_CTL and TX_CTL at their default values.

    Keep in mind this number may still need to be adjusted higher or lower based on the specifics of your design, but this should be a good start.

  • Hi,

    How about the RXD[0-3] skew delay ? leave it to default value 0x7777, or change to 0x0000 ?

    The miiphy_read() and miiphy_write() function only allow 8 bits phy register address, writing value to phy register 0x104 and 0x105 using miiphy_write() make writing value to phy register 0x04 and 0x05.

    Any other method to write to phy register 0x104 and 0x105?

    Thanks & Regards

    Keldy

  • Yes,

    Please set the RXD[0-3] skew delays to '0'. Again, you may have to tune these values based on the specifics of your implementation.

    As for extended register methods, please use the Extended Register Read and Extended Register Write functionality present in this PHY. This is described on page 33 of the KSZ9021 datasheet.

  • Keldy, please post back here if you have success getting the Micrel PHY to work with these settings.  We are laying out a board with the same PHY and may have to go through the same process.  Perhaps if we can get the Micrel chip timings right we can add support for this phy to the u-boot tree.

    It looks like there shouldn't be anything changed in the kernel right?  Just in u-boot?

  • Hi,

    Yes, just in uboot.

    Thanks & Regards

    Keldy

  • Hi Keldy,

    Any luck with the PHY? I have absolutely the same problem. I've stumbled upon this thread and am just curious if you get it work. I've tried everything including Extended Registers with no luck. And Micrel's tech support is just unresponsive, to say the least.

    Thank you,

    Vlad.

  • Hi,

    My custom PCB board just arrived, before this i just jump wire to test the micrel PHY. but i facing the UART0 boot problem now, will come back to this after i fix the boot problem.

    Thanks & Regards

    Keldy

  • Hi,

    it works! it was the skew delay problem. The ethernet driver is generic.

    setting the micrel phy register (0x104) to value 0x9797, and register(0x105) to value 0x0000 make my ethernet working. But there is a failure sometime, need to tune the skew delay properly to make sure working properly.

    Many Thanks to Paul, Steve K, and DK.

    Thanks & Regards

    Keldy 

  • Hi Keldy,

    You mentioned above that you were only making changes in U-boot, not Linux. In U-Boot, is it operating at 100Mbit/s or 1000Mbit/s? Did you get it to work in Linux?

    Currently we have the same PHY operating at 100Mbit/s, and only in U-boot. Our skew delays are slightly different (more optimized for the required delay and our hardware setup), and we're setting them in both U-boot and Linux, but in U-boot it is limited to 100Mbit/s and in Linux it comes up and then goes down as soon as it is actually configured with the cpsw driver. Therefore, I'm curious if you actually got it to work in Linux.

    Thanks,
    Russell 

  • Hi,

    only make changes in u-boot, i use ' mii ' command to write data to phy register, operating speed is 100Mbit/s, and i can boot kernel image and file system through network, and i can telnet into my board from linux PC. For 1000Mbit/s i haven't test yet. At least know AM335x SDK driver can support micrel phy, what need to do is tuning the skew.  

    Thanks and Regards

    Keldy

  • Keldy,

    My current PCB board is the same to you, used 9021,and want to work at 1000Mbit/s,do U test 1000Mbit/s by now,I'm a bit worry about this.

    Thanks and Regards

    YanTCK

  • Hi,

    It's work fine with gigabit ethernet.

    Thanks & Regards

    Keldy

  • Hi,

    We are using DM8148 on our board. We are using EMAC 1 as our Ethernet interface. AR8031 is our phy.

    In the u-boot the board works fine for 100Mbps. when we try using different data rate of 1000Mbps the board autonegotiation happens and the speed is reduced to 100Mbps automatically. here is the log:

    link up on port 0, speed 1000, full duplex
    Using cpsw device
    TFTP from server xx.xx.xx.xx; our IP address is xx.xx.xx.xx
    Filename 'uImage'.
    Load address: 0x81000000
    Loading: link down on port 0
    T link up on port 0, speed 100, full duplex
    T ##############################

    ###################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             #################################################################
             ###################
    done
    Bytes transfer

    As you can see initially the link is up for 1000 but then it comes down and goes up to 100. We want it to work on 1000 Mbps.

    Same problem is seen with 10Mbps also. Please help!!

    Thanks

    Prakash

  • Hello Keldy

    can you please explain your suggested value of 0x9797?

    i understand why skewing the clock by 1.8ns

    but isn't the TX_CTL treated as data? and therefore should have same value as the data -> 0?

    why not therefore use 0x9090?

    Thanks

    Oren.

  • Hi Keldy and all

    I'm trying to use the KSZ9031 phy (linux), but it has not worked yet.

    I tryed to set the RXC PAD Skew, TXC PAD Skew and RXDx PAD Skew, but it fails allways.

    My code is like:

    #define MMD_ACCESS_CTRL 0xd
    #define MMD_ACCESS_REG_DATA 0xe
    #define MMD_ACCESS_REG_MODE 0x0000
    #define MMD_ACCESS_DATANOPOST_MODE 0x4000
    #define MMD_ACCESS_DATAPOST_MODE 0x8000
    #define MMD_ACCESS_DATAPOSTWRTONLY_MODE 0xc000

    #define KSZ9031_PHY_CLK_PAD_SKEW_REG 0x08
    #define KSZ9031_RGMII_CLK_DLY 0x2d6
    #define KSZ9031_PHY_RXD_PAD_SKEW_REG 0x05
    #define KSZ9031_RGMII_RXD_DLY 0x0000

    static int wise_dly_phy_fixup(struct phy_device *phydev)
    {

    int temp;
    /// CLK
    phy_write(phydev, MMD_ACCESS_CTRL,MMD_ACCESS_REG_MODE|0x02);
    phy_write(phydev, MMD_ACCESS_REG_DATA, KSZ9031_PHY_CLK_PAD_SKEW_REG);
    phy_write(phydev, MMD_ACCESS_CTRL,MMD_ACCESS_DATANOPOST_MODE|0x02);
    temp = phy_read(phydev, MMD_ACCESS_REG_DATA);
    pr_info("phy read clk = 0x%x\n",temp);

    phy_write(phydev, MMD_ACCESS_REG_DATA, (temp&0xFC00) | KSZ9031_RGMII_CLK_DLY);

    temp = phy_read(phydev, MMD_ACCESS_REG_DATA);
    pr_info("phy read clk = 0x%x\n",temp);


    /// RXData
    phy_write(phydev, MMD_ACCESS_CTRL,MMD_ACCESS_REG_MODE|0x02);
    phy_write(phydev, MMD_ACCESS_REG_DATA, KSZ9031_PHY_RXD_PAD_SKEW_REG);
    phy_write(phydev, MMD_ACCESS_CTRL,MMD_ACCESS_DATANOPOST_MODE|0x02);
    temp = phy_read(phydev, MMD_ACCESS_REG_DATA);
    pr_info("phy read rxd = 0x%x\n",temp);

    phy_write(phydev, MMD_ACCESS_REG_DATA, KSZ9031_RGMII_RXD_DLY);

    temp = phy_read(phydev, MMD_ACCESS_REG_DATA);
    pr_info("phy read rxd = 0x%x\n",temp);
    return 0;


    }

    /**
    * Custom board
    */
    static void setup_customboard(void)
    {

    am335x_mmc[0].gpio_wp = -EINVAL;

    _configure_device(...

    am33xx_cpsw_init(AM33XX_CPSW_MODE_RGMII, NULL, NULL);

    // Micrel ksz9031 Clk delay Phy fixup
    phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
             wise_dly_phy_fixup);

    }


    When I try configuring network, the kernel outputs

    Configuring network interfaces... [ 5.478391] phy read clk = 0x3ed6
    [ 5.482085] phy read clk = 0x3ed6
    [ 5.486050] phy read rxd = 0x0
    [ 5.489495] phy read rxd = 0x0
    [ 5.492692] net eth0: CPSW phy found : id is : 0x221621
    eth0 no wireless extensions.

    udhcpc (v1.20.2) started
    Sending discover...
    [ 8.488169] PHY: 0:00 - Link is Up - 100/Full
    Sending discover...
    Sending discover...
    No lease, failing
    done.

    I'm using the second eth port.

    Any help is wellcome.

    Thank's!

  • Problem was resolved!

    I had seen this following message:

    [ 1.202098] davinci_mdio.0: probed
    [ 1.205702] davinci_mdio davinci_mdio.0: phy[0]: device 0:00, driver Micrel KSZ9031 Gigabit PHY, id 0x221621
    [ 1.215465] davinci_mdio davinci_mdio.0: phy[3]: device 0:03, driver Micrel KSZ9031 Gigabit PHY, id 0x221621

    But when I connected cable, I saw something like

    [ 8.488169] PHY: 0:00 - Link is Up - 100/Full

    As I was using the second eth port (there was nothing on first eth), I changed this 

    am33xx_cpsw_init(AM33XX_CPSW_MODE_RGMII, NULL, NULL);

    to

    am33xx_cpsw_init(AM33XX_CPSW_MODE_RGMII, "0:00", "0:03");


    The gigabit eth is working fine now. Even if I don't make delay adjust.

    Regards,

    Andre

  • What kernel rev are you on?

    I am building up a Beaglebone AM335X based design and switched to a Micrel KSZ9031 Ethernet PHY and it does not work. The current driver for the KSZ9031 (micrel.c) seems to be the latest however I have found documentation from Micrel that it only works with the 3.8 kernel (our kernel is 3.2) and I only have one parameter to am33xx_cpsw_init so I cannot make delay adjustments. Do you know at which point in the kernel distribution am33xx_cpsw_init was upgraded to allow the delay changes?

    -BL

  • Hi, Bruce

    I'm using 3.2 kernel, from ti-sdk-am335x-evm-05.07.00.

    Yes, micrel driver is for 3.8 kernel, but I've adjusted it for 3.2 one:

    /*
     * drivers/net/phy/micrel.c
     *
     * Driver for Micrel PHYs
     *
     * Author: David J. Choi
     *
     * Copyright (c) 2010 Micrel, Inc.
     *
     * This program is free software; you can redistribute  it and/or modify it
     * under  the terms of  the GNU General  Public License as published by the
     * Free Software Foundation;  either version 2 of the  License, or (at your
     * option) any later version.
     *
     * Support : Micrel Phys/switches:
     *		Giga phys: ksz9021, ksz9031
     *		100/10 Phys: ksz8001, ksz8021, ksz8031, ksz8041, ksz8051,
     *			   ksz8061, ksz8081, ksz8091,
     *			   ksz8721, ksz8737,
     *		Switches: ksz8873
     */
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/phy.h>
    #include <linux/micrel_phy.h>
    
    /* Operation Mode Strap Override */
    #define MII_KSZPHY_OMSO				0x16
    #define KSZPHY_OMSO_B_CAST_OFF			(1 << 9)
    #define KSZPHY_OMSO_RMII_OVERRIDE		(1 << 1)
    #define KSZPHY_OMSO_MII_OVERRIDE		(1 << 0)
    
    /* general Interrupt control/status reg in vendor specific block. */
    #define MII_KSZPHY_INTCS			0x1B
    #define	KSZPHY_INTCS_JABBER			(1 << 15)
    #define	KSZPHY_INTCS_RECEIVE_ERR		(1 << 14)
    #define	KSZPHY_INTCS_PAGE_RECEIVE		(1 << 13)
    #define	KSZPHY_INTCS_PARELLEL			(1 << 12)
    #define	KSZPHY_INTCS_LINK_PARTNER_ACK		(1 << 11)
    #define	KSZPHY_INTCS_LINK_DOWN			(1 << 10)
    #define	KSZPHY_INTCS_REMOTE_FAULT		(1 << 9)
    #define	KSZPHY_INTCS_LINK_UP			(1 << 8)
    #define	KSZPHY_INTCS_ALL			(KSZPHY_INTCS_LINK_UP |\
    						KSZPHY_INTCS_LINK_DOWN)
    
    /* general PHY control reg in vendor specific block. */
    #define	MII_KSZPHY_CTRL			0x1F
    /* bitmap of PHY register to set interrupt mode */
    #define KSZPHY_CTRL_INT_ACTIVE_HIGH		(1 << 9)
    #define KSZ90X1_CTRL_INT_ACTIVE_HIGH		(1 << 14)
    #define KSZ8737_CTRL_INT_ACTIVE_HIGH		(1 << 14)
    #define KSZ8051_RMII_50MHZ_CLK			(1 << 7)
    
    static int kszphy_ack_interrupt(struct phy_device *phydev)
    {
    	/* bit[7..0] int status, which is a read and clear register. */
    	int rc;
    
    	rc = phy_read(phydev, MII_KSZPHY_INTCS);
    
    	return (rc < 0) ? rc : 0;
    }
    
    static int kszphy_set_interrupt(struct phy_device *phydev)
    {
    	int temp;
    	temp = (PHY_INTERRUPT_ENABLED == phydev->interrupts) ?
    		KSZPHY_INTCS_ALL : 0;
    	return phy_write(phydev, MII_KSZPHY_INTCS, temp);
    }
    
    static int kszphy_config_intr(struct phy_device *phydev)
    {
    	int temp, rc;
    
    	/* set the interrupt pin active low */
    	temp = phy_read(phydev, MII_KSZPHY_CTRL);
    	temp &= ~KSZPHY_CTRL_INT_ACTIVE_HIGH;
    	phy_write(phydev, MII_KSZPHY_CTRL, temp);
    	rc = kszphy_set_interrupt(phydev);
    	return rc < 0 ? rc : 0;
    }
    
    static int ksz90x1_config_intr(struct phy_device *phydev)
    {
    	int temp, rc;
    
    	/* set the interrupt pin active low */
    	temp = phy_read(phydev, MII_KSZPHY_CTRL);
    	temp &= ~KSZ90X1_CTRL_INT_ACTIVE_HIGH;
    	phy_write(phydev, MII_KSZPHY_CTRL, temp);
    	rc = kszphy_set_interrupt(phydev);
    	return rc < 0 ? rc : 0;
    }
    
    static int ksz8737_config_intr(struct phy_device *phydev)
    {
    	int temp, rc;
    
    	/* set the interrupt pin active low */
    	temp = phy_read(phydev, MII_KSZPHY_CTRL);
    	temp &= ~KSZ8737_CTRL_INT_ACTIVE_HIGH;
    	phy_write(phydev, MII_KSZPHY_CTRL, temp);
    	rc = kszphy_set_interrupt(phydev);
    	return rc < 0 ? rc : 0;
    }
    
    static int kszphy_config_init(struct phy_device *phydev)
    {
    	return 0;
    }
    
    static int ksz8021_config_init(struct phy_device *phydev)
    {
    	const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
    	phy_write(phydev, MII_KSZPHY_OMSO, val);
    	return 0;
    }
    
    static int ks8051_config_init(struct phy_device *phydev)
    {
    	int regval;
    
    	if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
    		regval = phy_read(phydev, MII_KSZPHY_CTRL);
    		regval |= KSZ8051_RMII_50MHZ_CLK;
    		phy_write(phydev, MII_KSZPHY_CTRL, regval);
    	}
    
    	return 0;
    }
    
    #define KSZ8873MLL_GLOBAL_CONTROL_4	0x06
    #define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX	(1 << 6)
    #define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED	(1 << 4)
    int ksz8873mll_read_status(struct phy_device *phydev)
    {
    	int regval;
    
    	/* dummy read */
    	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
    
    	regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
    
    	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
    		phydev->duplex = DUPLEX_HALF;
    	else
    		phydev->duplex = DUPLEX_FULL;
    
    	if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
    		phydev->speed = SPEED_10;
    	else
    		phydev->speed = SPEED_100;
    
    	phydev->link = 1;
    	phydev->pause = phydev->asym_pause = 0;
    
    	return 0;
    }
    
    static int ksz8873mll_config_aneg(struct phy_device *phydev)
    {
    	return 0;
    }
    
    static struct phy_driver ksphy_driver[] = {
    {
    	.phy_id		= PHY_ID_KSZ8737,
    	.phy_id_mask	= 0x00fffff0,
    	.name		= "Micrel KSZ8737",
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= ksz8737_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8021,
    	.phy_id_mask	= 0x00ffffff,
    	.name		= "Micrel KSZ8021 or KSZ8031",
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
    			   SUPPORTED_Asym_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= ksz8021_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8041,
    	.phy_id_mask	= 0x00fffff0,
    	.name		= "Micrel KSZ8041",
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
    				| SUPPORTED_Asym_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8051,
    	.phy_id_mask	= 0x00fffff0,
    	.name		= "Micrel KSZ8051",
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
    				| SUPPORTED_Asym_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= ks8051_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8001,
    	.name		= "Micrel KSZ8001 or KSZ8721",
    	.phy_id_mask	= 0x00ffffff,
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8081,
    	.name		= "Micrel KSZ8081 or KSZ8091",
    	.phy_id_mask	= 0x00fffff0,
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ8061,
    	.name		= "Micrel KSZ8061",
    	.phy_id_mask	= 0x00fffff0,
    	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= kszphy_config_intr,
    	.driver		= { .owner = THIS_MODULE,},
    }, {
    	.phy_id		= PHY_ID_KSZ9021,
    	.phy_id_mask	= 0x00fffffe,
    	.name		= "Micrel KSZ9021 Gigabit PHY",
    	.features	= (PHY_GBIT_FEATURES | SUPPORTED_Pause
    				| SUPPORTED_Asym_Pause),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= ksz90x1_config_intr,
    	.driver		= { .owner = THIS_MODULE, },
    }, {
    	.phy_id		= PHY_ID_KSZ9031,
    	.phy_id_mask	= 0x00fffff0,
    	.name		= "Micrel KSZ9031 Gigabit PHY",
    	.features	= (PHY_GBIT_FEATURES /*| SUPPORTED_Pause
    				| SUPPORTED_Asym_Pause*/),
    	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
    	.ack_interrupt	= kszphy_ack_interrupt,
    	.config_intr	= ksz90x1_config_intr,
    	.driver		= { .owner = THIS_MODULE, },
    }, {
    	.phy_id		= PHY_ID_KSZ8873MLL,
    	.phy_id_mask	= 0x00fffff0,
    	.name		= "Micrel KSZ8873MLL Switch",
    	.features	= (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
    	.flags		= PHY_HAS_MAGICANEG,
    	.config_init	= kszphy_config_init,
    	.config_aneg	= ksz8873mll_config_aneg,
    	.read_status	= ksz8873mll_read_status,
    	.driver		= { .owner = THIS_MODULE, },
    } };
    
    static int __init ksphy_init(void)
    {
    	int ret;
    	char c = 8;
    //	for(c=0;c<10;c++){
    		ret = phy_driver_register(&ksphy_driver[c]);
    		if (ret)
    			goto err;
    //	}
    	return 0;
    
    err:
    	phy_driver_unregister(&ksphy_driver[c]);
    	return ret;
    }
    
    static void __exit ksphy_exit(void)
    {
    	char c;
    	for(c=0;c<10;c++){
    		phy_driver_unregister(&ksphy_driver[c]);
    	}
    }
    
    module_init(ksphy_init);
    module_exit(ksphy_exit);
    
    MODULE_DESCRIPTION("Micrel PHY driver");
    MODULE_AUTHOR("David J. Choi");
    MODULE_LICENSE("GPL");
    
    static struct mdio_device_id __maybe_unused micrel_tbl[] = {
    	{ PHY_ID_KSZ9021, 0x00fffffe },
    	{ PHY_ID_KSZ9031, 0x00fffff0 },
    	{ PHY_ID_KSZ8001, 0x00ffffff },
    	{ PHY_ID_KSZ8737, 0x00fffff0 },
    	{ PHY_ID_KSZ8021, 0x00ffffff },
    	{ PHY_ID_KSZ8041, 0x00fffff0 },
    	{ PHY_ID_KSZ8051, 0x00fffff0 },
    	{ PHY_ID_KSZ8061, 0x00fffff0 },
    	{ PHY_ID_KSZ8081, 0x00fffff0 },
    	{ PHY_ID_KSZ8873MLL, 0x00fffff0 },
    	{ }
    };
    
    MODULE_DEVICE_TABLE(mdio, micrel_tbl);
    

    I hope it helps.

    Regards,

    Andre

  • Hey Andre,

    Thanks for the quick response. I will give it a try.

    Can you post kernel/arch/arm/mach-omap2/devices.c as well? Any other related files that were in the fix would be much appreciated.

    -BL

  • I did not modify that file, just board-am335xevm.c, but all software modifications were already posted above, except micrel_phy.h (trivial).

    Regards,

    André

  • Ok, I see that I don't have the patch that updates am33xx_cpsw_init() to obtain mac mode & phy id. My am33xx_cpsw_init()  only takes one param. This is strange because I see that I am on 3.2.42 and the patches are being installed but that patch does not appear to be in there.

    Maybe there is a later release I should pull? I don't want to go too late where they get away from the board files and move to device trees as we have mods in our board file currently.

    -BL

  • Yes I will look into that next, so far its not working. I have the phy_fixup routine in there to ajust RXD delay and CLK delay and the driver you posted and this is what I see;

    from boot....

    ...

    [    1.140869] davinci_mdio davinci_mdio.0: davinci mdio revision 1.6
    [    1.147399] davinci_mdio davinci_mdio.0: detected phy mask fffffffe
    [    1.155334] phy read clk = 0x3def
    [    1.159027] phy read clk = 0x3e00
    [    1.163055] phy read rxd = 0x7777
    [    1.166748] phy read rxd = 0x20
    [    1.170196] davinci_mdio.0: probed
    [    1.173828] davinci_mdio davinci_mdio.0: phy[0]: device 0:00, driver Micrel KSZ9031 Gigabit PHY

    ...

    then after that finishes...

    Started Login Service                                                  [  OK  ]
    [    4.174224] ip_tables: (C) 2000-2006 Netfilter Core Team
    [    4.672424] phy read clk = 0x3e00
    [    4.676177] phy read clk = 0x3e00
    [    4.680145] phy read rxd = 0x20
    [    4.683715] phy read rxd = 0x20
    [    4.687042]
    [    4.687042] CPSW phy found : id is : 0x221622
    [    4.693939] PHY 0:01 not found
    [    4.699615] ADDRCONF(NETDEV_UP): eth0: link is not ready
    Starting Serial Getty on ttyO0...
    Started Serial Getty on ttyO0                                          [  OK  ]


    .---O---.
    |       |                  .-.           o o
    |   |   |-----.-----.-----.| |   .----..-----.-----.
    |       |     | __  |  ---'| '--.|  .-'|     |     |
    |   |   |  |  |     |---  ||  --'|  |  |  '  | | | |
    '---'---'--'--'--.  |-----''----''--'  '-----'-'-'-'
                    -'  |
                    '---'

    The Angstrom Distribution beaglebone ttyO0

    Angstrom v2012.05 - Kernel 3.2.42

    beaglebone login: root (automatic login)


    Last login: Sat Jan  1 00:00:04 UTC 2000 on ttyO0


    root@beaglebone:~# ifconfig


    eth0      Link encap:Ethernet  HWaddr BC:6A:29:A0:DE:29
              UP BROADCAST MULTICAST  MTU:1500  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

    then about 30s later...

    root@beaglebone:~# [   34.682495] PHY: 0:00 - Link is Up - 10/Full
    [   34.687255] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

    then after a minute or so it appears to fail to get a DHCP address and assignes an IP from the homeless network (169.254.0.0)

    root@beaglebone:~# ifconfig


    eth0      Link encap:Ethernet  HWaddr BC:6A:29:A0:DE:29
              inet addr:169.254.26.102  Bcast:169.254.255.255  Mask:255.255.0.0
              inet6 addr: fe80::be6a:29ff:fea0:de29/64 Scope:Link
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:39 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000
              RX bytes:0 (0.0 B)  TX bytes:11137 (10.8 KiB)

    lo        Link encap:Local Loopback
              inet addr:127.0.0.1  Mask:255.0.0.0
              inet6 addr: ::1/128 Scope:Host
              UP LOOPBACK RUNNING  MTU:16436  Metric:1
              RX packets:0 errors:0 dropped:0 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0
              RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

    Interestingly, Tx seems to work but Rx is not. I've tried several RXD delay and CLK delay combos to no avail. This is the same response I got with 3.2.42 out of the box so I don't think the orig driver was the problem.

    Any ideas?

    -BL

  • Hi

    We are also facing same issue with KSZ9021 micrel PHY, intially it did not worked with 10/100/1000 any speed but after adjusting delays(F0F0 ,0000,0000) it works for 10/100 speeds but still we are facing issue with 1000Mbps.

    looks me F0F0(104 reg)0000(105reg)0000(106reg) delays values are correct as all my TX pairs and RX pairs are length macthed, by setting above values we are ensure that min set up time of 1.3ns in any case(-500 skew case also)

    Can you please any one suggest me  whats going wrong with 1000Mbps?

    Thanks

    Shiva

  • As it turns out we did not have to modify signal timing. Our issue (after we got all our HW issues corrected) turned out to be pin muxing. Make sure your pin muxing is set correctly whether you are doing this in the source code or setting it after you boot.

    -BL

  • Hi

    Our case board is working fie with the 100Mbps,we are facing issue with 1000Mbps.looks like some timing issue in RGMII lines.

    Thanks

    Shiva

  • Keldy said:

    Hi,

    It's work fine with gigabit ethernet.

    Thanks & Regards

    Keldy

    Hi Keldy,

         Your ethernet interface is working in gigabit mode with delays 0x9797 and 0x0000? With these delays, my ethernet interface work only in 100M mode.

    Best regards,

    Christiano Belli.

  • The fastest and easiest way to dial-in your timing is to instrument the RGMII interface with a scope and use the wave forms as a guide to tune the PHY as needed. Hopefully, you did a timing analysis of the interface prior to PCB fab and your timing is off to a degree that the PHY can accommodate.