Power off SD card if no voltage range support.
The goal is to handle `FIXME` within WorkerThread that of MMCBus. [+] Extended SDHCIBus to have: > private PowerOff() to clear corresponding VDD1 power bit. > Public TerminateBus() to terminate the bus powering off,disabling clock and interrupts. Also called within the destructor. [+] Extend `mmc_bus_interface` to encapsulate terminate_bus coping the same style of other interface utilities. [+] MMCBus can its newly added private _TerminateBus() for handling sd cards not supporting proposed voltage range. Testing: - used false invokation on qemu emulated sd card to test the termination branch. - Successfully built and run,SD card doesn't show up in DriveSetup - debug Log show correct power and clock bit setting(power=0xe, clock=0x800b). Please Guide me further on more effective test method. Change-Id: Icc8eeac97b9c96dfbf0106871d26a41d7faea5dc Reviewed-on: https://review.haiku-os.org/c/haiku/+/10622 Haiku-Format: Haiku-format Bot <[email protected]> Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
committed by
Adrien Destugues
parent
ef2e71c652
commit
aaed8a220f
@@ -88,6 +88,8 @@ typedef struct mmc_bus_interface {
|
|||||||
// Pass the semaphore used for device rescan to the bus controller
|
// Pass the semaphore used for device rescan to the bus controller
|
||||||
void (*set_bus_width)(void* controller, int width);
|
void (*set_bus_width)(void* controller, int width);
|
||||||
// Set the data bus width to 1, 4 or 8 bit mode.
|
// Set the data bus width to 1, 4 or 8 bit mode.
|
||||||
|
void (*terminate_bus)(void* controller);
|
||||||
|
// Terminate use of the underlying sdhci bus.
|
||||||
} mmc_bus_interface;
|
} mmc_bus_interface;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,6 @@ MMCBus::~MMCBus()
|
|||||||
status_t result;
|
status_t result;
|
||||||
if (fWorkerThread != 0)
|
if (fWorkerThread != 0)
|
||||||
wait_for_thread(fWorkerThread, &result);
|
wait_for_thread(fWorkerThread, &result);
|
||||||
|
|
||||||
// TODO power off cards, stop clock, etc if needed.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -144,6 +142,13 @@ void MMCBus::_AcquireScanSemaphore()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MMCBus::_TerminateBus()
|
||||||
|
{
|
||||||
|
fController->terminate_bus(fCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
MMCBus::_WorkerThread(void* cookie)
|
MMCBus::_WorkerThread(void* cookie)
|
||||||
{
|
{
|
||||||
@@ -211,7 +216,9 @@ MMCBus::_WorkerThread(void* cookie)
|
|||||||
} else if (response != probe) {
|
} else if (response != probe) {
|
||||||
ERROR("Card does not support voltage range (expected %x, "
|
ERROR("Card does not support voltage range (expected %x, "
|
||||||
"reply %x)\n", probe, response);
|
"reply %x)\n", probe, response);
|
||||||
// TODO we should power off the bus in this case.
|
bus->_TerminateBus();
|
||||||
|
release_sem(bus->fLockSemaphore);
|
||||||
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Probe OCR, waiting for card to become ready
|
// Probe OCR, waiting for card to become ready
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
status_t _ActivateDevice(uint16_t rca);
|
status_t _ActivateDevice(uint16_t rca);
|
||||||
void _AcquireScanSemaphore();
|
void _AcquireScanSemaphore();
|
||||||
|
void _TerminateBus();
|
||||||
static status_t _WorkerThread(void*);
|
static status_t _WorkerThread(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ SdhciBus::SdhciBus(struct registers* registers, uint8_t irq, bool poll)
|
|||||||
|
|
||||||
SdhciBus::~SdhciBus()
|
SdhciBus::~SdhciBus()
|
||||||
{
|
{
|
||||||
DisableInterrupts();
|
TerminateBus();
|
||||||
|
|
||||||
if (fIrq != 0)
|
if (fIrq != 0)
|
||||||
remove_io_interrupt_handler(fIrq, sdhci_generic_interrupt, this);
|
remove_io_interrupt_handler(fIrq, sdhci_generic_interrupt, this);
|
||||||
@@ -605,6 +605,36 @@ SdhciBus::PowerOn()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SdhciBus::PowerOff()
|
||||||
|
{
|
||||||
|
fRegisters->power_control.PowerOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SdhciBus::TerminateBus()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
DisableInterrupts();
|
||||||
|
fRegisters->clock_control.DisableSD();
|
||||||
|
PowerOff();
|
||||||
|
/*
|
||||||
|
// Debugging.
|
||||||
|
uint8_t powerBits = fRegisters->power_control.Bits();
|
||||||
|
uint16_t clockBits = fRegisters->clock_control.Bits();
|
||||||
|
if ((powerBits & 0x1) != 0 || (clockBits & (1 << 2)) != 0) {
|
||||||
|
ERROR("TerminateBus: Not killed. "
|
||||||
|
"(power=%#x, clock=%#x)\n", powerBits, clockBits);
|
||||||
|
} else {
|
||||||
|
TRACE("TerminateBus: killed. (power=%#x, "
|
||||||
|
"clock=%#x)\n", powerBits, clockBits);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SdhciBus::RecoverError()
|
SdhciBus::RecoverError()
|
||||||
{
|
{
|
||||||
@@ -904,6 +934,14 @@ set_bus_width(void* controller, int width)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
terminate_bus(void* controller)
|
||||||
|
{
|
||||||
|
SdhciBus* bus = (SdhciBus*)controller;
|
||||||
|
bus->TerminateBus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Root device that binds to the ACPI or PCI bus. It will register an mmc_bus_interface
|
// Root device that binds to the ACPI or PCI bus. It will register an mmc_bus_interface
|
||||||
// node for each SD slot in the device.
|
// node for each SD slot in the device.
|
||||||
static driver_module_info sSDHCIDevice = {
|
static driver_module_info sSDHCIDevice = {
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ class SdhciBus {
|
|||||||
bool offsetAsSectors);
|
bool offsetAsSectors);
|
||||||
void SetScanSemaphore(sem_id sem);
|
void SetScanSemaphore(sem_id sem);
|
||||||
void SetBusWidth(int width);
|
void SetBusWidth(int width);
|
||||||
|
void TerminateBus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool PowerOn();
|
bool PowerOn();
|
||||||
|
void PowerOff();
|
||||||
void RecoverError();
|
void RecoverError();
|
||||||
static status_t _WorkerThread(void*);
|
static status_t _WorkerThread(void*);
|
||||||
|
|
||||||
@@ -516,6 +518,7 @@ status_t do_io(void* controller, uint8_t command,
|
|||||||
IOOperation* operation, bool offsetAsSectors);
|
IOOperation* operation, bool offsetAsSectors);
|
||||||
void set_scan_semaphore(void* controller, sem_id sem);
|
void set_scan_semaphore(void* controller, sem_id sem);
|
||||||
void set_bus_width(void* controller, int width);
|
void set_bus_width(void* controller, int width);
|
||||||
|
void terminate_bus(void* controller);
|
||||||
|
|
||||||
extern mmc_bus_interface gSDHCIACPIDeviceModule;
|
extern mmc_bus_interface gSDHCIACPIDeviceModule;
|
||||||
extern mmc_bus_interface gSDHCIPCIDeviceModule;
|
extern mmc_bus_interface gSDHCIPCIDeviceModule;
|
||||||
|
|||||||
@@ -239,4 +239,5 @@ mmc_bus_interface gSDHCIACPIDeviceModule = {
|
|||||||
.do_io = do_io,
|
.do_io = do_io,
|
||||||
.set_scan_semaphore = set_scan_semaphore,
|
.set_scan_semaphore = set_scan_semaphore,
|
||||||
.set_bus_width = set_bus_width,
|
.set_bus_width = set_bus_width,
|
||||||
|
.terminate_bus = terminate_bus,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -331,4 +331,5 @@ mmc_bus_interface gSDHCIPCIDeviceModule = {
|
|||||||
.do_io = do_io,
|
.do_io = do_io,
|
||||||
.set_scan_semaphore = set_scan_semaphore,
|
.set_scan_semaphore = set_scan_semaphore,
|
||||||
.set_bus_width = set_bus_width,
|
.set_bus_width = set_bus_width,
|
||||||
|
.terminate_bus = terminate_bus,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user