zoukankan      html  css  js  c++  java
  • I.MX6 Ethernet MAC (ENET) MAC Address hacking

    /*********************************************************************
     *        I.MX6 Ethernet MAC (ENET) MAC Address hacking
     * 说明:
     *     Lee对相关的一些代码进行了修改,所以这边跟一下这边相关的设置原理,
     * 主要是为了知道MAC address在Uboot、Linux kernel阶段的的设置,获取的
     * 工作机制。
     *
     *                                   2016-7-27 深圳 南山平山村 曾剑锋
     ********************************************************************/
    
    参考文档:
        Freescale i.MX6 Linux Ethernet Driver驱动源码分析
            http://blog.163.com/thinki_cao/blog/static/8394487520146308450620/
    
    
    
    cat lib_arm/board.c                                                             
    void start_armboot (void)                                                       
    {                                                                               
        ......                                                                      
        stdio_init ();    /* get the devices list going. */  ---------+             
        ......                                                        |             
        eth_initialize(gd->bd);                       ----------------*-+           
        ......                                                        | |           
    }                                                                 | |           
                                                                      | |           
    int stdio_init (void)               <-----------------------------+ |           
    {                                                                   |           
        ......                                                          |           
    #ifdef CONFIG_LCD                                                   |           
        drv_lcd_init ();                   ------------+                |           
    #endif                                             |                |           
        ......                                         |                |           
                                                       |                |           
        return (0);                                    |                |           
    }                                                  |                |           
                                                       |                |           
    int drv_lcd_init (void)               <------------+                |           
    {                                                                   |           
        ......                                                          |           
        lcd_init (lcd_base);        /* LCD initialization */ --------+  |           
        ......                                                       |  |           
    }                                                                |  |           
                                                                     |  |           
    static int lcd_init (void *lcdbase)                     <--------+  |           
    {                                                                   |           
        ......                                                          |           
        lcd_enable ();                                --------+         |           
        ......                                                |         |           
    }                                                         |         |           
                                                              |         |           
    #ifdef CONFIG_LCD                                         |         |           
    void lcd_enable(void)                            <--------+         |           
    {                                                                   |           
        ......                                                          |           
        setenv("ethaddr",buffer);                                       |           
        ......                                                          |           
    }                                                                   |           
                                                                        |           
    int eth_initialize(bd_t *bis)                <----------------------+           
    {                                                                               
        ......                                                                      
        /* Try board-specific initialization first.  If it fails or isn't           
         * present, try the cpu-specific initialization */                          
        if (board_eth_init(bis) < 0)                                                
            cpu_eth_init(bis);                   -------+                           
                                                        |                           
        ......                                          |                           
    }                                                   |                           
                                                        |                           
                                                        |                           
    int cpu_eth_init(bd_t *bis)                  <------+                           
    {                                                                               
        int rc = -ENODEV;                                                           
    #if defined(CONFIG_MXC_FEC)                                                     
        rc = mxc_fec_initialize(bis);            -------+                           
                                                        |                           
        /* Board level init */                          |                           
        enet_board_init();                              |                           
                                                        |                           
    #endif                                              |                           
        return rc;                                      |                           
    }                                                   |                           
                                                        |                           
    int mxc_fec_initialize(bd_t *bis)           <-------+                           
    {                                                                               
        struct eth_device *dev;                                                     
        int i;                                                                      
        unsigned char ethaddr[6];                                                   
                                                                                    
        for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) {              
    #ifdef CONFIG_ARCH_MMU                                                          
            int j;                                                                  
    #endif                                                                          
            dev =                                                                   
                (struct eth_device *)memalign(CONFIG_SYS_CACHELINE_SIZE,            
                              sizeof *dev);                                         
            if (dev == NULL)                                                        
                hang();                                                             
                                                                                    
            memset(dev, 0, sizeof(*dev));                                           
                                                                                    
            sprintf(dev->name, "FEC%d", fec_info[i].index);                         
            dev->priv = &fec_info[i];                       ----------+             
            dev->init = fec_init;                                     |             
            dev->halt = fec_halt;                                     |             
            dev->send = fec_send;                                     |             
            dev->recv = fec_recv;                                     |             
            ......                                                    |             
                                                                      |             
            if (fec_get_hwaddr(dev, ethaddr) == 0) {            ------*-----+       
                printf("got MAC address from IIM: %pM
    ", ethaddr);   |     |       
                memcpy(dev->enetaddr, ethaddr, 6);                    |     |       
                fec_set_hwaddr(dev);                            ------*-----*-+     
            }                                                         |     | |     
        }                                                             |     | |     
                                                                      |     | |     
        return 1;                                                     |     | |     
    }                                                                 |     | |     
                                                                      |     | |     
    struct fec_info_s fec_info[] = {                       <----------+     | |     
        {                                                             |     | |     
         0,            /* index */                                    |     | |     
         CONFIG_FEC0_IOBASE,    /* io base */               --------+-*-----*-*-+   
         CONFIG_FEC0_PHY_ADDR,    /* phy_addr */                    | |     | | |   
         0,            /* duplex and speed */                       | |     | | |   
         0,            /* phy name */                               | |     | | |   
         0,            /* phyname init */                           | |     | | |   
         0,            /* RX BD */                                  | |     | | |   
         0,            /* TX BD */                                  | |     | | |   
         0,            /* rx Index */                               | |     | | |   
         0,            /* tx Index */                               | |     | | |   
         0,            /* tx buffer */                              | |     | | |   
    #ifdef CONFIG_ARCH_MMU                                          | |     | | |   
         { 0 },            /* rx buffer */                          | |     | | |   
    #endif                                                          | |     | | |   
         0,            /* initialized flag */                       | |     | | |   
         },                                                         | |     | | |   
    };                                                              | |     | | |   
                                                                    | |     | | |   
    /* FEC private information */                                   | |     | | |   
    struct fec_info_s {                                  <----------*-+     | | |   
        int index;                                                  |       | | |   
        u32 iobase;                                                 |       | | |   
        int phy_addr;                                               |       | | |   
        int dup_spd;                                                |       | | |   
        char *phy_name;                                             |       | | |   
        int phyname_init;                                           |       | | |   
        cbd_t *rxbd;        /* Rx BD */                             |       | | |   
        cbd_t *txbd;        /* Tx BD */                             |       | | |   
        uint rxIdx;                                                 |       | | |   
        uint txIdx;                                                 |       | | |   
        char *txbuf;                                                |       | | |   
    #ifdef CONFIG_ARCH_MMU                                          |       | | |   
        char *rxbuf[PKTBUFSRX];                                     |       | | |   
    #endif                                                          |       | | |   
        int initialized;                                            |       | | |   
        struct fec_info_s *next;                                    |       | | |   
    };                                                              |       | | |   
                                                                    |       | | |   
    #define CONFIG_FEC0_IOBASE    ENET_BASE_ADDR       <------------+       | | |   
    #define ENET_BASE_ADDR              (AIPS2_OFF_BASE_ADDR + 0x8000)      | | |   
    #define AIPS2_OFF_BASE_ADDR         (ATZ2_BASE_ADDR + 0x80000)          | | |   
    #define ATZ2_BASE_ADDR              AIPS2_ARB_BASE_ADDR                 | | |   
    #define AIPS2_ARB_BASE_ADDR             0x02100000                      | | |   
                                                                            | | |   
    extern int fec_get_mac_addr(unsigned char *mac);                        | | |   
    static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) <-+ | |   
    {                                                                         | |   
    #ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM                                   | |   
        fec_get_mac_addr(mac);                          ----------+           | |   
                                                                  |           | |   
        return 0;                                                 |           | |   
    #else                                                         |           | |   
        return -1;                                                |           | |   
    #endif                                                        |           | |   
    }                                                             |           | |   
                                                                  |           | |   
    #ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM                       |           | |   
    int fec_get_mac_addr(unsigned char *mac)           <----------+           | |   
    {                                                                         | |   
    #if 0                                                                     | |   
        unsigned int value;                                                   | |   
                                                                              | |   
        value = readl(OCOTP_BASE_ADDR + HW_OCOTP_MACn(0));                    | |   
        mac[5] = value & 0xff;                                                | |   
        mac[4] = (value >> 8) & 0xff;                                         | |   
        mac[3] = (value >> 16) & 0xff;                                        | |   
        mac[2] = (value >> 24) & 0xff;                                        | |   
        value = readl(OCOTP_BASE_ADDR + HW_OCOTP_MACn(1));                    | |   
        mac[1] = value & 0xff;                                                | |   
        mac[0] = (value >> 8) & 0xff;                                         | |   
    #else                                                                     | |   
        eth_getenv_enetaddr("ethaddr", mac);            ----------+           | |   
    #endif                                                        |           | |   
        return 0;                                                 |           | |   
    }                                                             |           | |   
    #endif                                                        |           | |   
                                                                  |           | |   
    static int fec_set_hwaddr(struct eth_device *dev)        <----|-----------+ |   
    {                                                             |             |   
        uchar *mac = dev->enetaddr;                               |             |   
        struct fec_info_s *info = dev->priv;                      |             |   
        volatile fec_t *fecp = (fec_t *)(info->iobase);           |             |   
                                                                  |             |   
        writel(0, &fecp->iaur);                                   |             |   
        writel(0, &fecp->ialr);                                   |             |   
        writel(0, &fecp->gaur);                                   |             |   
        writel(0, &fecp->galr);                                   |             |   
                                                                  |             |   
        /*                                                        |             |   
         * Set physical address                                   |             |   
         */                                                       V             |   
        writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],  ------*-+ 
                &fecp->palr);                                                   | | 
        writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, &fecp->paur);          | | 
                                                                                | | 
        return 0;                                                               | | 
    }                                                                           | | 
                                                                                | | 
                                                                                | | 
    cat arch/arm/mach-mx6/board-mx6q_sabresd.c                                  | | 
    MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Boa|"|)
        /* Maintainer: Freescale Semiconductor, Inc. */                         | | 
        .boot_params = MX6_PHYS_OFFSET + 0x100,                                 | | 
        .fixup = fixup_mxc_board,                                               | | 
        .map_io = mx6_map_io,                                                   | | 
        .init_irq = mx6_init_irq,                                               | | 
        .init_machine = mx6_sabresd_board_init,      ----------+                | | 
        .timer = &mx6_sabresd_timer,                           |                | | 
        .reserve = mx6q_sabresd_reserve,                       |                | | 
    MACHINE_END                                                |                | | 
                                                               |                | | 
    /*!                                                        |                | | 
     * Board specific initialization.                          |                | | 
     */                                                        |                | | 
    static void __init mx6_sabresd_board_init(void)  <---------+                | | 
    {                                                                           | | 
        ......                                                                  | | 
        imx6_init_fec(fec_data);                                                | | 
        ......   |                                                              | | 
    }            |                                                              | | 
                 V                                                              | | 
    void __init imx6_init_fec(struct fec_platform_data fec_data)  ---------+    | | 
    {                                                                      |    | | 
        fec_get_mac_addr(fec_data.mac);                                    |    | | 
        /*                                                                 |    | | 
        if (!is_valid_ether_addr(fec_data.mac))                            |    | | 
            random_ether_addr(fec_data.mac);                               |    | | 
        */                                                                 |    | | 
                                                                           |    | | 
        if (cpu_is_mx6sl())                                                |    | | 
            imx6sl_add_fec(&fec_data);                                     |    | | 
        else                                                               |    | | 
            imx6q_add_fec(&fec_data);                                      |    | | 
    }                                                                      |    | | 
                                                                           |    | | 
    extern const struct imx_fec_data imx6q_fec_data __initconst;           |    | | 
    #define imx6q_add_fec(pdata)                     <--------------------+    | | 
        imx_add_fec(&imx6q_fec_data, pdata)           ---------------------+    | | 
                                                                           |    | | 
    #ifdef CONFIG_SOC_IMX6Q                                                |    | | 
    const struct imx_fec_data imx6q_fec_data __initconst =                 |    | | 
        imx_fec_data_entry_single(MX6Q, "enet");                           |    | | 
                                                                           |    | | 
    const struct imx_fec_data imx6sl_fec_data __initconst =     <----------+    | | 
        imx_fec_data_entry_single(MX6DL, "fec");               ----------+ |    | | 
    #endif                                                               | |    | | 
                                                                         | |    | | 
    struct platform_device *__init imx_add_fec(       <------------------*-+    | | 
            const struct imx_fec_data *data,                             |      | | 
            const struct fec_platform_data *pdata)                       |      | | 
    {                                                                    |      | | 
        struct resource res[] = {                                        |      | | 
            {                                                            |      | | 
                .start = data->iobase,                                   |      | | 
                .end = data->iobase + SZ_4K - 1,                         |      | | 
                .flags = IORESOURCE_MEM,                                 |      | | 
            }, {                                                         |      | | 
                .start = data->irq,                                      |      | | 
                .end = data->irq,                                        |      | | 
                .flags = IORESOURCE_IRQ,                                 |      | | 
            },                                                           |      | | 
        };                                                               |      | | 
                                                                         |      | | 
        if (!fuse_dev_is_available(MXC_DEV_ENET))                        |      | | 
            return ERR_PTR(-ENODEV);                                     |      | | 
                                                                         |      | | 
        return imx_add_platform_device_dmamask(data->devid, 0,           |      | | 
                res, ARRAY_SIZE(res),                                    |      | | 
                pdata, sizeof(*pdata), DMA_BIT_MASK(32));                |      | | 
    }                                                                    |      | | 
                                                                         |      | | 
    #define imx_fec_data_entry_single(soc, _devid)                 <----+      | | 
        {                                                                      | | 
            .iobase = soc ## _FEC_BASE_ADDR,                    --------+      | | 
            .irq = soc ## _INT_FEC,                                     |      | | 
            .devid = _devid,                                            |      | | 
        }                                                                |      | | 
                                                                         |      | | 
    #define MX6DL_FEC_BASE_ADDR        ENET_BASE_ADDR            <-------+------+ | 
    #define ENET_BASE_ADDR            (AIPS2_OFF_BASE_ADDR+0x8000)                | 
    #define AIPS2_OFF_BASE_ADDR        (ATZ2_BASE_ADDR + 0x80000)                 | 
    #define ATZ2_BASE_ADDR            AIPS2_ARB_BASE_ADDR                         | 
    #define AIPS2_ARB_BASE_ADDR        0x02100000                                 | 
                                                                                  | 
    cat drivers/net/fec.c                                                         | 
    static int __init                                                             | 
    fec_enet_module_init(void)                                                    | 
    {                                                                             | 
        printk(KERN_INFO "FEC Ethernet Driver
    ");                                | 
                                                                                  | 
        return platform_driver_register(&fec_driver);  ------+                    | 
    }                                                        |                    | 
                                                             |                    | 
    static void __exit                                       |                    | 
    fec_enet_cleanup(void)                                   |                    | 
    {                                                        |                    | 
        platform_driver_unregister(&fec_driver);             |                    | 
    }                                                        |                    | 
                                                             |                    | 
    module_exit(fec_enet_cleanup);                           |                    | 
    module_init(fec_enet_module_init);                       |                    | 
                                                             |                    | 
    MODULE_LICENSE("GPL");                                   |                    | 
                                                             |                    | 
    static struct platform_driver fec_driver = {       <-----+                    | 
        .driver    = {                                                            | 
            .name    = DRIVER_NAME,                                               | 
            .owner    = THIS_MODULE,                                              | 
    #ifdef CONFIG_PM                                                              | 
            .pm    = &fec_pm_ops,                                                 | 
    #endif                                                                        | 
        },                                                                        | 
        .id_table = fec_devtype,                                                  | 
        .probe    = fec_probe,                         ------+                    | 
        .remove    = __devexit_p(fec_drv_remove),            |                    | 
    };                                                       |                    | 
                                                             |                    | 
    static int __devinit                                     |                    | 
    fec_probe(struct platform_device *pdev)            <-----+                    | 
    {                                                                             | 
        ......                                                                    | 
        fep->hwp = ioremap(r->start, resource_size(r));      ---------------+     | 
        ......                                                              |     | 
        ret = fec_enet_init(ndev);                     ------+              |     | 
        if (ret)                                             |              |     | 
            goto failed_init;                                |              |     | 
        ......                                               |              |     | 
    }                                                        |              |     | 
                                                             |              |     | 
    static int fec_enet_init(struct net_device *ndev)  <-----+              |     | 
    {                                                                       |     | 
        ......                                                              |     | 
        /* Get the Ethernet address */                                      |     | 
        fec_get_mac(ndev);                             ----------------+    |     | 
        ......                                                         |    |     | 
    }                                                                  |    |     | 
                                                                       |    |     | 
    static void __inline__ fec_get_mac(struct net_device *ndev)  <-----+    |     | 
    {                                                                       |     | 
        struct fec_enet_private *fep = netdev_priv(ndev);                   |     | 
        struct fec_platform_data *pdata = fep->pdev->dev.platform_data;     |     | 
        unsigned char *iap, tmpaddr[ETH_ALEN];                              |     | 
                                                                            |     | 
        /*                                                                  |     | 
         * try to get mac address in following order:                       |     | 
         *                                                                  |     | 
         * 1) module parameter via kernel command line in form              |     | 
         *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0                     |     | 
         */                                                                 |     | 
        iap = macaddr;                                                      |     | 
                                                                            |     | 
        /*                                                                  |     | 
         * 2) from flash or fuse (via platform data)                        |     | 
         */                                                                 |     | 
        if (!is_valid_ether_addr(iap)) {                                    |     | 
    #ifdef CONFIG_M5272                                                     |     | 
            if (FEC_FLASHMAC)                                               |     | 
                iap = (unsigned char *)FEC_FLASHMAC;                        |     | 
    #else                                                                   |     | 
            if (pdata)                                                      |     | 
                memcpy(iap, pdata->mac, ETH_ALEN);                          |     | 
    #endif                                                                  |     | 
        }                                                                   |     | 
                                                                            |     | 
        /*                                                                  |     | 
         * 3) FEC mac registers set by bootloader                           |     | 
         */                                                                 |     | 
        if (!is_valid_ether_addr(iap)) {                                    |     | 
            *((unsigned long *) &tmpaddr[0]) =                              |     | 
                be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));     <----------+-----+ 
            *((unsigned short *) &tmpaddr[4]) =                                     
                be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);                 
            iap = &tmpaddr[0];                                                      
        }                                                                           
                                                                                    
        memcpy(ndev->dev_addr, iap, ETH_ALEN);                                      
                                                                                    
        /* Adjust MAC if using macaddr */                                           
        if (iap == macaddr)                                                         
             ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;      
    }                                                                               
  • 相关阅读:
    (转)LayoutInflater的使用
    SQLite入门
    字符排序 分类: java 20100103 14:28 791人阅读 评论(1) 收藏
    oracle常用日期函数 20091211 22:13 300人阅读 评论(0) 收藏
    several years later 分类: 人生墨客 20100106 12:29 470人阅读 评论(0) 收藏
    值传递与引用传递 分类: java 20091218 21:41 343人阅读 评论(0) 收藏
    第一章 基本知识 分类: java 20091229 16:49 307人阅读 评论(0) 收藏
    第三章 运算符、表达式与语句 分类: java 20091229 16:46 304人阅读 评论(0) 收藏
    第五章 继承、接口与泛型 分类: java 20091229 16:43 348人阅读 评论(0) 收藏
    第二章 基本数据类型,输入、输出,数组 分类: java 20091229 16:48 339人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/5711304.html
Copyright © 2011-2022 走看看