summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/xenon_sdhci.c79
-rw-r--r--drivers/pci/Kconfig1
-rw-r--r--drivers/pci/pci-aardvark.c29
3 files changed, 98 insertions, 11 deletions
diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c
index 356dd9846d6..7f9a579c838 100644
--- a/drivers/mmc/xenon_sdhci.c
+++ b/drivers/mmc/xenon_sdhci.c
@@ -22,6 +22,7 @@
#include <linux/libfdt.h>
#include <malloc.h>
#include <sdhci.h>
+#include <power/regulator.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -42,6 +43,14 @@ DECLARE_GLOBAL_DATA_PTR;
#define SDHC_SYS_EXT_OP_CTRL 0x010C
#define MASK_CMD_CONFLICT_ERROR BIT(8)
+#define SDHC_SLOT_EMMC_CTRL 0x0130
+#define ENABLE_DATA_STROBE_SHIFT 24
+#define SET_EMMC_RSTN_SHIFT 16
+#define EMMC_VCCQ_MASK 0x3
+#define EMMC_VCCQ_1_8V 0x1
+#define EMMC_VCCQ_1_2V 0x2
+#define EMMC_VCCQ_3_3V 0x3
+
#define SDHC_SLOT_RETUNING_REQ_CTRL 0x0144
/* retuning compatible */
#define RETUNING_COMPATIBLE 0x1
@@ -108,6 +117,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define MMC_TIMING_MMC_HS400 10
#define XENON_MMC_MAX_CLK 400000000
+#define XENON_MMC_3V3_UV 3300000
+#define XENON_MMC_1V8_UV 1800000
enum soc_pad_ctrl_type {
SOC_PAD_SD,
@@ -128,6 +139,8 @@ struct xenon_sdhci_priv {
void *pad_ctrl_reg;
int pad_type;
+
+ struct udevice *vqmmc;
};
static int xenon_mmc_phy_init(struct sdhci_host *host)
@@ -208,6 +221,51 @@ static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host)
writel(ARMADA_3700_SOC_PAD_3_3V, priv->pad_ctrl_reg);
}
+static int xenon_mmc_start_signal_voltage_switch(struct sdhci_host *host)
+{
+ struct xenon_sdhci_priv *priv = host->mmc->priv;
+ u8 voltage;
+ u32 ctrl;
+ int ret = 0;
+
+ /* If there is no vqmmc regulator, return */
+ if (!priv->vqmmc)
+ return 0;
+
+ if (priv->pad_type == SOC_PAD_FIXED_1_8V) {
+ /* Switch to 1.8v */
+ ret = regulator_set_value(priv->vqmmc,
+ XENON_MMC_1V8_UV);
+ } else if (priv->pad_type == SOC_PAD_SD) {
+ /* Get voltage info */
+ voltage = sdhci_readb(host, SDHCI_POWER_CONTROL);
+ voltage &= ~SDHCI_POWER_ON;
+
+ if (voltage == SDHCI_POWER_330) {
+ /* Switch to 3.3v */
+ ret = regulator_set_value(priv->vqmmc,
+ XENON_MMC_3V3_UV);
+ } else {
+ /* Switch to 1.8v */
+ ret = regulator_set_value(priv->vqmmc,
+ XENON_MMC_1V8_UV);
+ }
+ }
+
+ /* Set VCCQ, eMMC mode: 1.8V; SD/SDIO mode: 3.3V */
+ ctrl = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL);
+ if (IS_SD(host->mmc))
+ ctrl |= EMMC_VCCQ_3_3V;
+ else
+ ctrl |= EMMC_VCCQ_1_8V;
+ sdhci_writel(host, ctrl, SDHC_SLOT_EMMC_CTRL);
+
+ if (ret)
+ printf("Signal voltage switch fail\n");
+
+ return ret;
+}
+
static void xenon_mmc_phy_set(struct sdhci_host *host)
{
struct xenon_sdhci_priv *priv = host->mmc->priv;
@@ -334,6 +392,13 @@ static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
uint speed = host->mmc->tran_speed;
int pwr_18v = 0;
+ /*
+ * Signal Voltage Switching is only applicable for Host Controllers
+ * v3.00 and above.
+ */
+ if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
+ xenon_mmc_start_signal_voltage_switch(host);
+
if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) ==
SDHCI_POWER_180)
pwr_18v = 1;
@@ -394,6 +459,18 @@ static int xenon_sdhci_probe(struct udevice *dev)
/* Set default timing */
priv->timing = MMC_TIMING_LEGACY;
+ /* Get the vqmmc regulator if there is */
+ device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc);
+ /* Set the initial voltage value to 3.3V if there is regulator */
+ if (priv->vqmmc) {
+ ret = regulator_set_value(priv->vqmmc,
+ XENON_MMC_3V3_UV);
+ if (ret) {
+ printf("Failed to set VQMMC regulator to 3.3V\n");
+ return ret;
+ }
+ }
+
/* Disable auto clock gating during init */
xenon_mmc_set_acg(host, false);
@@ -426,7 +503,7 @@ static int xenon_sdhci_probe(struct udevice *dev)
host->ops = &xenon_sdhci_ops;
host->max_clk = XENON_MMC_MAX_CLK;
- ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
+ ret = sdhci_setup_cfg(&plat->cfg, host, XENON_MMC_MAX_CLK, 0);
if (ret)
return ret;
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index c19d09bc417..dd1cc652290 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -30,6 +30,7 @@ config PCI_AARDVARK
bool "Enable Aardvark PCIe driver"
default n
depends on DM_PCI
+ depends on DM_GPIO
depends on ARMADA_3700
help
Say Y here if you want to enable PCIe controller support on
diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c
index 711b930d0f9..b2c417701f2 100644
--- a/drivers/pci/pci-aardvark.c
+++ b/drivers/pci/pci-aardvark.c
@@ -148,6 +148,7 @@ struct pcie_advk {
void *base;
int first_busno;
struct udevice *dev;
+ struct gpio_desc reset_gpio;
};
static inline void advk_writel(struct pcie_advk *pcie, uint val, uint reg)
@@ -613,10 +614,7 @@ static int pcie_advk_probe(struct udevice *dev)
{
struct pcie_advk *pcie = dev_get_priv(dev);
-#if CONFIG_IS_ENABLED(DM_GPIO)
- struct gpio_desc reset_gpio;
-
- gpio_request_by_name(dev, "reset-gpio", 0, &reset_gpio,
+ gpio_request_by_name(dev, "reset-gpios", 0, &pcie->reset_gpio,
GPIOD_IS_OUT);
/*
* Issue reset to add-in card through the dedicated GPIO.
@@ -631,15 +629,14 @@ static int pcie_advk_probe(struct udevice *dev)
* possible before PCIe PHY initialization. Moreover, the PCIe
* clock should be gated as well.
*/
- if (dm_gpio_is_valid(&reset_gpio)) {
+ if (dm_gpio_is_valid(&pcie->reset_gpio)) {
dev_dbg(pcie->dev, "Toggle PCIE Reset GPIO ...\n");
- dm_gpio_set_value(&reset_gpio, 0);
+ dm_gpio_set_value(&pcie->reset_gpio, 1);
mdelay(200);
- dm_gpio_set_value(&reset_gpio, 1);
+ dm_gpio_set_value(&pcie->reset_gpio, 0);
+ } else {
+ dev_warn(pcie->dev, "PCIE Reset on GPIO support is missing\n");
}
-#else
- dev_dbg(pcie->dev, "PCIE Reset on GPIO support is missing\n");
-#endif /* DM_GPIO */
pcie->first_busno = dev->seq;
pcie->dev = pci_get_controller(dev);
@@ -647,6 +644,16 @@ static int pcie_advk_probe(struct udevice *dev)
return pcie_advk_setup_hw(pcie);
}
+static int pcie_advk_remove(struct udevice *dev)
+{
+ struct pcie_advk *pcie = dev_get_priv(dev);
+
+ if (dm_gpio_is_valid(&pcie->reset_gpio))
+ dm_gpio_set_value(&pcie->reset_gpio, 1);
+
+ return 0;
+}
+
/**
* pcie_advk_ofdata_to_platdata() - Translate from DT to device state
*
@@ -687,5 +694,7 @@ U_BOOT_DRIVER(pcie_advk) = {
.ops = &pcie_advk_ops,
.ofdata_to_platdata = pcie_advk_ofdata_to_platdata,
.probe = pcie_advk_probe,
+ .remove = pcie_advk_remove,
+ .flags = DM_FLAG_OS_PREPARE,
.priv_auto_alloc_size = sizeof(struct pcie_advk),
};