[vim3][sd] Enable SD slot on vim3
Bug: None
Test: lsblk shows SD and eMMC block devices
Test: device-enumeration-test
Change-Id: Ib3f71b6cbd3306cb4fac3f677c9ca05c8af8ab89
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/402495
Testability-Review: Braden Kell <bradenkell@google.com>
Commit-Queue: Braden Kell <bradenkell@google.com>
Reviewed-by: Marty Faltesek <mfaltesek@google.com>
Reviewed-by: Carl Norum <cjn@google.com>
diff --git a/src/devices/board/drivers/vim3/BUILD.gn b/src/devices/board/drivers/vim3/BUILD.gn
index c798d54..4929d94 100644
--- a/src/devices/board/drivers/vim3/BUILD.gn
+++ b/src/devices/board/drivers/vim3/BUILD.gn
@@ -18,6 +18,7 @@
"vim3-eth.cc",
"vim3-gpio.cc",
"vim3-i2c.cc",
+ "vim3-sd.cc",
"vim3-sysmem.cc",
"vim3.cc",
]
diff --git a/src/devices/board/drivers/vim3/vim3-sd.cc b/src/devices/board/drivers/vim3/vim3-sd.cc
new file mode 100644
index 0000000..37b2353
--- /dev/null
+++ b/src/devices/board/drivers/vim3/vim3-sd.cc
@@ -0,0 +1,87 @@
+// Copyright 2020 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <ddk/binding.h>
+#include <ddk/debug.h>
+#include <ddk/metadata.h>
+#include <ddk/platform-defs.h>
+#include <ddk/protocol/sdmmc.h>
+#include <soc/aml-a311d/a311d-gpio.h>
+#include <soc/aml-a311d/a311d-hw.h>
+#include <soc/aml-common/aml-sd-emmc.h>
+
+#include "vim3.h"
+
+namespace vim3 {
+
+static const pbus_mmio_t sd_mmios[] = {
+ {
+ .base = A311D_EMMC_B_BASE,
+ .length = A311D_EMMC_B_LENGTH,
+ },
+};
+
+static const pbus_irq_t sd_irqs[] = {
+ {
+ .irq = A311D_SD_EMMC_B_IRQ,
+ .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
+ },
+};
+
+static const pbus_bti_t sd_btis[] = {
+ {
+ .iommu_index = 0,
+ .bti_id = BTI_SD,
+ },
+};
+
+static aml_sd_emmc_config_t config = {
+ .supports_dma = true,
+ .min_freq = 400'000,
+ .max_freq = 50'000'000,
+ .version_3 = true,
+ .prefs = 0,
+};
+
+static const pbus_metadata_t sd_metadata[] = {
+ {
+ .type = DEVICE_METADATA_EMMC_CONFIG,
+ .data_buffer = &config,
+ .data_size = sizeof(config),
+ },
+};
+
+zx_status_t Vim3::SdInit() {
+ zx_status_t status;
+
+ pbus_dev_t sd_dev = {};
+ sd_dev.name = "aml_sd";
+ sd_dev.vid = PDEV_VID_AMLOGIC;
+ sd_dev.pid = PDEV_PID_GENERIC;
+ sd_dev.did = PDEV_DID_AMLOGIC_SD_EMMC_B;
+ sd_dev.mmio_list = sd_mmios;
+ sd_dev.mmio_count = countof(sd_mmios);
+ sd_dev.irq_list = sd_irqs;
+ sd_dev.irq_count = countof(sd_irqs);
+ sd_dev.bti_list = sd_btis;
+ sd_dev.bti_count = countof(sd_btis);
+ sd_dev.metadata_list = sd_metadata;
+ sd_dev.metadata_count = countof(sd_metadata);
+
+ gpio_impl_.SetAltFunction(A311D_GPIOC(0), A311D_GPIOC_0_SDCARD_D0_FN);
+ gpio_impl_.SetAltFunction(A311D_GPIOC(1), A311D_GPIOC_1_SDCARD_D1_FN);
+ gpio_impl_.SetAltFunction(A311D_GPIOC(2), A311D_GPIOC_2_SDCARD_D2_FN);
+ gpio_impl_.SetAltFunction(A311D_GPIOC(3), A311D_GPIOC_3_SDCARD_D3_FN);
+ gpio_impl_.SetAltFunction(A311D_GPIOC(4), A311D_GPIOC_4_SDCARD_CLK_FN);
+ gpio_impl_.SetAltFunction(A311D_GPIOC(5), A311D_GPIOC_5_SDCARD_CMD_FN);
+
+ if ((status = pbus_.CompositeDeviceAdd(&sd_dev, nullptr, 0, UINT32_MAX)) != ZX_OK) {
+ zxlogf(ERROR, "SdInit could not add sd_dev: %d", status);
+ return status;
+ }
+
+ return ZX_OK;
+}
+
+} // namespace vim3
diff --git a/src/devices/board/drivers/vim3/vim3.cc b/src/devices/board/drivers/vim3/vim3.cc
index 3e48daf..0d5c05b 100644
--- a/src/devices/board/drivers/vim3/vim3.cc
+++ b/src/devices/board/drivers/vim3/vim3.cc
@@ -89,6 +89,11 @@
init_txn_->Reply(ZX_ERR_INTERNAL);
return status;
}
+ if ((status = SdInit()) != ZX_OK) {
+ zxlogf(ERROR, "SdInit() failed: %d\n", status);
+ init_txn_->Reply(ZX_ERR_INTERNAL);
+ return status;
+ }
init_txn_->Reply(status);
return ZX_OK;
}
diff --git a/src/devices/board/drivers/vim3/vim3.h b/src/devices/board/drivers/vim3/vim3.h
index 04652eb..74b5aca 100644
--- a/src/devices/board/drivers/vim3/vim3.h
+++ b/src/devices/board/drivers/vim3/vim3.h
@@ -24,6 +24,7 @@
enum {
BTI_EMMC,
BTI_ETHERNET,
+ BTI_SD,
BTI_SYSMEM,
};
@@ -50,6 +51,7 @@
zx_status_t EthInit();
zx_status_t GpioInit();
zx_status_t I2cInit();
+ zx_status_t SdInit();
zx_status_t Start();
zx_status_t SysmemInit();
diff --git a/src/devices/lib/amlogic/include/soc/aml-a311d/a311d-gpio.h b/src/devices/lib/amlogic/include/soc/aml-a311d/a311d-gpio.h
index 635cadf..0e50a65 100644
--- a/src/devices/lib/amlogic/include/soc/aml-a311d/a311d-gpio.h
+++ b/src/devices/lib/amlogic/include/soc/aml-a311d/a311d-gpio.h
@@ -67,6 +67,14 @@
#define A311D_GPIOA_14_I2C_EE_M3_SDA_FN 2
#define A311D_GPIOA_15_I2C_EE_M3_SCL_FN 2
+// GPIOC pin alternate functions
+#define A311D_GPIOC_0_SDCARD_D0_FN 1
+#define A311D_GPIOC_1_SDCARD_D1_FN 1
+#define A311D_GPIOC_2_SDCARD_D2_FN 1
+#define A311D_GPIOC_3_SDCARD_D3_FN 1
+#define A311D_GPIOC_4_SDCARD_CLK_FN 1
+#define A311D_GPIOC_5_SDCARD_CMD_FN 1
+
// GPIOZ pin alternate functions
#define A311D_GPIOZ_0_ETH_MDIO_FN 1
#define A311D_GPIOZ_1_ETH_MDC_FN 1
diff --git a/zircon/system/utest/device-enumeration/main.cc b/zircon/system/utest/device-enumeration/main.cc
index 9bdd156..307a0c1 100644
--- a/zircon/system/utest/device-enumeration/main.cc
+++ b/zircon/system/utest/device-enumeration/main.cc
@@ -203,6 +203,7 @@
"sys/platform/05:00:2/aml-i2c/i2c/i2c-0-81/rtc",
"dwmac/eth_phy/phy_null_device",
"dwmac/Designware MAC/ethernet",
+ "aml_sd/aml-sd-emmc",
};
ASSERT_NO_FATAL_FAILURES(TestRunner(kDevicePaths, std::size(kDevicePaths)));