Add support for the SD/MMC clock to the geberic clock code and use it in
authorkettenis <kettenis@openbsd.org>
Sat, 27 Aug 2016 16:41:52 +0000 (16:41 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 27 Aug 2016 16:41:52 +0000 (16:41 +0000)
sximmc(4).

sys/arch/armv7/sunxi/sxiccmu.c
sys/arch/armv7/sunxi/sxiccmu_clocks.h
sys/arch/armv7/sunxi/sxiccmuvar.h [deleted file]
sys/arch/armv7/sunxi/sximmc.c

index 117e0d9..46e22af 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sxiccmu.c,v 1.16 2016/08/27 11:39:59 kettenis Exp $   */
+/*     $OpenBSD: sxiccmu.c,v 1.17 2016/08/27 16:41:52 kettenis Exp $   */
 /*
  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2013 Artturi Alm
@@ -32,7 +32,6 @@
 
 #include <armv7/armv7/armv7var.h>
 #include <armv7/sunxi/sunxireg.h>
-#include <armv7/sunxi/sxiccmuvar.h>
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_clock.h>
 #define DPRINTF(x)
 #endif
 
-#define CCMU_SDx_CLK(x)                        (0x88 + (x) * 4)
-#define CCMU_SDx_CLK_GATING            (1U << 31)
-#define CCMU_SDx_CLK_SRC_GATING_OSC24M (0 << 24)
-#define CCMU_SDx_CLK_SRC_GATING_PLL6   (1 << 24)
-#define CCMU_SDx_CLK_SRC_GATING_PLL5   (2 << 24)
-#define CCMU_SDx_CLK_SRC_GATING_MASK   (3 << 24)
-#define CCMU_SDx_CLK_FACTOR_N          (3 << 16)
-#define CCMU_SDx_CLK_FACTOR_N_SHIFT    16
-#define CCMU_SDx_CLK_FACTOR_M          (7 << 0)
-#define CCMU_SDx_CLK_FACTOR_M_SHIFT    0
-
 struct sxiccmu_ccu_bit {
        uint16_t reg;
        uint8_t bit;
@@ -172,6 +160,8 @@ uint32_t sxiccmu_pll6_get_frequency(void *, uint32_t *);
 void   sxiccmu_pll6_enable(void *, uint32_t *, int);
 uint32_t sxiccmu_apb1_get_frequency(void *, uint32_t *);
 int    sxiccmu_gmac_set_frequency(void *, uint32_t *, uint32_t);
+int    sxiccmu_mmc_set_frequency(void *, uint32_t *, uint32_t);
+void   sxiccmu_mmc_enable(void *, uint32_t *, int);
 void   sxiccmu_gate_enable(void *, uint32_t *, int);
 void   sxiccmu_reset(void *, uint32_t *, int);
 
@@ -204,6 +194,11 @@ struct sxiccmu_device sxiccmu_devices[] = {
                .get_frequency = sxiccmu_gen_get_frequency,
                .enable = sxiccmu_gate_enable
        },
+       {
+               .compat = "allwinner,sun4i-a10-mmc-clk",
+               .set_frequency = sxiccmu_mmc_set_frequency,
+               .enable = sxiccmu_mmc_enable
+       },
        {
                .compat = "allwinner,sun4i-a10-usb-clk",
                .get_frequency = sxiccmu_gen_get_frequency,
@@ -454,6 +449,65 @@ sxiccmu_gmac_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
        return 0;
 }
 
+#define CCU_SDx_SCLK_GATING            (1U << 31)
+#define CCU_SDx_CLK_SRC_SEL_OSC24M     (0 << 24)
+#define CCU_SDx_CLK_SRC_SEL_PLL6       (1 << 24)
+#define CCU_SDx_CLK_SRC_SEL_PLL5       (2 << 24)
+#define CCU_SDx_CLK_SRC_SEL_MASK       (3 << 24)
+#define CCU_SDx_CLK_DIV_RATIO_N_MASK   (3 << 16)
+#define CCU_SDx_CLK_DIV_RATIO_N_SHIFT  16
+#define CCU_SDx_CLK_DIV_RATIO_M_MASK   (7 << 0)
+#define CCU_SDx_CLK_DIV_RATIO_M_SHIFT  0
+
+int
+sxiccmu_mmc_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
+{
+       struct sxiccmu_clock *sc = cookie;
+       uint32_t reg, m, n;
+
+       if (cells[0] != 0)
+               return -1;
+
+       switch (freq) {
+       case 400000:
+               n = 2, m = 15;
+               break;
+       case 25000000:
+       case 26000000:
+       case 50000000:
+               /* XXX OSC24M */
+               n = 0, m = 0;
+               break;
+       default:
+               return -1;
+       }
+
+       reg = SXIREAD4(sc, 0);
+       reg &= ~CCU_SDx_CLK_SRC_SEL_MASK;
+       reg |= CCU_SDx_CLK_SRC_SEL_OSC24M;
+       reg &= ~CCU_SDx_CLK_DIV_RATIO_N_MASK;
+       reg |= n << CCU_SDx_CLK_DIV_RATIO_N_SHIFT;
+       reg &= ~CCU_SDx_CLK_DIV_RATIO_M_MASK;
+       reg |= m << CCU_SDx_CLK_DIV_RATIO_M_SHIFT;
+       SXIWRITE4(sc, 0, reg);
+
+       return 0;
+}
+
+void
+sxiccmu_mmc_enable(void *cookie, uint32_t *cells, int on)
+{
+       struct sxiccmu_clock *sc = cookie;
+
+       if (cells[0] != 0)
+               return;
+
+       if (on)
+               SXISET4(sc, 0, CCU_SDx_SCLK_GATING);
+       else
+               SXICLR4(sc, 0, CCU_SDx_SCLK_GATING);
+}
+
 void
 sxiccmu_gate_enable(void *cookie, uint32_t *cells, int on)
 {
@@ -510,8 +564,23 @@ sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells)
 int
 sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
 {
+       struct sxiccmu_softc *sc = cookie;
+       struct sxiccmu_clock clock;
+       uint32_t idx = cells[0];
+
+       switch (idx) {
+       case H3_CLK_MMC0:
+       case H3_CLK_MMC1:
+       case H3_CLK_MMC2:
+               idx = 0;
+               clock.sc_iot = sc->sc_iot;
+               bus_space_subregion(sc->sc_iot, sc->sc_ioh,
+                   sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
+               return sxiccmu_mmc_set_frequency(&clock, &idx, freq);
+       }
+
        printf("%s: 0x%08x\n", __func__, cells[0]);
-       return 0;
+       return -1;
 }
 
 void
@@ -555,33 +624,3 @@ sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert)
        else
                SXISET4(sc, reg, (1U << bit));
 }
