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/e8db4c015bdb
branches:  trunk
changeset: 466739:e8db4c015bdb
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 2f293e544bce -r e8db4c015bdb 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 2f293e544bce -r e8db4c015bdb 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 2f293e544bce -r e8db4c015bdb 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