Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115855592
D34029.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D34029.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D34029: sdhci_fsl_fdt: Add voltage switching through syscon
Attached
Detach File
Event Timeline
Log In to Comment