Page MenuHomeFreeBSD

D34029.diff
No OneTemporary

D34029.diff

diff --git a/sys/dev/sdhci/sdhci_fsl_fdt.c b/sys/dev/sdhci/sdhci_fsl_fdt.c
--- a/sys/dev/sdhci/sdhci_fsl_fdt.c
+++ b/sys/dev/sdhci/sdhci_fsl_fdt.c
@@ -43,6 +43,7 @@
#include <machine/resource.h>
#include <dev/extres/clk/clk.h>
+#include <dev/extres/syscon/syscon.h>
#include <dev/mmc/bridge.h>
#include <dev/mmc/mmcbrvar.h>
#include <dev/mmc/mmc_fdt_helpers.h>
@@ -53,6 +54,7 @@
#include "mmcbr_if.h"
#include "sdhci_if.h"
+#include "syscon_if.h"
#define RD4 (sc->read)
#define WR4 (sc->write)
@@ -142,6 +144,13 @@
#define SDHCI_FSL_ESDHC_CTRL_FAF (1 << 18)
#define SDHCI_FSL_ESDHC_CTRL_CLK_DIV2 (1 << 19)
+#define SCFG_SDHCIOVSELCR 0x408
+#define SCFG_SDHCIOVSELCR_TGLEN (1 << 0)
+#define SCFG_SDHCIOVSELCR_VS (1 << 31)
+#define SCFG_SDHCIOVSELCR_VSELVAL_MASK (3 << 1)
+#define SCFG_SDHCIOVSELCR_VSELVAL_1_8 0x0
+#define SCFG_SDHCIOVSELCR_VSELVAL_3_3 0x2
+
#define SDHCI_FSL_CAN_VDD_MASK \
(SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_300 | SDHCI_CAN_VDD_330)
@@ -162,6 +171,12 @@
*/
#define SDHCI_FSL_HS400_LIMITED_CLK_DIV (1 << 4)
+/*
+ * Some SoCs don't have a fixed regulator. Switching voltage
+ * requires special routine including syscon registers.
+ */
+#define SDHCI_FSL_MISSING_VCCQ_REG (1 << 5)
+
/*
* HS400 tuning is done in HS200 mode, but it has to be done using
* the target frequency. In order to apply the errata above we need to
@@ -197,12 +212,14 @@
int quirks;
int baseclk_div;
uint8_t errata;
+ char *syscon_compat;
};
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1012a_soc_data = {
.quirks = 0,
.baseclk_div = 1,
- .errata = SDHCI_FSL_UNSUPP_1_8V,
+ .errata = SDHCI_FSL_MISSING_VCCQ_REG | SDHCI_FSL_TUNING_ERRATUM_TYPE2,
+ .syscon_compat = "fsl,ls1012a-scfg",
};
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1028a_soc_data = {
@@ -216,7 +233,8 @@
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_ls1046a_soc_data = {
.quirks = SDHCI_QUIRK_DONT_SET_HISPD_BIT | SDHCI_QUIRK_BROKEN_AUTO_STOP,
.baseclk_div = 2,
- .errata = SDHCI_FSL_UNSUPP_1_8V | SDHCI_FSL_TUNING_ERRATUM_TYPE2,
+ .errata = SDHCI_FSL_MISSING_VCCQ_REG | SDHCI_FSL_TUNING_ERRATUM_TYPE2,
+ .syscon_compat = "fsl,ls1046a-scfg",
};
static const struct sdhci_fsl_fdt_soc_data sdhci_fsl_fdt_lx2160a_soc_data = {
@@ -621,6 +639,60 @@
return (0);
}
+static int
+sdhci_fsl_fdt_switch_syscon_voltage(device_t dev,
+ struct sdhci_fsl_fdt_softc *sc, enum mmc_vccq vccq)
+{
+ struct syscon *syscon;
+ phandle_t syscon_node;
+ uint32_t reg;
+
+ if (sc->soc_data->syscon_compat == NULL) {
+ device_printf(dev, "Empty syscon compat string.\n");
+ return (ENXIO);
+ }
+
+ syscon_node = ofw_bus_find_compatible(OF_finddevice("/"),
+ sc->soc_data->syscon_compat);
+
+ if (syscon_get_by_ofw_node(dev, syscon_node, &syscon) != 0) {
+ device_printf(dev, "Could not find syscon node.\n");
+ return (ENXIO);
+ }
+
+ reg = SYSCON_READ_4(syscon, SCFG_SDHCIOVSELCR);
+ reg &= ~SCFG_SDHCIOVSELCR_VSELVAL_MASK;
+ reg |= SCFG_SDHCIOVSELCR_TGLEN;
+
+ switch (vccq) {
+ case vccq_180:
+ reg |= SCFG_SDHCIOVSELCR_VSELVAL_1_8;
+ SYSCON_WRITE_4(syscon, SCFG_SDHCIOVSELCR, reg);
+
+ DELAY(5000);
+
+ reg = SYSCON_READ_4(syscon, SCFG_SDHCIOVSELCR);
+ reg |= SCFG_SDHCIOVSELCR_VS;
+ break;
+ case vccq_330:
+ reg |= SCFG_SDHCIOVSELCR_VSELVAL_3_3;
+ SYSCON_WRITE_4(syscon, SCFG_SDHCIOVSELCR, reg);
+
+ DELAY(5000);
+
+ reg = SYSCON_READ_4(syscon, SCFG_SDHCIOVSELCR);
+ reg &= ~SCFG_SDHCIOVSELCR_VS;
+ break;
+ default:
+ device_printf(dev, "Unsupported voltage requested.\n");
+ return (ENXIO);
+ }
+
+ SYSCON_WRITE_4(syscon, SCFG_SDHCIOVSELCR, reg);
+
+ return (0);
+}
+
static int
sdhci_fsl_fdt_switch_vccq(device_t brdev, device_t reqdev)
{
@@ -628,7 +700,7 @@
struct sdhci_slot *slot;
regulator_t vqmmc_supply;
uint32_t val_old, val;
- int uvolt, err;
+ int uvolt, err = 0;
sc = device_get_softc(brdev);
slot = device_get_ivars(reqdev);
@@ -653,6 +725,13 @@
WR4(sc, SDHCI_FSL_PROT_CTRL, val);
+ if (sc->soc_data->errata & SDHCI_FSL_MISSING_VCCQ_REG) {
+ err = sdhci_fsl_fdt_switch_syscon_voltage(brdev, sc,
+ slot->host.ios.vccq);
+ if (err != 0)
+ goto vccq_fail;
+ }
+
vqmmc_supply = sc->fdt_helper.vqmmc_supply;
/*
* Even though we expect to find a fixed regulator in this controller
@@ -660,15 +739,17 @@
*/
if (vqmmc_supply != NULL) {
err = regulator_set_voltage(vqmmc_supply, uvolt, uvolt);
- if (err != 0) {
- device_printf(sc->dev,
- "Cannot set vqmmc to %d<->%d\n", uvolt, uvolt);
- WR4(sc, SDHCI_FSL_PROT_CTRL, val_old);
- return (err);
- }
+ if (err != 0)
+ goto vccq_fail;
}
return (0);
+
+vccq_fail:
+ device_printf(sc->dev, "Cannot set vqmmc to %d<->%d\n", uvolt, uvolt);
+ WR4(sc, SDHCI_FSL_PROT_CTRL, val_old);
+
+ return (err);
}
static int

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 30, 3:02 PM (6 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17859835
Default Alt Text
D34029.diff (4 KB)

Event Timeline