sdhci_pci: fix quirk and interrupt handling for Ricoh device
- The quirk was not properly applied due to misuse of the device API - The interrupts could run out of sync, leading to not properly waiting for commands to terminate before reading their result. Add panic to check for that (at the start of the next command) and fix the code. Change-Id: If83b7bbb3c3446d374115ed22c09b91020028578 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3609 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
0db785d66c
commit
fa1f5839be
@@ -182,7 +182,11 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
|
||||
// only during command execution, and we don't leave this function with ac
|
||||
// command running.
|
||||
if (fRegisters->present_state.CommandInhibit()) {
|
||||
ERROR("Execution aborted, command inhibit\n");
|
||||
panic("Command execution impossible, command inhibit\n");
|
||||
return B_BUSY;
|
||||
}
|
||||
if (fRegisters->present_state.DataInhibit()) {
|
||||
panic("Command execution unwise, data inhibit\n");
|
||||
return B_BUSY;
|
||||
}
|
||||
|
||||
@@ -297,13 +301,15 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
|
||||
break;
|
||||
}
|
||||
|
||||
if (replyType == Command::kR1bType) {
|
||||
if (replyType == Command::kR1bType &&
|
||||
(fCommandResult & SDHCI_INT_TRANS_CMP == 0)) {
|
||||
// R1b commands may use the data line so we must wait for the
|
||||
// "transfer complete" interrupt here.
|
||||
TRACE("Waiting for data...\n");
|
||||
while (fRegisters->present_state.DataInhibit())
|
||||
TRACE("Waiting for data line...\n");
|
||||
do {
|
||||
acquire_sem(fSemaphore);
|
||||
TRACE("Got data.\n");
|
||||
} while (fRegisters->present_state.DataInhibit());
|
||||
TRACE("Dataline is released.\n");
|
||||
}
|
||||
|
||||
ERROR("Command execution %d complete\n", command);
|
||||
@@ -555,6 +561,7 @@ SdhciBus::HandleInterrupt()
|
||||
}
|
||||
|
||||
if (intmask & SDHCI_INT_TRANS_CMP) {
|
||||
fCommandResult = intmask;
|
||||
fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP;
|
||||
release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
|
||||
TRACE("Transfer complete interrupt handled\n");
|
||||
@@ -766,11 +773,11 @@ init_device(device_node* node, void** device_cookie)
|
||||
context->fNode = node;
|
||||
*device_cookie = context;
|
||||
|
||||
if (gDeviceManager->get_attr_uint16(node, B_DEVICE_VENDOR_ID, &vendorId,
|
||||
false) != B_OK
|
||||
if (gDeviceManager->get_attr_uint16(node, B_DEVICE_VENDOR_ID,
|
||||
&vendorId, true) != B_OK
|
||||
|| gDeviceManager->get_attr_uint16(node, B_DEVICE_ID, &deviceId,
|
||||
false) != B_OK) {
|
||||
TRACE("No vendor or device id attribute\n");
|
||||
true) != B_OK) {
|
||||
panic("No vendor or device id attribute\n");
|
||||
return B_OK; // Let's hope it didn't need the quirk?
|
||||
}
|
||||
|
||||
@@ -805,23 +812,21 @@ uninit_device(void* device_cookie)
|
||||
device_node* pciParent = gDeviceManager->get_parent_node(context->fNode);
|
||||
gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
|
||||
(void**)&device);
|
||||
gDeviceManager->put_node(pciParent);
|
||||
|
||||
if (gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_VENDOR_ID,
|
||||
&vendorId, false) != B_OK
|
||||
&vendorId, true) != B_OK
|
||||
|| gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_ID,
|
||||
&deviceId, false) != B_OK) {
|
||||
TRACE("No vendor or device id attribute\n");
|
||||
delete context;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vendorId == 0x1180 && deviceId == 0xe823) {
|
||||
ERROR("No vendor or device id attribute\n");
|
||||
} else if (vendorId == 0x1180 && deviceId == 0xe823) {
|
||||
pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0xfc);
|
||||
pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE, 1,
|
||||
context->fRicohOriginalMode);
|
||||
pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0);
|
||||
}
|
||||
|
||||
gDeviceManager->put_node(pciParent);
|
||||
|
||||
delete context;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user