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.

Porting of DDR, LAN & PMIC

Other Parts Discussed in Thread: AM3356, AM3352, TPS650250, DP83630, DP83865

Dear Ti E2E Community,

Am using ti sdk 7 BSP's on the custom board

We are planning to replace the following chips

AM3356 with a AM3352, run the CPU @300MHz,

DDR MT41K256M16HA-125 M:E to a MT41K128M16JT-125 M:K ,  TPS65217C with a TPS650250RHBR, LAN8710A with a KSZ8081MNXCA TR (MII micrel PHY)

Could you please help me out in clarifying the following doubts I have in bringup of ti sdk 7 with above new peripherals:

1.  Could you please let me know the necessary configurations that needs to be taken care for the above peripherals in  u-boot, DT, kernel & rootfs  of ti sdk 7??

2. Could you please let me know whether it is possible to do the bringup in within the RAM size limits of MT41K128M16JT-125 M:K??

i. I hope, DDR configurations needs to be taken care only in u-boot, could you please confirm on the same??.. or if not could you please let me know whether any changes need to be done in DT , Kernel or rootfs in ti sdk 7???

ii. Am trying to calculate  , could you please help me out how much of RAM size is required for ti sdk 7 uboot code execution ???

iii. Could you please help me out how much of RAM size is required for ti sdk 7 Kernel code execution  ??

iv. Could you please help me out how much of RAM size is required for ti sdk 7 rootfs execution??

3. And I hope . LAN & PMIC Chip also needs to be configured in u-boot, DT & kernel, could you please provide me some pointers, so that It would be very grateful in porting the drivers for this chipsets in ti sdk 7 (ie., in u-boot, DT, kernel & rootfs)

Kindly do the needful as early as possible

Awaiting for replies,

