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:
unknown rurouni
2026-04-21 06:55:27 +00:00
committed by Adrien Destugues
parent ef2e71c652
commit aaed8a220f
7 changed files with 57 additions and 4 deletions
+2
View File
@@ -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:
+39 -1
View File
@@ -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 = {
+3
View File
@@ -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,
}; };