Skip to content

Commit 99ce267

Browse files
fanwang-ambiqAlessandroLuo
authored andcommitted
drivers: sdhc: Add support for Apollo510 SDIO host
This commit adds support for ambiq SDIO host driver Signed-off-by: Fan Wang <fan.wang@ambiq.com>
1 parent d41716f commit 99ce267

File tree

10 files changed

+264
-2
lines changed

10 files changed

+264
-2
lines changed

boards/ambiq/apollo510_evb/apollo510_evb-pinctrl.dtsi

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,4 +380,78 @@
380380
drive-strength = "0.5";
381381
};
382382
};
383+
384+
sdio0_default: sdio0_default {
385+
group0 {
386+
pinmux = <SDIF0_DAT1_P85>,
387+
<SDIF0_DAT3_P87>,
388+
<SDIF0_DAT4_P156>,
389+
<SDIF0_DAT5_P157>,
390+
<SDIF0_DAT6_P158>,
391+
<SDIF0_DAT7_P159>;
392+
drive-strength = "1.0";
393+
};
394+
group1 {
395+
pinmux = <SDIF0_DAT0_P84>,
396+
<SDIF0_DAT2_P86>,
397+
<SDIF0_CMD_P160>,
398+
<SDIF0_CLKOUT_P88>;
399+
drive-strength = "1.0";
400+
bias-pull-up;
401+
ambiq,pull-up-ohms = <12000>;
402+
};
403+
group2 {
404+
pinmux = <GPIO_P161>;
405+
ambiq,sdif-cdwp = <1>;
406+
};
407+
group3 {
408+
pinmux = <GPIO_P175>;
409+
ambiq,sdif-cdwp = <2>;
410+
};
411+
group4 {
412+
pinmux = <GPIO_P161>;
413+
ambiq,sdif-cdwp = <3>;
414+
};
415+
group5 {
416+
pinmux = <GPIO_P175>;
417+
ambiq,sdif-cdwp = <4>;
418+
};
419+
};
420+
421+
sdio1_default: sdio1_default {
422+
group0 {
423+
pinmux = <SDIF1_DAT1_P126>,
424+
<SDIF1_DAT3_P128>,
425+
<SDIF1_DAT4_P130>,
426+
<SDIF1_DAT5_P131>,
427+
<SDIF1_DAT6_P132>,
428+
<SDIF1_DAT7_P133>;
429+
drive-strength = "1.0";
430+
};
431+
group1 {
432+
pinmux = <SDIF1_DAT0_P125>,
433+
<SDIF1_DAT2_P127>,
434+
<SDIF1_CMD_P134>,
435+
<SDIF1_CLKOUT_P129>;
436+
drive-strength = "1.0";
437+
bias-pull-up;
438+
ambiq,pull-up-ohms = <12000>;
439+
};
440+
group2 {
441+
pinmux = <GPIO_P161>;
442+
ambiq,sdif-cdwp = <1>;
443+
};
444+
group3 {
445+
pinmux = <GPIO_P175>;
446+
ambiq,sdif-cdwp = <2>;
447+
};
448+
group4 {
449+
pinmux = <GPIO_P161>;
450+
ambiq,sdif-cdwp = <3>;
451+
};
452+
group5 {
453+
pinmux = <GPIO_P175>;
454+
ambiq,sdif-cdwp = <4>;
455+
};
456+
};
383457
};

boards/ambiq/apollo510_evb/apollo510_evb.dts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,19 @@
199199
};
200200
};
201201

202+
&sdio0 {
203+
pinctrl-0 = <&sdio0_default>;
204+
pinctrl-names = "default";
205+
txdelay = <0>;
206+
rxdelay = <0>;
207+
status = "disabled";
208+
mmc {
209+
compatible = "zephyr,mmc-disk";
210+
disk-name = "SD2";
211+
status = "disabled";
212+
};
213+
};
214+
202215
zephyr_udc0: &usb {
203216
vddusb33-gpios = <&gpio64_95 27 (GPIO_PULL_UP)>;
204217
vddusb0p9-gpios = <&gpio64_95 26 (GPIO_PULL_UP)>;

boards/ambiq/apollo510_evb/apollo510_evb.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ supported:
2020
- clock_control
2121
- usbd
2222
- mspi
23+
- sdio
2324
testing:
2425
ignore_tags:
2526
- net

dts/arm/ambiq/ambiq_apollo510.dtsi

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,22 @@
559559
#io-channel-cells = <1>;
560560
};
561561

