Module Name:    src
Committed By:   jmcneill
Date:           Mon Dec 29 23:58:25 UTC 2014

Modified Files:
        src/sys/dev/ic: dwc_mmc.c dwc_mmc_var.h

Log Message:
- Simplify clock setup
- Add DWC_MMC_F_FORCE_CLK flag, which forces updating clock for each
  command (apparently required by Rockchip)
- Let bus glue limit the max clk speed used


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/ic/dwc_mmc.c \
    src/sys/dev/ic/dwc_mmc_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/dwc_mmc.c
diff -u src/sys/dev/ic/dwc_mmc.c:1.2 src/sys/dev/ic/dwc_mmc.c:1.3
--- src/sys/dev/ic/dwc_mmc.c:1.2	Sat Dec 27 19:18:04 2014
+++ src/sys/dev/ic/dwc_mmc.c	Mon Dec 29 23:58:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc.c,v 1.2 2014/12/27 19:18:04 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc.c,v 1.3 2014/12/29 23:58:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "opt_dwc_mmc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.2 2014/12/27 19:18:04 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.3 2014/12/29 23:58:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -105,15 +105,19 @@ dwc_mmc_init(struct dwc_mmc_softc *sc)
 	saa.saa_sct = &dwc_mmc_chip_functions;
 	saa.saa_sch = sc;
 	saa.saa_clkmin = 400;
-	saa.saa_clkmax = sc->sc_clock_freq / 1000;
+	if (sc->sc_clock_max) {
+		saa.saa_clkmax = sc->sc_clock_max;
+	} else {
+		saa.saa_clkmax = sc->sc_clock_freq / 1000;
+	}
 	saa.saa_caps = SMC_CAPS_4BIT_MODE|
 		       SMC_CAPS_8BIT_MODE|
 		       SMC_CAPS_SD_HIGHSPEED|
 		       SMC_CAPS_MMC_HIGHSPEED|
 		       SMC_CAPS_AUTO_STOP;
-	saa.saa_dmat = sc->sc_dmat;
 
 #if notyet
+	saa.saa_dmat = sc->sc_dmat;
 	saa.saa_caps |= SMC_CAPS_DMA|
 			SMC_CAPS_MULTI_SEG_DMA;
 #endif
@@ -161,25 +165,16 @@ dwc_mmc_intr(void *priv)
 static int
 dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq)
 {
-	u_int pll_freq = sc->sc_clock_freq / 1000;
-	u_int clk_div, mmc_div;
+	u_int pll_freq, clk_div;
 
-	mmc_div = min(howmany(pll_freq, freq), 0x3c);
-	clk_div = howmany(pll_freq / mmc_div, freq);
-	if (clk_div > 1 && (clk_div & 1) != 0)
+	pll_freq = sc->sc_clock_freq / 1000;
+	clk_div = (pll_freq / freq) >> 1;
+	if (pll_freq % freq)
 		clk_div++;
 
-#ifdef DWC_MMC_DEBUG
-	device_printf(sc->sc_dev, "%s: mmc_div=%u clk_div=%u freq=%u\n",
-	    __func__, mmc_div, clk_div, pll_freq / mmc_div / clk_div);
-#endif
-
 	MMC_WRITE(sc, DWC_MMC_CLKDIV_REG,
-	    __SHIFTIN(clk_div >> 1, DWC_MMC_CLKDIV_CLK_DIVIDER0));
-	if (dwc_mmc_update_clock(sc))
-		return ETIMEDOUT;
-
-	return sc->sc_set_clkdiv(sc, mmc_div);
+	    __SHIFTIN(clk_div, DWC_MMC_CLKDIV_CLK_DIVIDER0));
+	return dwc_mmc_update_clock(sc);
 }
 
 static int
@@ -389,6 +384,8 @@ dwc_mmc_bus_clock(sdmmc_chipset_handle_t
 
 	delay(1000);
 
+	sc->sc_cur_freq = freq;
+
 	return 0;
 }
 
@@ -435,6 +432,12 @@ dwc_mmc_exec_command(sdmmc_chipset_handl
 	    cmd->c_opcode, cmd->c_flags);
 #endif
 
+	if (sc->sc_flags & DWC_MMC_F_FORCE_CLK) {
+		cmd->c_error = dwc_mmc_bus_clock(sc, sc->sc_cur_freq);
+		if (cmd->c_error)
+			return;
+	}
+
 	if (sc->sc_flags & DWC_MMC_F_USE_HOLD_REG)
 		cmdval |= DWC_MMC_CMD_USE_HOLD_REG;
 
Index: src/sys/dev/ic/dwc_mmc_var.h
diff -u src/sys/dev/ic/dwc_mmc_var.h:1.2 src/sys/dev/ic/dwc_mmc_var.h:1.3
--- src/sys/dev/ic/dwc_mmc_var.h:1.2	Sat Dec 27 19:18:04 2014
+++ src/sys/dev/ic/dwc_mmc_var.h	Mon Dec 29 23:58:25 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc_mmc_var.h,v 1.2 2014/12/27 19:18:04 jmcneill Exp $ */
+/* $NetBSD: dwc_mmc_var.h,v 1.3 2014/12/29 23:58:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcne...@invisible.ca>
@@ -36,10 +36,12 @@ struct dwc_mmc_softc {
 	bus_dma_tag_t		sc_dmat;
 	void			*sc_ih;
 	unsigned int		sc_clock_freq;
+	unsigned int		sc_bus_freq;
 	unsigned int		sc_fifo_depth;
 	uint32_t		sc_flags;
 #define DWC_MMC_F_USE_HOLD_REG	0x0001	/* set USE_HOLD_REG with every cmd */
 #define DWC_MMC_F_PWREN_CLEAR	0x0002	/* clear POWER_ENABLE bit to enable */
+#define DWC_MMC_F_FORCE_CLK	0x0004	/* update clk div with every cmd */
 	int			(*sc_set_clkdiv)(struct dwc_mmc_softc *, int);
 
 	device_t		sc_sdmmc_dev;
@@ -47,6 +49,7 @@ struct dwc_mmc_softc {
 	kcondvar_t		sc_intr_cv;
 
 	uint32_t		sc_intr_rint;
+	u_int			sc_cur_freq;
 };
 
 void	dwc_mmc_init(struct dwc_mmc_softc *);

Reply via email to