-/* $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
#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;
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);
.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,
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)
{
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
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);
-}
#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
[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 },
};
/*
#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
[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 },
+++ /dev/null
-/* $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
-};
-/* $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 $ */
/*-
#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>
bus_space_handle_t sc_clk_bsh;
bus_dma_tag_t sc_dmat;
int sc_node;
- int sc_unit;
int sc_use_dma;
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;
sc->sc_use_dma = 1;
- printf(": unit %d\n", sc->sc_unit);
+ printf("\n");
pinctrl_byname(faa->fa_node, "default");
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;
}