wolfBoot/include/sdhci.h

494 lines
20 KiB
C

/* sdhci.h
*
* Cadence SD Host Controller Interface (SDHCI) Driver
* Generic implementation supporting SD cards and eMMC.
*
* Compile with DISK_SDCARD=1 or DISK_EMMC=1
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef SDHCI_H
#define SDHCI_H
#if defined(DISK_SDCARD) || defined(DISK_EMMC)
#include <stdint.h>
/* ============================================================================
* Configuration (override in target .config or platform header)
* ============================================================================ */
/* Block size */
#ifndef SDHCI_BLOCK_SIZE
#define SDHCI_BLOCK_SIZE 512
#endif
/* DMA threshold - minimum transfer size (bytes) to use SDMA instead of PIO.
* Default 4KB: forces SDMA for virtually all multi-block CMD18 reads.
* The PIO multi-block read path has a known race condition on Arasan SDHCI
* controllers (ZynqMP, Versal) where BRR (Buffer Read Ready) is re-checked
* too quickly between blocks under compiler optimization (-Os/-O2), causing
* stale data reads and firmware integrity failures. Using SDMA avoids the
* BRR polling loop entirely.
* Override in target .config if a larger PIO window is acceptable. */
#ifndef SDHCI_DMA_THRESHOLD
#define SDHCI_DMA_THRESHOLD (4U * 1024U)
#endif
/* Disk test block address (platform should override) */
#ifndef DISK_TEST_BLOCK_ADDR
#define DISK_TEST_BLOCK_ADDR 149504 /* ~76MB offset */
#endif
/* DMA buffer boundary: how often the SDMA engine pauses to refresh its
* address pointer (handled by sdhci_irq_handler() via SDHCI_SRS12_DMAINT).
* This is a throughput knob and is independent of SDHCI_DMA_THRESHOLD
* (which controls when to switch from PIO to SDMA). Override in target
* .config to match the largest expected single transfer for fewer
* boundary IRQs; otherwise auto-select based on the threshold. */
#ifndef SDHCI_DMA_BUFF_BOUNDARY
#if (SDHCI_DMA_THRESHOLD > (256U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_512KB
#if (SDHCI_DMA_THRESHOLD != (512U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 512KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (128U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_256KB
#if (SDHCI_DMA_THRESHOLD != (256U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 256KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (64U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_128KB
#if (SDHCI_DMA_THRESHOLD != (128U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 128KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (32U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_64KB
#if (SDHCI_DMA_THRESHOLD != (64U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 64KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (16U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_32KB
#if (SDHCI_DMA_THRESHOLD != (32U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 32KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (8U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_16KB
#if (SDHCI_DMA_THRESHOLD != (16U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 16KB"
#endif
#elif (SDHCI_DMA_THRESHOLD > (4U * 1024U))
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_8KB
#if (SDHCI_DMA_THRESHOLD != (8U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 8KB"
#endif
#else
#define SDHCI_DMA_BUFF_BOUNDARY SDHCI_SRS01_DMA_BUFF_4KB
#if (SDHCI_DMA_THRESHOLD != (4U * 1024U))
#warning "SDHCI_DMA_THRESHOLD rounded up to 4KB (minimum)"
#endif
#endif
#endif /* !SDHCI_DMA_BUFF_BOUNDARY */
/* Timeouts */
#ifndef SDHCI_INIT_TIMEOUT_US
#define SDHCI_INIT_TIMEOUT_US 500000 /* 500ms for initialization */
#endif
#ifndef SDHCI_DATA_TIMEOUT_US
#define SDHCI_DATA_TIMEOUT_US 3000000 /* 3000ms for data operations */
#endif
/* Clock frequencies (kHz) */
#ifndef SDHCI_CLK_400KHZ
#define SDHCI_CLK_400KHZ 400
#endif
#ifndef SDHCI_CLK_25MHZ
#define SDHCI_CLK_25MHZ 25000
#endif
#ifndef SDHCI_CLK_50MHZ
#define SDHCI_CLK_50MHZ 50000
#endif
/* ============================================================================
* Cadence SDHCI Register Offsets (SD4HC Standard)
* ============================================================================ */
/* Host Register Set (HRS) */
#define SDHCI_HRS00 0x000 /* General information */
#define SDHCI_HRS01 0x004 /* Debounce setting */
#define SDHCI_HRS02 0x008 /* Bus setting */
#define SDHCI_HRS04 0x010 /* PHY access port */
#define SDHCI_HRS06 0x018 /* eMMC control */
/* Slot Register Set (SRS) - SD Host Controller standard registers */
#define SDHCI_SRS00 0x200 /* SDMA System Address / Argument 2 */
#define SDHCI_SRS01 0x204 /* Block Size / Block Count */
#define SDHCI_SRS02 0x208 /* Argument 1 */
#define SDHCI_SRS03 0x20C /* Command / Transfer Mode */
#define SDHCI_SRS04 0x210 /* Response 0 */
#define SDHCI_SRS05 0x214 /* Response 1 */
#define SDHCI_SRS06 0x218 /* Response 2 */
#define SDHCI_SRS07 0x21C /* Response 3 */
#define SDHCI_SRS08 0x220 /* Data Port */
#define SDHCI_SRS09 0x224 /* Present State */
#define SDHCI_SRS10 0x228 /* Host Control 1 / Power / Block Gap / Wakeup */
#define SDHCI_SRS11 0x22C /* Clock Control / Timeout / Software Reset */
#define SDHCI_SRS12 0x230 /* Normal Interrupt Status */
#define SDHCI_SRS13 0x234 /* Normal Interrupt Status Enable */
#define SDHCI_SRS14 0x238 /* Normal Interrupt Signal Enable */
#define SDHCI_SRS15 0x23C /* Auto CMD Error Status / Host Control 2 */
#define SDHCI_SRS16 0x240 /* Capabilities 1 */
#define SDHCI_SRS17 0x244 /* Capabilities 2 */
#define SDHCI_SRS18 0x248 /* Maximum Current */
#define SDHCI_SRS22 0x258 /* ADMA2/SDMA Address (low) */
#define SDHCI_SRS23 0x25C /* ADMA2/SDMA Address (high) */
/* ============================================================================
* Register Bit Definitions
* ============================================================================ */
/* HRS00 - General Information Register */
#define SDHCI_HRS00_SWR (1U << 0) /* Software reset */
/* HRS01 - Debounce Setting Register */
#define SDHCI_HRS01_DP_SHIFT 16
#define SDHCI_HRS01_DP_MASK (0xFFFFU << 16)
/* HRS04 - PHY Access Port */
#define SDHCI_HRS04_UIS_ACK (1U << 26)
#define SDHCI_HRS04_UIS_WR (1U << 24)
#define SDHCI_HRS04_UIS_ADDR_MASK 0x3F
#define SDHCI_HRS04_UIS_WDATA_SHIFT 8
/* HRS06 - eMMC Control Register */
#define SDHCI_HRS06_EMM_MASK 0x07
#define SDHCI_HRS06_MODE_SD 0x00 /* SD mode */
#define SDHCI_HRS06_MODE_LEGACY 0x02 /* eMMC legacy mode */
/* SRS01 - Block Size / Block Count Register */
#define SDHCI_SRS01_BCCT_SHIFT 16 /* Block count shift */
#define SDHCI_SRS01_DMA_BUFF_4KB (0x0U << 12)
#define SDHCI_SRS01_DMA_BUFF_8KB (0x1U << 12)
#define SDHCI_SRS01_DMA_BUFF_16KB (0x2U << 12)
#define SDHCI_SRS01_DMA_BUFF_32KB (0x3U << 12)
#define SDHCI_SRS01_DMA_BUFF_64KB (0x4U << 12)
#define SDHCI_SRS01_DMA_BUFF_128KB (0x5U << 12)
#define SDHCI_SRS01_DMA_BUFF_256KB (0x6U << 12)
#define SDHCI_SRS01_DMA_BUFF_512KB (0x7U << 12)
/* SRS03 - Command / Transfer Mode Register */
#define SDHCI_SRS03_CIDX_SHIFT 24
#define SDHCI_SRS03_CIDX_MASK (0x3FU << 24)
#define SDHCI_SRS03_CT_SHIFT 22
#define SDHCI_SRS03_CT_MASK (0x03U << 22)
#define SDHCI_SRS03_CMD_NORMAL 0x00
#define SDHCI_SRS03_CMD_SUSPEND 0x01
#define SDHCI_SRS03_CMD_RESUME 0x02
#define SDHCI_SRS03_CMD_ABORT 0x03
#define SDHCI_SRS03_DPS (1U << 21) /* Data present */
#define SDHCI_SRS03_CICE (1U << 20) /* Command index check enable */
#define SDHCI_SRS03_CRCCE (1U << 19) /* Command CRC check enable */
#define SDHCI_SRS03_RID (1U << 17) /* Response interrupt disable */
#define SDHCI_SRS03_RECE (1U << 16) /* Response error check enable */
#define SDHCI_SRS03_RESP_NONE (0x0U << 16)
#define SDHCI_SRS03_RESP_136 (0x1U << 16)
#define SDHCI_SRS03_RESP_48 (0x2U << 16)
#define SDHCI_SRS03_RESP_48B (0x3U << 16)
#define SDHCI_SRS03_MSBS (1U << 5) /* Multi/single block select */
#define SDHCI_SRS03_DTDS (1U << 4) /* Data transfer direction (1=read) */
#define SDHCI_SRS03_BCE (1U << 1) /* Block count enable */
#define SDHCI_SRS03_DMAE (1U << 0) /* DMA enable */
/* SRS09 - Present State Register */
#define SDHCI_SRS09_CI (1U << 16) /* Card inserted */
#define SDHCI_SRS09_CSS (1U << 17) /* Card state stable */
#define SDHCI_SRS09_CICMD (1U << 0) /* Command inhibit (CMD) */
#define SDHCI_SRS09_CIDAT (1U << 1) /* Command inhibit (DAT) */
#define SDHCI_SRS09_DAT0_LVL (1U << 20) /* DAT0 signal level */
/* SRS10 - Host Control 1 / Power / Block Gap / Wakeup */
#define SDHCI_SRS10_DTW (1U << 1) /* Data transfer width (4-bit) */
#define SDHCI_SRS10_EDTW (1U << 5) /* Extended data transfer width (8-bit) */
#define SDHCI_SRS10_CDTL (1U << 6) /* Card Detect Test Level */
#define SDHCI_SRS10_CDSS (1U << 7) /* Card Detect Signal Selection */
#define SDHCI_SRS10_HSE (1U << 2) /* High speed enable */
#define SDHCI_SRS10_BP (1U << 8) /* Bus power */
#define SDHCI_SRS10_BVS_MASK (0x7U << 9)
#define SDHCI_SRS10_BVS_1_8V (0x5U << 9)
#define SDHCI_SRS10_BVS_3_0V (0x6U << 9)
#define SDHCI_SRS10_BVS_3_3V (0x7U << 9)
#define SDHCI_SRS10_DMA_SDMA (0x0U << 3)
/* SRS11 - Clock Control / Timeout / Software Reset */
#define SDHCI_SRS11_ICE (1U << 0) /* Internal clock enable */
#define SDHCI_SRS11_ICS (1U << 1) /* Internal clock stable */
#define SDHCI_SRS11_SDCE (1U << 2) /* SD clock enable */
#define SDHCI_SRS11_CGS (1U << 5) /* Clock generator select */
#define SDHCI_SRS11_SDCFSL_SHIFT 8
#define SDHCI_SRS11_SDCFSL_MASK (0xFFU << 8)
#define SDHCI_SRS11_SDCFSH_SHIFT 6
#define SDHCI_SRS11_SDCFSH_MASK (0x03U << 6)
#define SDHCI_SRS11_DTCV_SHIFT 16
#define SDHCI_SRS11_DTCV_MASK (0x0FU << 16)
#define SDHCI_SRS11_RESET_DAT_CMD ((1U << 25) | (1U << 26))
#define SDHCI_SRS11_RESET_ALL (1U << 24)
/* SRS12 - Normal Interrupt Status */
#define SDHCI_SRS12_CC (1U << 0) /* Command complete */
#define SDHCI_SRS12_TC (1U << 1) /* Transfer complete */
#define SDHCI_SRS12_BGE (1U << 2) /* Block gap event */
#define SDHCI_SRS12_DMAINT (1U << 3) /* DMA interrupt */
#define SDHCI_SRS12_BWR (1U << 4) /* Buffer write ready */
#define SDHCI_SRS12_BRR (1U << 5) /* Buffer read ready */
#define SDHCI_SRS12_CIN (1U << 6) /* Card insertion */
#define SDHCI_SRS12_CR (1U << 7) /* Card removal */
#define SDHCI_SRS12_CINT (1U << 8) /* Card interrupt */
#define SDHCI_SRS12_EINT (1U << 15) /* Error interrupt */
#define SDHCI_SRS12_ECT (1U << 16) /* Command timeout error */
#define SDHCI_SRS12_ECCRC (1U << 17) /* Command CRC error */
#define SDHCI_SRS12_ECEB (1U << 18) /* Command end bit error */
#define SDHCI_SRS12_ECI (1U << 19) /* Command index error */
#define SDHCI_SRS12_EDT (1U << 20) /* Data timeout error */
#define SDHCI_SRS12_EDCRC (1U << 21) /* Data CRC error */
#define SDHCI_SRS12_EDEB (1U << 22) /* Data end bit error */
#define SDHCI_SRS12_ECL (1U << 23) /* Current limit error */
#define SDHCI_SRS12_EAC (1U << 24) /* Auto CMD error */
#define SDHCI_SRS12_EADMA (1U << 25) /* ADMA error */
#define SDHCI_SRS12_NORM_STAT 0x0000FFFFU
#define SDHCI_SRS12_ERR_STAT 0xFFFF0000U
/* SRS13 - Normal Interrupt Status Enable */
#define SDHCI_SRS13_CC_SE (1U << 0)
#define SDHCI_SRS13_TC_SE (1U << 1)
#define SDHCI_SRS13_BGE_SE (1U << 2)
#define SDHCI_SRS13_DMAINT_SE (1U << 3)
#define SDHCI_SRS13_BWR_SE (1U << 4)
#define SDHCI_SRS13_BRR_SE (1U << 5)
#define SDHCI_SRS13_CIN_SE (1U << 6)
#define SDHCI_SRS13_CR_SE (1U << 7)
#define SDHCI_SRS13_CINT_SE (1U << 8)
#define SDHCI_SRS13_INT_ONA (1U << 9)
#define SDHCI_SRS13_INT_ONB (1U << 10)
#define SDHCI_SRS13_INT_ONC (1U << 11)
#define SDHCI_SRS13_RTUNE_SE (1U << 12)
#define SDHCI_SRS13_ECT_SE (1U << 16)
#define SDHCI_SRS13_ECCRC_SE (1U << 17)
#define SDHCI_SRS13_ECEB_SE (1U << 18)
#define SDHCI_SRS13_ECI_SE (1U << 19)
#define SDHCI_SRS13_EDT_SE (1U << 20)
#define SDHCI_SRS13_EDCRC_SE (1U << 21)
#define SDHCI_SRS13_EDEB_SE (1U << 22)
#define SDHCI_SRS13_ECL_SE (1U << 23)
#define SDHCI_SRS13_EAC_SE (1U << 24)
#define SDHCI_SRS13_EADMA_SE (1U << 25)
#define SDHCI_SRS13_ETUNE_SE (1U << 26)
#define SDHCI_SRS13_ERSP_SE (1U << 27)
#define SDHCI_SRS13_CQINT_SE (1U << 30)
/* SRS14 - Normal Interrupt Signal Enable */
#define SDHCI_SRS14_CC_IE (1U << 0)
#define SDHCI_SRS14_TC_IE (1U << 1)
#define SDHCI_SRS14_DMAINT_IE (1U << 3)
#define SDHCI_SRS14_EDT_IE (1U << 20)
/* SRS15 - Auto CMD Error Status / Host Control 2 */
#define SDHCI_SRS15_A64 (1U << 29) /* 64-bit addressing */
#define SDHCI_SRS15_HV4E (1U << 28) /* Host version 4 enable */
#define SDHCI_SRS15_UMS_MASK (0x7U << 16)
#define SDHCI_SRS15_UMS_SDR25 (0x1U << 16)
/* Host Control 2 occupies the upper 16 bits of SRS15, so 1.8V Signaling
* Enable (bit 3 of Host Control 2) lands at bit 19. */
#define SDHCI_SRS15_V18SE (1U << 19) /* 1.8V signaling enable */
#define SDHCI_SRS15_DSS_MASK (0x3U << 20)
#define SDHCI_SRS15_DSS_TYPE_B (0x0U << 20)
#define SDHCI_SRS15_EXTNG (1U << 22) /* Execute tuning */
#define SDHCI_SRS15_SCS (1U << 23) /* Sampling clock select */
/* SRS16 - Capabilities 1 */
#define SDHCI_SRS16_TCF_SHIFT 0
#define SDHCI_SRS16_TCF_MASK (0x3FU << 0)
#define SDHCI_SRS16_TCU (1U << 7) /* Timeout clock unit (1=MHz) */
#define SDHCI_SRS16_BCSDCLK_SHIFT 8
#define SDHCI_SRS16_BCSDCLK_MASK (0xFFU << 8)
#define SDHCI_SRS16_VS33 (1U << 24) /* 3.3V supported */
#define SDHCI_SRS16_VS30 (1U << 25) /* 3.0V supported */
#define SDHCI_SRS16_VS18 (1U << 26) /* 1.8V supported */
#define SDHCI_SRS16_A64S (1U << 28) /* 64-bit system bus support */
/* SRS17 - Capabilities 2 */
#define SDHCI_SRS17_SDR50 (1U << 0)
#define SDHCI_SRS17_SDR104 (1U << 1)
#define SDHCI_SRS17_DDR50 (1U << 2)
#define SDHCI_SRS17_TSDR50 (1U << 13) /* Tuning for SDR50 required */
/* SRS18 - Maximum Current */
#define SDHCI_SRS18_MC33_SHIFT 0
#define SDHCI_SRS18_MC33_MASK (0xFFU << 0)
#define SDHCI_SRS18_MC18_SHIFT 16
#define SDHCI_SRS18_MC18_MASK (0xFFU << 16)
/* ============================================================================
* MMC/SD Command Definitions
* ============================================================================ */
/* Common MMC/SD commands */
#define MMC_CMD0_GO_IDLE 0
#define MMC_CMD2_ALL_SEND_CID 2
#define MMC_CMD3_SET_REL_ADDR 3
#define MMC_CMD7_SELECT_CARD 7
#define MMC_CMD9_SEND_CSD 9
#define MMC_CMD12_STOP_TRANS 12
#define MMC_CMD13_SEND_STATUS 13
#define MMC_CMD17_READ_SINGLE 17
#define MMC_CMD18_READ_MULTIPLE 18
#define MMC_CMD24_WRITE_SINGLE 24
#define MMC_CMD25_WRITE_MULTIPLE 25
/* SD card-specific commands */
#define SD_CMD6_SWITCH_FUNC 6
#define SD_CMD8_SEND_IF_COND 8
#define SD_CMD16 16
#define SD_CMD19_SEND_TUNING 19
#define SD_CMD55_APP_CMD 55
#define SD_ACMD6_SET_BUS_WIDTH 6
#define SD_ACMD41_SEND_OP_COND 41
#define SD_ACMD51_SEND_SCR 51
/* eMMC-specific commands */
#define MMC_CMD1_SEND_OP_COND 1
#define MMC_CMD6_SWITCH 6
/* SD voltage check */
#define SD_IF_COND_27V_33V 0x1AA
/* SD RCA shift */
#define SD_RCA_SHIFT 16
/* SD/MMC OCR register bits */
#define SDCARD_ACMD41_HCS (1U << 30)
#define SDCARD_REG_OCR_READY (1U << 31)
#define SDCARD_REG_OCR_S18RA (1U << 24)
#define SDCARD_REG_OCR_XPC (1U << 28)
#define SDCARD_REG_OCR_2_9_3_0 (1U << 17)
#define SDCARD_REG_OCR_3_0_3_1 (1U << 18)
#define SDCARD_REG_OCR_3_1_3_2 (1U << 19)
#define SDCARD_REG_OCR_3_2_3_3 (1U << 20)
#define SDCARD_REG_OCR_3_3_3_4 (1U << 21)
/* SD switch function */
#define SDCARD_SWITCH_FUNC_MODE_CHECK (0U << 31)
#define SDCARD_SWITCH_FUNC_MODE_SWITCH (1U << 31)
#define SDCARD_SWITCH_ACCESS_MODE_SDR25 0x01
/* SCR register */
#define SCR_REG_DATA_SIZE 8
/* eMMC-specific constants */
#define MMC_DW_CSD 0x03B70000U
#define MMC_DEVICE_3_3V_VOLT_SET 0x40300000U
#define MMC_OCR_BUSY_BIT 0x80000000U
#define MMC_EMMC_RCA_DEFAULT 1
#define MMC_EXT_CSD_WIDTH_1BIT 0x00U
#define MMC_EXT_CSD_WIDTH_4BIT 0x01U
#define MMC_EXT_CSD_WIDTH_8BIT 0x02U
#define MMC_EXT_CSD_WIDTH_4BIT_DDR 0x05U
#define MMC_EXT_CSD_WIDTH_8BIT_DDR 0x06U
/* IRQ status flags */
#define SDHCI_IRQ_FLAG_CC 0x01
#define SDHCI_IRQ_FLAG_TC 0x02
#define SDHCI_IRQ_FLAG_DMAINT 0x04
#define SDHCI_IRQ_FLAG_ERROR 0x80
/* Response types */
typedef enum {
SDHCI_RESP_NONE,
SDHCI_RESP_R1,
SDHCI_RESP_R1B,
SDHCI_RESP_R2,
SDHCI_RESP_R3,
SDHCI_RESP_R4,
SDHCI_RESP_R5,
SDHCI_RESP_R5B,
SDHCI_RESP_R6,
SDHCI_RESP_R7,
SDHCI_RESP_R1A
} sdhci_resp_t;
/* ============================================================================
* Public API (implemented in src/sdhci.c)
* ============================================================================ */
/* Initialize controller and card */
int sdhci_init(void);
/* Block read/write */
int sdhci_read(uint32_t cmd_index, uint32_t block_addr, uint32_t* dst, uint32_t sz);
int sdhci_write(uint32_t cmd_index, uint32_t block_addr, const uint32_t* src, uint32_t sz);
/* Send command */
int sdhci_cmd(uint32_t cmd_index, uint32_t cmd_arg, uint8_t resp_type);
/* IRQ handler (call from platform IRQ) */
void sdhci_irq_handler(void);
/* Full controller software reset for OS handoff (returns host registers to
* power-on defaults so the OS driver finds a clean controller) */
void sdhci_shutdown(void);
/* ============================================================================
* HAL Interface (platform must implement in target HAL file)
* ============================================================================ */
/* Register access - platform provides base address and implementation */
uint32_t sdhci_reg_read(uint32_t offset);
void sdhci_reg_write(uint32_t offset, uint32_t val);
/* Direct buffer data port access (for tight transfer loops)
* Default implementation uses sdhci_reg_read/write, but platform may
* override with direct volatile access for better performance */
#ifndef SDHCI_BUF_READ
#define SDHCI_BUF_READ() sdhci_reg_read(SDHCI_SRS08)
#endif
#ifndef SDHCI_BUF_WRITE
#define SDHCI_BUF_WRITE(v) sdhci_reg_write(SDHCI_SRS08, v)
#endif
/* Platform initialization (clocks, resets, pin mux, debounce) */
void sdhci_platform_init(void);
/* Optional platform clock hook (weak no-op default in src/sdhci.c). Called
* from sdhci_set_clock with the requested card clock and the CAPS-derived
* base; returns the base clock (kHz) to divide from, or 0 on error. Platforms
* whose clock tree is owned by a PMC/BPMP (Tegra) set the module clock equal
* to the card clock and return that, keeping the internal divider ~1. */
uint32_t sdhci_platform_set_clock(uint32_t clock_khz, uint32_t base_clk_khz);
/* Platform interrupt setup (PLIC/NVIC/GIC/etc.) */
void sdhci_platform_irq_init(void);
/* Platform bus mode selection (SD vs eMMC) */
void sdhci_platform_set_bus_mode(int is_emmc);
#endif /* DISK_SDCARD || DISK_EMMC */
#endif /* SDHCI_H */