Many Thanks in advance

 

 

 

 

  • Hi Srini,

    For DDR follow these wiki guides: http://processors.wiki.ti.com/index.php/AM335x_EMIF_Configuration_tips , http://processors.wiki.ti.com/index.php/AM335x_DDR_PHY_register_configuration_for_DDR3_using_Software_Leveling , and you can also check this step-by-step tutorial: http://processors.wiki.ti.com/index.php/Sitara_Linux_Training:_Tuning_the_DDR3_Timings_on_BeagleBoneBlack . DDR is initialized only in u-boot.

    About PMIC, TPS650250 does not have any software interaction with the AM335X.

    About Ethernet PHY you will need to this on your own. I'm not sure support for this PHY is available in the SDK, but you can start from one of the Micrel PHYs that are supported and modify.

    About RAM sizes, u-boot uses up as much RAM as the image size, kernel reports available memory during start-up. It varies depending on configuration.

  • Hi Srini,

    In addition to the reply from Biser.

    For porting your PHY, first you need to add CONFIG_MICREL_PHY=y in your defconfig file (this should build the drivers/net/phy/micrel.c driver in the kernel). See if micrel support is included in menuconfig. Then properly configure the DT node (mac: ethernet@4a100000) to match your use case.  

    As Biser mentioned you may need to add the ksz8081 driver to kernel sources, if updating the defconfig & DTS is not enough.

    To see how much memory is needed from kernel code & kernel data, you can use cat /proc/iomem. On beagle bone boards (black & white) these occupy the following memory areas:

     80000000-9fdfffff : System RAM      (for beagle bone white System RAM occupies 80000000-8fdfffff)

        80008000-807ba053 : Kernel code                                                                                          

        80800000-80888737 : Kernel data

    So you can calculate the amount of system ram needed by the SDK.

    Hope this helps.

    Best Regards,

    Yordan

  • Thanks a lot for your quick replies Biser & Yordan, for proceeding further analysis

    Could you please help me out the system RAM size needed for rootfs, uboot, DT????

    Could you please help me out the necessary configurations that needs to be done in u-boot for KSZ8081MNXCA TR (MII micrel PHY)??

    I hope KSZ8081MNXCA TR (MII micrel PHY) configurations is mainly required in u-boot for the system to come up with uboot first,

    Could you please let me know whether it is possible to bringup the board without PHY??? if so could you please help me out how this can be bypassed

    Kindly do the needful as early as possible,

    Awaiting for your replies,

    Many Many Thanks in advance once again Biser & Yordan for your quick repsonses
  • Hi Srini,

    The u-boot is ~400KiB & dts is ~40KiB.

    In include/configs/am335x_evm.h, you need to add the Micrel phy in the following section of defines:

    /* Network. */

    #define CONFIG_PHY_GIGE

    #define CONFIG_PHYLIB

    #define CONFIG_PHY_SMSC

    #define CONFIG_PHY_MICREL

    Notе  that you will need to modify the u-boot/drivers/net/phy/micrel.c driver to add support for the KSZ8081 phy. You can use the following patch as a reference: https://patchwork.ozlabs.org/patch/453788/  

    You should also modify the board file in u-boot to initialize the ethernet phy, you can refer to the last two replies in this thread: e2e.ti.com/.../1022447

    Srini S said:

    Could you please let me know whether it is possible to bringup the board without PHY???

    It is possible to boot the board without PHY. To do that, just comment the ethernet configs in include/configs/am335x_evm.h.


    Hope this helps.


    Best Regards,
    Yordan

  • Dear Biser/Yordan,

    Thanks a lot for your quick replies,

    As am new for this DDR Bringup, could you please help me in reviewing the  attached AM335x_DDR_register_calc_tool.xls & datasheet MT41K128M16JT-125 M:K,

    And please correct me if any of timing settings is wrong as per the datasheet

    3833.AM335x_DDR_register_calc_tool.xls

    MT41K128M16JT-125M_K.pdf

    8032.RatioSeed_AM335x_boards.xls

    Kindly do the needful as early as possible,

    Awaiting for your replies,

    Many Many Thanks in advance

  • Dear Yordan/Biser

    Please kindly do the needful in clarifying the below queries as early as possible
    1) DDR
    =======
    1) Could you please provide any review inputs for the above query

    2) Could you please let me know is there any other configurations that needs to be done apart from the below structures & macros for DDR
    ie., ddr3_beagleblack_data, &ddr3_beagleblack_cmd_ctrl_data, &ddr3_beagleblack_emif_reg_data

    #define MT41K128M16HA125_EMIF_READ_LATENCY
    #define MT41K128M16HA125_EMIF_TIM1
    #define MT41K128M16HA125_EMIF_TIM2
    #define MT41K128M16HA125_EMIF_TIM3
    #define MT41K128M16HA125_EMIF_SDCFG
    #define MT41K128M16HA125_EMIF_SDREF
    #define MT41K128M16HA125_ZQ_CFG
    #define MT41K128M16HA125_RATIO
    #define MT41K128M16HA125_INVERT_CLKOUT
    #define MT41K128M16HA125_RD_DQS
    #define MT41K128M16HA125_WR_DQS
    #define MT41K128M16HA125_PHY_WR_DATA
    #define MT41K128M16HA125_PHY_FIFO_WE
    #define MT41K128M16HA125_IOCTRL_VALUE

    void sdram_init(void)
    {
    config_ddr(400, MT41K128M16HA125_IOCTRL_VALUE,
    &ddr3_beagleblack_data,
    &ddr3_beagleblack_cmd_ctrl_data,
    &ddr3_beagleblack_emif_reg_data, 0);
    }

    3) Could you please let me know where I can find the starting address of RAM, because I need to verify the entire RAM(ie., 256MB) by writing & reading back & please let me know how this 256MB can be verified, could you please let me know whether this starting address changes due to this RAM size change from 4Gb to 2Gb

    4) Could you please let me know is there any explicit memory mappings is required in kernel due the above RAM size change from 4Gb to 2Gb


    2) LAN
    =====
    1) As am new to PHY porting, could you pls let me is there any other configurations needs to be done apart from the below in uboot

    #define CONFIG_PHY_MICREL

    static struct phy_driver KSZ8081_driver = {
    .name = "Micrel KSZ8081",
    .uid = 0x221560,
    .mask = 0xfffff0,
    .features = PHY_BASIC_FEATURES,
    .config = &genphy_config,
    .startup = &genphy_startup,
    .shutdown = &genphy_shutdown,
    };


    int phy_micrel_init(void)
    {
    phy_register(&KSZ8081_driver);
    }

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

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

    2) Could you please how this is getting referenced in the board file of uboot, first I tried to figure it out for SMSC LAN8710A how this is getting referenced in board file of uboot, but I was unable to find, could you please help me out how this is referenced in board file of uboot

    3)Could you please let me know how this can be tested (any utilites in uboot??) once intial bringup is done for PHY

    Kindly do the needful as early as possible,

    Awaiting fro your replies
  • Could anybody please provide some suggestions to the above query as early as possible
  • Could you please provide any inputs w.r.t the above queries, as am awaiting for your inputs for my further development activities in ti sdk 7

  • Hi Srini, 

    Sorry for the late response. 

    Srini S said:

    2) Could you please let me know is there any other configurations that needs to be done apart from the below structures & macros for DDR
    ie., ddr3_beagleblack_data, &ddr3_beagleblack_cmd_ctrl_data, &ddr3_beagleblack_emif_reg_data

    You need to take care of RAM related defines in am335x_evm.h, ti_am335x_common.h, ti_armv7_common.h 

    Srini S said:
    3) Could you please let me know where I can find the starting address of RAM, because I need to verify the entire RAM(ie., 256MB) by writing & reading back & please let me know how this 256MB can be verified, could you please let me know whether this starting address changes due to this RAM size change from 4Gb to 2Gb

    You can see DDR starting address from AM335x TRM Table 2-1. L3 Memory Map (continued), see EMIF0 SDRAM => starting address is 0x80000000; end address is 0xBFFFFFFF (giving 1GB of memory space). 

    Srini S said:
    4) Could you please let me know is there any explicit memory mappings is required in kernel due the above RAM size change from 4Gb to 2Gb

    DDR initialization & configuration is done in u-boot. After that kernel is loaded in DDR & executed from there. 

    Srini S said:
    2) Could you please how this is getting referenced in the board file of uboot, first I tried to figure it out for SMSC LAN8710A how this is getting referenced in board file of uboot, but I was unable to find, could you please help me out how this is referenced in board file of uboot

    You should add CONFIG_PHY_MICREL in am335x_evm.h, as shown bellow: 

    /* Network. */
    #define CONFIG_PHY_GIGE
    #define CONFIG_PHYLIB
    #define CONFIG_PHY_SMSC
    #define CONFIG_PHY_MICREL

    Srini S said:
    3)Could you please let me know how this can be tested (any utilites in uboot??) once intial bringup is done for PHY

     

    You can try the ping command. 

    Best Regards, 

    Yordan

  • Dear Yordan,

    Thanks a lot for your replies w.r.t the above query,

    1. Now we are planning to use "DP83848" instead of Micrel fro our custom board, I did similar porting for DP83848 in u-boot ie.,, could you please let me know is there any thing needs to done w.r.t CPSW side, & could you please let me know id there anything else needs to be added inorder to get PHY up & running with DP83848 & could you please let me know does this enables AUTO-MDIX & speed at 100MBps??

    include/configs/am335x_evm.h

    #define CONFIG_PHY_NATSEMI 

    drivers/net/phy/Natsemi.c

    /* NatSemi DP83848 */
    static int dp83848_config(struct phy_device *phydev)
    {
    int mii_reg;
    u32 phyId;

    mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID1);
    phyId = (mii_reg & 0xffff) << 16;
    mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID2);
    phyId |= (mii_reg & 0xffff);
    printf("NatSemi DP83848 dp83848_config %s uid:%08X\n", phydev->drv->name, phydev->drv->uid);

    phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);

    genphy_config_aneg(phydev);

    return 0;
    }

    static struct phy_driver DP83848_driver = {
    .name = "NatSemi DP83848",
    .uid = 0x20005C90,
    .mask = 0x3FFFFFF0,
    .features = PHY_BASIC_FEATURES,
    .config = &dp83848_config,
    .startup = &genphy_startup,
    .shutdown = &genphy_shutdown,
    };

    2. Could you please let me know what are all the necesary changes that needs to be done in Device tree & kernel as well

    Kindly do the needful as early as possible,

    Awaiting for your replies,

    Many thanks in advance

  • Dear Yordan,

    Could you please provide any inputs w.r.t above DP83848 query

    Kindly do the needful as early as possible,
    Awaiting for your replies
    Many thanks in advance
  • Hi Srini,

    Srini said:
    could you please let me know is there any thing needs to done w.r.t CPSW side, & could you please let me know id there anything else needs to be added inorder to get PHY up & running with DP83848

    No, I don't think you need to tune the cpsw side, the additions you've done regarding the DP83848 phy should be enough.   

    Only check if the following code: 
      

    #ifdef CONFIG_PHY_NATSEMI
    phy_natsemi_init();
    #endif

    is present in u-boot/drivers/net/phy/phy.c 

    Srini said:
    2. Could you please let me know what are all the necesary changes that needs to be done in Device tree & kernel as well

     

    1. You need to add CONFIG_NATIONAL_PHY=y to your defconfig file. 

    2. You need to add support for dp83848 in the current natsemi phy driver as you've done in u-boot. 

    3. DTS configuration for cpsw is already done. You can check it & tune it according to your use case; see mac: ethernet@4a100000 dts node in am335x.dtsi AND  &mac, &davinci_mdio, &cpsw_emac0  and &cpsw_emac1 dts nodes in am335x-evmsk.dts (or whichever dts file you use). 

    Hope this helps.

    Best Regards, 

    Yordan

  • Dear Yordan,

    Hope you are doing good,

    Regarding DDR3 Bringup,

    I googled & found AM335x DDR3 Software Leveling Program MLO User Guide, here MLO is used for software levelling by placing it in SDcard,

    1. Could you please let me know where I can get this MLO & UBoot source code or MLO uboot image, if this MLO & uboot image is unique & validated for all DDR3's, could you please share this image

    Please kindly share me this image or source code modifications that needs to done in uboot  ti sdk 8

    2.Could you please confirm is there any necessity of using debugger , after placing this MLO image in SD card do we still need debugger for DDr3 bringup

    Kindly do the needful as early as possible

    Awaiting for your replies

    Many Thanks in advance

  • Dear Yordan,

    Could you please let me know what are the code changes that needs to be done, inorder to use this generate this MLO in ti sdk 8 or  do you have this image atleast could you please share it 

    Kindly do the needful as early as possible

    Thanks,
    Srini

  • Hi Srini,

    First refer to processors.wiki.ti.com/.../AM335x_EMIF_Configuration_tips (& the DDR configuration tool inside the wiki) in order to calculate the values you need to write in EMIF/PHY registers.

    The EMIF & DDR configurations are done in u-boot/arch/arm/cpu/armv7/am33xx/emif4.c, u-boot/arch/arm/cpu/armv7/am33xx/ddr.c & u-boot/board/ti/am335x/board.c

    Best Regards,
    Yordan

  • Hi Srini,

    Did you get your D83848 + AM335x setup to work?  I have the same changes as you have above but could not get the PHY working.

  • Yes Khanh

    You should change the phy address from 0 to 1 in uboot

    And you should enable the flag NATSEMI in uboot

    Will let you know the detailed source code today by EOD

    Thanks,

    Srini

  • Khanh,

    I verified this on ti sdk 8 bsp's , & got it working

    u-boot

    =======

    1. define the flag CONFIG_PHY_NATSEMI in include/configs/am335x_evm.h (Recheck your configuration file in uboot & add this flag)

    2. board.c

    static struct cpsw_slave_data cpsw_slaves[] = {

           {

                   .slave_reg_ofs  = 0x208,

                   .sliver_reg_ofs = 0xd80,

    #ifdef CONFIG_PHY_NATSEMI

      .phy_addr       = 1,

    #else

                   .phy_addr       = 0,

    #endif

           },

           {

                   .slave_reg_ofs  = 0x308,

                   .sliver_reg_ofs = 0xdc0,

                   .phy_addr       = 1,

           },

    };

    3. drivers/net/phy/phy.c

    /* NatSemi DP83848 */

    static int dp83848_config(struct phy_device *phydev)

    {

       int mii_reg;

       u32 phyId;

       mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID1);

       phyId = (mii_reg & 0xffff) << 16;

       mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID2);

       phyId |= (mii_reg & 0xffff);

       printf("TUNSTALLL NatSemi DP83848 dp83848_config %s uid:%08X\n", phydev->drv->name, phydev->drv->uid);

       phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);

       genphy_config_aneg(phydev);

       return 0;

    }

    static struct phy_driver DP83848_driver = {

       .name = "NatSemi DP83848",

       .uid  = 0x20005C90,

       .mask = 0x3FFFFFF0,

       .features = PHY_BASIC_FEATURES,

       .config = &dp83848_config,

       .startup = &genphy_startup,

       .shutdown = &genphy_shutdown,

    };

    int phy_natsemi_init(void)

    {

           phy_register(&DP83848_driver);

           phy_register(&DP83630_driver);

           phy_register(&DP83865_driver);

           return 0;

    }

    In device tree am335x-bone-common.dtsi

    &cpsw_emac0 {

    /*   phy_id = <&davinci_mdio>, <0>; */

       phy_id = <&davinci_mdio>, <1>;

       phy-mode = "mii";

    };

    In kernel

    Remodify for DP83848 as attached above drivers/net/phy/national.c

    /*
     * drivers/net/phy/national.c
     *
     * Driver for National Semiconductor PHYs
     *
     * Author: Stuart Menefy <stuart.menefy@st.com>
     * Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
     *
     * Copyright (c) 2008 STMicroelectronics Limited
     *
     * 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.
     *
     */
    
    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/mii.h>
    #include <linux/ethtool.h>
    #include <linux/phy.h>
    #include <linux/netdevice.h>
    
    #define DEBUG
    
    // ADDED BY SRINI DP83848 SUPPORT FOR TUNSTALL AM335x CUSTOM BOARD
    /* DP83848 phy identifier values */
    #define DP83848_PHY_ID	0x20005c90
    
    #define DP83848_EDCR 0x1D /*Energy Detect Control */
    #define DP83848_energy_detect_en 0xE81F /* Energy Detect Enable */
    #define DP83848_BMCR 0x00
    #define DP83848_PHYCR 0x19
    #define DP83848_PHYSTS 0x10
    #define DP83848_MICR 0x11 /* MICR */
    #define DP83848_MISR 0x12 /* MISR */
    #define DP83848_INT_EVENTS 0x007f
    #if 0
    
    /* DP83865 phy identifier values */
    #define DP83865_PHY_ID	0x20005c7a
    
    #define DP83865_INT_STATUS	0x14
    #define DP83865_INT_MASK	0x15
    #define DP83865_INT_CLEAR	0x17
    
    #define DP83865_INT_REMOTE_FAULT 0x0008
    #define DP83865_INT_ANE_COMPLETED 0x0010
    #define DP83865_INT_LINK_CHANGE	0xe000
    #define DP83865_INT_MASK_DEFAULT (DP83865_INT_REMOTE_FAULT | \
    				DP83865_INT_ANE_COMPLETED | \
    				DP83865_INT_LINK_CHANGE)
    
    /* Advanced proprietary configuration */
    #define NS_EXP_MEM_CTL	0x16
    #define NS_EXP_MEM_DATA	0x1d
    #define NS_EXP_MEM_ADD	0x1e
    
    #define LED_CTRL_REG 0x13
    #define AN_FALLBACK_AN 0x0001
    #define AN_FALLBACK_CRC 0x0002
    #define AN_FALLBACK_IE 0x0004
    #define ALL_FALLBACK_ON (AN_FALLBACK_AN |  AN_FALLBACK_CRC | AN_FALLBACK_IE)
    
    enum hdx_loopback {
    	hdx_loopback_on = 0,
    	hdx_loopback_off = 1,
    };
    
    static u8 ns_exp_read(struct phy_device *phydev, u16 reg)
    {
    	phy_write(phydev, NS_EXP_MEM_ADD, reg);
    	return phy_read(phydev, NS_EXP_MEM_DATA);
    }
    
    static void ns_exp_write(struct phy_device *phydev, u16 reg, u8 data)
    {
    	phy_write(phydev, NS_EXP_MEM_ADD, reg);
    	phy_write(phydev, NS_EXP_MEM_DATA, data);
    }
    
    static int ns_config_intr(struct phy_device *phydev)
    {
    	int err;
    
    	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
    		err = phy_write(phydev, DP83865_INT_MASK,
    				DP83865_INT_MASK_DEFAULT);
    	else
    		err = phy_write(phydev, DP83865_INT_MASK, 0);
    
    	return err;
    }
    
    static int ns_ack_interrupt(struct phy_device *phydev)
    {
    	int ret = phy_read(phydev, DP83865_INT_STATUS);
    	if (ret < 0)
    		return ret;
    
    	/* Clear the interrupt status bit by writing a “1”
    	 * to the corresponding bit in INT_CLEAR (2:0 are reserved) */
    	ret = phy_write(phydev, DP83865_INT_CLEAR, ret & ~0x7);
    
    	return ret;
    }
    
    static void ns_giga_speed_fallback(struct phy_device *phydev, int mode)
    {
    	int bmcr = phy_read(phydev, MII_BMCR);
    
    	phy_write(phydev, MII_BMCR, (bmcr | BMCR_PDOWN));
    
    	/* Enable 8 bit expended memory read/write (no auto increment) */
    	phy_write(phydev, NS_EXP_MEM_CTL, 0);
    	phy_write(phydev, NS_EXP_MEM_ADD, 0x1C0);
    	phy_write(phydev, NS_EXP_MEM_DATA, 0x0008);
    	phy_write(phydev, MII_BMCR, (bmcr & ~BMCR_PDOWN));
    	phy_write(phydev, LED_CTRL_REG, mode);
    }
    
    static void ns_10_base_t_hdx_loopack(struct phy_device *phydev, int disable)
    {
    	if (disable)
    		ns_exp_write(phydev, 0x1c0, ns_exp_read(phydev, 0x1c0) | 1);
    	else
    		ns_exp_write(phydev, 0x1c0,
    			     ns_exp_read(phydev, 0x1c0) & 0xfffe);
    
    	pr_debug("10BASE-T HDX loopback %s\n",
    		 (ns_exp_read(phydev, 0x1c0) & 0x0001) ? "off" : "on");
    }
    
    static int ns_config_init(struct phy_device *phydev)
    {
    	ns_giga_speed_fallback(phydev, ALL_FALLBACK_ON);
    	/* In the latest MAC or switches design, the 10 Mbps loopback
    	   is desired to be turned off. */
    	ns_10_base_t_hdx_loopack(phydev, hdx_loopback_off);
    	return ns_ack_interrupt(phydev);
    }
    
    static struct phy_driver dp83865_driver = {
    	.phy_id = DP83865_PHY_ID,
    	.phy_id_mask = 0xfffffff0,
    	.name = "NatSemi DP83865",
    	.features = PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause,
    	.flags = PHY_HAS_INTERRUPT,
    	.config_init = ns_config_init,
    	.config_aneg = genphy_config_aneg,
    	.read_status = genphy_read_status,
    	.ack_interrupt = ns_ack_interrupt,
    	.config_intr = ns_config_intr,
    	.driver = {.owner = THIS_MODULE,}
    };
    #endif
    
    #if 0
    static int dp83848_phy_config_intr(struct phy_device *phydev)
    {
    	int val;
    
    	val = phy_write (phydev, DP83848_MISR,
    			((PHY_INTERRUPT_ENABLED == phydev->interrupts)
    			? 0x7F
    			: 0));
    //	printk("\nIn config_intr MISR value: %x, phydev->interrupts=%x\n", val,phydev->interrupts);
    	return val < 0 ? val : 0;
    }
    #endif
    
    static int dp83848_phy_ack_interrupt(struct phy_device *phydev)
    {
    	int ret = phy_read(phydev, DP83848_MISR);
    	int value, /*data,*/value_link,value_speed,value_duplex,a,b;
    	if (ret < 0)
    		return ret;
        
    	value=ret & 0x4000;	
    
    	value_link=ret & 0x2000;	
    	value_speed=ret & 0x1000;	
    	value_duplex=ret & 0x0800;	
    
    	//printk("\n Entering dp83848_phy_ack_interrupt FUNCTION\n");
    
    	if((value>0))
    	{
    		//printk("\n Energy detect interrupt\n");
    		
    		a = phy_read(phydev, DP83848_EDCR);
    		b= a &0x0400;
    		if(b==0)
    		{
    		//printk("\n Entering energy detect mode\n");
    		}
    		else 
    		{
    	 //	printk("\n Entering normal mode of operation\n");
    
    		}
    
    		if(value_link>0)
    		{
    		//printk("\n Link status interrupt\n");
    		}
    
    	        if(value_speed>0)
    		{
    		//printk("\n Speed status interrupt\n");
    		}
    
    		if(value_duplex>0)
    		{
    	//printk("\n Duplex status interrupt\n");
    		}
        }
    
    	return 0;
    }
    
    static int dp83848_phy_config_init(struct phy_device *phydev)
    {
    	int val = phy_read(phydev, DP83848_EDCR);
    	int value,data;
    	if (val < 0)
    		return val;
    	
    	phy_write(phydev, DP83848_MICR, 0x0003); /*Enabling interrupts */
    
    	phy_write(phydev, DP83848_MISR, 0x007F);
           
    	/*Enable energy detect control */
            value = phy_write(phydev, DP83848_EDCR, val | DP83848_energy_detect_en);
    
          value=phy_read(phydev, DP83848_EDCR);
    	printk("\n Energy Value: ");
          printk(" %x",value);
    
    	value=phy_read(phydev, DP83848_PHYCR);
    	printk("\n Phy control register to check for AUTO-MDIX: ");
           printk(" %x",value);
            
     
           value=phy_read(phydev, DP83848_PHYSTS);
             
    	data=value & 0x4000;
    	
    	if(data>0)
    	{
    	printk("\n MDI pairs swapped\n");
    	}
    	else 
    	{
    	printk("\n MDI pairs normal\n");
    	}
    
    	return dp83848_phy_ack_interrupt(phydev);
    
    }
    
    static int phy_probe(struct phy_device *phydev)
    {
    phydev->irq=42;	
    printk("\n Entering phy_probe\n");
    return 0;
    };
    
    
    static struct phy_driver dp83848_driver = {
    	.phy_id		= DP83848_PHY_ID,
    	.phy_id_mask	= 0xfffffff0,
    	.name		= "DP83848 PHY",
    	.features	= PHY_BASIC_FEATURES,
    	.flags		= PHY_HAS_INTERRUPT,
    	.probe		= phy_probe,	
    	
    	/* basic functions */
    	
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
            .config_init	= dp83848_phy_config_init,
    
    	/* interrupt related */
    	.ack_interrupt	= dp83848_phy_ack_interrupt,
    //	.config_intr	= dp83848_phy_config_intr,
       	
    	.driver		= {.owner = THIS_MODULE,}
    };
    static int __init ns_init(void)
    {
    	//return phy_driver_register(&dp83865_driver);
    	return phy_driver_register(&dp83848_driver);
    }
    
    static void __exit ns_exit(void)
    {
    	//phy_driver_unregister(&dp83865_driver);
    	phy_driver_unregister(&dp83848_driver);
    }
    
    MODULE_DESCRIPTION("NatSemi PHY driver");
    MODULE_AUTHOR("Stuart Menefy");
    MODULE_LICENSE("GPL");
    
    module_init(ns_init);
    module_exit(ns_exit);
    
    static struct mdio_device_id __maybe_unused ns_tbl[] = {
    	//{ DP83865_PHY_ID, 0xfffffff0 },
    	{ DP83848_PHY_ID, 0xfffffff0 },	
    	{ }
    };
    
    MODULE_DEVICE_TABLE(mdio, ns_tbl);
    

    Let me know once, if it works for you...

    Srini

  • Srini

    Thanks for the quick reply. Are you using it in MII mode or RMII?  I currently have it in RMII and could not get it to read my PHY. But when I switch it to MII, it detects my PHY. Unfortunately...my board layout is missing TXCLK, RXCLK, TXD2, TD3, RXD3, and RXD4 lines for MII mode, so I could not get it to ping. 

    Khanh

  • Srini, I solved the problem.

    This need to be taken out of the pinmux:
    {OFFSET(mii1_rxdv), MODE(1) | RXACTIVE}, /* RMII1_RX_DV */

    This line is connected to the PHY_RESET on the DP83848
  • Thanks Khanh,

    Am using MII mode not RMII, any ways this might be useful if anybody configure DP83848 in MII mode with AM335x

    Srini

  • Hi Srini,

    Hope all is well. I'm currently having problem with the kernel and wonder if you got your working. The kernel was able to detect the PHY but I'm not able to ping to any any local network devices. 

    Which version of the kernel are you using? I'm using 3.2 from the TI SDK 6.0. 

    I switched out the /drivers/net/phy/national.c to the national.c file you attached in previous post. 

    kernel boot log:

  • Am using ti sdk 8, kernel 3.14 version,

    ifconfig eth0 192.168.1.24 netmask 255.255.255.0 up

    Outside network should be same class

    1. try dhcp..

    2. try configuring static ip during bootup time /etc/network/interfaces (google it)

    Thanks,

    Srini

  • Dear Khanh,

    Is this issue is fixed??? Have you got it working with static ip configuration, using the driver (national.c) in your kernel??

    Thanks,
    Srini
  • Hey Srini,

    Unfortunately, I still wasn't able to do any ping even with static ip configuration. Since I'm using RMII mode for my PHY, I also added this line in dp83848_phy_config_init():    phy_write(phydev, DP83848_RBR, 0x0031), to enabled RMII mode.  

    /*
     * drivers/net/phy/national.c
     *
     * Driver for National Semiconductor PHYs
     *
     * Author: Stuart Menefy <stuart.menefy@st.com>
     * Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
     *
     * Copyright (c) 2008 STMicroelectronics Limited
     *
     * 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.
     *
     */
    
    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/mii.h>
    #include <linux/ethtool.h>
    #include <linux/phy.h>
    #include <linux/netdevice.h>
    
    #define DEBUG
    
    // ADDED BY SRINI DP83848 SUPPORT FOR TUNSTALL AM335x CUSTOM BOARD
    /* DP83848 phy identifier values */
    #define DP83848_PHY_ID	0x20005c90
    
    #define DP83848_EDCR 0x1D 	/*Energy Detect Control */
    #define DP83848_energy_detect_en 0xE81F /* Energy Detect Enable */
    #define DP83848_BMCR 0x00
    #define DP83848_PHYCR 0x19
    #define DP83848_PHYSTS 0x10
    #define DP83848_MICR 0x11 	/* MICR */
    #define DP83848_MISR 0x12 	/* MISR */
    #define DP83848_RBR 0x17 	/* RMII */
    #define DP83848_ANAR 0x04 	/* Auto-Negotiation Advertisement */
    #define DP83848_INT_EVENTS 0x007f
    
    #if 0
    static int dp83848_phy_config_intr(struct phy_device *phydev)
    {
    	int val;
    
    	val = phy_write (phydev, DP83848_MISR,
    			((PHY_INTERRUPT_ENABLED == phydev->interrupts)
    			? 0x7F
    			: 0));
    //	printk("\nIn config_intr MISR value: %x, phydev->interrupts=%x\n", val,phydev->interrupts);
    	return val < 0 ? val : 0;
    }
    #endif
    
    static int dp83848_phy_ack_interrupt(struct phy_device *phydev)
    {
    	int ret = phy_read(phydev, DP83848_MISR);
    	int value, /*data,*/value_link,value_speed,value_duplex,a,b;
    	if (ret < 0)
    		return ret;
    
    	value=ret & 0x4000;
    
    	value_link=ret & 0x2000;
    	value_speed=ret & 0x1000;
    	value_duplex=ret & 0x0800;
    
    	//printk("\n Entering dp83848_phy_ack_interrupt FUNCTION\n");
    
    	if((value>0))
    	{
    		//printk("\n Energy detect interrupt\n");
    
    		a = phy_read(phydev, DP83848_EDCR);
    		b= a &0x0400;
    		if(b==0)
    		{
    		//printk("\n Entering energy detect mode\n");
    		}
    		else
    		{
    	 //	printk("\n Entering normal mode of operation\n");
    
    		}
    
    		if(value_link>0)
    		{
    		//printk("\n Link status interrupt\n");
    		}
    
    	        if(value_speed>0)
    		{
    		//printk("\n Speed status interrupt\n");
    		}
    
    		if(value_duplex>0)
    		{
    	//printk("\n Duplex status interrupt\n");
    		}
        }
    
    	return 0;
    }
    
    static int dp83848_phy_config_init(struct phy_device *phydev)
    {
    	int val = phy_read(phydev, DP83848_EDCR);
    	int value,data;
    	if (val < 0)
    		return val;
    
    	phy_write(phydev, DP83848_BMCR, 0x8000);
    	value=phy_read(phydev, DP83848_BMCR);
    	printk("\n BMCR: %x", value);
    
    	/* Enable RMII mode */
    	phy_write(phydev, DP83848_RBR, 0x0031);
    	value=phy_read(phydev, DP83848_RBR);
    	printk("\n RBR: %x", value);
    
    	/* Auto-Negotiation */
    	phy_write(phydev, DP83848_ANAR, 0x01F1);
    	value=phy_read(phydev, DP83848_ANAR);
    	printk("\n ANAR: %x", value);
    
    	/* Enable energy detect control */
            value = phy_write(phydev, DP83848_EDCR, DP83848_energy_detect_en);
          	value=phy_read(phydev, DP83848_EDCR);
    	printk("\n Energy Value: %x", value);
    
    	/* Enabling interrupts */
    	// phy_write(phydev, DP83848_MICR, 0x0003); 
    	// value=phy_read(phydev, DP83848_MICR);
    	// printk("\n MICR: %x", value);
    
    	// value=phy_read(phydev, DP83848_MISR);
    	// printk("\n MISR: %x", value);
    
    	value=phy_read(phydev, DP83848_PHYCR);
    	printk("\n Phy control register to check for AUTO-MDIX: %x", value);
    
           	value=phy_read(phydev, DP83848_PHYSTS);
           	printk("\n PHYSTS 0x%x", value);
    
    	data=value & 0x4000;
    
    	if(data>0)
    	{
    	printk("\n MDI pairs swapped\n");
    	}
    	else
    	{
    	printk("\n MDI pairs normal\n");
    	}
    
    	return dp83848_phy_ack_interrupt(phydev);
    
    }
    
    static int phy_probe(struct phy_device *phydev)
    {
    phydev->irq=42;
    printk("\n Entering phy_probe\n");
    return 0;
    };
    
    
    static struct phy_driver dp83848_driver = {
    	.phy_id		= DP83848_PHY_ID,
    	.phy_id_mask	= 0x3FFFFFF0, //0xfffffff0,
    	.name		= "DP83848 PHY",
    	.features	= PHY_BASIC_FEATURES,
    	.flags		= PHY_HAS_INTERRUPT,
    	.probe		= phy_probe,
    
    	/* basic functions */
    
    	.config_aneg	= genphy_config_aneg,
    	.read_status	= genphy_read_status,
            .config_init	= dp83848_phy_config_init,
    
    	/* interrupt related */
    	.ack_interrupt	= dp83848_phy_ack_interrupt,
    	//.config_intr	= dp83848_phy_config_intr,
    
    	.driver		= {.owner = THIS_MODULE,}
    };
    static int __init ns_init(void)
    {
    	return phy_driver_register(&dp83848_driver);
    }
    
    static void __exit ns_exit(void)
    {
    	phy_driver_unregister(&dp83848_driver);
    }
    
    MODULE_DESCRIPTION("NatSemi DP83848 PHY driver");
    MODULE_AUTHOR("Stuart Menefy");
    MODULE_LICENSE("GPL");
    
    module_init(ns_init);
    module_exit(ns_exit);
    
    static struct mdio_device_id __maybe_unused ns_tbl[] = {
    	{ DP83848_PHY_ID, 0xfffffff0 },
    	{ }
    };
    
    MODULE_DEVICE_TABLE(mdio, ns_tbl);
    

  • Where u able to ping with dhcp?? Even I haven't tried with static ip, will try & let you know.., but its working for me with dhcp 

  • I know the PHY works in U-Boot because I use TFTP to load the kernel onto the ram. I used dhcp in U-boot and it works flawless. I also tried dhcp on the kernel but it wasn't able to ping. Thanks for helping
  • If possible, can I get your .config file? See what if I'm missing something in mine.
  • Just to reconfirm does dhcp works in u-boot, hope kernel gets loaded to ram without any issues??? have u ever tried loading NFS (Network file system)? via dhcp??

    When am back to office on monday, will send you the config file
  • Yup dhcp works in u-boot and the kernel got loaded to the ram without any problem. The kernel boots fine also, but when I try to dhcp from the kernel, it wasn't able to get anything.  I haven't try loading NFS yet. Load it during u-boot along with the zImage?

  • Yes...

    setenv autoload no
    dhcp
    setenv serverip 192.168.82.40
    setenv netmask 255.255.255.0
    setenv gatewayip 192.168.82.1
    tftpboot ${fdtaddr} srini/am335x-boneblack.dtb
    tftpboot ${kloadaddr} srini/zImage
    setenv bootargs console=ttyO1,115200n8 root=/dev/nfs nfsroot=192.168.82.40:/tools/rootfs_dir/srini/rootfs rootwait ip=dhcp
    bootz 0x82000000 - 0x88000000

    Before this NFS server needs to be configured in your host pc
  • UART0 debug
    setenv bootargs console=ttyO0,115200n8 root=/dev/nfs nfsroot=192.168.82.40:/tools/rootfs_dir/srini/rootfs rootwait ip=dhcp
    UART1 debug
    setenv bootargs console=ttyO1,115200n8 root=/dev/nfs nfsroot=192.168.82.40:/tools/rootfs_dir/srini/rootfs rootwait ip=dhcp
  • I will try this and get back to you. Thanks