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, ); ||
mdelay(); ||
gpio_direction_output(SABRESD_FEC_PHY_RESET, ); ||
mdelay(); ||
gpio_direction_output(SABRESD_FEC_PHY_RESET, ); ||
mdelay(); ||
||
/* 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 << ); ||
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 ; | ||
} +------------------------------------+ ||
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 ; |
} |
|
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()); |||
printk("<danny debug> vaule = %x\n",value); |||
value = 0x03040506; |||
mac[] = value & 0xff; |||
mac[] = (value >> ) & 0xff; |||
mac[] = (value >> ) & 0xff; |||
mac[] = (value >> ) & 0xff; |||
value = readl(MX6_IO_ADDRESS(OCOTP_BASE_ADDR) + HW_OCOTP_MACn()); |||
printk("<danny debug> vaule = %x\n",value); |||
value = 0x0102; |||
mac[] = value & 0xff; |||
mac[] = (value >> ) & 0xff; |||
|||
return ; |||
} |||
|||
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[]; | ||
} | ||
| ||
static inline int is_zero_ether_addr(const u8 *addr) <-----+ ||
{ ||
return !(addr[] | addr[] | addr[] | addr[] | addr[] | addr[]); ||
} ||
||
static inline void random_ether_addr(u8 *addr) <--------------------*+
{ |
get_random_bytes (addr, ETH_ALEN); -----------------------+ |
addr [] &= 0xfe; /* clear multicast bit */ | |
addr [] |= 0x02; /* set local assignment bit (IEEE802) */ | |
} | |
| |
void get_random_bytes(void *buf, int nbytes) <--------------+ |
{ |
extract_entropy(&nonblocking_pool, buf, nbytes, , ); -----------+ |
} | |
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 - ,
.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, , --*-----+
res, ARRAY_SIZE(res), | |
pdata, sizeof(*pdata), DMA_BIT_MASK()); | |
} | |
| |
int fuse_dev_is_available(enum mxc_dev_type dev) <-----+ |
{ |
...... |
if (!cpu_is_mx6()) |
return ; |
|
/* mx6sl is still not supported */ |
if (cpu_is_mx6sl()) |
return ; |
|
switch (dev) { |
case MXC_DEV_PXP: |
if (cpu_is_mx6q()) |
return ; |
|
if (cpu_is_mx6dl()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x80000000; |
} |
break; |
case MXC_DEV_OVG: |
if (cpu_is_mx6dl()) |
return ; |
|
if (cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x40000000; |
} |
break; |
case MXC_DEV_DSI_CSI2: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x10000000; |
} |
break; |
case MXC_DEV_ENET: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x08000000; |
} |
break; |
case MXC_DEV_MLB: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x04000000; |
} |
break; |
case MXC_DEV_EPDC: |
if (cpu_is_mx6q()) |
return ; |
|
if (cpu_is_mx6dl()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x02000000; |
} |
break; |
case MXC_DEV_HDMI: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000080; |
} |
break; |
case MXC_DEV_PCIE: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000040; |
} |
break; |
case MXC_DEV_SATA: |
if (cpu_is_mx6dl()) |
return ; |
|
if (cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000020; |
} |
break; |
case MXC_DEV_DTCP: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000010; |
} |
break; |
case MXC_DEV_2D: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000008; |
} |
break; |
case MXC_DEV_3D: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000004; |
} |
break; |
case MXC_DEV_VPU: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00008000; |
} |
break; |
case MXC_DEV_DIVX3: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000400; |
} |
break; |
case MXC_DEV_RV: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000200; |
} |
break; |
case MXC_DEV_SORENSEN: |
if (cpu_is_mx6dl() || cpu_is_mx6q()) { |
reg = HW_OCOTP_CFGn(); |
mask = 0x00000100; |
} |
break; |
default: |
/* we treat the unkown device is avaiable by default */ |
return ; |
} |
|
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;
}
I.MX6 Ar8031 device register hacking的更多相关文章
- I.MX6 Power off register hacking
/*********************************************************************** * I.MX6 Power off register ...
- OK335xS GPMC nand device register hacking
/********************************************************************************* * OK335xS GPMC na ...
- OK335xS pwm device register hacking
/************************************************************************* * OK335xS pwm device regi ...
- I.MX6 ar1020 SPI device driver hacking
/************************************************************************************ * I.MX6 ar1020 ...
- I.MX6 Linux I2C device& driver hacking
/******************************************************************************************* * I.MX6 ...
- OK335xS CAN device register and deiver match hacking
/************************************************************************* * OK335xS CAN device regi ...
- I.MX6 AD7606-4 device driver registe hacking
/********************************************************************** * I.MX6 AD7606-4 device driv ...
- I.MX6 AR8031 寄存器操作
/*************************************************************************** * I.MX6 AR8031 寄存器操作 * ...
- I.MX6 PWM buzzer driver hacking with Demo test
/***************************************************************************** * I.MX6 PWM buzzer dr ...
随机推荐
- Qt5.3.2(VS2010)_调试_查看变量值
1.菜单栏 -->控件(W) --> 视图 2.在"Debug"状态下,选择一个变量(或者 按住左键 选择变量及其属性/方法)--> 右键 --> 添加表达 ...
- Cassandra 和 Spark 数据处理一窥
Apache Cassandra 数据库近来引起了很多的兴趣,这主要源于现代云端软件对于可用性及性能方面的要求. 那么,Apache Cassandra 是什么?它是一种为高可用性及线性可扩展性优化的 ...
- 简说Spring事务
一.事务定义: 事务指逻辑上的一组操作,这组操作要么全部成功,要么全部失败. 二.事务的特性: 1. 原子性 - 指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 2. 一致性 ...
- 从celery rabbitmq with docker-compose 引出对容器、依赖注入、TDD的感悟
用docker配置项目管理系统taiga的时候,不是我一个人遇到这个问题.https://github.com/douglasmiranda/docker-taiga/issues/5 问题描述: 用 ...
- 百度echart如何动态生成图表
百度echart如何动态生成图表 一.总结 一句话总结: clear hideloading setOption 主要是下面三行代码: myChart.clear(); //清空画布myChart.h ...
- 真核生物基因结构 & mRNA结构
参考: 分子生物学教材 再一次,翻看真核生物基因结构! mRNA基本结构特点 Structure and function of Messenger RNA (mRNA ) 基因结构 其实这个结构不完 ...
- codeforces 559b//Equivalent Strings// Codeforces Round #313(Div. 1)
题意:定义了字符串的相等,问两串是否相等. 卡了时间,空间,不能新建字符串,否则会卡. #pragma comment(linker,"/STACK:1024000000,102400000 ...
- memcached哈希表操作主要逻辑笔记
以下注释的源代码都在memcached项目的assoc.c文件中 /* how many powers of 2's worth of buckets we use */ unsigned int h ...
- php--------php库生成二维码和有logo的二维码
php生成二维码和带有logo的二维码,上一篇博客讲的是js实现二维码:php--------使用js生成二维码. 今天写的这个小案例是使用php库生成二维码: 效果图: 使用了 php ...
- SQL Server数据库入门学习总结
数据库基本是由表,关系,操作组成:对于初学者,首先要学的是: 1.数据库是如何存储数据的 —— 表.约束.触发器 2.数据库是如何操作数据的 —— insert,update,delete.T-sql ...