blob: 6b9767c2c3e7294a8d6ce35e671d7835feed7a5f [file] [log] [blame]
// Copyright 2018 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 <limits.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/metadata.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform/bus.h>
#include <ddktl/mmio.h>
#include <fbl/algorithm.h>
#include <hwreg/bitfields.h>
#include <soc/mt8167/mt8167-hw.h>
#include <soc/mt8167/mt8167-sdmmc.h>
#include "mt8167.h"
namespace {
constexpr uint16_t kPullUp = 0;
constexpr uint16_t kPullDown = 1;
constexpr uint16_t kPull10k = 1;
constexpr uint16_t kPull50k = 2;
constexpr uintptr_t kGpioBaseAligned = fbl::round_down<uintptr_t, uintptr_t>(MT8167_MSDC2_GPIO_BASE,
PAGE_SIZE);
constexpr size_t kGpioOffset = MT8167_MSDC2_GPIO_BASE - kGpioBaseAligned;
constexpr size_t kGpioSizeAligned = fbl::round_up<size_t, size_t>(
kGpioOffset + MT8167_MSDC2_GPIO_SIZE, PAGE_SIZE);
constexpr uint32_t kFifoDepth = 128;
constexpr uint32_t kSrcClkFreq = 188000000;
} // namespace
namespace board_mt8167 {
class PuPdCtrl4 : public hwreg::RegisterBase<PuPdCtrl4, uint16_t> {
public:
static auto Get() { return hwreg::RegisterAddr<PuPdCtrl4>(kGpioOffset); }
DEF_BIT(14, msdc2_dat2_pupd);
DEF_FIELD(13, 12, msdc2_dat2_pull);
DEF_BIT(10, msdc2_dat1_pupd);
DEF_FIELD(9, 8, msdc2_dat1_pull);
DEF_BIT(6, msdc2_dat0_pupd);
DEF_FIELD(5, 4, msdc2_dat0_pull);
};
class PuPdCtrl5 : public hwreg::RegisterBase<PuPdCtrl5, uint16_t> {
public:
static auto Get() { return hwreg::RegisterAddr<PuPdCtrl5>(kGpioOffset + 0x10); }
DEF_BIT(10, msdc2_cmd_pupd);
DEF_FIELD(9, 8, msdc2_cmd_pull);
DEF_BIT(6, msdc2_clk_pupd);
DEF_FIELD(5, 4, msdc2_clk_pull);
DEF_BIT(2, msdc2_dat3_pupd);
DEF_FIELD(1, 0, msdc2_dat3_pull);
};
zx_status_t Mt8167::SdioInit() {
static const pbus_mmio_t sdio_mmios[] = {
{
.base = MT8167_MSDC2_BASE,
.length = MT8167_MSDC2_SIZE,
},
};
static const pbus_bti_t sdio_btis[] = {
{
.iommu_index = 0,
.bti_id = BTI_SDIO,
}
};
static const MtkSdmmcConfig sdio_config = {
.fifo_depth = kFifoDepth,
.src_clk_freq = kSrcClkFreq
};
static const pbus_metadata_t sdio_metadata[] = {
{
.type = DEVICE_METADATA_PRIVATE,
.data_buffer = &sdio_config,
.data_size = sizeof(sdio_config)
}
};
static const pbus_irq_t sdio_irqs[] = {
{
.irq = MT8167_IRQ_MSDC2,
.mode = ZX_INTERRUPT_MODE_EDGE_HIGH
}
};
static const pbus_gpio_t sdio_ref_gpios[] = {
{
.gpio = MT8167_GPIO_MT7668_PMU_EN
}
};
static const pbus_gpio_t sdio_cleo_gpios[] = {
{
.gpio = MT8167_GPIO_MT7668_PMU_EN
},
{
.gpio = MT8167_CLEO_GPIO_HUB_PWR_EN
}
};
const pbus_gpio_t* sdio_gpios = sdio_ref_gpios;
size_t sdio_gpio_count = countof(sdio_ref_gpios);
if (board_info_.pid == PDEV_PID_CLEO) {
sdio_gpios = sdio_cleo_gpios;
sdio_gpio_count = countof(sdio_cleo_gpios);
}
pbus_dev_t sdio_dev = {};
sdio_dev.name = "sdio";
sdio_dev.vid = PDEV_VID_MEDIATEK;
sdio_dev.did = PDEV_DID_MEDIATEK_SDIO;
sdio_dev.mmio_list = sdio_mmios;
sdio_dev.mmio_count = countof(sdio_mmios);
sdio_dev.bti_list = sdio_btis;
sdio_dev.bti_count = countof(sdio_btis);
sdio_dev.metadata_list = sdio_metadata;
sdio_dev.metadata_count = countof(sdio_metadata);
sdio_dev.irq_list = sdio_irqs;
sdio_dev.irq_count = countof(sdio_irqs);
sdio_dev.gpio_list = sdio_gpios;
sdio_dev.gpio_count = sdio_gpio_count;
zx::unowned_resource root_resource(get_root_resource());
std::optional<ddk::MmioBuffer> gpio_mmio;
zx_status_t status = ddk::MmioBuffer::Create(kGpioBaseAligned, kGpioSizeAligned, *root_resource,
ZX_CACHE_POLICY_UNCACHED_DEVICE, &gpio_mmio);
if (status != ZX_OK) {
zxlogf(ERROR, "%s: Failed to set MSDC2 GPIOs: %d\n", __FUNCTION__, status);
return status;
}
// MSDC2 pins are not configured by the bootloader. Set the clk pin to 50k pull-down, all others
// to 10k pull-up to match the device tree settings.
PuPdCtrl4::Get()
.ReadFrom(&(*gpio_mmio))
.set_msdc2_dat2_pupd(kPullUp)
.set_msdc2_dat2_pull(kPull10k)
.set_msdc2_dat1_pupd(kPullUp)
.set_msdc2_dat1_pull(kPull10k)
.set_msdc2_dat0_pupd(kPullUp)
.set_msdc2_dat0_pull(kPull10k)
.WriteTo(&(*gpio_mmio));
PuPdCtrl5::Get()
.ReadFrom(&(*gpio_mmio))
.set_msdc2_cmd_pupd(kPullUp)
.set_msdc2_cmd_pull(kPull10k)
.set_msdc2_clk_pupd(kPullDown)
.set_msdc2_clk_pull(kPull50k)
.set_msdc2_dat3_pupd(kPullUp)
.set_msdc2_dat3_pull(kPull10k)
.WriteTo(&(*gpio_mmio));
if ((status = pbus_.DeviceAdd(&sdio_dev)) != ZX_OK) {
zxlogf(ERROR, "%s: DeviceAdd MSDC2 failed: %d\n", __FUNCTION__, status);
}
return status;
}
} // namespace board_mt8167