From 4718ccb1ff6298065eb8741f72536fec9d68c9d1 Mon Sep 17 00:00:00 2001 From: kettenis Date: Fri, 2 Feb 2024 12:01:49 +0000 Subject: [PATCH] Add a few more Allwinner D1 clocks. ok patrick@ --- sys/dev/fdt/sxiccmu.c | 101 ++++++++++++++++++++++++++++++++++- sys/dev/fdt/sxiccmu_clocks.h | 23 ++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c index 0707009b648..d64ba10c326 100644 --- a/sys/dev/fdt/sxiccmu.c +++ b/sys/dev/fdt/sxiccmu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sxiccmu.c,v 1.33 2024/01/26 17:50:00 kettenis Exp $ */ +/* $OpenBSD: sxiccmu.c,v 1.34 2024/02/02 12:01:49 kettenis Exp $ */ /* * Copyright (c) 2007,2009 Dale Rahn * Copyright (c) 2013 Artturi Alm @@ -1168,14 +1168,50 @@ sxiccmu_a80_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) } /* Allwinner D1 */ +#define D1_PLL_CPU_CTRL_REG 0x0000 +#define D1_PLL_CPU_FACTOR_M(x) (((x) >> 0) & 0x3) +#define D1_PLL_CPU_FACTOR_N(x) (((x) >> 8) & 0xff) +#define D1_RISCV_CLK_REG 0x0d00 +#define D1_RISCV_CLK_SEL (7 << 24) +#define D1_RISCV_CLK_SEL_HOSC (0 << 24) +#define D1_RISCV_CLK_SEL_PLL_CPU (5 << 24) +#define D1_RISCV_DIV_CFG_FACTOR_M(x) (((x) >> 0) & 0x1f) uint32_t sxiccmu_d1_get_frequency(struct sxiccmu_softc *sc, uint32_t idx) { + uint32_t parent; + uint32_t reg; + uint32_t m, n; + switch (idx) { + case D1_CLK_HOSC: + return clock_get_frequency(sc->sc_node, "hosc"); + case D1_CLK_PLL_CPU: + reg = SXIREAD4(sc, D1_PLL_CPU_CTRL_REG); + m = D1_PLL_CPU_FACTOR_M(reg) + 1; + n = D1_PLL_CPU_FACTOR_N(reg) + 1; + return (24000000 * n) / m; + case D1_CLK_PLL_PERIPH0: + /* Not hardcoded, but recommended. */ + return 600000000; case D1_CLK_APB1: /* XXX Controlled by a MUX. */ return 24000000; + case D1_CLK_RISCV: + reg = SXIREAD4(sc, D1_RISCV_CLK_REG); + switch (reg & D1_RISCV_CLK_SEL) { + case D1_RISCV_CLK_SEL_HOSC: + parent = D1_CLK_HOSC; + break; + case D1_RISCV_CLK_SEL_PLL_CPU: + parent = D1_CLK_PLL_CPU; + break; + default: + return 0; + } + m = D1_RISCV_DIV_CFG_FACTOR_M(reg) + 1; + return sxiccmu_ccu_get_frequency(sc, &parent) / m; } printf("%s: 0x%08x\n", __func__, idx); @@ -1671,9 +1707,72 @@ sxiccmu_a80_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) return -1; } +#define D1_SMHC0_CLK_REG 0x0830 +#define D1_SMHC1_CLK_REG 0x0834 +#define D1_SMHC2_CLK_REG 0x0838 +#define D1_SMHC_CLK_SRC_SEL (0x3 << 24) +#define D1_SMHC_CLK_SRC_SEL_HOSC (0x0 << 24) +#define D1_SMHC_CLK_SRC_SEL_PLL_PERIPH0 (0x1 << 24) +#define D1_SMHC_FACTOR_N_MASK (0x3 << 8) +#define D1_SMHC_FACTOR_N_SHIFT 8 +#define D1_SMHC_FACTOR_M_MASK (0xf << 0) +#define D1_SMHC_FACTOR_M_SHIFT 0 + +int +sxiccmu_d1_mmc_set_frequency(struct sxiccmu_softc *sc, bus_size_t offset, + uint32_t freq) +{ + uint32_t parent_freq; + uint32_t reg, m, n; + uint32_t clk_src; + + switch (freq) { + case 400000: + n = 2, m = 15; + clk_src = D1_SMHC_CLK_SRC_SEL_HOSC; + break; + case 20000000: + case 25000000: + case 26000000: + case 50000000: + case 52000000: + n = 0, m = 0; + clk_src = D1_SMHC_CLK_SRC_SEL_PLL_PERIPH0; + parent_freq = + sxiccmu_d1_get_frequency(sc, D1_CLK_PLL_PERIPH0); + while ((parent_freq / (1 << n) / 16) > freq) + n++; + while ((parent_freq / (1 << n) / (m + 1)) > freq) + m++; + break; + default: + return -1; + } + + reg = SXIREAD4(sc, offset); + reg &= ~D1_SMHC_CLK_SRC_SEL; + reg |= clk_src; + reg &= ~D1_SMHC_FACTOR_N_MASK; + reg |= n << D1_SMHC_FACTOR_N_SHIFT; + reg &= ~D1_SMHC_FACTOR_M_MASK; + reg |= m << D1_SMHC_FACTOR_M_SHIFT; + SXIWRITE4(sc, offset, reg); + + return 0; +} + int sxiccmu_d1_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq) { + switch (idx) { + case D1_CLK_MMC0: + return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC0_CLK_REG, freq); + case D1_CLK_MMC1: + return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC1_CLK_REG, freq); + case D1_CLK_MMC2: + return sxiccmu_d1_mmc_set_frequency(sc, D1_SMHC2_CLK_REG, freq); + } + printf("%s: 0x%08x\n", __func__, idx); return -1; } diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h index 7dc5a90f1d4..f8b4a85fd0a 100644 --- a/sys/dev/fdt/sxiccmu_clocks.h +++ b/sys/dev/fdt/sxiccmu_clocks.h @@ -304,7 +304,15 @@ const struct sxiccmu_ccu_bit sun9i_a80_mmc_gates[] = { /* D1 */ +#define D1_CLK_PLL_CPU 0 +#define D1_CLK_PLL_PERIPH0 5 #define D1_CLK_APB1 25 +#define D1_CLK_MMC0 56 +#define D1_CLK_MMC1 57 +#define D1_CLK_MMC2 58 +#define D1_CLK_BUS_MMC0 59 +#define D1_CLK_BUS_MMC1 60 +#define D1_CLK_BUS_MMC2 61 #define D1_CLK_BUS_UART0 62 #define D1_CLK_BUS_UART1 63 #define D1_CLK_BUS_UART2 64 @@ -317,8 +325,17 @@ const struct sxiccmu_ccu_bit sun9i_a80_mmc_gates[] = { #define D1_CLK_BUS_OHCI1 100 #define D1_CLK_BUS_EHCI0 101 #define D1_CLK_BUS_EHCI1 102 +#define D1_CLK_RISCV 132 + +#define D1_CLK_HOSC 255 const struct sxiccmu_ccu_bit sun20i_d1_gates[] = { + [D1_CLK_MMC0] = { 0x0830, 31 }, + [D1_CLK_MMC1] = { 0x0834, 31 }, + [D1_CLK_MMC2] = { 0x0838, 31 }, + [D1_CLK_BUS_MMC0] = { 0x084c, 0 }, + [D1_CLK_BUS_MMC1] = { 0x084c, 1 }, + [D1_CLK_BUS_MMC2] = { 0x084c, 2 }, [D1_CLK_BUS_UART0] = { 0x090c, 0, D1_CLK_APB1 }, [D1_CLK_BUS_UART1] = { 0x090c, 1, D1_CLK_APB1 }, [D1_CLK_BUS_UART2] = { 0x090c, 2, D1_CLK_APB1 }, @@ -801,6 +818,9 @@ const struct sxiccmu_ccu_bit sun9i_a80_mmc_resets[] = { /* D1 */ +#define D1_RST_BUS_MMC0 15 +#define D1_RST_BUS_MMC1 16 +#define D1_RST_BUS_MMC2 17 #define D1_RST_BUS_UART0 18 #define D1_RST_BUS_UART1 19 #define D1_RST_BUS_UART2 20 @@ -815,6 +835,9 @@ const struct sxiccmu_ccu_bit sun9i_a80_mmc_resets[] = { #define D1_RST_BUS_EHCI1 45 const struct sxiccmu_ccu_bit sun20i_d1_resets[] = { + [D1_RST_BUS_MMC0] = { 0x084c, 16 }, + [D1_RST_BUS_MMC1] = { 0x084c, 17 }, + [D1_RST_BUS_MMC2] = { 0x084c, 18 }, [D1_RST_BUS_UART0] = { 0x090c, 16 }, [D1_RST_BUS_UART1] = { 0x090c, 17 }, [D1_RST_BUS_UART2] = { 0x090c, 18 }, -- 2.20.1