2013-06-18 20 views
0

我的问题是我读ADI_DEV_CORE_STATUS的,仍是0x2A的价值,即使我写一篇关于位22断言1,使电源模式的请求,并且在数值没有改变之后,我直接打印出数值。我试着写寄存器喜的某些位发起功耗模式进入睡眠

我试图发送AA请求进入睡眠模式,

在ADI DEV核心地位寄存器,

位26被定义为功率模式失效(只读),

位25在睡眠定义为核心(只读),

位24被定义为用于局部睡眠(读/写)的功率模式请求,

位23被定义为用于睡眠模式(读/写)的功率模式请求,

位22被定义为能够使主机发起功率模式请求(读/写),

位21被定义为启动的发送COMWAKE突发模式从睡眠唤醒(读/写)

位5被定义为物理层设备就绪(只读),

位4被定义为复位(读/写),

位3被定义为指示设备状态机在Id中(1h:建立第一代速率)(2:h:第二代速率建立)(3h:第三代速率)(1h:无连接)(1h:第一代速率建立),

比特[2:建立)(为后代保留其它值)

其它值在代码中定义

u32 read; 
u32 write; 
u32 mask; 
u32 rc; 
/*Device Application Status (DevCoreStatus Register 0x002C)*/ 
DEV_STATUS_SIM  = (1 << 31), /*Core in Simulation*/ 
DEV_STATUS_PM_FAIL = (1 << 26), /*Power Mode Fail*/ 
DEV_STATUS_CORE_SLEEP = (1 << 25), /*Successful Transition into Sleep Mode*/ 
DEV_STATUS_PARTIAL_GO = (1 << 24), /*Power Mode Request for Partial Mode*/ 
DEV_STATUS_SLUMBER_GO = (1 << 23), /*Power Mode Request for Slumber Mode*/ 
DEV_STATUS_EN_PWDN = (1 << 22), /*Enables Host Initiated Power Mode Requests*/ 
DEV_STATUS_COMWAKE = (1 << 21), /*Initiates the Sending of COMWAKE Burst Pattern to Allow for Waking up from Slumber*/ 
DEV_STATUS_PHYRDY  = (1 << 5), /*Indicates the Device Core has Achieved a Phy-Ready State*/ 
DEV_STATUS_RESET  = (1 << 4), /*Upon Exit From Reset, Device will Send a COMINIT*/ 
DEV_STATUS_DEVIDL  = (1 << 3), /*Device State Machine is in Idle*/ 
DEV_STATUS_SPEED_0 = (0x0 << 0), /*0h: No Connection to the Host Established*/ 
DEV_STATUS_SPEED_1 = (0x1 << 0), /*1h: Gen 1 Communication Established*/ 
DEV_STATUS_SPEED_2 = (0x2 << 0), /*2h: Gen 2 Communication Established*/ 
DEV_STATUS_SPEED_3 = (0x3 << 0), /*3h: Gen 3 Communication Established*/ 

struct DevDesc { 
    u32 * mmio; //memory mapped io address 
    u32 qd_cmd; //queued command - doesnt appear to be used yet. guessing active-high 32 bits 
    u8 phy_rdy; //phy_rdy flag - set by software 
    u8 spd_allowed; //same as below. doesnt appear to be used yet 
    u8 cur_lnk_spd; /* 00 -> Not phyrdy, 01 -> Gen1 -> 02 -> Gen2, 03-> Gen3*/ 
    u8 dev_mode; /* DEV_MODE_xxx, eg SATA, SAS, dual */ 
    struct ata_port_operations *ops; //what is this? doesnt appear to be used 
}; 

struct MemDesc { 
    u32 * non_qd_dev_mem_addr; 
    u32 non_qd_dev_mem_span; 
    u32 * qd_dev_mem_addr; 
    u32 qd_dev_mem_span; 
    u32 * sg_addr; 
    u32 sg_span; 
}; 

struct MemDesc mem_desc_g = { 
    .non_qd_dev_mem_addr = (u32*)(DEV_PORT_MEMORY_BASE), //Non-queued command memory. base=0x40000 
    .non_qd_dev_mem_span = DEV_PORT_MEMORY_SPAN, //65536 bytes - 0x40000:0x4FFFF 
    .qd_dev_mem_addr = (u32*)(DATA_BUFFER_BASE_ADDRESS), //Queued command buffer. base=0x50000. 
    .qd_dev_mem_span = DATA_BUFFER_SPAN, //65536 bytes - 0x50000:0x5FFFF 
    .sg_addr = (u32*)(DEV_SG_MEMORY_BASE), //Scatter-gather list. base=0x60000 
    .sg_span = DEV_SG_MEMORY_SPAN, //65536 bytes - 0x60000:0x6FFFF 
}; 

//System descriptor 
//Points to components 
struct SysDesc sys_desc_g = { 
    .dd = &dev_desc, //device core descriptor 
    .md = &mem_desc_g, //memory structure descriptor 
}; 

u32 RegRead32(u32* BaseAddr, u32 Offset) 
{ 
    u32 temp; 
    temp = (u32)BaseAddr + Offset; 
    return *(volatile int *)temp; 
} 

