Skip to content

Commit b5c0185

Browse files
committed
Fixes for register width and slot type.
1 parent 658459f commit b5c0185

File tree

1 file changed

+75
-21
lines changed

1 file changed

+75
-21
lines changed

hal/zynq.c

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,11 +1866,19 @@ static int test_ext_flash(QspiDev_t* dev)
18661866

18671867
#define CADENCE_SRS_OFFSET 0x200
18681868

1869-
/* Standard SDHCI Software Reset is in the Clock/Timeout/Reset register */
1870-
#define STD_SDHCI_RESET_REG 0x2C /* Clock Control / Timeout / SW Reset */
1871-
#define STD_SDHCI_SRA (1U << 24) /* Software Reset for All */
1872-
#define STD_SDHCI_SRCMD (1U << 25) /* Software Reset for CMD Line */
1873-
#define STD_SDHCI_SRDAT (1U << 26) /* Software Reset for DAT Line */
1869+
/* Standard SDHCI register offsets (byte addresses within the controller) */
1870+
#define STD_SDHCI_HOST_CTRL1 0x28 /* Host Control 1 (8-bit) */
1871+
#define STD_SDHCI_POWER_CTRL 0x29 /* Power Control (8-bit) */
1872+
#define STD_SDHCI_BLKGAP_CTRL 0x2A /* Block Gap Control (8-bit) */
1873+
#define STD_SDHCI_WAKEUP_CTRL 0x2B /* Wakeup Control (8-bit) */
1874+
#define STD_SDHCI_CLK_CTRL 0x2C /* Clock Control (16-bit) */
1875+
#define STD_SDHCI_TIMEOUT_CTRL 0x2E /* Timeout Control (8-bit) */
1876+
#define STD_SDHCI_SW_RESET 0x2F /* Software Reset (8-bit) */
1877+
1878+
/* Software Reset register bits (at offset 0x2F, 8-bit register) */
1879+
#define STD_SDHCI_SRA 0x01 /* Software Reset for All */
1880+
#define STD_SDHCI_SRCMD 0x02 /* Software Reset for CMD Line */
1881+
#define STD_SDHCI_SRDAT 0x04 /* Software Reset for DAT Line */
18741882

