Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev dwcmmc improvements:
details: https://anonhg.NetBSD.org/src/rev/de99b9e64ba8
branches: trunk
changeset: 968046:de99b9e64ba8
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Wed Jan 01 11:21:15 2020 +0000
description:
dwcmmc improvements:
- Use mmcpwrseq resources if available
- Only set 4- or 8-bit mode if specified in the dt properties
- Add quirk for implementations with inverted power enable logic
- Support switching signal voltage between 1.8V and 3.3V
- Fix a clock divider issue on Rockchip SoCs
diffstat:
sys/dev/fdt/dwcmmc_fdt.c | 77 ++++++++++++++++++++++++++++++++++++++++++++---
sys/dev/ic/dwc_mmc.c | 45 +++++++++++++++++++++++----
sys/dev/ic/dwc_mmc_var.h | 8 ++++-
3 files changed, 117 insertions(+), 13 deletions(-)
diffs (298 lines):
diff -r 0e13f3054605 -r de99b9e64ba8 sys/dev/fdt/dwcmmc_fdt.c
--- a/sys/dev/fdt/dwcmmc_fdt.c Wed Jan 01 11:18:13 2020 +0000
+++ b/sys/dev/fdt/dwcmmc_fdt.c Wed Jan 01 11:21:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwcmmc_fdt.c,v 1.8 2019/04/30 23:10:33 jmcneill Exp $ */
+/* $NetBSD: dwcmmc_fdt.c,v 1.9 2020/01/01 11:21:15 jmcneill Exp $ */
/*-
* Copyright (c) 2015-2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwcmmc_fdt.c,v 1.8 2019/04/30 23:10:33 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwcmmc_fdt.c,v 1.9 2020/01/01 11:21:15 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -40,20 +40,28 @@
#include <sys/gpio.h>
#include <dev/ic/dwc_mmc_var.h>
+#include <dev/sdmmc/sdmmcchip.h>
#include <dev/fdt/fdtvar.h>
static int dwcmmc_fdt_match(device_t, cfdata_t, void *);
static void dwcmmc_fdt_attach(device_t, device_t, void *);
+static void dwcmmc_fdt_pre_power_on(struct dwc_mmc_softc *);
+static void dwcmmc_fdt_post_power_on(struct dwc_mmc_softc *);
+
static int dwcmmc_fdt_card_detect(struct dwc_mmc_softc *);
static int dwcmmc_fdt_bus_clock(struct dwc_mmc_softc *, int);
+static int dwcmmc_fdt_signal_voltage(struct dwc_mmc_softc *, int);
struct dwcmmc_fdt_config {
u_int ciu_div;
+ u_int flags;
};
static const struct dwcmmc_fdt_config dwcmmc_rk3288_config = {
.ciu_div = 2,
+ .flags = DWC_MMC_F_USE_HOLD_REG |
+ DWC_MMC_F_DMA,
};
static const struct of_compat_data compat_data[] = {
@@ -68,6 +76,8 @@
struct fdtbus_gpio_pin *sc_pin_cd;
const struct dwcmmc_fdt_config *sc_conf;
u_int sc_ciu_div;
+ struct fdtbus_regulator *sc_vqmmc;
+ struct fdtbus_mmc_pwrseq *sc_pwrseq;
};
CFATTACH_DECL_NEW(dwcmmc_fdt, sizeof(struct dwcmmc_fdt_softc),
@@ -126,6 +136,9 @@
return;
}
+ esc->sc_vqmmc = fdtbus_regulator_acquire(phandle, "vqmmc-supply");
+ esc->sc_pwrseq = fdtbus_mmc_pwrseq_get(phandle);
+
sc->sc_dev = self;
sc->sc_bst = faa->faa_bst;
sc->sc_dmat = faa->faa_dmat;
@@ -137,13 +150,17 @@
}
esc->sc_conf = (void *)of_search_compatible(phandle, compat_data)->data;
-
if (of_getprop_uint32(phandle, "max-frequency", &sc->sc_clock_freq) != 0)
sc->sc_clock_freq = UINT_MAX;
+ if (of_getprop_uint32(phandle, "bus-width", &sc->sc_bus_width) != 0)
+ sc->sc_bus_width = 4;
sc->sc_fifo_depth = fifo_depth;
- sc->sc_flags = DWC_MMC_F_USE_HOLD_REG | DWC_MMC_F_DMA;
+ sc->sc_flags = esc->sc_conf->flags;
+ sc->sc_pre_power_on = dwcmmc_fdt_pre_power_on;
+ sc->sc_post_power_on = dwcmmc_fdt_post_power_on;
sc->sc_bus_clock = dwcmmc_fdt_bus_clock;
+ sc->sc_signal_voltage = dwcmmc_fdt_signal_voltage;
esc->sc_pin_cd = fdtbus_gpio_acquire(phandle, "cd-gpios",
GPIO_PIN_INPUT);
@@ -171,6 +188,24 @@
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
}
+static void
+dwcmmc_fdt_pre_power_on(struct dwc_mmc_softc *sc)
+{
+ struct dwcmmc_fdt_softc *esc = device_private(sc->sc_dev);
+
+ if (esc->sc_pwrseq != NULL)
+ fdtbus_mmc_pwrseq_pre_power_on(esc->sc_pwrseq);
+}
+
+static void
+dwcmmc_fdt_post_power_on(struct dwc_mmc_softc *sc)
+{
+ struct dwcmmc_fdt_softc *esc = device_private(sc->sc_dev);
+
+ if (esc->sc_pwrseq != NULL)
+ fdtbus_mmc_pwrseq_post_power_on(esc->sc_pwrseq);
+}
+
static int
dwcmmc_fdt_card_detect(struct dwc_mmc_softc *sc)
{
@@ -195,10 +230,42 @@
return error;
}
- sc->sc_clock_freq = clk_get_rate(esc->sc_clk_ciu) / ciu_div;
+ sc->sc_clock_freq = clk_get_rate(esc->sc_clk_ciu);
aprint_debug_dev(sc->sc_dev, "set clock rate to %u kHz (target %u kHz)\n",
sc->sc_clock_freq, rate);
return 0;
}
+
+static int
+dwcmmc_fdt_signal_voltage(struct dwc_mmc_softc *sc, int signal_voltage)
+{
+ struct dwcmmc_fdt_softc *esc = device_private(sc->sc_dev);
+ u_int uvol;
+ int error;
+
+ if (esc->sc_vqmmc == NULL)
+ return 0;
+
+ switch (signal_voltage) {
+ case SDMMC_SIGNAL_VOLTAGE_180:
+ uvol = 1800000;
+ break;
+ case SDMMC_SIGNAL_VOLTAGE_330:
+ uvol = 3300000;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ error = fdtbus_regulator_supports_voltage(esc->sc_vqmmc, uvol, uvol);
+ if (error != 0)
+ return 0;
+
+ error = fdtbus_regulator_set_voltage(esc->sc_vqmmc, uvol, uvol);
+ if (error != 0)
+ return error;
+
+ return fdtbus_regulator_enable(esc->sc_vqmmc);
+}
diff -r 0e13f3054605 -r de99b9e64ba8 sys/dev/ic/dwc_mmc.c
--- a/sys/dev/ic/dwc_mmc.c Wed Jan 01 11:18:13 2020 +0000
+++ b/sys/dev/ic/dwc_mmc.c Wed Jan 01 11:21:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc.c,v 1.18 2019/10/05 12:27:14 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.19 2020/01/01 11:21:15 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.18 2019/10/05 12:27:14 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.19 2020/01/01 11:21:15 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -54,6 +54,7 @@
static int dwc_mmc_bus_clock(sdmmc_chipset_handle_t, int);
static int dwc_mmc_bus_width(sdmmc_chipset_handle_t, int);
static int dwc_mmc_bus_rod(sdmmc_chipset_handle_t, int);
+static int dwc_mmc_signal_voltage(sdmmc_chipset_handle_t, int);
static void dwc_mmc_exec_command(sdmmc_chipset_handle_t,
struct sdmmc_command *);
static void dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
@@ -69,6 +70,7 @@
.bus_clock = dwc_mmc_bus_clock,
.bus_width = dwc_mmc_bus_width,
.bus_rod = dwc_mmc_bus_rod,
+ .signal_voltage = dwc_mmc_signal_voltage,
.exec_command = dwc_mmc_exec_command,
.card_enable_intr = dwc_mmc_card_enable_intr,
.card_intr_ack = dwc_mmc_card_intr_ack,
@@ -160,9 +162,16 @@
struct dwc_mmc_softc *sc = device_private(self);
struct sdmmcbus_attach_args saa;
+ if (sc->sc_pre_power_on)
+ sc->sc_pre_power_on(sc);
+
+ dwc_mmc_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_330);
dwc_mmc_host_reset(sc);
dwc_mmc_bus_width(sc, 1);
+ if (sc->sc_post_power_on)
+ sc->sc_post_power_on(sc);
+
memset(&saa, 0, sizeof(saa));
saa.saa_busname = "sdmmc";
saa.saa_sct = &dwc_mmc_chip_functions;
@@ -170,13 +179,15 @@
saa.saa_clkmin = 400;
saa.saa_clkmax = sc->sc_clock_freq / 1000;
saa.saa_dmat = sc->sc_dmat;
- saa.saa_caps = SMC_CAPS_4BIT_MODE|
- SMC_CAPS_8BIT_MODE|
- SMC_CAPS_SD_HIGHSPEED|
- SMC_CAPS_MMC_HIGHSPEED|
+ saa.saa_caps = SMC_CAPS_SD_HIGHSPEED |
+ SMC_CAPS_MMC_HIGHSPEED |
SMC_CAPS_AUTO_STOP |
SMC_CAPS_DMA |
SMC_CAPS_MULTI_SEG_DMA;
+ if (sc->sc_bus_width == 8)
+ saa.saa_caps |= SMC_CAPS_8BIT_MODE;
+ else
+ saa.saa_caps |= SMC_CAPS_4BIT_MODE;
if (sc->sc_card_detect)
saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
@@ -201,7 +212,16 @@
aprint_normal_dev(sc->sc_dev, "host reset\n");
#endif
- MMC_WRITE(sc, DWC_MMC_PWREN, 1);
+ if (ISSET(sc->sc_flags, DWC_MMC_F_PWREN_INV))
+ MMC_WRITE(sc, DWC_MMC_PWREN, 0);
+ else
+ MMC_WRITE(sc, DWC_MMC_PWREN, 1);
+
+ ctrl = MMC_READ(sc, DWC_MMC_GCTRL);
+ ctrl &= ~DWC_MMC_GCTRL_USE_INTERNAL_DMAC;
+ MMC_WRITE(sc, DWC_MMC_GCTRL, ctrl);
+
+ MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET);
MMC_WRITE(sc, DWC_MMC_GCTRL,
MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_RESET);
@@ -280,6 +300,17 @@
}
static int
+dwc_mmc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
+{
+ struct dwc_mmc_softc *sc = sch;
+
+ if (sc->sc_signal_voltage == NULL)
+ return 0;
+
+ return sc->sc_signal_voltage(sc, signal_voltage);
+}
+
+static int
dwc_mmc_update_clock(struct dwc_mmc_softc *sc)
{
uint32_t cmd;
diff -r 0e13f3054605 -r de99b9e64ba8 sys/dev/ic/dwc_mmc_var.h
--- a/sys/dev/ic/dwc_mmc_var.h Wed Jan 01 11:18:13 2020 +0000
+++ b/sys/dev/ic/dwc_mmc_var.h Wed Jan 01 11:21:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_var.h,v 1.9 2019/10/05 12:27:14 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_var.h,v 1.10 2020/01/01 11:21:15 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -39,9 +39,11 @@
u_int sc_flags;
#define DWC_MMC_F_DMA __BIT(0)
#define DWC_MMC_F_USE_HOLD_REG __BIT(1)
+#define DWC_MMC_F_PWREN_INV __BIT(2)
uint32_t sc_fifo_reg;
uint32_t sc_fifo_depth;
u_int sc_clock_freq;
+ u_int sc_bus_width;
void *sc_ih;
kmutex_t sc_intr_lock;
@@ -70,10 +72,14 @@
bool sc_wait_cmd;
bool sc_wait_data;
+ void (*sc_pre_power_on)(struct dwc_mmc_softc *);
+ void (*sc_post_power_on)(struct dwc_mmc_softc *);
+
int (*sc_card_detect)(struct dwc_mmc_softc *);
int (*sc_write_protect)(struct dwc_mmc_softc *);
void (*sc_set_led)(struct dwc_mmc_softc *, int);
int (*sc_bus_clock)(struct dwc_mmc_softc *, int);
+ int (*sc_signal_voltage)(struct dwc_mmc_softc *, int);
};
int dwc_mmc_init(struct dwc_mmc_softc *);
Home |
Main Index |
Thread Index |
Old Index