void RegWrite32(u32* BaseAddr, u32 Offset, u32 WriteData) 
{ 
    u32 temp; 
    temp = (u32)BaseAddr + Offset; 
    *(volatile int *)temp = WriteData; 
    return; 
} 

u32 wait_reg(u32* reg_addr, u32 mask, u32 val, u32 interval_usec, u32 timeout_usec) 
{ 
    u32 ii = 0; 
    u32 rc = 0; 
    for(ii=0;ii<(timeout_usec/interval_usec); ii++){ 
    rc = RegRead32(reg_addr, 0); 
    if((rc & mask) != val){ 
    return rc; 
} 
    //branch slot pad... 
    RegRead32(reg_addr, 0); 
    usleep(interval_usec); 
} 
//iprop_printf("%s:: wait reg timout. ending register value == %08X\n\r",__func__,rc); 
return rc; 
} 


u32 power_mode_sleep (struct SysDesc * sd) 
{ 
    rc = RegRead32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS); 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 1.) %x \n", rc); /*Should print out 0x2A, phy-ready, in idle, and Gen2 speed*/ 
    rc = rc & 0xFF3FFFFF; 
    rc |= DEV_STATUS_EN_PWDN; //DEV_STATUS_EN_PWDN = (1<<22) 
    RegWrite32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS, rc); 
    read = RegRead32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS); 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 2.) %x \n", read); 
    rc |= DEV_STATUS_SLUMBER_GO; 
    RegWrite32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS, rc); 
    read = RegRead32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS); 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 3.) %x \n", read); 
    rc = wait_reg((u32*)(DEV_BUS_SLAVE_BASE + ADI_OFFSET + ADI_DEV_CORE_STATUS), 
    0x2000000, // only look at bit 25. 
    0x000000, // if bit-25 == 1, We're core in sleep 
    1, // wait 1us between register reads 
    100000); // ~100ms 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 4.) %x \n", rc); /**/ 
    read = RegRead32((u32*)DEV_BUS_SLAVE_BASE, ADI_OFFSET + ADI_DEV_CORE_STATUS); 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 5.) %x \n", read); 

    if ((read & 0x2000000) == DEV_STATUS_CORE_SLEEP) 
    { 
    alt_printf("Successfully Transitioned into sleep mode.\n"); 
    } 
    else if ((read & 0x4000000) == DEV_STATUS_PM_FAIL) 
    { 
    alt_printf("Unsuccessful Transition into sleep mode.\n"); 
    } 
    else 
    alt_printf("The value of ADI_DEV_CORE_STATUS is 6.) %x \n", rc); 
    return STATUS_SUCCESS; 
    } 
} 

所有我的alt_printf(该值是%X”,读);打印出0x2a,当使能电源模式时,我应该读取0x40002a,当使能电源模式时,我应该读取0xC0002a,并且我正在发送睡眠模式的电源请求,并且在核心处于睡眠状态时发送0x2000000。

+9

你所有的位都属于总线。 – jxh

回答

0

首先,改写搞砸指针运算。我假设偏移量是以字节为单位,而不是u32字。

u32 RegRead32(u32* BaseAddr, u32 Offset) 
{ 
    volatile u32 *temp = (volatile u32 *) ((char *) BaseAddr + Offset); 
    return *temp; 
} 

void RegWrite32(u32* BaseAddr, u32 Offset, u32 WriteData) 
{ 
    volatile u32 *temp = (volatile u32 *) ((char *) BaseAddr + Offset); 
    *temp = WriteData; 
    /* empty return at the end of a void function not needed */ 
} 

由于您已经#定义了一些常量,请不要在事后使用它们的数值,因为您可能犯了一个错误。即只需测试

if (read & DEV_STATUS_CORE_SLEEP) 

并且该位置位时结果将为真。

但最重要的是,后一个完整的示例代码(代码缺少一些变量声明和wait_reg()),并尽可能简化您的测试案例。同时发布预期的输出。您向寄存器写入并多次读取它们,但不清楚哪个写入失败。

现在,如果写还是不沾,重新读取数据表,以确保你按照设备期望的协议。也可以查看与该设备有关的技术说明 - 有时硬件有问题,并且不符合数据表(我过去曾遇到过使用ADI DSP的问题)。如果是这样,这将是一个硬件问题,而不是一个SO问题。

+0

我感谢你的帮助。我可以在评论部分发布更多代码,或者我可以编辑我的代码并添加更多代码。我的alt_printf语句的预期输出如下: 1.)0x2a //意味着phy0rdy,空闲,第2代速度 2.)0x40002a //意味着启用电源模式,phy-rdy,idle,gen 2 speed 3)0xC0002a //指睡眠的要求,使功率模式,PHY-RDY,闲置,Gen 2的速度 3)0x2000000 //指核心处于休眠状态,这是我想读 4什么。 )5.)&6.)应该全部打印0x2000000,因为我想让核心处于睡眠状态 它已经为我的所有打印语句打印0x2a。 – Cwells

+0

只需编辑您的原始代码即可完成。我的意思是实际产出,而不是预期产出 - 我不知道哪一步与您的预期不符。并确保你没有任何1位错误,这就是我提出重写的原因。 – dan3

+0

你有电子邮件我可以给你发送文件吗?我只是在大约8个不同的文件中有代码,这会使这个页面变得很长。您可以发送电子邮件至[email protected] – Cwells