18751883
/* Handle reads from Cadence HRS registers (0x000-0x1FF) */
18761884
static uint32_t zynqmp_sdhci_hrs_read(uint32_t hrs_offset)
@@ -1880,11 +1888,8 @@ static uint32_t zynqmp_sdhci_hrs_read(uint32_t hrs_offset)
18801888
switch (hrs_offset) {
18811889
case 0x000: /* HRS00 - Software Reset */
18821890
{
1883-
/* Map standard SRA (bit 24 of 0x2C) to Cadence SWR (bit 0).
1884-
* SRA is safe because sdhci_platform_init() sets the slot type
1885-
* to "Embedded", so the controller accepts BP/SDCE writes after
1886-
* reset. */
1887-
uint32_t val = *((volatile uint32_t *)(base + STD_SDHCI_RESET_REG));
1891+
/* Map standard SRA (byte at 0x2F) to Cadence SWR (bit 0) */
1892+
uint8_t val = *((volatile uint8_t *)(base + STD_SDHCI_SW_RESET));
18881893
return (val & STD_SDHCI_SRA) ? 1U : 0U;
18891894
}
18901895
case 0x010: /* HRS04 - PHY access (Cadence-specific) */
@@ -1904,14 +1909,10 @@ static void zynqmp_sdhci_hrs_write(uint32_t hrs_offset, uint32_t val)
19041909
switch (hrs_offset) {
19051910
case 0x000: /* HRS00 - Software Reset */
19061911
if (val & 1U) {
1907-
/* Issue SRA (Software Reset for All).
1908-
* This is safe because sdhci_platform_init() configures the
1909-
* IOU_SLCR slot type to "Embedded" before this reset, so the
1910-
* controller will accept Bus Power and SD Clock Enable writes
1911-
* during the subsequent initialization. */
1912-
uint32_t reg = *((volatile uint32_t *)(base + STD_SDHCI_RESET_REG));
1913-
reg |= STD_SDHCI_SRA;
1914-
*((volatile uint32_t *)(base + STD_SDHCI_RESET_REG)) = reg;
1912+
/* Issue SRA via 8-bit write to offset 0x2F (per SDHCI spec).
1913+
* The Arasan controller requires byte-level access for the
1914+
* Software Reset register. */
1915+
*((volatile uint8_t *)(base + STD_SDHCI_SW_RESET)) = STD_SDHCI_SRA;
19151916
}
19161917
break;
19171918
default:
@@ -1921,13 +1922,24 @@ static void zynqmp_sdhci_hrs_write(uint32_t hrs_offset, uint32_t val)
19211922
}
19221923

19231924
/* Register access functions for generic SDHCI driver.
1924-
* Translates Cadence SD4HC register offsets to standard Arasan SDHCI layout. */
1925+
* Translates Cadence SD4HC register offsets to standard Arasan SDHCI layout.
1926+
*
1927+
* IMPORTANT: The Arasan SDHCI on ZynqMP requires specific register access
1928+
* widths matching the SDHCI specification (see Xilinx SDPS driver reference):
1929+
* - Host Control 1 (0x28): 8-bit
1930+
* - Power Control (0x29): 8-bit
1931+
* - Clock Control (0x2C): 16-bit
1932+
* - Timeout Control (0x2E): 8-bit
1933+
* - Software Reset (0x2F): 8-bit
1934+
* The Cadence driver uses 32-bit SRS10/SRS11 registers that span these byte
1935+
* offsets. We decompose 32-bit writes into the correct access widths. */
19251936
uint32_t sdhci_reg_read(uint32_t offset)
19261937
{
19271938
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
19281939

19291940
/* Cadence SRS registers (0x200+) -> standard SDHCI (subtract 0x200) */
19301941
if (offset >= CADENCE_SRS_OFFSET) {
1942+
/* 32-bit reads work for all SDHCI registers */
19311943
return *((volatile uint32_t *)(base + offset - CADENCE_SRS_OFFSET));
19321944
}
19331945
/* Cadence HRS registers (0x000-0x1FF) -> translate to standard equivalents */
@@ -1938,9 +1950,42 @@ void sdhci_reg_write(uint32_t offset, uint32_t val)
19381950
{
19391951
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;
19401952

1941-
/* Cadence SRS registers (0x200+) -> standard SDHCI (subtract 0x200) */
19421953
if (offset >= CADENCE_SRS_OFFSET) {
1943-
*((volatile uint32_t *)(base + offset - CADENCE_SRS_OFFSET)) = val;
1954+
uint32_t std_off = offset - CADENCE_SRS_OFFSET;
1955+
1956+
/* SRS10 (Cadence 0x228) = standard 0x28-0x2B:
1957+
* 0x28: Host Control 1 (8-bit)
1958+
* 0x29: Power Control (8-bit)
1959+
* 0x2A: Block Gap Control (8-bit)
1960+
* 0x2B: Wakeup Control (8-bit) */
1961+
if (std_off == 0x28) {
1962+
*((volatile uint8_t *)(base + STD_SDHCI_HOST_CTRL1)) =
1963+
(uint8_t)(val & 0xFF);
1964+
*((volatile uint8_t *)(base + STD_SDHCI_POWER_CTRL)) =
1965+
(uint8_t)((val >> 8) & 0xFF);
1966+
*((volatile uint8_t *)(base + STD_SDHCI_BLKGAP_CTRL)) =
1967+
(uint8_t)((val >> 16) & 0xFF);
1968+
*((volatile uint8_t *)(base + STD_SDHCI_WAKEUP_CTRL)) =
1969+
(uint8_t)((val >> 24) & 0xFF);
1970+
return;
1971+
}
1972+
1973+
/* SRS11 (Cadence 0x22C) = standard 0x2C-0x2F:
1974+
* 0x2C: Clock Control (16-bit)
1975+
* 0x2E: Timeout Control (8-bit)
1976+
* 0x2F: Software Reset (8-bit) */
1977+
if (std_off == 0x2C) {
1978+
*((volatile uint16_t *)(base + STD_SDHCI_CLK_CTRL)) =
1979+
(uint16_t)(val & 0xFFFF);
1980+
*((volatile uint8_t *)(base + STD_SDHCI_TIMEOUT_CTRL)) =
1981+
(uint8_t)((val >> 16) & 0xFF);
1982+
*((volatile uint8_t *)(base + STD_SDHCI_SW_RESET)) =
1983+
(uint8_t)((val >> 24) & 0xFF);
1984+
return;
1985+
}
1986+
1987+
/* All other SRS registers: 32-bit write */
1988+
*((volatile uint32_t *)(base + std_off)) = val;
19441989
return;
19451990
}
19461991
/* Cadence HRS registers (0x000-0x1FF) -> translate to standard equivalents */
@@ -1964,6 +2009,7 @@ void sdhci_reg_write(uint32_t offset, uint32_t val)
19642009
void sdhci_platform_init(void)
19652010
{
19662011
uint32_t reg;
2012+
volatile int i;
19672013

19682014
/* Set SD1 slot type to "Embedded Slot for One Device" (01).
19692015
* This feeds into the SDHCI Capabilities register bits 31:30 and makes
@@ -1974,6 +2020,14 @@ void sdhci_platform_init(void)
19742020
reg |= (1UL << SD_CONFIG_REG2_SD1_SLOTTYPE_SHIFT); /* 01 = Embedded */
19752021
IOU_SLCR_SD_CONFIG_REG2 = reg;
19762022

2023+
/* The SDHCI Capabilities register latches IOU_SLCR values on controller
2024+
* reset. Issue SDIO1 reset via CRL_APB so the controller picks up the
2025+
* new slot type configuration. */
2026+
RST_LPD_IOU2 |= RST_LPD_IOU2_SDIO1; /* Assert SDIO1 reset */
2027+
for (i = 0; i < 100; i++) {} /* Brief delay */
2028+
RST_LPD_IOU2 &= ~RST_LPD_IOU2_SDIO1; /* De-assert SDIO1 reset */
2029+
for (i = 0; i < 1000; i++) {} /* Wait for controller ready */
2030+
19772031
#ifdef DEBUG_SDHCI
19782032
{
19792033
volatile uint8_t *base = (volatile uint8_t *)ZYNQMP_SDHCI_BASE;

0 commit comments

Comments
 (0)