How to enable wifi through sdio interface on Jetson Nano

I am trying to integrate AP6255 WIFI module into board, and notice that the SDIO bus connects to SDMMC3 pins (reg:0x700b0400 and alias as sdhci2) from PCB layout. Then, I am trying to enable SDMMC3 by only changing its “status” to “okay” in tegra210-p3448-0002-p3449-0000-b00.dts, and adding or removing some attributes in this DTS
but wifi device can not be attached on sdio bus. Firstly, I want to find reason from the DTS configuration of SDMMC3, but there is a lot of attributes about it, I am not sure how to set it properly, So for my case, how to set correct DTS of SDMMC3 for wifi SDIO connection ? Is there any samples for such case ?

Hi rd1,

We don’t have wifi on sdio case on Nano but only verified on TX2.

You could firstly enable the status in dts with the reference of :

Could you supply the reference or sample about the wifi sdio configuration on TX2, such as the DTS snippet of sdmmc which SDIO interface connects to ? Thanks !

Hi rd1,

Sorry for late reply. Actually, you could refer to jetson TX1 SDIO configuration first.
Jetson TX1 also uses SDIO WIFI and it is same t210 series chip as Nano.

Thank you for your reply, but I can not tell which host is used as a SDIO host controller in TX1 ? Is it the same with Jetson Nano, using dhci@700b0400 or another ? May I take “tegra210-jetson-tx1-p2597-2180-a01-devkit.dts” as a TX1’s reference according to your opinion ?


I think you could firstly read the TX1 product design guide to know which sdmmc controller is responsible for wifi sdio.

Then, please learn how to tell which dtb is in use on your board. You could check your flash log or dmesg |grep dts on your board.

Hi, wayneWWW,
Right now It seems that I can successfully load WIFI module without firmware downloading, seeing from the below information:
cat /sys/kernel/debug/mmc1/ios
clock:150000000 Hz
actual clock : 150000000 Hz
vdd : 21 (3.3 ~ 3.4 v)
bus mode : 2 (push-pull)
chip select : 0 (don’t care)
power mode : 2 (on)
bus width : 2 (4 bits)
timing spec : 6 (sd uhs SDR104)
signal voltage : 0 (1.80 V)
driver type : 0 (driver type B)

But when I enable loading module with firmware and nvram, I find data writing is correct, but data reading cause data CRC error and kernel panic, the detail log shown as below:

