From aaed8a220fe54a79417eed2aaf450c27abd1a1b3 Mon Sep 17 00:00:00 2001 From: unknown rurouni Date: Sun, 29 Mar 2026 23:34:30 +0200 Subject: [PATCH] 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 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- headers/private/drivers/mmc.h | 2 + .../kernel/bus_managers/mmc/mmc_bus.cpp | 13 ++++-- src/add-ons/kernel/bus_managers/mmc/mmc_bus.h | 1 + src/add-ons/kernel/busses/mmc/sdhci.cpp | 40 ++++++++++++++++++- src/add-ons/kernel/busses/mmc/sdhci.h | 3 ++ src/add-ons/kernel/busses/mmc/sdhci_acpi.cpp | 1 + src/add-ons/kernel/busses/mmc/sdhci_pci.cpp | 1 + 7 files changed, 57 insertions(+), 4 deletions(-) diff --git a/headers/private/drivers/mmc.h b/headers/private/drivers/mmc.h index e48937bac0..90f84174c6 100644 --- a/headers/private/drivers/mmc.h +++ b/headers/private/drivers/mmc.h @@ -88,6 +88,8 @@ typedef struct mmc_bus_interface { // Pass the semaphore used for device rescan to the bus controller void (*set_bus_width)(void* controller, int width); // 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; diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp index 43f8070b1f..487c1d7d2b 100644 --- a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp +++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp @@ -61,8 +61,6 @@ MMCBus::~MMCBus() status_t result; if (fWorkerThread != 0) 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 MMCBus::_WorkerThread(void* cookie) { @@ -211,7 +216,9 @@ MMCBus::_WorkerThread(void* cookie) } else if (response != probe) { ERROR("Card does not support voltage range (expected %x, " "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 diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h index 0adc3b9c49..ec70d6021f 100644 --- a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h +++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h @@ -55,6 +55,7 @@ public: private: status_t _ActivateDevice(uint16_t rca); void _AcquireScanSemaphore(); + void _TerminateBus(); static status_t _WorkerThread(void*); private: diff --git a/src/add-ons/kernel/busses/mmc/sdhci.cpp b/src/add-ons/kernel/busses/mmc/sdhci.cpp index ee75ca5764..6e44ecd4fd 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci.cpp +++ b/src/add-ons/kernel/busses/mmc/sdhci.cpp @@ -149,7 +149,7 @@ SdhciBus::SdhciBus(struct registers* registers, uint8_t irq, bool poll) SdhciBus::~SdhciBus() { - DisableInterrupts(); + TerminateBus(); if (fIrq != 0) 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 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 // node for each SD slot in the device. static driver_module_info sSDHCIDevice = { diff --git a/src/add-ons/kernel/busses/mmc/sdhci.h b/src/add-ons/kernel/busses/mmc/sdhci.h index 36480d29a6..f3d43d0d45 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci.h +++ b/src/add-ons/kernel/busses/mmc/sdhci.h @@ -34,9 +34,11 @@ class SdhciBus { bool offsetAsSectors); void SetScanSemaphore(sem_id sem); void SetBusWidth(int width); + void TerminateBus(); private: bool PowerOn(); + void PowerOff(); void RecoverError(); static status_t _WorkerThread(void*); @@ -516,6 +518,7 @@ status_t do_io(void* controller, uint8_t command, IOOperation* operation, bool offsetAsSectors); void set_scan_semaphore(void* controller, sem_id sem); void set_bus_width(void* controller, int width); +void terminate_bus(void* controller); extern mmc_bus_interface gSDHCIACPIDeviceModule; extern mmc_bus_interface gSDHCIPCIDeviceModule; diff --git a/src/add-ons/kernel/busses/mmc/sdhci_acpi.cpp b/src/add-ons/kernel/busses/mmc/sdhci_acpi.cpp index 246aa4866b..c2404132e4 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci_acpi.cpp +++ b/src/add-ons/kernel/busses/mmc/sdhci_acpi.cpp @@ -239,4 +239,5 @@ mmc_bus_interface gSDHCIACPIDeviceModule = { .do_io = do_io, .set_scan_semaphore = set_scan_semaphore, .set_bus_width = set_bus_width, + .terminate_bus = terminate_bus, }; diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp index e7207d01d9..4ff44f805b 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp +++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp @@ -331,4 +331,5 @@ mmc_bus_interface gSDHCIPCIDeviceModule = { .do_io = do_io, .set_scan_semaphore = set_scan_semaphore, .set_bus_width = set_bus_width, + .terminate_bus = terminate_bus, };