562+
sdio0: sdio@SDIO0_BASE_NAME {
563+
compatible = "ambiq,sdio";
564+
reg = <SDIO0_REG_BASE SDIO0_REG_SIZE>;
565+
interrupts = <26 0>;
566+
status = "disabled";
567+
zephyr,pm-device-runtime-auto;
568+
};
569+
570+
sdio1: sdio@SDIO1_BASE_NAME {
571+
compatible = "ambiq,sdio";
572+
reg = <SDIO1_REG_BASE SDIO1_REG_SIZE>;
573+
interrupts = <84 0>;
574+
status = "disabled";
575+
zephyr,pm-device-runtime-auto;
576+
};
577+
562578
pinctrl: pin-controller@GPIO_BASE_NAME {
563579
compatible = "ambiq,apollo5-pinctrl";
564580
reg = <GPIO_REG_BASE GPIO_REG_SIZE>;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CONFIG_DISK_DRIVER_MMC=y
2+
CONFIG_MMC_STACK=y
3+
CONFIG_SDHC=y
4+
CONFIG_MMC_SUBSYS=y
5+
6+
CONFIG_MAIN_STACK_SIZE=8192
7+
CONFIG_IDLE_STACK_SIZE=4096
8+
CONFIG_AMBIQ_SDIO_ASYNC=y
9+
CONFIG_PM=y
10+
CONFIG_PM_DEVICE=y
11+
CONFIG_PM_DEVICE_RUNTIME=y
12+
CONFIG_MMC_DDR50=y
13+
CONFIG_MMC_CARD_8BIT_WIDTH=y
14+
15+
CONFIG_ICACHE=y
16+
CONFIG_DCACHE=n
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (C) 2025 Ambiq Micro Inc. <www.ambiq.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
sdhc0 = &sdio0;
10+
};
11+
};
12+
13+
&sdio0 {
14+
status = "okay";
15+
mmc {
16+
status = "okay";
17+
};
18+
};

samples/subsys/fs/fs_sample/sample.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,8 @@ tests:
8282
sample.filesystem.fat_fs.stm32h747i_disco_m7_sdmmc:
8383
build_only: true
8484
platform_allow: stm32h747i_disco/stm32h747xx/m7
85+
sample.filesystem.fat_fs.apollo510_evb_sdmmc:
86+
build_only: true
87+
platform_allow: apollo510_evb
88+
extra_args:
89+
- OVERLAY_CONFIG=boards/apollo510_evb.conf

subsys/sd/Kconfig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,36 @@ config SD_STACK
2828
help
2929
Enable SD card support.
3030

31+
if SDIO_STACK
32+
config SDIO_CARD_1BIT_WIDTH
33+
bool "SDIO CARD 1 bit width support"
34+
default n
35+
help
36+
Enable SDIO card 1 bit width mode.
37+
endif # SDIO_STACK
38+
39+
if MMC_STACK
40+
41+
config MMC_DDR50
42+
bool "MMC DDR50 mode support"
43+
default n
44+
help
45+
Enable MMC DDR50 mode.
46+
47+
config MMC_CARD_4BIT_WIDTH
48+
bool "MMC CARD 4 bit width support"
49+
default n
50+
help
51+
Enable MMC card 4 bit width mode.
52+
53+
config MMC_CARD_8BIT_WIDTH
54+
bool "MMC CARD 8 bit width support"
55+
default n
56+
help
57+
Enable MMC card 8 bit width mode.
58+
59+
endif # MMC_STACK
60+
3161
if SD_STACK
3262

3363
module = SD

