2013-06-18 24 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