-
-
-void
-sxiccmu_set_sd_clock(int mod, int freq)
-{
-       struct sxiccmu_softc *sc = sxiccmu_cd.cd_devs[0];
-       uint32_t clk;
-       int m, n;
-
-       if (freq <= 400000) {
-               n = 2;
-               if (freq > 0)
-                       m = ((24000000 / (1 << n)) / freq) - 1;
-               else
-                       m = 15;
-       } else {
-               n = 0;
-               m = 0;
-       }
-       
-       clk = SXIREAD4(sc, CCMU_SDx_CLK(mod - CCMU_SDMMC0));
-       clk &= ~CCMU_SDx_CLK_SRC_GATING_MASK;
-       clk |= CCMU_SDx_CLK_SRC_GATING_OSC24M;
-       clk &= ~CCMU_SDx_CLK_FACTOR_N;
-       clk |= n << CCMU_SDx_CLK_FACTOR_N_SHIFT;
-       clk &= ~CCMU_SDx_CLK_FACTOR_M;
-       clk |= m << CCMU_SDx_CLK_FACTOR_M_SHIFT;
-       clk |= CCMU_SDx_CLK_GATING;
-       SXIWRITE4(sc, CCMU_SDx_CLK(mod - CCMU_SDMMC0), clk);
-}
index 0d2a74e..bfe51fa 100644 (file)
 #define H3_CLK_BUS_UART2       64
 #define H3_CLK_BUS_UART3       65
 
+#define H3_CLK_MMC0            71
+#define H3_CLK_MMC1            74
+#define H3_CLK_MMC2            77
+
 #define H3_CLK_USB_PHY0                88
 #define H3_CLK_USB_PHY1                89
 #define H3_CLK_USB_PHY2                90