[ 36.359374] dhdsdio_probe: venid 0x14e4 devid 0x0000
[ 36.426285] F1 signature OK, socitype:0x1 chip:0x4345 rev:0x6 pkg:0x2
[ 36.436590] dhdsdio_probe : check dhd_download_fw_on_driverload -> 1
[ 36.443235] dhd_bus_download_firmware : calling dhdsdio_download_firmware
[ 36.450292] dhdsdio_download_firmware : calling _dhdsdio_download_firmware
[ 36.457354] _dhdsdio_download_firmwware : calling dhdsdio_download_state
[ 36.464350] dhdsdio_download_state: enter is 1
[ 36.468983] dhdsdio_download_state: find ARM7S and ARMCM3 core !
[ 36.475135] dhdsdio_download_state: find ARMCR4 core !
[ 36.480380] dhdsdio_download_state: calling si_core_reset2 !
[ 36.487975] dhdsdio_download_state: si_setcore failed at exit!
[ 36.493959] dhdsdio_download_state: exit with err-0 !
[ 36.499081] _dhdsdio_download_firmwware : trying to download /lib/firmware/brcm/fw_bcm43455c0_ag.bin
[ 36.508398] dhdsdio_download_code_file : fw_path is /lib/firmware/brcm/fw_bcm43455c0_ag.bin
[ 36.592402] dhdsido_download_code_file : memory free
[ 36.597546] dhdsido_download_code_file : calling dhd_os_close_image
[ 36.604039] dhdsido_download_code_file : exit with err-0
[ 36.609468] _dhdsdio_download_firmwware : trying to download /lib/firmware/brcm/nvram_ap6255.txt
[ 36.618448] dhdsdio_download_nvram : calling dhd_os_get_image_block
[ 36.626072] dhdsdio_download_nvram : calling dhdsdio_downloadvars
[ 36.632229] dhdsdio_download_nvram : memory free
[ 36.636863] dhdsdio_download_nvram : calling dhd_os_close_image
[ 36.642982] dhdsdio_download_nvram : exit with err-0
[ 36.647958] _dhdsdio_download_firmwware : calling dhdsdio_download_state
[ 36.654731] dhdsdio_download_state: enter is 0
[ 36.659248] dhdsdio_download_state: calling si_setcore -> set ARMCR4 !
[ 36.665783] dhdsdio_download_state: calling dhdsdio_write_vars !
[ 36.671876] dhdsdio_write_vars : calling dhdsdio_membytes1 (address:0x00277970 size:1676)
[ 36.681693] dhdsdio_write_vars : calling dhdsdio_membytes1 status (0)
[ 36.688351] Compare NVRAM dl & ul; varsize=1676
[ 36.692981] dhdsdio_write_vars : calling dhdsdio_membytes2 (address:0x00277970 size:1676)
[ 36.701564] mmc1: Data CRC error
[ 36.704786] sdhci: =========== REGISTER DUMP (mmc1)===========
[ 36.710607] sdhci: Sys addr: 0x00000000 | Version: 0x00000303
[ 36.716427] sdhci: Blk size: 0x00007040 | Blk cnt: 0x00000019
[ 36.722247] sdhci: Argument: 0x1df2e01a | Trn mode: 0x00000033
[ 36.728066] sdhci: Present: 0x01fb0008 | Host ctl: 0x00000017
[ 36.733886] sdhci: Power: 0x00000001 | Blk gap: 0x00000000
[ 36.739705] sdhci: Wake-up: 0x00000000 | Clock: 0x00000007
[ 36.745525] sdhci: Timeout: 0x0000000e | Int stat: 0x00001000
[ 36.751345] sdhci: Int enab: 0x02ff100b | Sig enab: 0x02fc100b
[ 36.757165] sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
[ 36.762983] sdhci: Caps: 0x376cd08c | Caps_1: 0x10006f73
[ 36.768803] sdhci: Cmd: 0x0000353a | Max curr: 0x00000000
[ 36.774621] sdhci: Host ctl2: 0x0000308b
[ 36.778536] sdhci: ADMA Err: 0x00000000 | ADMA Ptr: 0x00000000ffefe410
[ 36.785126] sdhci: ===========================================

I am not sure it is a HW issue or SW issue, could you please help me out with this problem I encountered, thanks !

Please also share your schematic.

Hi WayneWWW,
Limited by the file format, the related schematic:


Do you have a sdmmc_vdd_en connection there?


There is no sdmmc_vdd_en connetion, all the power of WiFi module is contorlled by sys_rst*.

Hi, WayneWWW,
About Nvidia Jetson Nano, Could you give a suggestion what type of WIFI+BT module is most suitable to this platform, no matter what kind of the interfaces (SDIO, PCIe or USB) it uses ? And it could not be better if the solution has been examined before by Nvidia.

Hi ljs220,

Please put this patch to your driver to enable more log.

diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index c7a6f85..3add7dc 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -403,7 +403,7 @@
 	u32 trim_delay;
 	u8 i;
