From d524c0fae259fe7d7363c34b96ab0960b16355bb Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 24 Dec 2017 18:24:06 +0000 Subject: [PATCH] Implement A10/A20 CPU clock. --- sys/dev/fdt/sxiccmu.c | 67 +++++++++++++++++++++++++++++------- sys/dev/fdt/sxiccmu_clocks.h | 5 +++ 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c index 66129292a02..238641813a8 100644 --- a/sys/dev/fdt/sxiccmu.c +++ b/sys/dev/fdt/sxiccmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxiccmu.c,v 1.11 2017/12/15 09:15:36 kettenis Exp $ */ +/* $OpenBSD: sxiccmu.c,v 1.12 2017/12/24 18:24:06 kettenis Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn * Copyright (c) 2013 Artturi Alm @@ -755,27 +755,58 @@ sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells) return sc->sc_get_frequency(sc, idx); } -/* Allwinner H3/A64 */ -#define CCU_AHB1_APB1_CFG_REG 0x0054 -#define CCU_AHB1_CLK_SRC_SEL (3 << 12) -#define CCU_AHB1_CLK_SRC_SEL_LOSC (0 << 12) -#define CCU_AHB1_CLK_SRC_SEL_OSC24M (1 << 12) -#define CCU_AHB1_CLK_SRC_SEL_AXI (2 << 12) -#define CCU_AHB1_CLK_SRC_SEL_PERIPH0 (3 << 12) -#define CCU_AHB1_PRE_DIV(x) ((((x) >> 6) & 3) + 1) -#define CCU_AHB1_CLK_DIV_RATIO(x) (1 << (((x) >> 4) & 3)) -#define CCU_AHB2_CFG_REG 0x005c -#define CCU_AHB2_CLK_CFG (3 << 0) +/* Allwinner A10/A20 */ +#define A10_PLL1_CFG_REG 0x0000 +#define A10_PLL1_OUT_EXT_DIVP(x) (((x) >> 16) & 0x3) +#define A10_PLL1_FACTOR_N(x) (((x) >> 8) & 0x1f) +#define A10_PLL1_FACTOR_K(x) (((x) >> 4) & 0x3) +#define A10_PLL1_FACTOR_M(x) (((x) >> 0) & 0x3) +#define A10_CPU_AHB_APB0_CFG_REG 0x0054 +#define A10_CPU_CLK_SRC_SEL (0x3 << 16) +#define A10_CPU_CLK_SRC_SEL_LOSC (0x0 << 16) +#define A10_CPU_CLK_SRC_SEL_OSC24M (0x1 << 16) +#define A10_CPU_CLK_SRC_SEL_PLL1 (0x2 << 16) +#define A10_CPU_CLK_SRC_SEL_200MHZ (0x3 << 16) uint32_t sxiccmu_a10_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { + uint32_t parent; + uint32_t reg, k, m, n, p; + switch (idx) { + case A10_CLK_LOSC: + return clock_get_frequency(sc->sc_node, "losc"); + case A10_CLK_HOSC: + return clock_get_frequency(sc->sc_node, "hosc"); + case A10_CLK_PLL_CORE: + reg = SXIREAD4(sc, A10_PLL1_CFG_REG); + k = A10_PLL1_FACTOR_K(reg) + 1; + m = A10_PLL1_FACTOR_M(reg) + 1; + n = A10_PLL1_FACTOR_N(reg); + p = 1 << A10_PLL1_OUT_EXT_DIVP(reg); + return (24000000 * n * k) / (m * p); case A10_CLK_PLL_PERIPH_BASE: /* Not hardcoded, but recommended. */ return 600000000; case A10_CLK_PLL_PERIPH: return sxiccmu_a10_get_frequency(sc, A10_CLK_PLL_PERIPH_BASE) * 2; + case A10_CLK_CPU: + reg = SXIREAD4(sc, A10_CPU_AHB_APB0_CFG_REG); + switch (reg & A10_CPU_CLK_SRC_SEL) { + case A10_CPU_CLK_SRC_SEL_LOSC: + parent = A10_CLK_LOSC; + break; + case A10_CPU_CLK_SRC_SEL_OSC24M: + parent = A10_CLK_HOSC; + break; + case A10_CPU_CLK_SRC_SEL_PLL1: + parent = A10_CLK_PLL_CORE; + break; + case A10_CPU_CLK_SRC_SEL_200MHZ: + return 200000000; + } + return sxiccmu_ccu_get_frequency(sc, &parent); case A10_CLK_APB1: /* XXX Controlled by a MUX. */ return 24000000; @@ -785,6 +816,18 @@ sxiccmu_a10_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) return 0; } +/* Allwinner H3/A64 */ +#define CCU_AHB1_APB1_CFG_REG 0x0054 +#define CCU_AHB1_CLK_SRC_SEL (3 << 12) +#define CCU_AHB1_CLK_SRC_SEL_LOSC (0 << 12) +#define CCU_AHB1_CLK_SRC_SEL_OSC24M (1 << 12) +#define CCU_AHB1_CLK_SRC_SEL_AXI (2 << 12) +#define CCU_AHB1_CLK_SRC_SEL_PERIPH0 (3 << 12) +#define CCU_AHB1_PRE_DIV(x) ((((x) >> 6) & 3) + 1) +#define CCU_AHB1_CLK_DIV_RATIO(x) (1 << (((x) >> 4) & 3)) +#define CCU_AHB2_CFG_REG 0x005c +#define CCU_AHB2_CLK_CFG (3 << 0) + uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h index 74bed95dea7..58800aab6a6 100644 --- a/sys/dev/fdt/sxiccmu_clocks.h +++ b/sys/dev/fdt/sxiccmu_clocks.h @@ -7,9 +7,12 @@ /* A10/A20 */ +#define A10_CLK_HOSC 1 +#define A10_CLK_PLL_CORE 2 #define A10_CLK_PLL_PERIPH_BASE 14 #define A10_CLK_PLL_PERIPH 15 +#define A10_CLK_CPU 20 #define A10_CLK_APB1 25 #define A10_CLK_AHB_EHCI0 27 @@ -43,6 +46,8 @@ #define A10_CLK_SATA 122 #define A10_CLK_USB_PHY 125 +#define A10_CLK_LOSC 254 + struct sxiccmu_ccu_bit sun4i_a10_gates[] = { [A10_CLK_AHB_EHCI0] = { 0x0060, 1 }, [A10_CLK_AHB_EHCI1] = { 0x0060, 3 }, -- 2.20.1