Я пытаюсь записать определенные биты регистра привет, чтобы инициировать режим питания в сон
Моя проблема в том, что я читаю значение ADI_DEV_CORE_STATUS, оно остается равным 0x2A, даже после того, как я записываю утверждение 1 на бит 22, чтобы включить запросы режима питания, и я распечатываю значение непосредственно после того, как значение не изменяется.
Я пытаюсь отправить запрос на переход в режим сна,
В регистре ADI DEV CORE STATUS,
бит 26 определяется как сбой режима питания (только чтение),
бит 25 определяется как Core в спящем режиме (только для чтения),
бит 24 определяется как запрос режима питания для частичного дремоты (чтение / запись),
бит 23 определяется как запрос режима питания для режима сна (чтение / запись),
бит 22 определен как включающий запросы режима питания, инициированные хостом (чтение / запись),
бит 21 определен как инициирующий отправку шаблона COMWAKE Burst для пробуждения от дремоты (чтение / запись)
бит 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(значение%x", чтение); распечатайте 0x2a, я должен прочитать 0x40002a, когда режимы питания включены, 0xC0002a, когда режимы питания включены, и я отправляю запрос питания для режима сна и 0x2000000 когда ядро во сне.
1 ответ
Прежде всего, перепишите арифметику испорченного указателя. Я предполагаю, что смещение в байтах, а не в словах 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). Если это так, то это будет аппаратная проблема, а не вопрос ТАК.