Skip to content

Commit 8dcc1f3

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 8dcc1f3

File tree

10 files changed

+259
-1
lines changed

10 files changed

+259
-1
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: 75 additions & 1 deletion
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))
@@ -41,7 +44,7 @@
4144
#define MMC_SWITCH_HS200_TIMING_ARG \
4245
(0xFC000000 & (0U << 26)) + (0x03000000 & (0b11 << 24)) + (0x00FF0000 & (185U << 16)) + \
4346
(0x0000FF00 & (2U << 8)) + (0x000000F7 & (0U << 3)) + (0x00000000 & (3U << 0))
44-
#define MMC_RCA_ARG (CONFIG_MMC_RCA << 16U)
47+
#define MMC_RCA_ARG (CONFIG_MMC_RCA << 16U)
4548
#define MMC_REL_ADR_ARG (card->relative_addr << 16U)
4649
#define MMC_SWITCH_PWR_CLASS_ARG \
4750
(0xFC000000 & (0U << 26)) + (0x03000000 & (0b11 << 24)) + (0x00FF0000 & (187U << 16)) + \
@@ -89,8 +92,13 @@ 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*/
94102

95103
/* Enable cache for emmc if applicable */
96104
static int mmc_set_cache(struct sd_card *card, struct mmc_ext_csd *card_ext_csd);
@@ -177,11 +185,19 @@ int mmc_card_init(struct sd_card *card)
177185
return ret;
178186
}
179187

188+
#ifdef CONFIG_MMC_DDR50
189+
/* Set MMC DDR50 timing */
190+
ret = mmc_set_ddr50_timing(card, &card_ext_csd);
191+
if (ret) {
192+
return ret;
193+
}
194+
#else
180195
/* Set timing to fastest supported */
181196
ret = mmc_set_timing(card, &card_ext_csd);
182197
if (ret) {
183198
return ret;
184199
}
200+
#endif /*CONFIG_MMC_DDR50*/
185201

186202
/* Turn on cache if it exists */
187203
ret = mmc_set_cache(card, &card_ext_csd);
@@ -372,6 +388,12 @@ static int mmc_set_bus_width(struct sd_card *card)
372388
int ret;
373389
struct sdhc_command cmd = {0};
374390

391+
#if defined(MMC_CARD_8BIT_WIDTH)
392+
card->bus_width = 8;
393+
#elif defined(MMC_CARD_4BIT_WIDTH)
394+
card->bus_width = 4;
395+
#endif
396+
375397
if (card->host_props.host_caps.bus_8_bit_support && card->bus_width == 8) {
376398
cmd.arg = MMC_SWITCH_8_BIT_BUS_ARG;
377399
card->bus_io.bus_width = SDHC_BUS_WIDTH8BIT;
@@ -404,6 +426,57 @@ static int mmc_set_bus_width(struct sd_card *card)
404426
return ret;
405427
}
406428

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

561635
static int mmc_read_ext_csd(struct sd_card *card, struct mmc_ext_csd *card_ext_csd)
562636
{

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)