zoukankan      html  css  js  c++  java
  • I.MX6 Ar8031 device register hacking

    /*****************************************************************************
     *                   I.MX6 Ar8031 device register hacking
     * 声明:
     *   主要是为了知道网卡的注册流程,如果需要对网卡中的一些需求进行修改时,能够
     *   能够快速的对需求进行分析、修改。
     *
     *                                   2015-8-15 雨 深圳 南山区平山村 曾剑锋
     ****************************************************************************/
    
    /*
     * initialize __mach_desc_MX6Q_SABRESD data structure.
     */
    MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board")
        /* 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); -----------------------------------------------+
        ......           |                                                      |
    }                    +-------------+                                        |
                                       |                                        |
    /*SBC-7112 NET Driver*/            V                                        |
    static struct fec_platform_data fec_data __initdata = {                     |
            .init                   = mx6q_sabresd_fec_phy_init,   -----+       |
            .power_hibernate        = mx6_sabresd_fec_power_hibernate,--*------+|
            .phy                    = PHY_INTERFACE_MODE_RGMII,         |      ||
    #ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO                                  |      ||
            .gpio_irq = MX6_ENET_IRQ,                                   |      ||
    #endif                                                              |      ||
    };                                                                  |      ||
                                                                        |      ||
    static int mx6q_sabresd_fec_phy_init(struct phy_device *phydev) <---+      ||
    {                                                                          ||
        unsigned short val;                                                    ||
        gpio_request(SABRESD_FEC_PHY_RESET,"phy-rst");                         ||
        gpio_direction_output(SABRESD_FEC_PHY_RESET, 1);                       ||
        mdelay(1);                                                             ||
        gpio_direction_output(SABRESD_FEC_PHY_RESET, 0);                       ||
        mdelay(20);                                                            ||
        gpio_direction_output(SABRESD_FEC_PHY_RESET, 1);                       ||
        mdelay(5);                                                             ||
                                                                               ||
        /* Ar8031 phy SmartEEE feature cause link status generates glitch,     ||
         * which cause ethernet link down/up issue, so disable SmartEEE        ||
         */                                                                    ||
        phy_write(phydev, 0xd, 0x3);                                           ||
        phy_write(phydev, 0xe, 0x805d);                                        ||
        phy_write(phydev, 0xd, 0x4003);                                        ||
        val = phy_read(phydev, 0xe);                                           ||
        val &= ~(0x1 << 8);                                                    ||
        phy_write(phydev, 0xe, val);                                           ||
                                                                               ||
        /* To enable AR8031 ouput a 125MHz clk from CLK_25M */                 ||
        phy_write(phydev, 0xd, 0x7);                                           ||
        phy_write(phydev, 0xe, 0x8016);                                        ||
        phy_write(phydev, 0xd, 0x4007);                                        ||
        val = phy_read(phydev, 0xe);                                           ||
                                                                               ||
        val &= 0xffe3;                                                         ||
        val |= 0x18;                                                           ||
        phy_write(phydev, 0xe, val);                                           ||
                                                                               ||
        /* introduce tx clock delay */                                         ||
        phy_write(phydev, 0x1d, 0x5);                                          ||
        val = phy_read(phydev, 0x1e);                                          ||
        val |= 0x0100;                                                         ||
        phy_write(phydev, 0x1e, val);                                          ||
                                                                               ||
        /*check phy power*/                                                    ||
        val = phy_read(phydev, 0x0);                                           ||
        if (val & BMCR_PDOWN)                                                  ||
            phy_write(phydev, 0x0, (val & ~BMCR_PDOWN)); --------+             ||
        return 0;                                                |             ||
    }                       +------------------------------------+             ||
                            V                                                  ||
    static inline void phy_write(struct mii_phy *phy, int reg, int val)        ||
    {                                                                          ||
        phy->mdio_write(phy->dev, phy->address, reg, val);                     ||
    }                                                                          ||
                                                                               ||
    static int mx6_sabresd_fec_power_hibernate(struct phy_device *phydev)  <---+|
    {                                                                           |
        unsigned short val;                                                     |
                                                                                |
        /*set AR8031 debug reg 0xb to hibernate power*/                         |
        phy_write(phydev, 0x1d, 0xb);                                           |
        val = phy_read(phydev, 0x1e);                                           |
                                                                                |
        val |= 0x8000;                                                          |
        phy_write(phydev, 0x1e, val);                                           |
                                                                                |
        return 0;                                                               |
    }                                                                           |
                                                                                |
    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);            --------*---------------------+||
    }                                                    |                     |||
                                                         |                     |||
    static int fec_get_mac_addr(unsigned char *mac) <----+                     |||
    {                                                                          |||
        unsigned int value;                                                    |||
                                                                               |||
        value = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_MACn(0));     |||
        printk("<danny debug> vaule = %x
    ",value);                            |||
        value = 0x03040506;                                                    |||
        mac[5] = value & 0xff;                                                 |||
        mac[4] = (value >> 8) & 0xff;                                          ||| 
        mac[3] = (value >> 16) & 0xff;                                         |||
        mac[2] = (value >> 24) & 0xff;                                         |||
        value = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_MACn(1));     |||
        printk("<danny debug> vaule = %x
    ",value);                            |||
        value = 0x0102;                                                        |||
        mac[1] = value & 0xff;                                                 |||
        mac[0] = (value >> 8) & 0xff;                                          |||
                                                                               |||
        return 0;                                                              |||
    }                                                                          |||
                                                                               |||
    static inline int is_valid_ether_addr(const u8 *addr)         <------------**+
    {                                                                          ||  
        /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to        ||
         * explicitly check for it here. */                                    ||
        return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);    ||
    }                          ^                                  V            ||
                               V                                  |            ||
    static inline int is_multicast_ether_addr(const u8 *addr)     |            ||
    {                                                             |            ||  
        return 0x01 & addr[0];                                    |            ||
    }                                                             |            ||
                                                                  |            ||
    static inline int is_zero_ether_addr(const u8 *addr)    <-----+            ||
    {                                                                          ||
        return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);   ||
    }                                                                          ||
                                                                               ||
    static inline void random_ether_addr(u8 *addr)        <--------------------*+
    {                                                                          |
        get_random_bytes (addr, ETH_ALEN);      -----------------------+       |
        addr [0] &= 0xfe;   /* clear multicast bit */                  |       |
        addr [0] |= 0x02;   /* set local assignment bit (IEEE802) */   |       |
    }                                                                  |       |
                                                                       |       |
    void get_random_bytes(void *buf, int nbytes)        <--------------+       |
    {                                                                          |
        extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);  -----------+   |
    }                                                                      |   |
    EXPORT_SYMBOL(get_random_bytes);                                       |   |
                                                                           |   |
    /********************************************************************* |   |
     *                                                                     |   |
     * Entropy extraction routines                                         |   |
     *                                                                     |   |
     ********************************************************************/ |   |
                                                                           |   |
    static ssize_t extract_entropy(struct entropy_store *r, void *buf,  <--+   |
                       size_t nbytes, int min, int rsvd);                      |
                                                                               |
    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                                                        |         |
                                                                  |         |
    #define imx_fec_data_entry_single(soc, _devid)          <----+         |
        {                                                                  |
            .iobase = soc ## _FEC_BASE_ADDR,                               |
            .irq = soc ## _INT_FEC,                                        |
            .devid = _devid,                                               |
        }                                                                   |
                                                                            |
    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));        |     |
    }                                                            |     |
                                                                 |     |
    int fuse_dev_is_available(enum mxc_dev_type dev)       <-----+     |
    {                                                                  |
        ......                                                         |
        if (!cpu_is_mx6())                                             |
            return 1;                                                  |
                                                                       |
        /* mx6sl is still not supported */                             |
        if (cpu_is_mx6sl())                                            |
            return 1;                                                  |
                                                                       |
        switch (dev) {                                                 |
        case MXC_DEV_PXP:                                              |
            if (cpu_is_mx6q())                                         |
                return 0;                                              |
                                                                       |
            if (cpu_is_mx6dl()) {                                      |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x80000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_OVG:                                              |
            if (cpu_is_mx6dl())                                        |
                return 0;                                              |
                                                                       |
            if (cpu_is_mx6q()) {                                       |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x40000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_DSI_CSI2:                                         |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x10000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_ENET:                                             |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x08000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_MLB:                                              |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x04000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_EPDC:                                             |
            if (cpu_is_mx6q())                                         |
                return 0;                                              |
                                                                       |
            if (cpu_is_mx6dl()) {                                      |
                reg = HW_OCOTP_CFGn(2);                                |
                mask = 0x02000000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_HDMI:                                             |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000080;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_PCIE:                                             |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000040;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_SATA:                                             |
            if (cpu_is_mx6dl())                                        |
                return 0;                                              |
                                                                       |
            if (cpu_is_mx6q()) {                                       |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000020;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_DTCP:                                             |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000010;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_2D:                                               |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000008;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_3D:                                               |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000004;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_VPU:                                              |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00008000;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_DIVX3:                                            |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000400;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_RV:                                               |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000200;                                     |
            }                                                          |
            break;                                                     |
        case MXC_DEV_SORENSEN:                                         |
            if (cpu_is_mx6dl() || cpu_is_mx6q()) {                     |
                reg = HW_OCOTP_CFGn(3);                                |
                mask = 0x00000100;                                     |
            }                                                          |
            break;                                                     |
        default:                                                       |
            /* we treat the unkown device is avaiable by default */    |
            return 1;                                                  |
        }                                                              |
                                                                       |
        ret = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + reg) & mask;     |
        pr_debug("fuse_check: %s is %s
    ", names[dev], ret ?           |
                        "unavailable" : "available");                  |
                                                                       |
        return !ret;                                                   |
    }                                        +-------------------------+
                                             V
    struct platform_device *__init imx_add_platform_device_dmamask(
            const char *name, int id,
            const struct resource *res, unsigned int num_resources,
            const void *data, size_t size_data, u64 dmamask)
    {
        int ret = -ENOMEM;
        struct platform_device *pdev;
    
        pdev = platform_device_alloc(name, id);
        if (!pdev)
            goto err;
    
        if (dmamask) {
            /*
             * This memory isn't freed when the device is put,
             * I don't have a nice idea for that though.  Conceptually
             * dma_mask in struct device should not be a pointer.
             * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
             */
            pdev->dev.dma_mask =
                kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
            if (!pdev->dev.dma_mask)
                /* ret is still -ENOMEM; */
                goto err;
    
            *pdev->dev.dma_mask = dmamask;
            pdev->dev.coherent_dma_mask = dmamask;
        }
    
        if (res) {
            ret = platform_device_add_resources(pdev, res, num_resources);
            if (ret)
                goto err;
        }
    
        if (data) {
            ret = platform_device_add_data(pdev, data, size_data);
            if (ret)
                goto err;
        }
    
        ret = platform_device_add(pdev);
        if (ret) {
    err:
            if (dmamask)
                kfree(pdev->dev.dma_mask);
            platform_device_put(pdev);
            return ERR_PTR(ret);
        }
    
        return pdev;
    }
  • 相关阅读:
    oracle 大文本由clob来存
    merge into 语法缺陷
    基本元素的增加 jquery
    报表 jquery
    购物车的高级实现 逻辑结构清晰
    购物车的实现 js
    定时器的制作与清除
    div的大小设置
    二级菜单联动(自定义框架)
    编写数组删除模板
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/4731816.html
Copyright © 2011-2022 走看看