@@ -48,10 +52,13 @@ struct sxiccmu_ccu_bit sun8i_h3_gates[] = {
        [H3_CLK_BUS_UART1] = { 0x006c, 17, H3_CLK_APB2 },
        [H3_CLK_BUS_UART2] = { 0x006c, 18, H3_CLK_APB2 },
        [H3_CLK_BUS_UART3] = { 0x006c, 19, H3_CLK_APB2 },
-       [H3_CLK_USB_PHY0] = { 0x00cc, 8 },
-       [H3_CLK_USB_PHY1] = { 0x00cc, 9 },
-       [H3_CLK_USB_PHY2] = { 0x00cc, 10 },
-       [H3_CLK_USB_PHY3] = { 0x00cc, 11 },
+       [H3_CLK_MMC0]      = { 0x0088, 31 },
+       [H3_CLK_MMC1]      = { 0x008c, 31 },
+       [H3_CLK_MMC2]      = { 0x0090, 31 },
+       [H3_CLK_USB_PHY0]  = { 0x00cc, 8 },
+       [H3_CLK_USB_PHY1]  = { 0x00cc, 9 },
+       [H3_CLK_USB_PHY2]  = { 0x00cc, 10 },
+       [H3_CLK_USB_PHY3]  = { 0x00cc, 11 },
 };
 
 /*
@@ -63,6 +70,10 @@ struct sxiccmu_ccu_bit sun8i_h3_gates[] = {
 #define H3_RST_USB_PHY2                2
 #define H3_RST_USB_PHY3                3
 
+#define H3_RST_BUS_MMC0                7
+#define H3_RST_BUS_MMC1                8
+#define H3_RST_BUS_MMC2                9
+
 #define H3_RST_BUS_EHCI0       18
 #define H3_RST_BUS_EHCI1       19
 #define H3_RST_BUS_EHCI2       20
@@ -77,6 +88,9 @@ struct sxiccmu_ccu_bit sun8i_h3_resets[] = {
        [H3_RST_USB_PHY1] =  { 0x00cc, 1 },
        [H3_RST_USB_PHY2] =  { 0x00cc, 2 },
        [H3_RST_USB_PHY3] =  { 0x00cc, 3 },
+       [H3_RST_BUS_MMC0] =  { 0x02c0, 8 },
+       [H3_RST_BUS_MMC1] =  { 0x02c0, 9 },
+       [H3_RST_BUS_MMC2] =  { 0x02c0, 10 },
        [H3_RST_BUS_EHCI0] = { 0x02c0, 24 },
        [H3_RST_BUS_EHCI1] = { 0x02c0, 25 },
        [H3_RST_BUS_EHCI2] = { 0x02c0, 26 },
diff --git a/sys/arch/armv7/sunxi/sxiccmuvar.h b/sys/arch/armv7/sunxi/sxiccmuvar.h
deleted file mode 100644 (file)
index 9cd081f..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*     $OpenBSD: sxiccmuvar.h,v 1.5 2016/08/22 19:43:49 kettenis Exp $ */
-/*
- * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-void sxiccmu_set_sd_clock(int, int);
-
-enum CCMU_MODULES {
-       CCMU_SDMMC0,
-       CCMU_SDMMC1,
-       CCMU_SDMMC2,
-       CCMU_SDMMC3
-};
index b0dc5e7..93ae407 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sximmc.c,v 1.4 2016/08/27 12:41:47 kettenis Exp $ */
+/* $OpenBSD: sximmc.c,v 1.5 2016/08/27 16:41:52 kettenis Exp $ */
 /* $NetBSD: awin_mmc.c,v 1.23 2015/11/14 10:32:40 bouyer Exp $ */
 
 /*-
@@ -40,9 +40,6 @@
 #include <dev/sdmmc/sdmmcchip.h>
 #include <dev/sdmmc/sdmmc_ioreg.h>
 
-#include <armv7/sunxi/sunxireg.h>
-#include <armv7/sunxi/sxiccmuvar.h>
-
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_clock.h>
 #include <dev/ofw/ofw_gpio.h>
@@ -239,7 +236,6 @@ struct sximmc_softc {
        bus_space_handle_t sc_clk_bsh;
        bus_dma_tag_t sc_dmat;
        int sc_node;
-       int sc_unit;
 
        int sc_use_dma;
 
@@ -350,7 +346,6 @@ sximmc_attach(struct device *parent, struct device *self, void *aux)
                return;
 
        sc->sc_node = faa->fa_node;
-       sc->sc_unit = (faa->fa_reg[0].addr - SDMMC0_ADDR) / SDMMCx_SIZE;
        sc->sc_bst = faa->fa_iot;
        sc->sc_dmat = faa->fa_dmat;
 
@@ -362,7 +357,7 @@ sximmc_attach(struct device *parent, struct device *self, void *aux)
 
        sc->sc_use_dma = 1;
 
-       printf(": unit %d\n", sc->sc_unit);
+       printf("\n");
 
        pinctrl_byname(faa->fa_node, "default");
 
@@ -536,8 +531,14 @@ sximmc_set_clock(struct sximmc_softc *sc, u_int freq)
        delay(20000);
 #endif
 
-       sxiccmu_set_sd_clock(CCMU_SDMMC0 + sc->sc_unit, freq * 1000);
-       delay(20000);
+       if (freq > 0) {
+               if (clock_set_frequency(sc->sc_node, "mmc", freq * 1000))
+                       return EIO;
+               clock_enable(sc->sc_node, "mmc");
+               delay(20000);
+       } else
+               clock_disable(sc->sc_node, "mmc");
+
        return 0;
 }