From a7956ae81417d5e410c31232da7eba95566247bf Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 27 Aug 2016 16:41:52 +0000 Subject: [PATCH] Add support for the SD/MMC clock to the geberic clock code and use it in sximmc(4). --- sys/arch/armv7/sunxi/sxiccmu.c | 127 +++++++++++++++++--------- sys/arch/armv7/sunxi/sxiccmu_clocks.h | 22 ++++- sys/arch/armv7/sunxi/sxiccmuvar.h | 25 ----- sys/arch/armv7/sunxi/sximmc.c | 19 ++-- 4 files changed, 111 insertions(+), 82 deletions(-) delete mode 100644 sys/arch/armv7/sunxi/sxiccmuvar.h diff --git a/sys/arch/armv7/sunxi/sxiccmu.c b/sys/arch/armv7/sunxi/sxiccmu.c index 117e0d991d9..46e22af15eb 100644 --- a/sys/arch/armv7/sunxi/sxiccmu.c +++ b/sys/arch/armv7/sunxi/sxiccmu.c @@ -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 * Copyright (c) 2013 Artturi Alm @@ -32,7 +32,6 @@ #include #include -#include #include #include @@ -43,17 +42,6 @@ #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); -} diff --git a/sys/arch/armv7/sunxi/sxiccmu_clocks.h b/sys/arch/armv7/sunxi/sxiccmu_clocks.h index 0d2a74edbee..bfe51fa4d5b 100644 --- a/sys/arch/armv7/sunxi/sxiccmu_clocks.h +++ b/sys/arch/armv7/sunxi/sxiccmu_clocks.h @@ -27,6 +27,10 @@ #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 index 9cd081f194a..00000000000 --- a/sys/arch/armv7/sunxi/sxiccmuvar.h +++ /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 - * - * 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 -}; diff --git a/sys/arch/armv7/sunxi/sximmc.c b/sys/arch/armv7/sunxi/sximmc.c index b0dc5e77a88..93ae4072aac 100644 --- a/sys/arch/armv7/sunxi/sximmc.c +++ b/sys/arch/armv7/sunxi/sximmc.c @@ -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 #include -#include -#include - #include #include #include @@ -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; } -- 2.20.1