subsys/sd/mmc.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#define MMC_SWITCH_8_BIT_BUS_ARG \
3030
(0xFC000000 & (0U << 26)) + (0x03000000 & (0b11 << 24)) + (0x00FF0000 & (183U << 16)) + \
3131
(0x0000FF00 & (2U << 8)) + (0x000000F7 & (0U << 3)) + (0x00000000 & (3U << 0))
32+
#define MMC_SWITCH_4_BIT_DDR_BUS_ARG \
33+
(0xFC000000 & (0U << 26)) + (0x03000000 & (0b11 << 24)) + (0x00FF0000 & (183U << 16)) + \
34+
(0x0000FF00 & (5U << 8)) + (0x000000F7 & (0U << 3)) + (0x00000000 & (3U << 0))
3235
#define MMC_SWITCH_4_BIT_BUS_ARG \
3336
(0xFC000000 & (0U << 26)) + (0x03000000 & (0b11 << 24)) + (0x00FF0000 & (183U << 16)) + \
3437
(0x0000FF00 & (1U << 8)) + (0x000000F7 & (0U << 3)) + (0x00000000 & (3U << 0))
@@ -89,8 +92,25 @@ static inline int mmc_set_max_freq(struct sd_card *card, struct sd_csd *card_csd
8992
/* Sends CMD6 to switch bus width*/
9093
static int mmc_set_bus_width(struct sd_card *card);
9194

95+
#ifdef CONFIG_MMC_DDR50
96+
/* Sets card to DDR50 mode (using CMD6) */
97+
static int mmc_set_ddr50_timing(struct sd_card *card, struct mmc_ext_csd *card_ext_csd);
98+
#else
9299
/* Sets card to the fastest timing mode (using CMD6) and SDHC to max frequency */
93100
static int mmc_set_timing(struct sd_card *card, struct mmc_ext_csd *card_ext_csd);
101+
#endif /*CONFIG_MMC_DDR50*/
102+
103+
/* Sets card timing mode (e.g., DDR50, HS) based on configuration */
104+
static int mmc_set_timing_mode(struct sd_card *card, struct mmc_ext_csd *card_ext_csd)
105+
{
106+
#ifdef CONFIG_MMC_DDR50
107+
/* DDR50 mode logic */
108+
return mmc_set_ddr50_timing(card, card_ext_csd);
109+
#else
110+
/* Fastest timing mode logic */
111+
return mmc_set_timing(card, card_ext_csd);
112+
#endif /* CONFIG_MMC_DDR50 */
113+
}
94114

95115
/* Enable cache for emmc if applicable */
96116
static int mmc_set_cache(struct sd_card *card, struct mmc_ext_csd *card_ext_csd);
@@ -177,8 +197,8 @@ int mmc_card_init(struct sd_card *card)
177197
return ret;
178198
}
179199

180-
/* Set timing to fastest supported */
181-
ret = mmc_set_timing(card, &card_ext_csd);
200+
/* Sets card timing mode */
201+
ret = mmc_set_timing_mode(card, &card_ext_csd);
182202
if (ret) {
183203
return ret;
184204
}
@@ -372,6 +392,12 @@ static int mmc_set_bus_width(struct sd_card *card)
372392
int ret;
373393
struct sdhc_command cmd = {0};
374394

395+
#if defined(CONFIG_MMC_CARD_8BIT_WIDTH)
396+
card->bus_width = 8;
397+
#elif defined(CONFIG_MMC_CARD_4BIT_WIDTH)
398+
card->bus_width = 4;
399+
#endif
400+
375401
if (card->host_props.host_caps.bus_8_bit_support && card->bus_width == 8) {
376402
cmd.arg = MMC_SWITCH_8_BIT_BUS_ARG;
377403
card->bus_io.bus_width = SDHC_BUS_WIDTH8BIT;
@@ -404,6 +430,57 @@ static int mmc_set_bus_width(struct sd_card *card)
404430
return ret;
405431
}
406432