-	pr_debug("======= %s: Tuning windows =======\n",
+	pr_err("======= %s: Tuning windows =======\n",
 	reg = sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0);
 	for (i = 0; i <= TUNING_WORD_SEL_MASK; i++) {
@@ -411,7 +411,7 @@
 		reg |= i;
 		sdhci_writel(host, reg, SDHCI_VNDR_TUN_CTRL0_0);
 		tuning_status = sdhci_readl(host, SDHCI_TEGRA_VNDR_TUNING_STATUS0);
-		pr_debug("%s: tuning window[%d]: %#x\n",
+		pr_err("%s: tuning window[%d]: %#x\n",
 			mmc_hostname(host->mmc), i, tuning_status);
 	reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
@@ -419,35 +419,35 @@
 	trim_delay = reg >> SDHCI_CLOCK_CTRL_TRIM_SHIFT;
-	pr_debug("sdhci: Tap value: %u | Trim value: %u\n", tap_delay,
+	pr_err("sdhci: Tap value: %u | Trim value: %u\n", tap_delay,
-	pr_debug("==================================\n");
+	pr_err("==================================\n");
-	pr_debug("Vendor clock ctrl: %#x\n",
+	pr_err("Vendor clock ctrl: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL));
-	pr_debug("Vendor SysSW ctrl: %#x\n",
+	pr_err("Vendor SysSW ctrl: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL));
-	pr_debug("Vendor Err interrupt status : %#x\n",
+	pr_err("Vendor Err interrupt status : %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_ERR_INTR_STATUS));
-	pr_debug("Vendor Cap overrides: %#x\n",
+	pr_err("Vendor Cap overrides: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_CAP_OVERRIDES));
-	pr_debug("Vendor Misc ctrl: %#x\n",
+	pr_err("Vendor Misc ctrl: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL));
-	pr_debug("Vendor Misc ctrl_1: %#x\n",
+	pr_err("Vendor Misc ctrl_1: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL_1));
-	pr_debug("Vendor Misc ctrl_2: %#x\n",
+	pr_err("Vendor Misc ctrl_2: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL_2));
-	pr_debug("Vendor IO trim ctrl: %#x\n",
+	pr_err("Vendor IO trim ctrl: %#x\n",
 		sdhci_readl(host, SDMMC_VNDR_IO_TRIM_CTRL_0));
-	pr_debug("Vendor Tuning ctrl: %#x\n",
+	pr_err("Vendor Tuning ctrl: %#x\n",
 		sdhci_readl(host, SDHCI_VNDR_TUN_CTRL0_0));
-	pr_debug("SDMEM comp padctrl: %#x\n",
+	pr_err("SDMEM comp padctrl: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_SDMEM_COMP_PADCTRL));
-	pr_debug("Autocal config: %#x\n",
+	pr_err("Autocal config: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_CONFIG));
-	pr_debug("Autocal status: %#x\n",
+	pr_err("Autocal status: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_AUTO_CAL_STATUS));
-	pr_debug("Tuning Status1: %#x\n",
+	pr_err("Tuning Status1: %#x\n",
 		sdhci_readl(host, SDHCI_TEGRA_VNDR_TUNING_STATUS1));
@@ -743,7 +743,7 @@
 	   (end_tap == (num_tun_iter - 1)) ||
 	   (window_width >= upperthreshold)) {
-		pr_info("%s: Applying tuning correction\n",
+		pr_err("%s: Applying tuning correction\n",
 		tegra_sdhci_apply_tuning_correction(host, num_tun_iter,
 				upperthreshold, lowerthreshold, fixed_tap);
@@ -1450,13 +1450,14 @@
 		sdhci_writel(host, reg, SDHCI_VNDR_TUN_CTRL0_0);
-	if ((soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP) &&
-		card_clk_enabled) {
+	if (soc_data->nvquirks & NVQUIRK_DIS_CARD_CLK_CONFIG_TAP) {
 		sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
-		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
-		sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+		if (card_clk_enabled) {
+			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+			sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+		}

Also, we want the full dmesg instead of partial one. Thus, please attach it.

Hi WayneWWW,

Thanks for the patch! It seems that the patch is incomplete. Please help to confirm.

Updated. Please check the comment again.

Hi, WayneWWW,
I applied above patch and attached the full kernel message from bootup to module bcmdhd inserting. Please check the log for details, thanks !
kern.log (465.6 KB)

Hi rd1,

Do you still see the CRC error and register dump in latest status?

Hi, WayneWWW,
the data crc error and kernel panic issue are both fixed now, because I rectify the dongle base ram the in dhd_sdio.c accroding to my WIFI module :
#if 0
bus->dongle_ram_base = CR4_4345_RAM_BASE;
bus->dongle_ram_base = (bus->sih->chiprev < 6) ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE; /* for 43455C0 */
but the module is still failed in its loading progress due to timer expiration (calling dhdcdc_query_ioctl failed with command 98 and err -110). The log was just attached in last session.

HI rd1,

Sorry for late reply.

Could you share the detail about the chip you are using?
“failed with command 98” means there is a failure to get the revision. The vendor tells us it is probably firmware issue.

There is no update from you for a period, assuming this is not an issue any more.
Hence we are closing this topic. If need further support, please open a new one.

Hi @rd1,

Please kindly reply or we will close this. It may take longer time if you want to check this again once we close.