0

私の問題は、ADI_DEV_CORE_STATUS の値を読み取っても、ビット 22 に 1 をアサートして電力モード要求を有効にした後でも 0x2A のままであり、値が変化しない直後に値を出力することです。

眠りモードに入るリクエストを送ろうとしているのですが、

ADI DEV CORE STATUS レジスタでは、

ビット 26 は、電力モード失敗 (読み取り専用) として定義されます。

ビット 25 はスリープ中のコアとして定義されます (読み取り専用)。

ビット 24 は、パーシャル スランバー (読み取り/書き込み) の電力モード要求として定義されます。

ビット 23 は、スランバー モード (読み取り/書き込み) の電力モード要求として定義されます。

ビット 22 は、ホストが開始する電源モード要求 (読み取り/書き込み) を有効にするように定義されています。

ビット 21 は、COMWAKE バースト パターンの送信を開始してスランバーからウェイクアップするように定義されています (読み取り/書き込み)。

ビット 5 は Phy-Ready (読み取り専用) として定義されています。

ビット 4 はリセット (読み取り/書き込み) として定義されます。

ビット 3 は、デバイス ステート マシンがアイドル状態 (読み取り専用) であることを示すように定義されています。

ビット [2:0] は、現在のインターフェイス速度として定義されます (0h: 接続なし)(1h: Gen1 レートが確立されます)(2:h: Gen 2 レートが確立されます)(3h: Gen3 レートが確立されます) (その他の値は将来の世代のために予約されています)

コードで定義されたその他の値

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(The value is %x", read); 出力 0x2a、電源モードが有効な場合は 0x40002a、電源モードが有効な場合は 0xC0002a を読み取る必要があり、スランバー モードの電源要求と 0x2000000 を送信していますコアがスリープ状態のとき。

4

1 に答える 1

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 */
}

いくつかの定数を #define したので、後でそれらの数値を使用しないでください。間違いを犯す可能性があります。つまり、単にテストする

if (read & DEV_STATUS_CORE_SLEEP)

ビットが設定されている場合、結果は true になります。

しかし、最も重要なことは、完全なコード サンプル (コードにはいくつかの変数宣言と wait_reg() がありません) を投稿し、テスト ケースを可能な限り単純化することです。また、予想される出力を投稿します。レジスタへの書き込みと読み取りを数回繰り返しますが、どの書き込みが失敗したかは不明です。

それでも書き込みがうまくいかない場合は、データシートを読み直して、デバイスが期待するプロトコルに従っていることを確認してください。デバイスに関連するテクニカル ノートも探してください。ハードウェアにバグがあり、データシートに従って動作しないことがあります (過去に ADI DSP でこの問題が発生したことがあります)。もしそうなら、これはハードウェアの問題であり、SO の質問ではありません。

于 2013-06-18T21:42:43.647 に答える