433+
#ifdef CONFIG_MMC_DDR50
434+
static int mmc_set_ddr50_timing(struct sd_card *card, struct mmc_ext_csd *ext)
435+
{
436+
int ret = 0;
437+
struct sdhc_command cmd = {0};
438+
439+
if (ext->device_type.MMC_HS_DDR_1800MV && card->host_props.host_caps.ddr50_support &&
440+
(card->bus_io.bus_width >= SDHC_BUS_WIDTH4BIT)) {
441+
442+
cmd.arg = MMC_SWITCH_HS_TIMING_ARG;
443+
cmd.opcode = SD_SWITCH;
444+
cmd.response_type = SD_RSP_TYPE_R1b;
445+
cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT;
446+
ret = sdhc_request(card->sdhc, &cmd, NULL);
447+
sdmmc_wait_ready(card);
448+
if (ret) {
449+
LOG_ERR("Setting HS Timing mode failed: %d", ret);
450+
return ret;
451+
}
452+
453+
if (card->bus_io.bus_width == SDHC_BUS_WIDTH4BIT) {
454+
cmd.arg = MMC_SWITCH_4_BIT_DDR_BUS_ARG;
455+
} else {
456+
cmd.arg = MMC_SWITCH_8_BIT_DDR_BUS_ARG;
457+
}
458+
cmd.opcode = SD_SWITCH;
459+
cmd.response_type = SD_RSP_TYPE_R1b;
460+
cmd.timeout_ms = CONFIG_SD_CMD_TIMEOUT;
461+
ret = sdhc_request(card->sdhc, &cmd, NULL);
462+
sdmmc_wait_ready(card);
463+
if (ret) {
464+
LOG_ERR("Setting DDR data bus width failed: %d", ret);
465+
return ret;
466+
}
467+
468+
/* Max frequency in DDR50 mode is 52 MHz */
469+
card->bus_io.clock = MMC_CLOCK_DDR52;
470+
card->bus_io.timing = SDHC_TIMING_DDR52;
471+
/* Change SDHC bus timing */
472+
ret = sdhc_set_io(card->sdhc, &card->bus_io);
473+
if (ret) {
474+
return ret;
475+
}
476+
card->card_speed = MMC_HS_TIMING;
477+
} else {
478+
return -ENOTSUP;
479+
}
480+
481+
return ret;
482+
}
483+
#else
407484
static int mmc_set_hs_timing(struct sd_card *card)
408485
{
409486
int ret = 0;
@@ -557,6 +634,7 @@ static int mmc_set_timing(struct sd_card *card, struct mmc_ext_csd *ext)
557634
}
558635
return ret;
559636
}
637+
#endif /*CONFIG_MMC_DDR50*/
560638

561639
static int mmc_read_ext_csd(struct sd_card *card, struct mmc_ext_csd *card_ext_csd)
562640
{

subsys/sd/sdio.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ static int sdio_send_ocr(struct sd_card *card, uint32_t ocr)
5858
/* Card is not a supported SD device */
5959
return -ENOTSUP;
6060
}
61+
62+
/* Save OCR value from CMD5 response */
63+
card->ocr = cmd.response[0];
64+
6165
/* Card has IO present, return zero to
6266
* indicate SDIO card
6367
*/
@@ -567,6 +571,9 @@ int sdio_card_init(struct sd_card *card)
567571
/* See if the card also supports 1.8V */
568572
ocr_arg |= SD_OCR_SWITCH_18_REQ_FLAG;
569573
}
574+
/* Set OCR_ARG based on OCR value */
575+
ocr_arg = card->ocr & 0x01FFFF00;
576+
570577
ret = sdio_send_ocr(card, ocr_arg);
571578
if (ret) {
572579
return ret;
@@ -646,7 +653,11 @@ int sdio_card_init(struct sd_card *card)
646653
((card->cccr_flags & SDIO_SUPPORT_HS) ||
647654
(card->cccr_flags & SDIO_SUPPORT_4BIT_LS_BUS))) {
648655
/* Raise bus width to 4 bits */
656+
#ifdef CONFIG_SDIO_CARD_1BIT_WIDTH
657+
ret = sdio_set_bus_width(card, SDHC_BUS_WIDTH1BIT);
658+
#else
649659
ret = sdio_set_bus_width(card, SDHC_BUS_WIDTH4BIT);
660+
#endif
650661
if (ret) {
651662
return ret;
652663
}

0 commit comments

Comments
 (0)