I.MX6 Ar8031 device register hacking

简介: /***************************************************************************** * 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\n",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\n",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\n", 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;
}

 

目录
相关文章
|
Linux Perl
I.MX6 Linux 自动获取AR1020 event input节点
/*********************************************************************** * I.MX6 Linux 自动获取AR1020 event input节点 * 说明: * 本文主要记录如何自动获取AR1020 SPI电阻Touch产生的设备节点。
731 0
|
BI SoC
I.MX6 ar1020 SPI device driver hacking
/************************************************************************************ * I.
870 0
|
3月前
|
机器学习/深度学习 人工智能 vr&ar
H4H:面向AR/VR应用的NPU-CIM异构系统混合卷积-Transformer架构搜索——论文阅读
H4H是一种面向AR/VR应用的混合卷积-Transformer架构,基于NPU-CIM异构系统,通过神经架构搜索实现高效模型设计。该架构结合卷积神经网络(CNN)的局部特征提取与视觉Transformer(ViT)的全局信息处理能力,提升模型性能与效率。通过两阶段增量训练策略,缓解混合模型训练中的梯度冲突问题,并利用异构计算资源优化推理延迟与能耗。实验表明,H4H在相同准确率下显著降低延迟和功耗,为AR/VR设备上的边缘AI推理提供了高效解决方案。
445 0
|
6月前
|
人工智能 JavaScript vr&ar
眼镜不是“玩具”,是下一个时代的入口:聊聊VR和AR的未来走向
眼镜不是“玩具”,是下一个时代的入口:聊聊VR和AR的未来走向
199 5
|
人工智能 编解码 5G
虚拟现实(VR)与增强现实(AR)的融合:开启全新交互时代
【6月更文挑战第17天】虚拟现实(VR)与增强现实(AR)融合成混合现实(MR),打造全新交互体验。MR结合VR的沉浸感和AR的现实增强,应用于教育、游戏、设计和营销,带来创新教学方式、沉浸式游戏体验和高效设计工具。尽管面临技术挑战,随着5G和AI的发展,MR有望引领未来交互的革命。
|
传感器 数据可视化 安全
【虚拟现实】二、主要的AR/VR硬件设备
【虚拟现实】二、主要的AR/VR硬件设备
620 3
|
前端开发 JavaScript API
惊呆了!这些前端技巧竟然能让你的网站支持AR/VR体验!
【10月更文挑战第31天】在数字化时代,用户对网页交互体验的要求日益提高,传统二维网页已难以满足需求。本文介绍如何利用前端技术,特别是Three.js,实现AR/VR体验,提升用户满意度和网站价值。通过示例代码,展示如何创建简单的3D场景,并探讨AR/VR技术的基本原理和常用工具,帮助开发者打造沉浸式体验。
750 6
|
Go vr&ar 图形学
重塑体验:AR/VR技术在游戏与娱乐行业的创新应用
【10月更文挑战第29天】本文探讨了AR/VR技术如何改变游戏与娱乐行业,介绍了AR和VR的基本概念及其在游戏和娱乐中的应用实例,包括《精灵宝可梦GO》的AR开发和VR视频播放器的实现代码,并展望了未来的发展趋势。
861 2
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
405 1
|
传感器 人工智能 数据可视化
虚拟现实(VR)与增强现实(AR)的技术革新:塑造未来的沉浸式体验
【7月更文挑战第24天】VR和AR作为两种前沿的沉浸式技术,正以前所未有的速度改变着我们的世界。随着技术的不断革新和应用的不断拓展,我们有理由相信,未来的VR和AR将为我们带来更多令人惊叹的体验和技术革新。

热门文章

最新文章