From 714c53aa2e2d6d60ca1e7d18980767c8b715c288 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 11 Jul 2017 16:58:42 +0200 Subject: clk: renesas: Add r8a77995 CPG Core Clock Definitions Add all R-Car D3 Clock Pulse Generator Core Clock Outputs, as listed in Table 8.2f ("List of Clocks [R-Car D3]") of the R-Car Series, 3rd Generation Hardware User's Manual (Rev. 0.55, Jun. 30, 2017). Note that internal CPG clocks (S0, S1, S2, S3, S1C, S3C, SDSRC, and SSPSRC) are not included, as they are used as internal clock sources only, and never referenced from DT. Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd --- include/dt-bindings/clock/r8a77995-cpg-mssr.h | 57 +++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 include/dt-bindings/clock/r8a77995-cpg-mssr.h (limited to 'include/dt-bindings') diff --git a/include/dt-bindings/clock/r8a77995-cpg-mssr.h b/include/dt-bindings/clock/r8a77995-cpg-mssr.h new file mode 100644 index 000000000000..4e8ae3dee590 --- /dev/null +++ b/include/dt-bindings/clock/r8a77995-cpg-mssr.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 Glider bvba + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ + +#include + +/* r8a77995 CPG Core Clocks */ +#define R8A77995_CLK_Z2 0 +#define R8A77995_CLK_ZG 1 +#define R8A77995_CLK_ZTR 2 +#define R8A77995_CLK_ZT 3 +#define R8A77995_CLK_ZX 4 +#define R8A77995_CLK_S0D1 5 +#define R8A77995_CLK_S1D1 6 +#define R8A77995_CLK_S1D2 7 +#define R8A77995_CLK_S1D4 8 +#define R8A77995_CLK_S2D1 9 +#define R8A77995_CLK_S2D2 10 +#define R8A77995_CLK_S2D4 11 +#define R8A77995_CLK_S3D1 12 +#define R8A77995_CLK_S3D2 13 +#define R8A77995_CLK_S3D4 14 +#define R8A77995_CLK_S1D4C 15 +#define R8A77995_CLK_S3D1C 16 +#define R8A77995_CLK_S3D2C 17 +#define R8A77995_CLK_S3D4C 18 +#define R8A77995_CLK_LB 19 +#define R8A77995_CLK_CL 20 +#define R8A77995_CLK_ZB3 21 +#define R8A77995_CLK_ZB3D2 22 +#define R8A77995_CLK_CR 23 +#define R8A77995_CLK_CRD2 24 +#define R8A77995_CLK_SD0H 25 +#define R8A77995_CLK_SD0 26 +#define R8A77995_CLK_SSP2 27 +#define R8A77995_CLK_SSP1 28 +#define R8A77995_CLK_RPC 29 +#define R8A77995_CLK_RPCD2 30 +#define R8A77995_CLK_ZA2 31 +#define R8A77995_CLK_ZA8 32 +#define R8A77995_CLK_Z2D 33 +#define R8A77995_CLK_CANFD 34 +#define R8A77995_CLK_MSO 35 +#define R8A77995_CLK_R 36 +#define R8A77995_CLK_OSC 37 +#define R8A77995_CLK_LV0 38 +#define R8A77995_CLK_LV1 39 +#define R8A77995_CLK_CP 40 + +#endif /* __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ */ -- cgit v1.2.3 From cd030a78f7aa06fe216f6665a6ea84b8f3e5b3d3 Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Tue, 15 Aug 2017 13:55:29 +0800 Subject: clk: sunxi-ng: support R40 SoC Allwinner R40 SoC have a clock controller module in the style of the SoCs beyond sun6i, however, it's more rich and complex. Add support for it. Signed-off-by: Icenowy Zheng Signed-off-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/Kconfig | 5 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 1290 +++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun8i-r40.h | 69 ++ include/dt-bindings/clock/sun8i-r40-ccu.h | 187 +++++ include/dt-bindings/reset/sun8i-r40-ccu.h | 130 +++ 6 files changed, 1682 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-r40.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-r40.h create mode 100644 include/dt-bindings/clock/sun8i-r40-ccu.h create mode 100644 include/dt-bindings/reset/sun8i-r40-ccu.h (limited to 'include/dt-bindings') diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 7342928c35cd..7a360737fe3c 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -48,6 +48,11 @@ config SUN8I_V3S_CCU config SUN8I_DE2_CCU bool "Support for the Allwinner SoCs DE2 CCU" +config SUN8I_R40_CCU + bool "Support for the Allwinner R40 CCU" + default MACH_SUN8I + depends on MACH_SUN8I || COMPILE_TEST + config SUN9I_A80_CCU bool "Support for the Allwinner A80 CCU" default MACH_SUN9I diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 0c45fa50283d..58741cd647c3 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o +obj-$(CONFIG_SUN8I_R40_CCU) += ccu-sun8i-r40.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c new file mode 100644 index 000000000000..933f2e68f42a --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -0,0 +1,1290 @@ +/* + * Copyright (c) 2017 Icenowy Zheng + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" +#include "ccu_phase.h" + +#include "ccu-sun8i-r40.h" + +/* TODO: The result of N*K is required to be in [10, 88] range. */ +static struct ccu_nkmp pll_cpu_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT(4, 2), + .m = _SUNXI_CCU_DIV(0, 2), + .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-cpu", + "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from + * the base (2x, 4x and 8x), and one variable divider (the one true + * pll audio). + * + * We don't have any need for the variable divider for now, so we just + * hardcode it to match with the clock names + */ +#define SUN8I_R40_PLL_AUDIO_REG 0x008 + +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* TODO: The result of N/M is required to be in [8, 25] range. */ +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", + "osc24M", 0x0010, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* TODO: The result of N/M is required to be in [8, 25] range. */ +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", + "osc24M", 0x0018, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* TODO: The result of N*K is required to be in [10, 77] range. */ +static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", + "osc24M", 0x020, + 8, 5, /* N */ + 4, 2, /* K */ + 0, 2, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* TODO: The result of N*K is required to be in [21, 58] range. */ +static struct ccu_nk pll_periph0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT(4, 2), + .fixed_post_div = 2, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", + &ccu_nk_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static struct ccu_div pll_periph0_sata_clk = { + .enable = BIT(24), + .div = _SUNXI_CCU_DIV(0, 2), + /* + * The formula of pll-periph0 (1x) is 24MHz*N*K/2, and the formula + * of pll-periph0-sata is 24MHz*N*K/M/6, so the postdiv here is + * 6/2 = 3. + */ + .fixed_post_div = 3, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0-sata", + "pll-periph0", + &ccu_div_ops, 0), + }, +}; + +/* TODO: The result of N*K is required to be in [21, 58] range. */ +static struct ccu_nk pll_periph1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT(4, 2), + .fixed_post_div = 2, + .common = { + .reg = 0x02c, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", + &ccu_nk_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* TODO: The result of N/M is required to be in [8, 25] range. */ +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", + "osc24M", 0x030, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static struct ccu_nkm pll_sata_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 5), + .k = _SUNXI_CCU_MULT(4, 2), + .m = _SUNXI_CCU_DIV(0, 2), + .fixed_post_div = 6, + .common = { + .reg = 0x034, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-sata", "osc24M", + &ccu_nkm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const char * const pll_sata_out_parents[] = { "pll-sata", + "pll-periph0-sata" }; +static SUNXI_CCU_MUX_WITH_GATE(pll_sata_out_clk, "pll-sata-out", + pll_sata_out_parents, 0x034, + 30, 1, /* mux */ + BIT(14), /* gate */ + CLK_SET_RATE_PARENT); + +/* TODO: The result of N/M is required to be in [8, 25] range. */ +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", + "osc24M", 0x038, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* + * The MIPI PLL has 2 modes: "MIPI" and "HDMI". + * + * The MIPI mode is a standard NKM-style clock. The HDMI mode is an + * integer / fractional clock with switchable multipliers and dividers. + * This is not supported here. We hardcode the PLL to MIPI mode. + * + * TODO: In the MIPI mode, M/N is required to be equal or lesser than 3, + * which cannot be implemented now. + */ +#define SUN8I_R40_PLL_MIPI_REG 0x040 + +static const char * const pll_mipi_parents[] = { "pll-video0" }; +static struct ccu_nkm pll_mipi_clk = { + .enable = BIT(31) | BIT(23) | BIT(22), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .m = _SUNXI_CCU_DIV(0, 4), + .mux = _SUNXI_CCU_MUX(21, 1), + .common = { + .reg = 0x040, + .hw.init = CLK_HW_INIT_PARENTS("pll-mipi", + pll_mipi_parents, + &ccu_nkm_ops, + CLK_SET_RATE_UNGATE) + }, +}; + +/* TODO: The result of N/M is required to be in [8, 25] range. */ +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", + "osc24M", 0x048, + 8, 7, /* N */ + 0, 4, /* M */ + BIT(24), /* frac enable */ + BIT(25), /* frac select */ + 270000000, /* frac rate 0 */ + 297000000, /* frac rate 1 */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +/* TODO: The N factor is required to be in [16, 75] range. */ +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", + "osc24M", 0x04c, + 8, 7, /* N */ + 0, 2, /* M */ + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); + +static const char * const cpu_parents[] = { "osc32k", "osc24M", + "pll-cpu", "pll-cpu" }; +static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents, + 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x050, 0, 2, 0); + +static const char * const ahb1_parents[] = { "osc32k", "osc24M", + "axi", "pll-periph0" }; +static const struct ccu_mux_var_prediv ahb1_predivs[] = { + { .index = 3, .shift = 6, .width = 2 }, +}; +static struct ccu_div ahb1_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 12, + .width = 2, + + .var_predivs = ahb1_predivs, + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), + }, + + .common = { + .reg = 0x054, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("ahb1", + ahb1_parents, + &ccu_div_ops, + 0), + }, +}; + +static struct clk_div_table apb1_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 8 }, + { /* Sentinel */ }, +}; +static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", + 0x054, 8, 2, apb1_div_table, 0); + +static const char * const apb2_parents[] = { "osc32k", "osc24M", + "pll-periph0-2x", + "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, + 0, 5, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", + 0x060, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", + 0x060, BIT(5), 0); +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", + 0x060, BIT(6), 0); +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", + 0x060, BIT(8), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", + 0x060, BIT(9), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", + 0x060, BIT(10), 0); +static SUNXI_CCU_GATE(bus_mmc3_clk, "bus-mmc3", "ahb1", + 0x060, BIT(11), 0); +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", + 0x060, BIT(13), 0); +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", + 0x060, BIT(14), 0); +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb1", + 0x060, BIT(17), 0); +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", + 0x060, BIT(18), 0); +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", + 0x060, BIT(19), 0); +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", + 0x060, BIT(20), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", + 0x060, BIT(21), 0); +static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb1", + 0x060, BIT(22), 0); +static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3", "ahb1", + 0x060, BIT(23), 0); +static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata", "ahb1", + 0x060, BIT(24), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", + 0x060, BIT(25), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", + 0x060, BIT(26), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb1", + 0x060, BIT(27), 0); +static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb1", + 0x060, BIT(28), 0); +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", + 0x060, BIT(29), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb1", + 0x060, BIT(30), 0); +static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb1", + 0x060, BIT(31), 0); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", + 0x064, BIT(0), 0); +static SUNXI_CCU_GATE(bus_mp_clk, "bus-mp", "ahb1", + 0x064, BIT(2), 0); +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", + 0x064, BIT(5), 0); +static SUNXI_CCU_GATE(bus_csi0_clk, "bus-csi0", "ahb1", + 0x064, BIT(8), 0); +static SUNXI_CCU_GATE(bus_csi1_clk, "bus-csi1", "ahb1", + 0x064, BIT(9), 0); +static SUNXI_CCU_GATE(bus_hdmi0_clk, "bus-hdmi0", "ahb1", + 0x064, BIT(10), 0); +static SUNXI_CCU_GATE(bus_hdmi1_clk, "bus-hdmi1", "ahb1", + 0x064, BIT(11), 0); +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", + 0x064, BIT(12), 0); +static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb1", + 0x064, BIT(13), 0); +static SUNXI_CCU_GATE(bus_tve1_clk, "bus-tve1", "ahb1", + 0x064, BIT(14), 0); +static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb1", + 0x064, BIT(15), 0); +static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac", "ahb1", + 0x064, BIT(17), 0); +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", + 0x064, BIT(20), 0); +static SUNXI_CCU_GATE(bus_tvd0_clk, "bus-tvd0", "ahb1", + 0x064, BIT(21), 0); +static SUNXI_CCU_GATE(bus_tvd1_clk, "bus-tvd1", "ahb1", + 0x064, BIT(22), 0); +static SUNXI_CCU_GATE(bus_tvd2_clk, "bus-tvd2", "ahb1", + 0x064, BIT(23), 0); +static SUNXI_CCU_GATE(bus_tvd3_clk, "bus-tvd3", "ahb1", + 0x064, BIT(24), 0); +static SUNXI_CCU_GATE(bus_tvd_top_clk, "bus-tvd-top", "ahb1", + 0x064, BIT(25), 0); +static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb1", + 0x064, BIT(26), 0); +static SUNXI_CCU_GATE(bus_tcon_lcd1_clk, "bus-tcon-lcd1", "ahb1", + 0x064, BIT(27), 0); +static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb1", + 0x064, BIT(28), 0); +static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb1", + 0x064, BIT(29), 0); +static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb1", + 0x064, BIT(30), 0); + +static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", + 0x068, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", + 0x068, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97", "apb1", + 0x068, BIT(2), 0); +static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", + 0x068, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ir0_clk, "bus-ir0", "apb1", + 0x068, BIT(6), 0); +static SUNXI_CCU_GATE(bus_ir1_clk, "bus-ir1", "apb1", + 0x068, BIT(7), 0); +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", + 0x068, BIT(8), 0); +static SUNXI_CCU_GATE(bus_keypad_clk, "bus-keypad", "apb1", + 0x068, BIT(10), 0); +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", + 0x068, BIT(12), 0); +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", + 0x068, BIT(13), 0); +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", + 0x068, BIT(14), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", + 0x06c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", + 0x06c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", + 0x06c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", + 0x06c, BIT(3), 0); +/* + * In datasheet here's "Reserved", however the gate exists in BSP soucre + * code. + */ +static SUNXI_CCU_GATE(bus_can_clk, "bus-can", "apb2", + 0x06c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", + 0x06c, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ps20_clk, "bus-ps20", "apb2", + 0x06c, BIT(6), 0); +static SUNXI_CCU_GATE(bus_ps21_clk, "bus-ps21", "apb2", + 0x06c, BIT(7), 0); +static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", + 0x06c, BIT(15), 0); +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", + 0x06c, BIT(16), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", + 0x06c, BIT(17), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", + 0x06c, BIT(18), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", + 0x06c, BIT(19), 0); +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", + 0x06c, BIT(20), 0); +static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", + 0x06c, BIT(21), 0); +static SUNXI_CCU_GATE(bus_uart6_clk, "bus-uart6", "apb2", + 0x06c, BIT(22), 0); +static SUNXI_CCU_GATE(bus_uart7_clk, "bus-uart7", "apb2", + 0x06c, BIT(23), 0); + +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", + 0x070, BIT(7), 0); + +static const char * const ths_parents[] = { "osc24M" }; +static struct ccu_div ths_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0x074, + .hw.init = CLK_HW_INIT_PARENTS("ths", + ths_parents, + &ccu_div_ops, + 0), + }, +}; + +static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", + "pll-periph1" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 4, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0ac, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", + "pll-audio-2x", "pll-audio" }; +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", i2s_parents, + 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_parents, + 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static const char * const keypad_parents[] = { "osc24M", "osc32k" }; +static const u8 keypad_table[] = { 0, 2 }; +static struct ccu_mp keypad_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(0, 5), + .p = _SUNXI_CCU_DIV(16, 2), + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), + .common = { + .reg = 0x0c4, + .hw.init = CLK_HW_INIT_PARENTS("keypad", + keypad_parents, + &ccu_mp_ops, + 0), + } +}; + +static const char * const sata_parents[] = { "pll-sata-out", "sata-ext" }; +static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, + 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); + +/* + * There are 3 OHCI 12M clock source selection bits in this register. + * We will force them to 0 (12M divided from 48M). + */ +#define SUN8I_R40_USB_CLK_REG 0x0cc + +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", + 0x0cc, BIT(8), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", + 0x0cc, BIT(9), 0); +static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", + 0x0cc, BIT(10), 0); +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", + 0x0cc, BIT(16), 0); +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", + 0x0cc, BIT(17), 0); +static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", + 0x0cc, BIT(18), 0); + +static const char * const ir_parents[] = { "osc24M", "pll-periph0", + "pll-periph1", "osc32k" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_clk, "ir0", ir_parents, 0x0d0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_clk, "ir1", ir_parents, 0x0d4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; +static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, + 0x0f4, 0, 2, 20, 2, CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", + 0x100, BIT(0), 0); +static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "dram", + 0x100, BIT(1), 0); +static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "dram", + 0x100, BIT(2), 0); +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", + 0x100, BIT(3), 0); +static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "dram", + 0x100, BIT(4), 0); +static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "dram", + 0x100, BIT(5), 0); +static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", + 0x100, BIT(6), 0); + +static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, + 0x104, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(mp_clk, "mp", de_parents, + 0x108, 0, 4, 24, 3, BIT(31), 0); + +static const char * const tcon_parents[] = { "pll-video0", "pll-video1", + "pll-video0-2x", "pll-video1-2x", + "pll-mipi" }; +static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents, + 0x110, 24, 3, BIT(31), CLK_SET_RATE_PARENT); +static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents, + 0x114, 24, 3, BIT(31), CLK_SET_RATE_PARENT); +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents, + 0x118, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents, + 0x11c, 0, 4, 24, 3, BIT(31), 0); + +static const char * const deinterlace_parents[] = { "pll-periph0", + "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", + deinterlace_parents, 0x124, 0, 4, 24, 3, + BIT(31), 0); + +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", + "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", csi_mclk_parents, + 0x130, 0, 5, 8, 3, BIT(15), 0); + +static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, + 0x134, 16, 4, 24, 3, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", csi_mclk_parents, + 0x134, 0, 5, 8, 3, BIT(15), 0); + +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", + 0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", + 0x140, BIT(31), CLK_SET_RATE_PARENT); +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", + 0x144, BIT(31), 0); + +static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, + 0x150, 0, 4, 24, 2, BIT(31), 0); + +static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", + 0x154, BIT(31), 0); + +/* + * In the SoC's user manual, the P factor is mentioned, but not used in + * the frequency formula. + * + * Here the factor is included, according to the BSP kernel source, + * which contains the P factor of this clock. + */ +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", + "pll-ddr0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_IS_CRITICAL); + +static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-video1", + "pll-periph0" }; +static SUNXI_CCU_M_WITH_MUX_GATE(dsi_dphy_clk, "dsi-dphy", dsi_dphy_parents, + 0x168, 0, 4, 8, 2, BIT(15), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(tve0_clk, "tve0", tcon_parents, + 0x180, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(tve1_clk, "tve1", tcon_parents, + 0x184, 0, 4, 24, 3, BIT(31), 0); + +static const char * const tvd_parents[] = { "pll-video0", "pll-video1", + "pll-video0-2x", "pll-video1-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(tvd0_clk, "tvd0", tvd_parents, + 0x188, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(tvd1_clk, "tvd1", tvd_parents, + 0x18c, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(tvd2_clk, "tvd2", tvd_parents, + 0x190, 0, 4, 24, 3, BIT(31), 0); +static SUNXI_CCU_M_WITH_MUX_GATE(tvd3_clk, "tvd3", tvd_parents, + 0x194, 0, 4, 24, 3, BIT(31), 0); + +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); + +static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" }; +static const struct ccu_mux_fixed_prediv out_predivs[] = { + { .index = 0, .div = 750, }, +}; + +static struct ccu_mp outa_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(8, 5), + .p = _SUNXI_CCU_DIV(20, 2), + .mux = { + .shift = 24, + .width = 2, + .fixed_predivs = out_predivs, + .n_predivs = ARRAY_SIZE(out_predivs), + }, + .common = { + .reg = 0x1f0, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("outa", out_parents, + &ccu_mp_ops, 0), + } +}; + +static struct ccu_mp outb_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(8, 5), + .p = _SUNXI_CCU_DIV(20, 2), + .mux = { + .shift = 24, + .width = 2, + .fixed_predivs = out_predivs, + .n_predivs = ARRAY_SIZE(out_predivs), + }, + .common = { + .reg = 0x1f4, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("outb", out_parents, + &ccu_mp_ops, 0), + } +}; + +static struct ccu_common *sun8i_r40_ccu_clks[] = { + &pll_cpu_clk.common, + &pll_audio_base_clk.common, + &pll_video0_clk.common, + &pll_ve_clk.common, + &pll_ddr0_clk.common, + &pll_periph0_clk.common, + &pll_periph0_sata_clk.common, + &pll_periph1_clk.common, + &pll_video1_clk.common, + &pll_sata_clk.common, + &pll_sata_out_clk.common, + &pll_gpu_clk.common, + &pll_mipi_clk.common, + &pll_de_clk.common, + &pll_ddr1_clk.common, + &cpu_clk.common, + &axi_clk.common, + &ahb1_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &bus_mipi_dsi_clk.common, + &bus_ce_clk.common, + &bus_dma_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_mmc3_clk.common, + &bus_nand_clk.common, + &bus_dram_clk.common, + &bus_emac_clk.common, + &bus_ts_clk.common, + &bus_hstimer_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &bus_spi2_clk.common, + &bus_spi3_clk.common, + &bus_sata_clk.common, + &bus_otg_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_ehci2_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ohci2_clk.common, + &bus_ve_clk.common, + &bus_mp_clk.common, + &bus_deinterlace_clk.common, + &bus_csi0_clk.common, + &bus_csi1_clk.common, + &bus_hdmi0_clk.common, + &bus_hdmi1_clk.common, + &bus_de_clk.common, + &bus_tve0_clk.common, + &bus_tve1_clk.common, + &bus_tve_top_clk.common, + &bus_gmac_clk.common, + &bus_gpu_clk.common, + &bus_tvd0_clk.common, + &bus_tvd1_clk.common, + &bus_tvd2_clk.common, + &bus_tvd3_clk.common, + &bus_tvd_top_clk.common, + &bus_tcon_lcd0_clk.common, + &bus_tcon_lcd1_clk.common, + &bus_tcon_tv0_clk.common, + &bus_tcon_tv1_clk.common, + &bus_tcon_top_clk.common, + &bus_codec_clk.common, + &bus_spdif_clk.common, + &bus_ac97_clk.common, + &bus_pio_clk.common, + &bus_ir0_clk.common, + &bus_ir1_clk.common, + &bus_ths_clk.common, + &bus_keypad_clk.common, + &bus_i2s0_clk.common, + &bus_i2s1_clk.common, + &bus_i2s2_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_i2c3_clk.common, + &bus_can_clk.common, + &bus_scr_clk.common, + &bus_ps20_clk.common, + &bus_ps21_clk.common, + &bus_i2c4_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_uart5_clk.common, + &bus_uart6_clk.common, + &bus_uart7_clk.common, + &bus_dbg_clk.common, + &ths_clk.common, + &nand_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &mmc3_clk.common, + &ts_clk.common, + &ce_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &spi3_clk.common, + &i2s0_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &ac97_clk.common, + &spdif_clk.common, + &keypad_clk.common, + &sata_clk.common, + &usb_phy0_clk.common, + &usb_phy1_clk.common, + &usb_phy2_clk.common, + &usb_ohci0_clk.common, + &usb_ohci1_clk.common, + &usb_ohci2_clk.common, + &ir0_clk.common, + &ir1_clk.common, + &dram_clk.common, + &dram_ve_clk.common, + &dram_csi0_clk.common, + &dram_csi1_clk.common, + &dram_ts_clk.common, + &dram_tvd_clk.common, + &dram_mp_clk.common, + &dram_deinterlace_clk.common, + &de_clk.common, + &mp_clk.common, + &tcon_lcd0_clk.common, + &tcon_lcd1_clk.common, + &tcon_tv0_clk.common, + &tcon_tv1_clk.common, + &deinterlace_clk.common, + &csi1_mclk_clk.common, + &csi_sclk_clk.common, + &csi0_mclk_clk.common, + &ve_clk.common, + &codec_clk.common, + &avs_clk.common, + &hdmi_clk.common, + &hdmi_slow_clk.common, + &mbus_clk.common, + &dsi_dphy_clk.common, + &tve0_clk.common, + &tve1_clk.common, + &tvd0_clk.common, + &tvd1_clk.common, + &tvd2_clk.common, + &tvd3_clk.common, + &gpu_clk.common, + &outa_clk.common, + &outb_clk.common, +}; + +/* Fixed Factor clocks */ +static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0); + +/* We hardcode the divider to 4 for now */ +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", + "pll-periph0", 1, 2, 0); +static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", + "pll-periph1", 1, 2, 0); +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", + "pll-video0", 1, 2, 0); +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", + "pll-video1", 1, 2, 0); + +static struct clk_hw_onecell_data sun8i_r40_hw_clks = { + .hws = { + [CLK_OSC_12M] = &osc12M_clk.hw, + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw, + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_SATA] = &pll_periph0_sata_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, + [CLK_PLL_SATA] = &pll_sata_clk.common.hw, + [CLK_PLL_SATA_OUT] = &pll_sata_out_clk.common.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, + [CLK_PLL_DE] = &pll_de_clk.common.hw, + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, + [CLK_CPU] = &cpu_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_AHB1] = &ahb1_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_MMC3] = &bus_mmc3_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, + [CLK_BUS_TS] = &bus_ts_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw, + [CLK_BUS_SATA] = &bus_sata_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_MP] = &bus_mp_clk.common.hw, + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, + [CLK_BUS_CSI0] = &bus_csi0_clk.common.hw, + [CLK_BUS_CSI1] = &bus_csi1_clk.common.hw, + [CLK_BUS_HDMI0] = &bus_hdmi0_clk.common.hw, + [CLK_BUS_HDMI1] = &bus_hdmi1_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, + [CLK_BUS_TVE1] = &bus_tve1_clk.common.hw, + [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, + [CLK_BUS_GMAC] = &bus_gmac_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_BUS_TVD0] = &bus_tvd0_clk.common.hw, + [CLK_BUS_TVD1] = &bus_tvd1_clk.common.hw, + [CLK_BUS_TVD2] = &bus_tvd2_clk.common.hw, + [CLK_BUS_TVD3] = &bus_tvd3_clk.common.hw, + [CLK_BUS_TVD_TOP] = &bus_tvd_top_clk.common.hw, + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw, + [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw, + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, + [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_BUS_AC97] = &bus_ac97_clk.common.hw, + [CLK_BUS_PIO] = &bus_pio_clk.common.hw, + [CLK_BUS_IR0] = &bus_ir0_clk.common.hw, + [CLK_BUS_IR1] = &bus_ir1_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_BUS_KEYPAD] = &bus_keypad_clk.common.hw, + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, + [CLK_BUS_CAN] = &bus_can_clk.common.hw, + [CLK_BUS_SCR] = &bus_scr_clk.common.hw, + [CLK_BUS_PS20] = &bus_ps20_clk.common.hw, + [CLK_BUS_PS21] = &bus_ps21_clk.common.hw, + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, + [CLK_BUS_UART6] = &bus_uart6_clk.common.hw, + [CLK_BUS_UART7] = &bus_uart7_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_THS] = &ths_clk.common.hw, + [CLK_NAND] = &nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_MMC3] = &mmc3_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_AC97] = &ac97_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_KEYPAD] = &keypad_clk.common.hw, + [CLK_SATA] = &sata_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, + [CLK_IR0] = &ir0_clk.common.hw, + [CLK_IR1] = &ir1_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_MP] = &mp_clk.common.hw, + [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw, + [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw, + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, + [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, + [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_CODEC] = &codec_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, + [CLK_TVE0] = &tve0_clk.common.hw, + [CLK_TVE1] = &tve1_clk.common.hw, + [CLK_TVD0] = &tvd0_clk.common.hw, + [CLK_TVD1] = &tvd1_clk.common.hw, + [CLK_TVD2] = &tvd2_clk.common.hw, + [CLK_TVD3] = &tvd3_clk.common.hw, + [CLK_GPU] = &gpu_clk.common.hw, + [CLK_OUTA] = &outa_clk.common.hw, + [CLK_OUTB] = &outb_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun8i_r40_ccu_resets[] = { + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, + [RST_USB_PHY2] = { 0x0cc, BIT(2) }, + + [RST_DRAM] = { 0x0f4, BIT(31) }, + [RST_MBUS] = { 0x0fc, BIT(31) }, + + [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, + [RST_BUS_CE] = { 0x2c0, BIT(5) }, + [RST_BUS_DMA] = { 0x2c0, BIT(6) }, + [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, + [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, + [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, + [RST_BUS_MMC3] = { 0x2c0, BIT(11) }, + [RST_BUS_NAND] = { 0x2c0, BIT(13) }, + [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, + [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, + [RST_BUS_TS] = { 0x2c0, BIT(18) }, + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, + [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, + [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, + [RST_BUS_SPI2] = { 0x2c0, BIT(22) }, + [RST_BUS_SPI3] = { 0x2c0, BIT(23) }, + [RST_BUS_SATA] = { 0x2c0, BIT(24) }, + [RST_BUS_OTG] = { 0x2c0, BIT(25) }, + [RST_BUS_EHCI0] = { 0x2c0, BIT(26) }, + [RST_BUS_EHCI1] = { 0x2c0, BIT(27) }, + [RST_BUS_EHCI2] = { 0x2c0, BIT(28) }, + [RST_BUS_OHCI0] = { 0x2c0, BIT(29) }, + [RST_BUS_OHCI1] = { 0x2c0, BIT(30) }, + [RST_BUS_OHCI2] = { 0x2c0, BIT(31) }, + + [RST_BUS_VE] = { 0x2c4, BIT(0) }, + [RST_BUS_MP] = { 0x2c4, BIT(2) }, + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, + [RST_BUS_CSI0] = { 0x2c4, BIT(8) }, + [RST_BUS_CSI1] = { 0x2c4, BIT(9) }, + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, + [RST_BUS_DE] = { 0x2c4, BIT(12) }, + [RST_BUS_TVE0] = { 0x2c4, BIT(13) }, + [RST_BUS_TVE1] = { 0x2c4, BIT(14) }, + [RST_BUS_TVE_TOP] = { 0x2c4, BIT(15) }, + [RST_BUS_GMAC] = { 0x2c4, BIT(17) }, + [RST_BUS_GPU] = { 0x2c4, BIT(20) }, + [RST_BUS_TVD0] = { 0x2c4, BIT(21) }, + [RST_BUS_TVD1] = { 0x2c4, BIT(22) }, + [RST_BUS_TVD2] = { 0x2c4, BIT(23) }, + [RST_BUS_TVD3] = { 0x2c4, BIT(24) }, + [RST_BUS_TVD_TOP] = { 0x2c4, BIT(25) }, + [RST_BUS_TCON_LCD0] = { 0x2c4, BIT(26) }, + [RST_BUS_TCON_LCD1] = { 0x2c4, BIT(27) }, + [RST_BUS_TCON_TV0] = { 0x2c4, BIT(28) }, + [RST_BUS_TCON_TV1] = { 0x2c4, BIT(29) }, + [RST_BUS_TCON_TOP] = { 0x2c4, BIT(30) }, + [RST_BUS_DBG] = { 0x2c4, BIT(31) }, + + [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, + + [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, + [RST_BUS_AC97] = { 0x2d0, BIT(2) }, + [RST_BUS_IR0] = { 0x2d0, BIT(6) }, + [RST_BUS_IR1] = { 0x2d0, BIT(7) }, + [RST_BUS_THS] = { 0x2d0, BIT(8) }, + [RST_BUS_KEYPAD] = { 0x2d0, BIT(10) }, + [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, + [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, + [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, + + [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, + [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, + [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, + [RST_BUS_I2C3] = { 0x2d8, BIT(3) }, + [RST_BUS_CAN] = { 0x2d8, BIT(4) }, + [RST_BUS_SCR] = { 0x2d8, BIT(5) }, + [RST_BUS_PS20] = { 0x2d8, BIT(6) }, + [RST_BUS_PS21] = { 0x2d8, BIT(7) }, + [RST_BUS_I2C4] = { 0x2d8, BIT(15) }, + [RST_BUS_UART0] = { 0x2d8, BIT(16) }, + [RST_BUS_UART1] = { 0x2d8, BIT(17) }, + [RST_BUS_UART2] = { 0x2d8, BIT(18) }, + [RST_BUS_UART3] = { 0x2d8, BIT(19) }, + [RST_BUS_UART4] = { 0x2d8, BIT(20) }, + [RST_BUS_UART5] = { 0x2d8, BIT(21) }, + [RST_BUS_UART6] = { 0x2d8, BIT(22) }, + [RST_BUS_UART7] = { 0x2d8, BIT(23) }, +}; + +static const struct sunxi_ccu_desc sun8i_r40_ccu_desc = { + .ccu_clks = sun8i_r40_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun8i_r40_ccu_clks), + + .hw_clks = &sun8i_r40_hw_clks, + + .resets = sun8i_r40_ccu_resets, + .num_resets = ARRAY_SIZE(sun8i_r40_ccu_resets), +}; + +static struct ccu_pll_nb sun8i_r40_pll_cpu_nb = { + .common = &pll_cpu_clk.common, + /* copy from pll_cpu_clk */ + .enable = BIT(31), + .lock = BIT(28), +}; + +static struct ccu_mux_nb sun8i_r40_cpu_nb = { + .common = &cpu_clk.common, + .cm = &cpu_clk.mux, + .delay_us = 1, /* > 8 clock cycles at 24 MHz */ + .bypass_index = 1, /* index of 24 MHz oscillator */ +}; + +static void __init sun8i_r40_ccu_setup(struct device_node *node) +{ + void __iomem *reg; + u32 val; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%s: Could not map the clock registers\n", + of_node_full_name(node)); + return; + } + + /* Force the PLL-Audio-1x divider to 4 */ + val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); + val &= ~GENMASK(19, 16); + writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); + + /* Force PLL-MIPI to MIPI mode */ + val = readl(reg + SUN8I_R40_PLL_MIPI_REG); + val &= ~BIT(16); + writel(val, reg + SUN8I_R40_PLL_MIPI_REG); + + /* Force OHCI 12M parent to 12M divided from 48M */ + val = readl(reg + SUN8I_R40_USB_CLK_REG); + val &= ~GENMASK(25, 20); + writel(val, reg + SUN8I_R40_USB_CLK_REG); + + sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc); + + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb); + + /* Reparent CPU during PLL CPU rate changes */ + ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, + &sun8i_r40_cpu_nb); +} +CLK_OF_DECLARE(sun8i_r40_ccu, "allwinner,sun8i-r40-ccu", + sun8i_r40_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.h b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h new file mode 100644 index 000000000000..0db8e1e97af8 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Icenowy Zheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CCU_SUN8I_R40_H_ +#define _CCU_SUN8I_R40_H_ + +#include +#include + +#define CLK_OSC_12M 0 +#define CLK_PLL_CPU 1 +#define CLK_PLL_AUDIO_BASE 2 +#define CLK_PLL_AUDIO 3 +#define CLK_PLL_AUDIO_2X 4 +#define CLK_PLL_AUDIO_4X 5 +#define CLK_PLL_AUDIO_8X 6 +#define CLK_PLL_VIDEO0 7 +#define CLK_PLL_VIDEO0_2X 8 +#define CLK_PLL_VE 9 +#define CLK_PLL_DDR0 10 +#define CLK_PLL_PERIPH0 11 +#define CLK_PLL_PERIPH0_SATA 12 +#define CLK_PLL_PERIPH0_2X 13 +#define CLK_PLL_PERIPH1 14 +#define CLK_PLL_PERIPH1_2X 15 +#define CLK_PLL_VIDEO1 16 +#define CLK_PLL_VIDEO1_2X 17 +#define CLK_PLL_SATA 18 +#define CLK_PLL_SATA_OUT 19 +#define CLK_PLL_GPU 20 +#define CLK_PLL_MIPI 21 +#define CLK_PLL_DE 22 +#define CLK_PLL_DDR1 23 + +/* The CPU clock is exported */ + +#define CLK_AXI 25 +#define CLK_AHB1 26 +#define CLK_APB1 27 +#define CLK_APB2 28 + +/* All the bus gates are exported */ + +/* The first bunch of module clocks are exported */ + +#define CLK_DRAM 132 + +/* All the DRAM gates are exported */ + +/* Some more module clocks are exported */ + +#define CLK_MBUS 155 + +/* Another bunch of module clocks are exported */ + +#define CLK_NUMBER (CLK_OUTB + 1) + +#endif /* _CCU_SUN8I_R40_H_ */ diff --git a/include/dt-bindings/clock/sun8i-r40-ccu.h b/include/dt-bindings/clock/sun8i-r40-ccu.h new file mode 100644 index 000000000000..4fa5f69fc297 --- /dev/null +++ b/include/dt-bindings/clock/sun8i-r40-ccu.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2017 Icenowy Zheng + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN8I_R40_H_ +#define _DT_BINDINGS_CLK_SUN8I_R40_H_ + +#define CLK_CPU 24 + +#define CLK_BUS_MIPI_DSI 29 +#define CLK_BUS_CE 30 +#define CLK_BUS_DMA 31 +#define CLK_BUS_MMC0 32 +#define CLK_BUS_MMC1 33 +#define CLK_BUS_MMC2 34 +#define CLK_BUS_MMC3 35 +#define CLK_BUS_NAND 36 +#define CLK_BUS_DRAM 37 +#define CLK_BUS_EMAC 38 +#define CLK_BUS_TS 39 +#define CLK_BUS_HSTIMER 40 +#define CLK_BUS_SPI0 41 +#define CLK_BUS_SPI1 42 +#define CLK_BUS_SPI2 43 +#define CLK_BUS_SPI3 44 +#define CLK_BUS_SATA 45 +#define CLK_BUS_OTG 46 +#define CLK_BUS_EHCI0 47 +#define CLK_BUS_EHCI1 48 +#define CLK_BUS_EHCI2 49 +#define CLK_BUS_OHCI0 50 +#define CLK_BUS_OHCI1 51 +#define CLK_BUS_OHCI2 52 +#define CLK_BUS_VE 53 +#define CLK_BUS_MP 54 +#define CLK_BUS_DEINTERLACE 55 +#define CLK_BUS_CSI0 56 +#define CLK_BUS_CSI1 57 +#define CLK_BUS_HDMI1 58 +#define CLK_BUS_HDMI0 59 +#define CLK_BUS_DE 60 +#define CLK_BUS_TVE0 61 +#define CLK_BUS_TVE1 62 +#define CLK_BUS_TVE_TOP 63 +#define CLK_BUS_GMAC 64 +#define CLK_BUS_GPU 65 +#define CLK_BUS_TVD0 66 +#define CLK_BUS_TVD1 67 +#define CLK_BUS_TVD2 68 +#define CLK_BUS_TVD3 69 +#define CLK_BUS_TVD_TOP 70 +#define CLK_BUS_TCON_LCD0 71 +#define CLK_BUS_TCON_LCD1 72 +#define CLK_BUS_TCON_TV0 73 +#define CLK_BUS_TCON_TV1 74 +#define CLK_BUS_TCON_TOP 75 +#define CLK_BUS_CODEC 76 +#define CLK_BUS_SPDIF 77 +#define CLK_BUS_AC97 78 +#define CLK_BUS_PIO 79 +#define CLK_BUS_IR0 80 +#define CLK_BUS_IR1 81 +#define CLK_BUS_THS 82 +#define CLK_BUS_KEYPAD 83 +#define CLK_BUS_I2S0 84 +#define CLK_BUS_I2S1 85 +#define CLK_BUS_I2S2 86 +#define CLK_BUS_I2C0 87 +#define CLK_BUS_I2C1 88 +#define CLK_BUS_I2C2 89 +#define CLK_BUS_I2C3 90 +#define CLK_BUS_CAN 91 +#define CLK_BUS_SCR 92 +#define CLK_BUS_PS20 93 +#define CLK_BUS_PS21 94 +#define CLK_BUS_I2C4 95 +#define CLK_BUS_UART0 96 +#define CLK_BUS_UART1 97 +#define CLK_BUS_UART2 98 +#define CLK_BUS_UART3 99 +#define CLK_BUS_UART4 100 +#define CLK_BUS_UART5 101 +#define CLK_BUS_UART6 102 +#define CLK_BUS_UART7 103 +#define CLK_BUS_DBG 104 + +#define CLK_THS 105 +#define CLK_NAND 106 +#define CLK_MMC0 107 +#define CLK_MMC1 108 +#define CLK_MMC2 109 +#define CLK_MMC3 110 +#define CLK_TS 111 +#define CLK_CE 112 +#define CLK_SPI0 113 +#define CLK_SPI1 114 +#define CLK_SPI2 115 +#define CLK_SPI3 116 +#define CLK_I2S0 117 +#define CLK_I2S1 118 +#define CLK_I2S2 119 +#define CLK_AC97 120 +#define CLK_SPDIF 121 +#define CLK_KEYPAD 122 +#define CLK_SATA 123 +#define CLK_USB_PHY0 124 +#define CLK_USB_PHY1 125 +#define CLK_USB_PHY2 126 +#define CLK_USB_OHCI0 127 +#define CLK_USB_OHCI1 128 +#define CLK_USB_OHCI2 129 +#define CLK_IR0 130 +#define CLK_IR1 131 + +#define CLK_DRAM_VE 133 +#define CLK_DRAM_CSI0 134 +#define CLK_DRAM_CSI1 135 +#define CLK_DRAM_TS 136 +#define CLK_DRAM_TVD 137 +#define CLK_DRAM_MP 138 +#define CLK_DRAM_DEINTERLACE 139 +#define CLK_DE 140 +#define CLK_MP 141 +#define CLK_TCON_LCD0 142 +#define CLK_TCON_LCD1 143 +#define CLK_TCON_TV0 144 +#define CLK_TCON_TV1 145 +#define CLK_DEINTERLACE 146 +#define CLK_CSI1_MCLK 147 +#define CLK_CSI_SCLK 148 +#define CLK_CSI0_MCLK 149 +#define CLK_VE 150 +#define CLK_CODEC 151 +#define CLK_AVS 152 +#define CLK_HDMI 153 +#define CLK_HDMI_SLOW 154 + +#define CLK_DSI_DPHY 156 +#define CLK_TVE0 157 +#define CLK_TVE1 158 +#define CLK_TVD0 159 +#define CLK_TVD1 160 +#define CLK_TVD2 161 +#define CLK_TVD3 162 +#define CLK_GPU 163 +#define CLK_OUTA 164 +#define CLK_OUTB 165 + +#endif /* _DT_BINDINGS_CLK_SUN8I_R40_H_ */ diff --git a/include/dt-bindings/reset/sun8i-r40-ccu.h b/include/dt-bindings/reset/sun8i-r40-ccu.h new file mode 100644 index 000000000000..c5ebcf6672e4 --- /dev/null +++ b/include/dt-bindings/reset/sun8i-r40-ccu.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2017 Icenowy Zheng + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_RST_SUN8I_R40_H_ +#define _DT_BINDINGS_RST_SUN8I_R40_H_ + +#define RST_USB_PHY0 0 +#define RST_USB_PHY1 1 +#define RST_USB_PHY2 2 + +#define RST_DRAM 3 +#define RST_MBUS 4 + +#define RST_BUS_MIPI_DSI 5 +#define RST_BUS_CE 6 +#define RST_BUS_DMA 7 +#define RST_BUS_MMC0 8 +#define RST_BUS_MMC1 9 +#define RST_BUS_MMC2 10 +#define RST_BUS_MMC3 11 +#define RST_BUS_NAND 12 +#define RST_BUS_DRAM 13 +#define RST_BUS_EMAC 14 +#define RST_BUS_TS 15 +#define RST_BUS_HSTIMER 16 +#define RST_BUS_SPI0 17 +#define RST_BUS_SPI1 18 +#define RST_BUS_SPI2 19 +#define RST_BUS_SPI3 20 +#define RST_BUS_SATA 21 +#define RST_BUS_OTG 22 +#define RST_BUS_EHCI0 23 +#define RST_BUS_EHCI1 24 +#define RST_BUS_EHCI2 25 +#define RST_BUS_OHCI0 26 +#define RST_BUS_OHCI1 27 +#define RST_BUS_OHCI2 28 +#define RST_BUS_VE 29 +#define RST_BUS_MP 30 +#define RST_BUS_DEINTERLACE 31 +#define RST_BUS_CSI0 32 +#define RST_BUS_CSI1 33 +#define RST_BUS_HDMI0 34 +#define RST_BUS_HDMI1 35 +#define RST_BUS_DE 36 +#define RST_BUS_TVE0 37 +#define RST_BUS_TVE1 38 +#define RST_BUS_TVE_TOP 39 +#define RST_BUS_GMAC 40 +#define RST_BUS_GPU 41 +#define RST_BUS_TVD0 42 +#define RST_BUS_TVD1 43 +#define RST_BUS_TVD2 44 +#define RST_BUS_TVD3 45 +#define RST_BUS_TVD_TOP 46 +#define RST_BUS_TCON_LCD0 47 +#define RST_BUS_TCON_LCD1 48 +#define RST_BUS_TCON_TV0 49 +#define RST_BUS_TCON_TV1 50 +#define RST_BUS_TCON_TOP 51 +#define RST_BUS_DBG 52 +#define RST_BUS_LVDS 53 +#define RST_BUS_CODEC 54 +#define RST_BUS_SPDIF 55 +#define RST_BUS_AC97 56 +#define RST_BUS_IR0 57 +#define RST_BUS_IR1 58 +#define RST_BUS_THS 59 +#define RST_BUS_KEYPAD 60 +#define RST_BUS_I2S0 61 +#define RST_BUS_I2S1 62 +#define RST_BUS_I2S2 63 +#define RST_BUS_I2C0 64 +#define RST_BUS_I2C1 65 +#define RST_BUS_I2C2 66 +#define RST_BUS_I2C3 67 +#define RST_BUS_CAN 68 +#define RST_BUS_SCR 69 +#define RST_BUS_PS20 70 +#define RST_BUS_PS21 71 +#define RST_BUS_I2C4 72 +#define RST_BUS_UART0 73 +#define RST_BUS_UART1 74 +#define RST_BUS_UART2 75 +#define RST_BUS_UART3 76 +#define RST_BUS_UART4 77 +#define RST_BUS_UART5 78 +#define RST_BUS_UART6 79 +#define RST_BUS_UART7 80 + +#endif /* _DT_BINDINGS_RST_SUN8I_R40_H_ */ -- cgit v1.2.3 From 9762e7ff163213e18ed8e7cc723d74b54bf9cb98 Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Fri, 18 Aug 2017 11:49:24 +0800 Subject: clk: rockchip: add rk3228 sclk_sdio_src ID This patch exports sdio src clock for dts reference. Signed-off-by: Elaine Zhang Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3228-cru.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/dt-bindings') diff --git a/include/dt-bindings/clock/rk3228-cru.h b/include/dt-bindings/clock/rk3228-cru.h index 56f841c22801..55655ab0a4c4 100644 --- a/include/dt-bindings/clock/rk3228-cru.h +++ b/include/dt-bindings/clock/rk3228-cru.h @@ -49,6 +49,7 @@ #define SCLK_EMMC_DRV 117 #define SCLK_SDMMC_SAMPLE 118 #define SCLK_SDIO_SAMPLE 119 +#define SCLK_SDIO_SRC 120 #define SCLK_EMMC_SAMPLE 121 #define SCLK_VOP 122 #define SCLK_HDMI_HDCP 123 -- cgit v1.2.3 From 1858698e0ac63f4fd3a633064893b5fd6ef8aa8d Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Mon, 21 Aug 2017 16:16:04 +0800 Subject: clk: rockchip: add rv1108 ACLK_GAMC and PCLK_GMAC ID This patch exports gmac aclk and pclk for dts reference. Signed-off-by: Elaine Zhang Reviewed-by: David Wu Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rv1108-cru.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/dt-bindings') diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h index f269d833e41a..2239ae2a19b9 100644 --- a/include/dt-bindings/clock/rv1108-cru.h +++ b/include/dt-bindings/clock/rv1108-cru.h @@ -110,6 +110,7 @@ #define ACLK_CIF2 207 #define ACLK_CIF3 208 #define ACLK_PERI 209 +#define ACLK_GMAC 210 /* pclk gates */ #define PCLK_GPIO1 256 @@ -141,6 +142,7 @@ #define PCLK_EFUSE0 282 #define PCLK_EFUSE1 283 #define PCLK_WDT 284 +#define PCLK_GMAC 285 /* hclk gates */ #define HCLK_I2S0_8CH 320 -- cgit v1.2.3 From c7d0045b08a36c2fb7874efc48d747613c6a1ccf Mon Sep 17 00:00:00 2001 From: Elaine Zhang Date: Mon, 21 Aug 2017 16:16:06 +0800 Subject: clk: rockchip: rename rv1108 macphy clock to mac This MAC has no internal phy for rv1108 and the whole clock infrastructure hasn't been used yet, so is safe to fix. Signed-off-by: Elaine Zhang Reviewed-by: David Wu Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rv1108.c | 12 ++++++------ include/dt-bindings/clock/rv1108-cru.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'include/dt-bindings') diff --git a/drivers/clk/rockchip/clk-rv1108.c b/drivers/clk/rockchip/clk-rv1108.c index 0e441ec21e90..c9045f85b498 100644 --- a/drivers/clk/rockchip/clk-rv1108.c +++ b/drivers/clk/rockchip/clk-rv1108.c @@ -140,7 +140,7 @@ PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; -PNAME(mux_sclk_macphy_p) = { "ext_gmac", "sclk_macphy_pre" }; +PNAME(mux_sclk_mac_p) = { "ext_gmac", "sclk_mac_pre" }; PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "dummy", "xin12m" }; @@ -755,14 +755,14 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { RV1108_CLKGATE_CON(5), 4, GFLAGS), GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), - COMPOSITE(SCLK_MACPHY_PRE, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, + COMPOSITE(SCLK_MAC_PRE, "sclk_mac_pre", mux_pll_src_apll_gpll_p, 0, RV1108_CLKSEL_CON(24), 12, 1, MFLAGS, 0, 5, DFLAGS, RV1108_CLKGATE_CON(4), 10, GFLAGS), - MUX(SCLK_MACPHY, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, + MUX(SCLK_MAC, "sclk_mac", mux_sclk_mac_p, CLK_SET_RATE_PARENT, RV1108_CLKSEL_CON(24), 8, 1, MFLAGS), - GATE(SCLK_MACPHY_RX, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), - GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), - GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), + GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), + GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), + GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), GATE(ACLK_GMAC, "aclk_gmac", "aclk_periph", 0, RV1108_CLKGATE_CON(15), 4, GFLAGS), GATE(PCLK_GMAC, "pclk_gmac", "pclk_periph", 0, RV1108_CLKGATE_CON(15), 5, GFLAGS), diff --git a/include/dt-bindings/clock/rv1108-cru.h b/include/dt-bindings/clock/rv1108-cru.h index 2239ae2a19b9..d8d0e0456dc2 100644 --- a/include/dt-bindings/clock/rv1108-cru.h +++ b/include/dt-bindings/clock/rv1108-cru.h @@ -67,9 +67,9 @@ #define SCLK_SPI 108 #define SCLK_SARADC 109 #define SCLK_TSADC 110 -#define SCLK_MACPHY_PRE 111 -#define SCLK_MACPHY 112 -#define SCLK_MACPHY_RX 113 +#define SCLK_MAC_PRE 111 +#define SCLK_MAC 112 +#define SCLK_MAC_RX 113 #define SCLK_MAC_REF 114 #define SCLK_MAC_REFOUT 115 #define SCLK_DSP_PFM 116 -- cgit v1.2.3 From 69a6beab085264cdcdb9e3160b1a2ae61b2efde1 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 14 Aug 2017 12:26:34 +0200 Subject: clk: msm8996-gcc: add missing smmu clks This patch adds missing LPASS smmu clks which are required by the audio driver. Signed-off-by: Srinivas Kandagatla Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8996.c | 28 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8996.h | 2 ++ 2 files changed, 30 insertions(+) (limited to 'include/dt-bindings') diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 8abc200d4fd3..7ddec886fcd3 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -2730,6 +2730,32 @@ static struct clk_fixed_factor ufs_rx_cfg_clk_src = { }, }; +static struct clk_branch gcc_hlos1_vote_lpass_core_smmu_clk = { + .halt_reg = 0x7d010, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "hlos1_vote_lpass_core_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_hlos1_vote_lpass_adsp_smmu_clk = { + .halt_reg = 0x7d014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7d014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "hlos1_vote_lpass_adsp_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_ufs_rx_cfg_clk = { .halt_reg = 0x75014, .clkr = { @@ -3307,6 +3333,8 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, + [GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &gcc_hlos1_vote_lpass_core_smmu_clk.clkr, + [GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &gcc_hlos1_vote_lpass_adsp_smmu_clk.clkr, [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, diff --git a/include/dt-bindings/clock/qcom,gcc-msm8996.h b/include/dt-bindings/clock/qcom,gcc-msm8996.h index 1f5c42254798..75b07cf5eed0 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8996.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8996.h @@ -233,6 +233,8 @@ #define GCC_PCIE_CLKREF_CLK 216 #define GCC_RX2_USB2_CLKREF_CLK 217 #define GCC_RX1_USB2_CLKREF_CLK 218 +#define GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK 219 +#define GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 220 #define GCC_SYSTEM_NOC_BCR 0 #define GCC_CONFIG_NOC_BCR 1 -- cgit v1.2.3 From c84f5683f6e9fee78e054431d89121225ccb7464 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Wed, 23 Aug 2017 20:23:29 +0300 Subject: clk: sunxi-ng: Add sun4i/sun7i CCU driver Introduce a clock controller driver for sun4i A10 and sun7i A20 series SoCs. Signed-off-by: Priit Laes Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/Kconfig | 13 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 1456 +++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun4i-a10.h | 61 ++ include/dt-bindings/clock/sun4i-a10-ccu.h | 200 ++++ include/dt-bindings/clock/sun7i-a20-ccu.h | 53 ++ include/dt-bindings/reset/sun4i-a10-ccu.h | 69 ++ 7 files changed, 1853 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun4i-a10.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun4i-a10.h create mode 100644 include/dt-bindings/clock/sun4i-a10-ccu.h create mode 100644 include/dt-bindings/clock/sun7i-a20-ccu.h create mode 100644 include/dt-bindings/reset/sun4i-a10-ccu.h (limited to 'include/dt-bindings') diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 7a360737fe3c..6427d0ebe2de 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -11,6 +11,19 @@ config SUN50I_A64_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN4I_A10_CCU + bool "Support for the Allwinner A10/A20 CCU" + select SUNXI_CCU_DIV + select SUNXI_CCU_MULT + select SUNXI_CCU_NK + select SUNXI_CCU_NKM + select SUNXI_CCU_NM + select SUNXI_CCU_MP + select SUNXI_CCU_PHASE + default MACH_SUN4I + default MACH_SUN7I + depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST + config SUN5I_CCU bool "Support for the Allwinner sun5i family CCM" default MACH_SUN5I diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 58741cd647c3..1fd8fe9c1e3e 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -19,6 +19,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_mp.o # SoC support obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o +obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c new file mode 100644 index 000000000000..286b0049b7b6 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -0,0 +1,1456 @@ +/* + * Copyright (c) 2017 Priit Laes . + * Copyright (c) 2017 Maxime Ripard. + * Copyright (c) 2017 Jonathan Liu. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" +#include "ccu_phase.h" + +#include "ccu-sun4i-a10.h" + +static struct ccu_nkmp pll_core_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .m = _SUNXI_CCU_DIV(0, 2), + .p = _SUNXI_CCU_DIV(16, 2), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-core", + "hosc", + &ccu_nkmp_ops, + 0), + }, +}; + +/* + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from + * the base (2x, 4x and 8x), and one variable divider (the one true + * pll audio). + * + * We don't have any need for the variable divider for now, so we just + * hardcode it to match with the clock names. + */ +#define SUN4I_PLL_AUDIO_REG 0x008 +static struct ccu_nm pll_audio_base_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), + .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), + .common = { + .reg = 0x008, + .hw.init = CLK_HW_INIT("pll-audio-base", + "hosc", + &ccu_nm_ops, + 0), + }, + +}; + +static struct ccu_mult pll_video0_clk = { + .enable = BIT(31), + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), + 270000000, 297000000), + .common = { + .reg = 0x010, + .features = (CCU_FEATURE_FRACTIONAL | + CCU_FEATURE_ALL_PREDIV), + .prediv = 8, + .hw.init = CLK_HW_INIT("pll-video0", + "hosc", + &ccu_mult_ops, + 0), + }, +}; + +static struct ccu_nkmp pll_ve_sun4i_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .m = _SUNXI_CCU_DIV(0, 2), + .p = _SUNXI_CCU_DIV(16, 2), + .common = { + .reg = 0x018, + .hw.init = CLK_HW_INIT("pll-ve", + "hosc", + &ccu_nkmp_ops, + 0), + }, +}; + +static struct ccu_nk pll_ve_sun7i_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .common = { + .reg = 0x018, + .hw.init = CLK_HW_INIT("pll-ve", + "hosc", + &ccu_nk_ops, + 0), + }, +}; + +static struct ccu_nk pll_ddr_base_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .common = { + .reg = 0x020, + .hw.init = CLK_HW_INIT("pll-ddr-base", + "hosc", + &ccu_nk_ops, + 0), + }, +}; + +static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2, + CLK_IS_CRITICAL); + +static struct ccu_div pll_ddr_other_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO), + .common = { + .reg = 0x020, + .hw.init = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base", + &ccu_div_ops, + 0), + }, +}; + +static struct ccu_nk pll_periph_base_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .common = { + .reg = 0x028, + .hw.init = CLK_HW_INIT("pll-periph-base", + "hosc", + &ccu_nk_ops, + 0), + }, +}; + +static CLK_FIXED_FACTOR(pll_periph_clk, "pll-periph", "pll-periph-base", + 2, 1, CLK_SET_RATE_PARENT); + +/* Not documented on A10 */ +static struct ccu_div pll_periph_sata_clk = { + .enable = BIT(14), + .div = _SUNXI_CCU_DIV(0, 2), + .fixed_post_div = 6, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph-sata", + "pll-periph-base", + &ccu_div_ops, 0), + }, +}; + +static struct ccu_mult pll_video1_clk = { + .enable = BIT(31), + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), + 270000000, 297000000), + .common = { + .reg = 0x030, + .features = (CCU_FEATURE_FRACTIONAL | + CCU_FEATURE_ALL_PREDIV), + .prediv = 8, + .hw.init = CLK_HW_INIT("pll-video1", + "hosc", + &ccu_mult_ops, + 0), + }, +}; + +/* Not present on A10 */ +static struct ccu_nk pll_gpu_clk = { + .enable = BIT(31), + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), + .k = _SUNXI_CCU_MULT(4, 2), + .common = { + .reg = 0x040, + .hw.init = CLK_HW_INIT("pll-gpu", + "hosc", + &ccu_nk_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(hosc_clk, "hosc", "osc24M", 0x050, BIT(0), 0); + +static const char *const cpu_parents[] = { "osc32k", "hosc", + "pll-core", "pll-periph" }; +static const struct ccu_mux_fixed_prediv cpu_predivs[] = { + { .index = 3, .div = 3, }, +}; + +#define SUN4I_AHB_REG 0x054 +static struct ccu_mux cpu_clk = { + .mux = { + .shift = 16, + .width = 2, + .fixed_predivs = cpu_predivs, + .n_predivs = ARRAY_SIZE(cpu_predivs), + }, + .common = { + .reg = 0x054, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("cpu", + cpu_parents, + &ccu_mux_ops, + CLK_IS_CRITICAL), + } +}; + +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0); + +static struct ccu_div ahb_sun4i_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), + .common = { + .reg = 0x054, + .hw.init = CLK_HW_INIT("ahb", "axi", &ccu_div_ops, 0), + }, +}; + +static const char *const ahb_sun7i_parents[] = { "axi", "pll-periph", + "pll-periph" }; +static const struct ccu_mux_fixed_prediv ahb_sun7i_predivs[] = { + { .index = 1, .div = 2, }, + { /* Sentinel */ }, +}; +static struct ccu_div ahb_sun7i_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = { + .shift = 6, + .width = 2, + .fixed_predivs = ahb_sun7i_predivs, + .n_predivs = ARRAY_SIZE(ahb_sun7i_predivs), + }, + + .common = { + .reg = 0x054, + .hw.init = CLK_HW_INIT_PARENTS("ahb", + ahb_sun7i_parents, + &ccu_div_ops, + 0), + }, +}; + +static struct clk_div_table apb0_div_table[] = { + { .val = 0, .div = 2 }, + { .val = 1, .div = 2 }, + { .val = 2, .div = 4 }, + { .val = 3, .div = 8 }, + { /* Sentinel */ }, +}; +static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb", + 0x054, 8, 2, apb0_div_table, 0); + +static const char *const apb1_parents[] = { "hosc", "pll-periph", "osc32k" }; +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058, + 0, 5, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + 0); + +/* Not present on A20 */ +static SUNXI_CCU_GATE(axi_dram_clk, "axi-dram", "ahb", + 0x05c, BIT(31), 0); + +static SUNXI_CCU_GATE(ahb_otg_clk, "ahb-otg", "ahb", + 0x060, BIT(0), 0); +static SUNXI_CCU_GATE(ahb_ehci0_clk, "ahb-ehci0", "ahb", + 0x060, BIT(1), 0); +static SUNXI_CCU_GATE(ahb_ohci0_clk, "ahb-ohci0", "ahb", + 0x060, BIT(2), 0); +static SUNXI_CCU_GATE(ahb_ehci1_clk, "ahb-ehci1", "ahb", + 0x060, BIT(3), 0); +static SUNXI_CCU_GATE(ahb_ohci1_clk, "ahb-ohci1", "ahb", + 0x060, BIT(4), 0); +static SUNXI_CCU_GATE(ahb_ss_clk, "ahb-ss", "ahb", + 0x060, BIT(5), 0); +static SUNXI_CCU_GATE(ahb_dma_clk, "ahb-dma", "ahb", + 0x060, BIT(6), 0); +static SUNXI_CCU_GATE(ahb_bist_clk, "ahb-bist", "ahb", + 0x060, BIT(7), 0); +static SUNXI_CCU_GATE(ahb_mmc0_clk, "ahb-mmc0", "ahb", + 0x060, BIT(8), 0); +static SUNXI_CCU_GATE(ahb_mmc1_clk, "ahb-mmc1", "ahb", + 0x060, BIT(9), 0); +static SUNXI_CCU_GATE(ahb_mmc2_clk, "ahb-mmc2", "ahb", + 0x060, BIT(10), 0); +static SUNXI_CCU_GATE(ahb_mmc3_clk, "ahb-mmc3", "ahb", + 0x060, BIT(11), 0); +static SUNXI_CCU_GATE(ahb_ms_clk, "ahb-ms", "ahb", + 0x060, BIT(12), 0); +static SUNXI_CCU_GATE(ahb_nand_clk, "ahb-nand", "ahb", + 0x060, BIT(13), 0); +static SUNXI_CCU_GATE(ahb_sdram_clk, "ahb-sdram", "ahb", + 0x060, BIT(14), CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE(ahb_ace_clk, "ahb-ace", "ahb", + 0x060, BIT(16), 0); +static SUNXI_CCU_GATE(ahb_emac_clk, "ahb-emac", "ahb", + 0x060, BIT(17), 0); +static SUNXI_CCU_GATE(ahb_ts_clk, "ahb-ts", "ahb", + 0x060, BIT(18), 0); +static SUNXI_CCU_GATE(ahb_spi0_clk, "ahb-spi0", "ahb", + 0x060, BIT(20), 0); +static SUNXI_CCU_GATE(ahb_spi1_clk, "ahb-spi1", "ahb", + 0x060, BIT(21), 0); +static SUNXI_CCU_GATE(ahb_spi2_clk, "ahb-spi2", "ahb", + 0x060, BIT(22), 0); +static SUNXI_CCU_GATE(ahb_spi3_clk, "ahb-spi3", "ahb", + 0x060, BIT(23), 0); +static SUNXI_CCU_GATE(ahb_pata_clk, "ahb-pata", "ahb", + 0x060, BIT(24), 0); +/* Not documented on A20 */ +static SUNXI_CCU_GATE(ahb_sata_clk, "ahb-sata", "ahb", + 0x060, BIT(25), 0); +/* Not present on A20 */ +static SUNXI_CCU_GATE(ahb_gps_clk, "ahb-gps", "ahb", + 0x060, BIT(26), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer", "ahb", + 0x060, BIT(28), 0); + +static SUNXI_CCU_GATE(ahb_ve_clk, "ahb-ve", "ahb", + 0x064, BIT(0), 0); +static SUNXI_CCU_GATE(ahb_tvd_clk, "ahb-tvd", "ahb", + 0x064, BIT(1), 0); +static SUNXI_CCU_GATE(ahb_tve0_clk, "ahb-tve0", "ahb", + 0x064, BIT(2), 0); +static SUNXI_CCU_GATE(ahb_tve1_clk, "ahb-tve1", "ahb", + 0x064, BIT(3), 0); +static SUNXI_CCU_GATE(ahb_lcd0_clk, "ahb-lcd0", "ahb", + 0x064, BIT(4), 0); +static SUNXI_CCU_GATE(ahb_lcd1_clk, "ahb-lcd1", "ahb", + 0x064, BIT(5), 0); +static SUNXI_CCU_GATE(ahb_csi0_clk, "ahb-csi0", "ahb", + 0x064, BIT(8), 0); +static SUNXI_CCU_GATE(ahb_csi1_clk, "ahb-csi1", "ahb", + 0x064, BIT(9), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(ahb_hdmi1_clk, "ahb-hdmi1", "ahb", + 0x064, BIT(10), 0); +static SUNXI_CCU_GATE(ahb_hdmi0_clk, "ahb-hdmi0", "ahb", + 0x064, BIT(11), 0); +static SUNXI_CCU_GATE(ahb_de_be0_clk, "ahb-de-be0", "ahb", + 0x064, BIT(12), 0); +static SUNXI_CCU_GATE(ahb_de_be1_clk, "ahb-de-be1", "ahb", + 0x064, BIT(13), 0); +static SUNXI_CCU_GATE(ahb_de_fe0_clk, "ahb-de-fe0", "ahb", + 0x064, BIT(14), 0); +static SUNXI_CCU_GATE(ahb_de_fe1_clk, "ahb-de-fe1", "ahb", + 0x064, BIT(15), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(ahb_gmac_clk, "ahb-gmac", "ahb", + 0x064, BIT(17), 0); +static SUNXI_CCU_GATE(ahb_mp_clk, "ahb-mp", "ahb", + 0x064, BIT(18), 0); +static SUNXI_CCU_GATE(ahb_gpu_clk, "ahb-gpu", "ahb", + 0x064, BIT(20), 0); + +static SUNXI_CCU_GATE(apb0_codec_clk, "apb0-codec", "apb0", + 0x068, BIT(0), 0); +static SUNXI_CCU_GATE(apb0_spdif_clk, "apb0-spdif", "apb0", + 0x068, BIT(1), 0); +static SUNXI_CCU_GATE(apb0_ac97_clk, "apb0-ac97", "apb0", + 0x068, BIT(2), 0); +static SUNXI_CCU_GATE(apb0_i2s0_clk, "apb0-i2s0", "apb0", + 0x068, BIT(3), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(apb0_i2s1_clk, "apb0-i2s1", "apb0", + 0x068, BIT(4), 0); +static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0", + 0x068, BIT(5), 0); +static SUNXI_CCU_GATE(apb0_ir0_clk, "apb0-ir0", "apb0", + 0x068, BIT(6), 0); +static SUNXI_CCU_GATE(apb0_ir1_clk, "apb0-ir1", "apb0", + 0x068, BIT(7), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(apb0_i2s2_clk, "apb0-i2s2", "apb0", + 0x068, BIT(8), 0); +static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad", "apb0", + 0x068, BIT(10), 0); + +static SUNXI_CCU_GATE(apb1_i2c0_clk, "apb1-i2c0", "apb1", + 0x06c, BIT(0), 0); +static SUNXI_CCU_GATE(apb1_i2c1_clk, "apb1-i2c1", "apb1", + 0x06c, BIT(1), 0); +static SUNXI_CCU_GATE(apb1_i2c2_clk, "apb1-i2c2", "apb1", + 0x06c, BIT(2), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(apb1_i2c3_clk, "apb1-i2c3", "apb1", + 0x06c, BIT(3), 0); +static SUNXI_CCU_GATE(apb1_can_clk, "apb1-can", "apb1", + 0x06c, BIT(4), 0); +static SUNXI_CCU_GATE(apb1_scr_clk, "apb1-scr", "apb1", + 0x06c, BIT(5), 0); +static SUNXI_CCU_GATE(apb1_ps20_clk, "apb1-ps20", "apb1", + 0x06c, BIT(6), 0); +static SUNXI_CCU_GATE(apb1_ps21_clk, "apb1-ps21", "apb1", + 0x06c, BIT(7), 0); +/* Not present on A10 */ +static SUNXI_CCU_GATE(apb1_i2c4_clk, "apb1-i2c4", "apb1", + 0x06c, BIT(15), 0); +static SUNXI_CCU_GATE(apb1_uart0_clk, "apb1-uart0", "apb1", + 0x06c, BIT(16), 0); +static SUNXI_CCU_GATE(apb1_uart1_clk, "apb1-uart1", "apb1", + 0x06c, BIT(17), 0); +static SUNXI_CCU_GATE(apb1_uart2_clk, "apb1-uart2", "apb1", + 0x06c, BIT(18), 0); +static SUNXI_CCU_GATE(apb1_uart3_clk, "apb1-uart3", "apb1", + 0x06c, BIT(19), 0); +static SUNXI_CCU_GATE(apb1_uart4_clk, "apb1-uart4", "apb1", + 0x06c, BIT(20), 0); +static SUNXI_CCU_GATE(apb1_uart5_clk, "apb1-uart5", "apb1", + 0x06c, BIT(21), 0); +static SUNXI_CCU_GATE(apb1_uart6_clk, "apb1-uart6", "apb1", + 0x06c, BIT(22), 0); +static SUNXI_CCU_GATE(apb1_uart7_clk, "apb1-uart7", "apb1", + 0x06c, BIT(23), 0); + +static const char *const mod0_default_parents[] = { "hosc", "pll-periph", + "pll-ddr-other" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* Undocumented on A10 */ +static SUNXI_CCU_MP_WITH_MUX_GATE(ms_clk, "ms", mod0_default_parents, 0x084, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* MMC output and sample clocks are not present on A10 */ +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0", + 0x088, 8, 3, 0); +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0", + 0x088, 20, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* MMC output and sample clocks are not present on A10 */ +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1", + 0x08c, 8, 3, 0); +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1", + 0x08c, 20, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* MMC output and sample clocks are not present on A10 */ +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2", + 0x090, 8, 3, 0); +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2", + 0x090, 20, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* MMC output and sample clocks are not present on A10 */ +static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3_output", "mmc3", + 0x094, 8, 3, 0); +static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3_sample", "mmc3", + 0x094, 20, 3, 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* Undocumented on A10 */ +static SUNXI_CCU_MP_WITH_MUX_GATE(pata_clk, "pata", mod0_default_parents, 0x0ac, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* TODO: Check whether A10 actually supports osc32k as 4th parent? */ +static const char *const ir_parents_sun4i[] = { "hosc", "pll-periph", + "pll-ddr-other" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun4i_clk, "ir0", ir_parents_sun4i, 0x0b0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun4i_clk, "ir1", ir_parents_sun4i, 0x0b4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); +static const char *const ir_parents_sun7i[] = { "hosc", "pll-periph", + "pll-ddr-other", "osc32k" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun7i_clk, "ir0", ir_parents_sun7i, 0x0b0, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun7i_clk, "ir1", ir_parents_sun7i, 0x0b4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static const char *const audio_parents[] = { "pll-audio-8x", "pll-audio-4x", + "pll-audio-2x", "pll-audio" }; +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", audio_parents, + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", audio_parents, + 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +/* Undocumented on A10 */ +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", audio_parents, + 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static const char *const keypad_parents[] = { "hosc", "losc"}; +static const u8 keypad_table[] = { 0, 2 }; +static struct ccu_mp keypad_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(0, 5), + .p = _SUNXI_CCU_DIV(16, 2), + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), + .common = { + .reg = 0x0c4, + .hw.init = CLK_HW_INIT_PARENTS("keypad", + keypad_parents, + &ccu_mp_ops, + 0), + }, +}; + +/* + * SATA supports external clock as parent via BIT(24) and is probably an + * optional crystal or oscillator that can be connected to the + * SATA-CLKM / SATA-CLKP pins. + */ +static const char *const sata_parents[] = {"pll-periph-sata", "sata-ext"}; +static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, + 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); + + +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "pll-periph", + 0x0cc, BIT(6), 0); +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "pll-periph", + 0x0cc, BIT(7), 0); +static SUNXI_CCU_GATE(usb_phy_clk, "usb-phy", "pll-periph", + 0x0cc, BIT(8), 0); + +/* TODO: GPS CLK 0x0d0 */ + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0d4, + 0, 4, /* M */ + 16, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +/* Not present on A10 */ +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", audio_parents, + 0x0d8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +/* Not present on A10 */ +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", audio_parents, + 0x0dc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr", + 0x100, BIT(0), 0); +static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "pll-ddr", + 0x100, BIT(1), 0); +static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "pll-ddr", + 0x100, BIT(2), 0); +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "pll-ddr", + 0x100, BIT(3), 0); +static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr", + 0x100, BIT(4), 0); +static SUNXI_CCU_GATE(dram_tve0_clk, "dram-tve0", "pll-ddr", + 0x100, BIT(5), 0); +static SUNXI_CCU_GATE(dram_tve1_clk, "dram-tve1", "pll-ddr", + 0x100, BIT(6), 0); + +/* Clock seems to be critical only on sun4i */ +static SUNXI_CCU_GATE(dram_out_clk, "dram-out", "pll-ddr", + 0x100, BIT(15), CLK_IS_CRITICAL); +static SUNXI_CCU_GATE(dram_de_fe1_clk, "dram-de-fe1", "pll-ddr", + 0x100, BIT(24), 0); +static SUNXI_CCU_GATE(dram_de_fe0_clk, "dram-de-fe0", "pll-ddr", + 0x100, BIT(25), 0); +static SUNXI_CCU_GATE(dram_de_be0_clk, "dram-de-be0", "pll-ddr", + 0x100, BIT(26), 0); +static SUNXI_CCU_GATE(dram_de_be1_clk, "dram-de-be1", "pll-ddr", + 0x100, BIT(27), 0); +static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "pll-ddr", + 0x100, BIT(28), 0); +static SUNXI_CCU_GATE(dram_ace_clk, "dram-ace", "pll-ddr", + 0x100, BIT(29), 0); + +static const char *const de_parents[] = { "pll-video0", "pll-video1", + "pll-ddr-other" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_be0_clk, "de-be0", de_parents, + 0x104, 0, 4, 24, 2, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(de_be1_clk, "de-be1", de_parents, + 0x108, 0, 4, 24, 2, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe0_clk, "de-fe0", de_parents, + 0x10c, 0, 4, 24, 2, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe1_clk, "de-fe1", de_parents, + 0x110, 0, 4, 24, 2, BIT(31), 0); + +/* Undocumented on A10 */ +static SUNXI_CCU_M_WITH_MUX_GATE(de_mp_clk, "de-mp", de_parents, + 0x114, 0, 4, 24, 2, BIT(31), 0); + +static const char *const disp_parents[] = { "pll-video0", "pll-video1", + "pll-video0-2x", "pll-video1-2x" }; +static SUNXI_CCU_MUX_WITH_GATE(tcon0_ch0_clk, "tcon0-ch0-sclk", disp_parents, + 0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT); +static SUNXI_CCU_MUX_WITH_GATE(tcon1_ch0_clk, "tcon1-ch0-sclk", disp_parents, + 0x11c, 24, 2, BIT(31), CLK_SET_RATE_PARENT); + +static const char *const csi_sclk_parents[] = { "pll-video0", "pll-ve", + "pll-ddr-other", "pll-periph" }; + +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", + csi_sclk_parents, + 0x120, 0, 4, 24, 2, BIT(31), 0); + +/* TVD clock setup for A10 */ +static const char *const tvd_parents[] = { "pll-video0", "pll-video1" }; +static SUNXI_CCU_MUX_WITH_GATE(tvd_sun4i_clk, "tvd", tvd_parents, + 0x128, 24, 1, BIT(31), 0); + +/* TVD clock setup for A20 */ +static SUNXI_CCU_MP_WITH_MUX_GATE(tvd_sclk2_sun7i_clk, + "tvd-sclk2", tvd_parents, + 0x128, + 0, 4, /* M */ + 16, 4, /* P */ + 8, 1, /* mux */ + BIT(15), /* gate */ + 0); + +static SUNXI_CCU_M_WITH_GATE(tvd_sclk1_sun7i_clk, "tvd-sclk1", "tvd-sclk2", + 0x128, 0, 4, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(tcon0_ch1_sclk2_clk, "tcon0-ch1-sclk2", + disp_parents, + 0x12c, 0, 4, 24, 2, BIT(31), + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M_WITH_GATE(tcon0_ch1_clk, + "tcon0-ch1-sclk1", "tcon0-ch1-sclk2", + 0x12c, 11, 1, BIT(15), + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_ch1_sclk2_clk, "tcon1-ch1-sclk2", + disp_parents, + 0x130, 0, 4, 24, 2, BIT(31), + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_M_WITH_GATE(tcon1_ch1_clk, + "tcon1-ch1-sclk1", "tcon1-ch1-sclk2", + 0x130, 11, 1, BIT(15), + CLK_SET_RATE_PARENT); + +static const char *const csi_parents[] = { "hosc", "pll-video0", "pll-video1", + "pll-video0-2x", "pll-video1-2x"}; +static const u8 csi_table[] = { 0, 1, 2, 5, 6}; +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_clk, "csi0", + csi_parents, csi_table, + 0x134, 0, 5, 24, 3, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_clk, "csi1", + csi_parents, csi_table, + 0x138, 0, 5, 24, 3, BIT(31), 0); + +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c, 16, 8, BIT(31), 0); + +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", + 0x140, BIT(31), CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(avs_clk, "avs", "hosc", 0x144, BIT(31), 0); + +static const char *const ace_parents[] = { "pll-ve", "pll-ddr-other" }; +static SUNXI_CCU_M_WITH_MUX_GATE(ace_clk, "ace", ace_parents, + 0x148, 0, 4, 24, 1, BIT(31), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", disp_parents, + 0x150, 0, 4, 24, 2, BIT(31), + CLK_SET_RATE_PARENT); + +static const char *const gpu_parents_sun4i[] = { "pll-video0", "pll-ve", + "pll-ddr-other", + "pll-video1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_sun4i_clk, "gpu", gpu_parents_sun4i, + 0x154, 0, 4, 24, 2, BIT(31), + CLK_SET_RATE_PARENT); + +static const char *const gpu_parents_sun7i[] = { "pll-video0", "pll-ve", + "pll-ddr-other", "pll-video1", + "pll-gpu" }; +static const u8 gpu_table_sun7i[] = { 0, 1, 2, 3, 4 }; +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_sun7i_clk, "gpu", + gpu_parents_sun7i, gpu_table_sun7i, + 0x154, 0, 4, 24, 3, BIT(31), + CLK_SET_RATE_PARENT); + +static const char *const mbus_sun4i_parents[] = { "hosc", "pll-periph", + "pll-ddr-other" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun4i_clk, "mbus", mbus_sun4i_parents, + 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), + 0); +static const char *const mbus_sun7i_parents[] = { "hosc", "pll-periph-base", + "pll-ddr-other" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun7i_clk, "mbus", mbus_sun7i_parents, + 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), + CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE(hdmi1_slow_clk, "hdmi1-slow", "hosc", 0x178, BIT(31), 0); + +static const char *const hdmi1_parents[] = { "pll-video0", "pll-video1" }; +static const u8 hdmi1_table[] = { 0, 1}; +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi1_clk, "hdmi1", + hdmi1_parents, hdmi1_table, + 0x17c, 0, 4, 24, 2, BIT(31), + CLK_SET_RATE_PARENT); + +static const char *const out_parents[] = { "hosc", "osc32k", "hosc" }; +static const struct ccu_mux_fixed_prediv clk_out_predivs[] = { + { .index = 0, .div = 750, }, +}; + +static struct ccu_mp out_a_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(8, 5), + .p = _SUNXI_CCU_DIV(20, 2), + .mux = { + .shift = 24, + .width = 2, + .fixed_predivs = clk_out_predivs, + .n_predivs = ARRAY_SIZE(clk_out_predivs), + }, + .common = { + .reg = 0x1f0, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("out-a", + out_parents, + &ccu_mp_ops, + 0), + }, +}; +static struct ccu_mp out_b_clk = { + .enable = BIT(31), + .m = _SUNXI_CCU_DIV(8, 5), + .p = _SUNXI_CCU_DIV(20, 2), + .mux = { + .shift = 24, + .width = 2, + .fixed_predivs = clk_out_predivs, + .n_predivs = ARRAY_SIZE(clk_out_predivs), + }, + .common = { + .reg = 0x1f4, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("out-b", + out_parents, + &ccu_mp_ops, + 0), + }, +}; + +static struct ccu_common *sun4i_sun7i_ccu_clks[] = { + &hosc_clk.common, + &pll_core_clk.common, + &pll_audio_base_clk.common, + &pll_video0_clk.common, + &pll_ve_sun4i_clk.common, + &pll_ve_sun7i_clk.common, + &pll_ddr_base_clk.common, + &pll_ddr_clk.common, + &pll_ddr_other_clk.common, + &pll_periph_base_clk.common, + &pll_periph_sata_clk.common, + &pll_video1_clk.common, + &pll_gpu_clk.common, + &cpu_clk.common, + &axi_clk.common, + &axi_dram_clk.common, + &ahb_sun4i_clk.common, + &ahb_sun7i_clk.common, + &apb0_clk.common, + &apb1_clk.common, + &ahb_otg_clk.common, + &ahb_ehci0_clk.common, + &ahb_ohci0_clk.common, + &ahb_ehci1_clk.common, + &ahb_ohci1_clk.common, + &ahb_ss_clk.common, + &ahb_dma_clk.common, + &ahb_bist_clk.common, + &ahb_mmc0_clk.common, + &ahb_mmc1_clk.common, + &ahb_mmc2_clk.common, + &ahb_mmc3_clk.common, + &ahb_ms_clk.common, + &ahb_nand_clk.common, + &ahb_sdram_clk.common, + &ahb_ace_clk.common, + &ahb_emac_clk.common, + &ahb_ts_clk.common, + &ahb_spi0_clk.common, + &ahb_spi1_clk.common, + &ahb_spi2_clk.common, + &ahb_spi3_clk.common, + &ahb_pata_clk.common, + &ahb_sata_clk.common, + &ahb_gps_clk.common, + &ahb_hstimer_clk.common, + &ahb_ve_clk.common, + &ahb_tvd_clk.common, + &ahb_tve0_clk.common, + &ahb_tve1_clk.common, + &ahb_lcd0_clk.common, + &ahb_lcd1_clk.common, + &ahb_csi0_clk.common, + &ahb_csi1_clk.common, + &ahb_hdmi1_clk.common, + &ahb_hdmi0_clk.common, + &ahb_de_be0_clk.common, + &ahb_de_be1_clk.common, + &ahb_de_fe0_clk.common, + &ahb_de_fe1_clk.common, + &ahb_gmac_clk.common, + &ahb_mp_clk.common, + &ahb_gpu_clk.common, + &apb0_codec_clk.common, + &apb0_spdif_clk.common, + &apb0_ac97_clk.common, + &apb0_i2s0_clk.common, + &apb0_i2s1_clk.common, + &apb0_pio_clk.common, + &apb0_ir0_clk.common, + &apb0_ir1_clk.common, + &apb0_i2s2_clk.common, + &apb0_keypad_clk.common, + &apb1_i2c0_clk.common, + &apb1_i2c1_clk.common, + &apb1_i2c2_clk.common, + &apb1_i2c3_clk.common, + &apb1_can_clk.common, + &apb1_scr_clk.common, + &apb1_ps20_clk.common, + &apb1_ps21_clk.common, + &apb1_i2c4_clk.common, + &apb1_uart0_clk.common, + &apb1_uart1_clk.common, + &apb1_uart2_clk.common, + &apb1_uart3_clk.common, + &apb1_uart4_clk.common, + &apb1_uart5_clk.common, + &apb1_uart6_clk.common, + &apb1_uart7_clk.common, + &nand_clk.common, + &ms_clk.common, + &mmc0_clk.common, + &mmc0_output_clk.common, + &mmc0_sample_clk.common, + &mmc1_clk.common, + &mmc1_output_clk.common, + &mmc1_sample_clk.common, + &mmc2_clk.common, + &mmc2_output_clk.common, + &mmc2_sample_clk.common, + &mmc3_clk.common, + &mmc3_output_clk.common, + &mmc3_sample_clk.common, + &ts_clk.common, + &ss_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &pata_clk.common, + &ir0_sun4i_clk.common, + &ir1_sun4i_clk.common, + &ir0_sun7i_clk.common, + &ir1_sun7i_clk.common, + &i2s0_clk.common, + &ac97_clk.common, + &spdif_clk.common, + &keypad_clk.common, + &sata_clk.common, + &usb_ohci0_clk.common, + &usb_ohci1_clk.common, + &usb_phy_clk.common, + &spi3_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &dram_ve_clk.common, + &dram_csi0_clk.common, + &dram_csi1_clk.common, + &dram_ts_clk.common, + &dram_tvd_clk.common, + &dram_tve0_clk.common, + &dram_tve1_clk.common, + &dram_out_clk.common, + &dram_de_fe1_clk.common, + &dram_de_fe0_clk.common, + &dram_de_be0_clk.common, + &dram_de_be1_clk.common, + &dram_mp_clk.common, + &dram_ace_clk.common, + &de_be0_clk.common, + &de_be1_clk.common, + &de_fe0_clk.common, + &de_fe1_clk.common, + &de_mp_clk.common, + &tcon0_ch0_clk.common, + &tcon1_ch0_clk.common, + &csi_sclk_clk.common, + &tvd_sun4i_clk.common, + &tvd_sclk1_sun7i_clk.common, + &tvd_sclk2_sun7i_clk.common, + &tcon0_ch1_sclk2_clk.common, + &tcon0_ch1_clk.common, + &tcon1_ch1_sclk2_clk.common, + &tcon1_ch1_clk.common, + &csi0_clk.common, + &csi1_clk.common, + &ve_clk.common, + &codec_clk.common, + &avs_clk.common, + &ace_clk.common, + &hdmi_clk.common, + &gpu_sun4i_clk.common, + &gpu_sun7i_clk.common, + &mbus_sun4i_clk.common, + &mbus_sun7i_clk.common, + &hdmi1_slow_clk.common, + &hdmi1_clk.common, + &out_a_clk.common, + &out_b_clk.common +}; + +/* Post-divider for pll-audio is hardcoded to 4 */ +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", + "pll-video0", 1, 2, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", + "pll-video1", 1, 2, CLK_SET_RATE_PARENT); + + +static struct clk_hw_onecell_data sun4i_a10_hw_clks = { + .hws = { + [CLK_HOSC] = &hosc_clk.common.hw, + [CLK_PLL_CORE] = &pll_core_clk.common.hw, + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VE] = &pll_ve_sun4i_clk.common.hw, + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, + [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, + [CLK_PLL_PERIPH] = &pll_periph_clk.hw, + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, + [CLK_CPU] = &cpu_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_AXI_DRAM] = &axi_dram_clk.common.hw, + [CLK_AHB] = &ahb_sun4i_clk.common.hw, + [CLK_APB0] = &apb0_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, + [CLK_AHB_SS] = &ahb_ss_clk.common.hw, + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, + [CLK_AHB_MS] = &ahb_ms_clk.common.hw, + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, + [CLK_AHB_TS] = &ahb_ts_clk.common.hw, + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, + [CLK_AHB_GPS] = &ahb_gps_clk.common.hw, + [CLK_AHB_VE] = &ahb_ve_clk.common.hw, + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, + [CLK_AHB_MP] = &ahb_mp_clk.common.hw, + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, + [CLK_APB1_CAN] = &apb1_can_clk.common.hw, + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, + [CLK_NAND] = &nand_clk.common.hw, + [CLK_MS] = &ms_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_MMC3] = &mmc3_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_SS] = &ss_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_PATA] = &pata_clk.common.hw, + [CLK_IR0] = &ir0_sun4i_clk.common.hw, + [CLK_IR1] = &ir1_sun4i_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_AC97] = &ac97_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_KEYPAD] = &keypad_clk.common.hw, + [CLK_SATA] = &sata_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_PHY] = &usb_phy_clk.common.hw, + /* CLK_GPS is unimplemented */ + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, + [CLK_DRAM_OUT] = &dram_out_clk.common.hw, + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, + [CLK_DE_BE0] = &de_be0_clk.common.hw, + [CLK_DE_BE1] = &de_be1_clk.common.hw, + [CLK_DE_FE0] = &de_fe0_clk.common.hw, + [CLK_DE_FE1] = &de_fe1_clk.common.hw, + [CLK_DE_MP] = &de_mp_clk.common.hw, + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, + [CLK_TVD] = &tvd_sun4i_clk.common.hw, + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, + [CLK_CSI0] = &csi0_clk.common.hw, + [CLK_CSI1] = &csi1_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_CODEC] = &codec_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_ACE] = &ace_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_GPU] = &gpu_sun7i_clk.common.hw, + [CLK_MBUS] = &mbus_sun4i_clk.common.hw, + }, + .num = CLK_NUMBER_SUN4I, +}; +static struct clk_hw_onecell_data sun7i_a20_hw_clks = { + .hws = { + [CLK_HOSC] = &hosc_clk.common.hw, + [CLK_PLL_CORE] = &pll_core_clk.common.hw, + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VE] = &pll_ve_sun7i_clk.common.hw, + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, + [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, + [CLK_PLL_PERIPH] = &pll_periph_clk.hw, + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_CPU] = &cpu_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_AHB] = &ahb_sun7i_clk.common.hw, + [CLK_APB0] = &apb0_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, + [CLK_AHB_SS] = &ahb_ss_clk.common.hw, + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, + [CLK_AHB_MS] = &ahb_ms_clk.common.hw, + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, + [CLK_AHB_TS] = &ahb_ts_clk.common.hw, + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, + [CLK_AHB_HSTIMER] = &ahb_hstimer_clk.common.hw, + [CLK_AHB_VE] = &ahb_ve_clk.common.hw, + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, + [CLK_AHB_HDMI1] = &ahb_hdmi1_clk.common.hw, + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, + [CLK_AHB_GMAC] = &ahb_gmac_clk.common.hw, + [CLK_AHB_MP] = &ahb_mp_clk.common.hw, + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, + [CLK_APB0_I2S1] = &apb0_i2s1_clk.common.hw, + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, + [CLK_APB0_I2S2] = &apb0_i2s2_clk.common.hw, + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, + [CLK_APB1_I2C3] = &apb1_i2c3_clk.common.hw, + [CLK_APB1_CAN] = &apb1_can_clk.common.hw, + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, + [CLK_APB1_I2C4] = &apb1_i2c4_clk.common.hw, + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, + [CLK_NAND] = &nand_clk.common.hw, + [CLK_MS] = &ms_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, + [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, + [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw, + [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw, + [CLK_MMC3] = &mmc3_clk.common.hw, + [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw, + [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_SS] = &ss_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_PATA] = &pata_clk.common.hw, + [CLK_IR0] = &ir0_sun7i_clk.common.hw, + [CLK_IR1] = &ir1_sun7i_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_AC97] = &ac97_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_KEYPAD] = &keypad_clk.common.hw, + [CLK_SATA] = &sata_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_PHY] = &usb_phy_clk.common.hw, + /* CLK_GPS is unimplemented */ + [CLK_SPI3] = &spi3_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, + [CLK_DRAM_OUT] = &dram_out_clk.common.hw, + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, + [CLK_DE_BE0] = &de_be0_clk.common.hw, + [CLK_DE_BE1] = &de_be1_clk.common.hw, + [CLK_DE_FE0] = &de_fe0_clk.common.hw, + [CLK_DE_FE1] = &de_fe1_clk.common.hw, + [CLK_DE_MP] = &de_mp_clk.common.hw, + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, + [CLK_TVD_SCLK2] = &tvd_sclk2_sun7i_clk.common.hw, + [CLK_TVD] = &tvd_sclk1_sun7i_clk.common.hw, + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, + [CLK_CSI0] = &csi0_clk.common.hw, + [CLK_CSI1] = &csi1_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_CODEC] = &codec_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_ACE] = &ace_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_GPU] = &gpu_sun7i_clk.common.hw, + [CLK_MBUS] = &mbus_sun7i_clk.common.hw, + [CLK_HDMI1_SLOW] = &hdmi1_slow_clk.common.hw, + [CLK_HDMI1] = &hdmi1_clk.common.hw, + [CLK_OUT_A] = &out_a_clk.common.hw, + [CLK_OUT_B] = &out_b_clk.common.hw, + }, + .num = CLK_NUMBER_SUN7I, +}; + +static struct ccu_reset_map sunxi_a10_a20_ccu_resets[] = { + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, + [RST_USB_PHY2] = { 0x0cc, BIT(2) }, + [RST_GPS] = { 0x0d0, BIT(0) }, + [RST_DE_BE0] = { 0x104, BIT(30) }, + [RST_DE_BE1] = { 0x108, BIT(30) }, + [RST_DE_FE0] = { 0x10c, BIT(30) }, + [RST_DE_FE1] = { 0x110, BIT(30) }, + [RST_DE_MP] = { 0x114, BIT(30) }, + [RST_TVE0] = { 0x118, BIT(29) }, + [RST_TCON0] = { 0x118, BIT(30) }, + [RST_TVE1] = { 0x11c, BIT(29) }, + [RST_TCON1] = { 0x11c, BIT(30) }, + [RST_CSI0] = { 0x134, BIT(30) }, + [RST_CSI1] = { 0x138, BIT(30) }, + [RST_VE] = { 0x13c, BIT(0) }, + [RST_ACE] = { 0x148, BIT(16) }, + [RST_LVDS] = { 0x14c, BIT(0) }, + [RST_GPU] = { 0x154, BIT(30) }, + [RST_HDMI_H] = { 0x170, BIT(0) }, + [RST_HDMI_SYS] = { 0x170, BIT(1) }, + [RST_HDMI_AUDIO_DMA] = { 0x170, BIT(2) }, +}; + +static const struct sunxi_ccu_desc sun4i_a10_ccu_desc = { + .ccu_clks = sun4i_sun7i_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), + + .hw_clks = &sun4i_a10_hw_clks, + + .resets = sunxi_a10_a20_ccu_resets, + .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), +}; + +static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = { + .ccu_clks = sun4i_sun7i_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), + + .hw_clks = &sun7i_a20_hw_clks, + + .resets = sunxi_a10_a20_ccu_resets, + .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), +}; + +static void __init sun4i_ccu_init(struct device_node *node, + const struct sunxi_ccu_desc *desc) +{ + void __iomem *reg; + u32 val; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%s: Could not map the clock registers\n", + of_node_full_name(node)); + return; + } + + /* Force the PLL-Audio-1x divider to 4 */ + val = readl(reg + SUN4I_PLL_AUDIO_REG); + val &= ~GENMASK(29, 26); + writel(val | (4 << 26), reg + SUN4I_PLL_AUDIO_REG); + + /* + * Use the peripheral PLL6 as the AHB parent, instead of CPU / + * AXI which have rate changes due to cpufreq. + * + * This is especially a big deal for the HS timer whose parent + * clock is AHB. + * + * NB! These bits are undocumented in A10 manual. + */ + val = readl(reg + SUN4I_AHB_REG); + val &= ~GENMASK(7, 6); + writel(val | (2 << 6), reg + SUN4I_AHB_REG); + + sunxi_ccu_probe(node, reg, desc); +} + +static void __init sun4i_a10_ccu_setup(struct device_node *node) +{ + sun4i_ccu_init(node, &sun4i_a10_ccu_desc); +} +CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu", + sun4i_a10_ccu_setup); + +static void __init sun7i_a20_ccu_setup(struct device_node *node) +{ + sun4i_ccu_init(node, &sun7i_a20_ccu_desc); +} +CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu", + sun7i_a20_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.h b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h new file mode 100644 index 000000000000..c5947c7c050e --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.h @@ -0,0 +1,61 @@ +/* + * Copyright 2017 Priit Laes + * + * Priit Laes + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _CCU_SUN4I_A10_H_ +#define _CCU_SUN4I_A10_H_ + +#include +#include +#include + +/* The HOSC is exported */ +#define CLK_PLL_CORE 2 +#define CLK_PLL_AUDIO_BASE 3 +#define CLK_PLL_AUDIO 4 +#define CLK_PLL_AUDIO_2X 5 +#define CLK_PLL_AUDIO_4X 6 +#define CLK_PLL_AUDIO_8X 7 +#define CLK_PLL_VIDEO0 8 +#define CLK_PLL_VIDEO0_2X 9 +#define CLK_PLL_VE 10 +#define CLK_PLL_DDR_BASE 11 +#define CLK_PLL_DDR 12 +#define CLK_PLL_DDR_OTHER 13 +#define CLK_PLL_PERIPH_BASE 14 +#define CLK_PLL_PERIPH 15 +#define CLK_PLL_PERIPH_SATA 16 +#define CLK_PLL_VIDEO1 17 +#define CLK_PLL_VIDEO1_2X 18 +#define CLK_PLL_GPU 19 + +/* The CPU clock is exported */ +#define CLK_AXI 21 +#define CLK_AXI_DRAM 22 +#define CLK_AHB 23 +#define CLK_APB0 24 +#define CLK_APB1 25 + +/* AHB gates are exported (23..68) */ +/* APB0 gates are exported (69..78) */ +/* APB1 gates are exported (79..95) */ +/* IP module clocks are exported (96..128) */ +/* DRAM gates are exported (129..142)*/ +/* Media (display engine clocks & etc) are exported (143..169) */ + +#define CLK_NUMBER_SUN4I (CLK_MBUS + 1) +#define CLK_NUMBER_SUN7I (CLK_OUT_B + 1) + +#endif /* _CCU_SUN4I_A10_H_ */ diff --git a/include/dt-bindings/clock/sun4i-a10-ccu.h b/include/dt-bindings/clock/sun4i-a10-ccu.h new file mode 100644 index 000000000000..c5a53f38d654 --- /dev/null +++ b/include/dt-bindings/clock/sun4i-a10-ccu.h @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2017 Priit Laes + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN4I_A10_H_ +#define _DT_BINDINGS_CLK_SUN4I_A10_H_ + +#define CLK_HOSC 1 +#define CLK_CPU 20 + +/* AHB Gates */ +#define CLK_AHB_OTG 26 +#define CLK_AHB_EHCI0 27 +#define CLK_AHB_OHCI0 28 +#define CLK_AHB_EHCI1 29 +#define CLK_AHB_OHCI1 30 +#define CLK_AHB_SS 31 +#define CLK_AHB_DMA 32 +#define CLK_AHB_BIST 33 +#define CLK_AHB_MMC0 34 +#define CLK_AHB_MMC1 35 +#define CLK_AHB_MMC2 36 +#define CLK_AHB_MMC3 37 +#define CLK_AHB_MS 38 +#define CLK_AHB_NAND 39 +#define CLK_AHB_SDRAM 40 +#define CLK_AHB_ACE 41 +#define CLK_AHB_EMAC 42 +#define CLK_AHB_TS 43 +#define CLK_AHB_SPI0 44 +#define CLK_AHB_SPI1 45 +#define CLK_AHB_SPI2 46 +#define CLK_AHB_SPI3 47 +#define CLK_AHB_PATA 48 +#define CLK_AHB_SATA 49 +#define CLK_AHB_GPS 50 +#define CLK_AHB_HSTIMER 51 +#define CLK_AHB_VE 52 +#define CLK_AHB_TVD 53 +#define CLK_AHB_TVE0 54 +#define CLK_AHB_TVE1 55 +#define CLK_AHB_LCD0 56 +#define CLK_AHB_LCD1 57 +#define CLK_AHB_CSI0 58 +#define CLK_AHB_CSI1 59 +#define CLK_AHB_HDMI0 60 +#define CLK_AHB_HDMI1 61 +#define CLK_AHB_DE_BE0 62 +#define CLK_AHB_DE_BE1 63 +#define CLK_AHB_DE_FE0 64 +#define CLK_AHB_DE_FE1 65 +#define CLK_AHB_GMAC 66 +#define CLK_AHB_MP 67 +#define CLK_AHB_GPU 68 + +/* APB0 Gates */ +#define CLK_APB0_CODEC 69 +#define CLK_APB0_SPDIF 70 +#define CLK_APB0_I2S0 71 +#define CLK_APB0_AC97 72 +#define CLK_APB0_I2S1 73 +#define CLK_APB0_PIO 74 +#define CLK_APB0_IR0 75 +#define CLK_APB0_IR1 76 +#define CLK_APB0_I2S2 77 +#define CLK_APB0_KEYPAD 78 + +/* APB1 Gates */ +#define CLK_APB1_I2C0 79 +#define CLK_APB1_I2C1 80 +#define CLK_APB1_I2C2 81 +#define CLK_APB1_I2C3 82 +#define CLK_APB1_CAN 83 +#define CLK_APB1_SCR 84 +#define CLK_APB1_PS20 85 +#define CLK_APB1_PS21 86 +#define CLK_APB1_I2C4 87 +#define CLK_APB1_UART0 88 +#define CLK_APB1_UART1 89 +#define CLK_APB1_UART2 90 +#define CLK_APB1_UART3 91 +#define CLK_APB1_UART4 92 +#define CLK_APB1_UART5 93 +#define CLK_APB1_UART6 94 +#define CLK_APB1_UART7 95 + +/* IP clocks */ +#define CLK_NAND 96 +#define CLK_MS 97 +#define CLK_MMC0 98 +#define CLK_MMC0_OUTPUT 99 +#define CLK_MMC0_SAMPLE 100 +#define CLK_MMC1 101 +#define CLK_MMC1_OUTPUT 102 +#define CLK_MMC1_SAMPLE 103 +#define CLK_MMC2 104 +#define CLK_MMC2_OUTPUT 105 +#define CLK_MMC2_SAMPLE 106 +#define CLK_MMC3 107 +#define CLK_MMC3_OUTPUT 108 +#define CLK_MMC3_SAMPLE 109 +#define CLK_TS 110 +#define CLK_SS 111 +#define CLK_SPI0 112 +#define CLK_SPI1 113 +#define CLK_SPI2 114 +#define CLK_PATA 115 +#define CLK_IR0 116 +#define CLK_IR1 117 +#define CLK_I2S0 118 +#define CLK_AC97 119 +#define CLK_SPDIF 120 +#define CLK_KEYPAD 121 +#define CLK_SATA 122 +#define CLK_USB_OHCI0 123 +#define CLK_USB_OHCI1 124 +#define CLK_USB_PHY 125 +#define CLK_GPS 126 +#define CLK_SPI3 127 +#define CLK_I2S1 128 +#define CLK_I2S2 129 + +/* DRAM Gates */ +#define CLK_DRAM_VE 130 +#define CLK_DRAM_CSI0 131 +#define CLK_DRAM_CSI1 132 +#define CLK_DRAM_TS 133 +#define CLK_DRAM_TVD 134 +#define CLK_DRAM_TVE0 135 +#define CLK_DRAM_TVE1 136 +#define CLK_DRAM_OUT 137 +#define CLK_DRAM_DE_FE1 138 +#define CLK_DRAM_DE_FE0 139 +#define CLK_DRAM_DE_BE0 140 +#define CLK_DRAM_DE_BE1 141 +#define CLK_DRAM_MP 142 +#define CLK_DRAM_ACE 143 + +/* Display Engine Clocks */ +#define CLK_DE_BE0 144 +#define CLK_DE_BE1 145 +#define CLK_DE_FE0 146 +#define CLK_DE_FE1 147 +#define CLK_DE_MP 148 +#define CLK_TCON0_CH0 149 +#define CLK_TCON1_CH0 150 +#define CLK_CSI_SCLK 151 +#define CLK_TVD_SCLK2 152 +#define CLK_TVD 153 +#define CLK_TCON0_CH1_SCLK2 154 +#define CLK_TCON0_CH1 155 +#define CLK_TCON1_CH1_SCLK2 156 +#define CLK_TCON1_CH1 157 +#define CLK_CSI0 158 +#define CLK_CSI1 159 +#define CLK_CODEC 160 +#define CLK_VE 161 +#define CLK_AVS 162 +#define CLK_ACE 163 +#define CLK_HDMI 164 +#define CLK_GPU 165 + +#endif /* _DT_BINDINGS_CLK_SUN4I_A10_H_ */ diff --git a/include/dt-bindings/clock/sun7i-a20-ccu.h b/include/dt-bindings/clock/sun7i-a20-ccu.h new file mode 100644 index 000000000000..045a5178da0c --- /dev/null +++ b/include/dt-bindings/clock/sun7i-a20-ccu.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2017 Priit Laes + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_CLK_SUN7I_A20_H_ +#define _DT_BINDINGS_CLK_SUN7I_A20_H_ + +#include + +#define CLK_MBUS 166 +#define CLK_HDMI1_SLOW 167 +#define CLK_HDMI1 168 +#define CLK_OUT_A 169 +#define CLK_OUT_B 170 + +#endif /* _DT_BINDINGS_CLK_SUN7I_A20_H_ */ diff --git a/include/dt-bindings/reset/sun4i-a10-ccu.h b/include/dt-bindings/reset/sun4i-a10-ccu.h new file mode 100644 index 000000000000..5f4480bedc8a --- /dev/null +++ b/include/dt-bindings/reset/sun4i-a10-ccu.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2017 Priit Laes + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _DT_BINDINGS_RST_SUN4I_A10_H +#define _DT_BINDINGS_RST_SUN4I_A10_H + +#define RST_USB_PHY0 1 +#define RST_USB_PHY1 2 +#define RST_USB_PHY2 3 +#define RST_GPS 4 +#define RST_DE_BE0 5 +#define RST_DE_BE1 6 +#define RST_DE_FE0 7 +#define RST_DE_FE1 8 +#define RST_DE_MP 9 +#define RST_TVE0 10 +#define RST_TCON0 11 +#define RST_TVE1 12 +#define RST_TCON1 13 +#define RST_CSI0 14 +#define RST_CSI1 15 +#define RST_VE 16 +#define RST_ACE 17 +#define RST_LVDS 18 +#define RST_GPU 19 +#define RST_HDMI_H 20 +#define RST_HDMI_SYS 21 +#define RST_HDMI_AUDIO_DMA 22 + +#endif /* DT_BINDINGS_RST_SUN4I_A10_H */ -- cgit v1.2.3 From 3e4d618b0722b64c551c3f2fc4c4f9cb3558ed93 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Mon, 21 Aug 2017 13:59:02 +0200 Subject: clk: stm32h7: Add stm32h743 clock driver This patch enables clocks for STM32H743 boards. Signed-off-by: Gabriel Fernandez for MFD changes: Acked-by: Lee Jones for DT-Bindings Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/st,stm32h7-rcc.txt | 71 + drivers/clk/Makefile | 1 + drivers/clk/clk-stm32h7.c | 1410 ++++++++++++++++++++ include/dt-bindings/clock/stm32h7-clks.h | 165 +++ include/dt-bindings/mfd/stm32h7-rcc.h | 136 ++ 5 files changed, 1783 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt create mode 100644 drivers/clk/clk-stm32h7.c create mode 100644 include/dt-bindings/clock/stm32h7-clks.h create mode 100644 include/dt-bindings/mfd/stm32h7-rcc.h (limited to 'include/dt-bindings') diff --git a/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt new file mode 100644 index 000000000000..a135504c7d57 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/st,stm32h7-rcc.txt @@ -0,0 +1,71 @@ +STMicroelectronics STM32H7 Reset and Clock Controller +===================================================== + +The RCC IP is both a reset and a clock controller. + +Please refer to clock-bindings.txt for common clock controller binding usage. +Please also refer to reset.txt for common reset controller binding usage. + +Required properties: +- compatible: Should be: + "st,stm32h743-rcc" + +- reg: should be register base and length as documented in the + datasheet + +- #reset-cells: 1, see below + +- #clock-cells : from common clock binding; shall be set to 1 + +- clocks: External oscillator clock phandle + - high speed external clock signal (HSE) + - low speed external clock signal (LSE) + - external I2S clock (I2S_CKIN) + +Optional properties: +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain + write protection (RTC clock). + +Example: + + rcc: reset-clock-controller@58024400 { + compatible = "st,stm32h743-rcc", "st,stm32-rcc"; + reg = <0x58024400 0x400>; + #reset-cells = <1>; + #clock-cells = <2>; + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>; + + st,syscfg = <&pwrcfg>; +}; + +The peripheral clock consumer should specify the desired clock by +having the clock ID in its "clocks" phandle cell. + +Example: + + timer5: timer@40000c00 { + compatible = "st,stm32-timer"; + reg = <0x40000c00 0x400>; + interrupts = <50>; + clocks = <&rcc TIM5_CK>; + }; + +Specifying softreset control of devices +======================================= + +Device nodes should specify the reset channel required in their "resets" +property, containing a phandle to the reset device node and an index specifying +which channel to use. +The index is the bit number within the RCC registers bank, starting from RCC +base address. +It is calculated as: index = register_offset / 4 * 32 + bit_offset. +Where bit_offset is the bit offset within the register. + +For example, for CRC reset: + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107 + +Example: + + timer2 { + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>; + }; diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 72e7c0eef32f..f87d085805a9 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o +obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300) += clk-u300.o diff --git a/drivers/clk/clk-stm32h7.c b/drivers/clk/clk-stm32h7.c new file mode 100644 index 000000000000..a94c3f56c590 --- /dev/null +++ b/drivers/clk/clk-stm32h7.c @@ -0,0 +1,1410 @@ +/* + * Copyright (C) Gabriel Fernandez 2017 + * Author: Gabriel Fernandez + * + * License terms: GPL V2.0. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Reset Clock Control Registers */ +#define RCC_CR 0x00 +#define RCC_CFGR 0x10 +#define RCC_D1CFGR 0x18 +#define RCC_D2CFGR 0x1C +#define RCC_D3CFGR 0x20 +#define RCC_PLLCKSELR 0x28 +#define RCC_PLLCFGR 0x2C +#define RCC_PLL1DIVR 0x30 +#define RCC_PLL1FRACR 0x34 +#define RCC_PLL2DIVR 0x38 +#define RCC_PLL2FRACR 0x3C +#define RCC_PLL3DIVR 0x40 +#define RCC_PLL3FRACR 0x44 +#define RCC_D1CCIPR 0x4C +#define RCC_D2CCIP1R 0x50 +#define RCC_D2CCIP2R 0x54 +#define RCC_D3CCIPR 0x58 +#define RCC_BDCR 0x70 +#define RCC_CSR 0x74 +#define RCC_AHB3ENR 0xD4 +#define RCC_AHB1ENR 0xD8 +#define RCC_AHB2ENR 0xDC +#define RCC_AHB4ENR 0xE0 +#define RCC_APB3ENR 0xE4 +#define RCC_APB1LENR 0xE8 +#define RCC_APB1HENR 0xEC +#define RCC_APB2ENR 0xF0 +#define RCC_APB4ENR 0xF4 + +static DEFINE_SPINLOCK(stm32rcc_lock); + +static void __iomem *base; +static struct clk_hw **hws; + +/* System clock parent */ +static const char * const sys_src[] = { + "hsi_ck", "csi_ck", "hse_ck", "pll1_p" }; + +static const char * const tracein_src[] = { + "hsi_ck", "csi_ck", "hse_ck", "pll1_r" }; + +static const char * const per_src[] = { + "hsi_ker", "csi_ker", "hse_ck", "disabled" }; + +static const char * const pll_src[] = { + "hsi_ck", "csi_ck", "hse_ck", "no clock" }; + +static const char * const sdmmc_src[] = { "pll1_q", "pll2_r" }; + +static const char * const dsi_src[] = { "ck_dsi_phy", "pll2_q" }; + +static const char * const qspi_src[] = { + "hclk", "pll1_q", "pll2_r", "per_ck" }; + +static const char * const fmc_src[] = { + "hclk", "pll1_q", "pll2_r", "per_ck" }; + +/* Kernel clock parent */ +static const char * const swp_src[] = { "pclk1", "hsi_ker" }; + +static const char * const fdcan_src[] = { "hse_ck", "pll1_q", "pll2_q" }; + +static const char * const dfsdm1_src[] = { "pclk2", "sys_ck" }; + +static const char * const spdifrx_src[] = { + "pll1_q", "pll2_r", "pll3_r", "hsi_ker" }; + +static const char *spi_src1[5] = { + "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; + +static const char * const spi_src2[] = { + "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; + +static const char * const spi_src3[] = { + "pclk4", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; + +static const char * const lptim_src1[] = { + "pclk1", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; + +static const char * const lptim_src2[] = { + "pclk4", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; + +static const char * const cec_src[] = {"lse_ck", "lsi_ck", "csi_ker_div122" }; + +static const char * const usbotg_src[] = {"pll1_q", "pll3_q", "rc48_ck" }; + +/* i2c 1,2,3 src */ +static const char * const i2c_src1[] = { + "pclk1", "pll3_r", "hsi_ker", "csi_ker" }; + +static const char * const i2c_src2[] = { + "pclk4", "pll3_r", "hsi_ker", "csi_ker" }; + +static const char * const rng_src[] = { + "rc48_ck", "pll1_q", "lse_ck", "lsi_ck" }; + +/* usart 1,6 src */ +static const char * const usart_src1[] = { + "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; + +/* usart 2,3,4,5,7,8 src */ +static const char * const usart_src2[] = { + "pclk1", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; + +static const char *sai_src[5] = { + "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; + +static const char * const adc_src[] = { "pll2_p", "pll3_r", "per_ck" }; + +/* lptim 2,3,4,5 src */ +static const char * const lpuart1_src[] = { + "pclk3", "pll2_q", "pll3_q", "csi_ker", "lse_ck" }; + +static const char * const hrtim_src[] = { "tim2_ker", "d1cpre" }; + +/* RTC clock parent */ +static const char * const rtc_src[] = { "off", "lse_ck", "lsi_ck", "hse_1M" }; + +/* Micro-controller output clock parent */ +static const char * const mco_src1[] = { + "hsi_ck", "lse_ck", "hse_ck", "pll1_q", "rc48_ck" }; + +static const char * const mco_src2[] = { + "sys_ck", "pll2_p", "hse_ck", "pll1_p", "csi_ck", "lsi_ck" }; + +/* LCD clock */ +static const char * const ltdc_src[] = {"pll3_r"}; + +/* Gate clock with ready bit and backup domain management */ +struct stm32_ready_gate { + struct clk_gate gate; + u8 bit_rdy; +}; + +#define to_ready_gate_clk(_rgate) container_of(_rgate, struct stm32_ready_gate,\ + gate) + +#define RGATE_TIMEOUT 10000 + +static int ready_gate_clk_enable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); + int bit_status; + unsigned int timeout = RGATE_TIMEOUT; + + if (clk_gate_ops.is_enabled(hw)) + return 0; + + clk_gate_ops.enable(hw); + + /* We can't use readl_poll_timeout() because we can blocked if + * someone enables this clock before clocksource changes. + * Only jiffies counter is available. Jiffies are incremented by + * interruptions and enable op does not allow to be interrupted. + */ + do { + bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy)); + + if (bit_status) + udelay(100); + + } while (bit_status && --timeout); + + return bit_status; +} + +static void ready_gate_clk_disable(struct clk_hw *hw) +{ + struct clk_gate *gate = to_clk_gate(hw); + struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); + int bit_status; + unsigned int timeout = RGATE_TIMEOUT; + + if (!clk_gate_ops.is_enabled(hw)) + return; + + clk_gate_ops.disable(hw); + + do { + bit_status = !!(readl(gate->reg) & BIT(rgate->bit_rdy)); + + if (bit_status) + udelay(100); + + } while (bit_status && --timeout); +} + +static const struct clk_ops ready_gate_clk_ops = { + .enable = ready_gate_clk_enable, + .disable = ready_gate_clk_disable, + .is_enabled = clk_gate_is_enabled, +}; + +static struct clk_hw *clk_register_ready_gate(struct device *dev, + const char *name, const char *parent_name, + void __iomem *reg, u8 bit_idx, u8 bit_rdy, + unsigned long flags, spinlock_t *lock) +{ + struct stm32_ready_gate *rgate; + struct clk_init_data init = { NULL }; + struct clk_hw *hw; + int ret; + + rgate = kzalloc(sizeof(*rgate), GFP_KERNEL); + if (!rgate) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &ready_gate_clk_ops; + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + rgate->bit_rdy = bit_rdy; + rgate->gate.lock = lock; + rgate->gate.reg = reg; + rgate->gate.bit_idx = bit_idx; + rgate->gate.hw.init = &init; + + hw = &rgate->gate.hw; + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(rgate); + hw = ERR_PTR(ret); + } + + return hw; +} + +struct gate_cfg { + u32 offset; + u8 bit_idx; +}; + +struct muxdiv_cfg { + u32 offset; + u8 shift; + u8 width; +}; + +struct composite_clk_cfg { + struct gate_cfg *gate; + struct muxdiv_cfg *mux; + struct muxdiv_cfg *div; + const char *name; + const char * const *parent_name; + int num_parents; + u32 flags; +}; + +struct composite_clk_gcfg_t { + u8 flags; + const struct clk_ops *ops; +}; + +/* + * General config definition of a composite clock (only clock diviser for rate) + */ +struct composite_clk_gcfg { + struct composite_clk_gcfg_t *mux; + struct composite_clk_gcfg_t *div; + struct composite_clk_gcfg_t *gate; +}; + +#define M_CFG_MUX(_mux_ops, _mux_flags)\ + .mux = &(struct composite_clk_gcfg_t) { _mux_flags, _mux_ops} + +#define M_CFG_DIV(_rate_ops, _rate_flags)\ + .div = &(struct composite_clk_gcfg_t) {_rate_flags, _rate_ops} + +#define M_CFG_GATE(_gate_ops, _gate_flags)\ + .gate = &(struct composite_clk_gcfg_t) { _gate_flags, _gate_ops} + +static struct clk_mux *_get_cmux(void __iomem *reg, u8 shift, u8 width, + u32 flags, spinlock_t *lock) +{ + struct clk_mux *mux; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = reg; + mux->shift = shift; + mux->mask = (1 << width) - 1; + mux->flags = flags; + mux->lock = lock; + + return mux; +} + +static struct clk_divider *_get_cdiv(void __iomem *reg, u8 shift, u8 width, + u32 flags, spinlock_t *lock) +{ + struct clk_divider *div; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + + if (!div) + return ERR_PTR(-ENOMEM); + + div->reg = reg; + div->shift = shift; + div->width = width; + div->flags = flags; + div->lock = lock; + + return div; +} + +static struct clk_gate *_get_cgate(void __iomem *reg, u8 bit_idx, u32 flags, + spinlock_t *lock) +{ + struct clk_gate *gate; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + return ERR_PTR(-ENOMEM); + + gate->reg = reg; + gate->bit_idx = bit_idx; + gate->flags = flags; + gate->lock = lock; + + return gate; +} + +struct composite_cfg { + struct clk_hw *mux_hw; + struct clk_hw *div_hw; + struct clk_hw *gate_hw; + + const struct clk_ops *mux_ops; + const struct clk_ops *div_ops; + const struct clk_ops *gate_ops; +}; + +static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg, + const struct composite_clk_cfg *cfg, + struct composite_cfg *composite, spinlock_t *lock) +{ + struct clk_mux *mux = NULL; + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + const struct clk_ops *mux_ops, *div_ops, *gate_ops; + struct clk_hw *mux_hw; + struct clk_hw *div_hw; + struct clk_hw *gate_hw; + + mux_ops = div_ops = gate_ops = NULL; + mux_hw = div_hw = gate_hw = NULL; + + if (gcfg->mux && gcfg->mux) { + mux = _get_cmux(base + cfg->mux->offset, + cfg->mux->shift, + cfg->mux->width, + gcfg->mux->flags, lock); + + if (!IS_ERR(mux)) { + mux_hw = &mux->hw; + mux_ops = gcfg->mux->ops ? + gcfg->mux->ops : &clk_mux_ops; + } + } + + if (gcfg->div && cfg->div) { + div = _get_cdiv(base + cfg->div->offset, + cfg->div->shift, + cfg->div->width, + gcfg->div->flags, lock); + + if (!IS_ERR(div)) { + div_hw = &div->hw; + div_ops = gcfg->div->ops ? + gcfg->div->ops : &clk_divider_ops; + } + } + + if (gcfg->gate && gcfg->gate) { + gate = _get_cgate(base + cfg->gate->offset, + cfg->gate->bit_idx, + gcfg->gate->flags, lock); + + if (!IS_ERR(gate)) { + gate_hw = &gate->hw; + gate_ops = gcfg->gate->ops ? + gcfg->gate->ops : &clk_gate_ops; + } + } + + composite->mux_hw = mux_hw; + composite->mux_ops = mux_ops; + + composite->div_hw = div_hw; + composite->div_ops = div_ops; + + composite->gate_hw = gate_hw; + composite->gate_ops = gate_ops; +} + +/* Kernel Timer */ +struct timer_ker { + u8 dppre_shift; + struct clk_hw hw; + spinlock_t *lock; +}; + +#define to_timer_ker(_hw) container_of(_hw, struct timer_ker, hw) + +static unsigned long timer_ker_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct timer_ker *clk_elem = to_timer_ker(hw); + u32 timpre; + u32 dppre_shift = clk_elem->dppre_shift; + u32 prescaler; + u32 mul; + + timpre = (readl(base + RCC_CFGR) >> 15) & 0x01; + + prescaler = (readl(base + RCC_D2CFGR) >> dppre_shift) & 0x03; + + mul = 2; + + if (prescaler < 4) + mul = 1; + + else if (timpre && prescaler > 4) + mul = 4; + + return parent_rate * mul; +} + +static const struct clk_ops timer_ker_ops = { + .recalc_rate = timer_ker_recalc_rate, +}; + +static struct clk_hw *clk_register_stm32_timer_ker(struct device *dev, + const char *name, const char *parent_name, + unsigned long flags, + u8 dppre_shift, + spinlock_t *lock) +{ + struct timer_ker *element; + struct clk_init_data init; + struct clk_hw *hw; + int err; + + element = kzalloc(sizeof(*element), GFP_KERNEL); + if (!element) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &timer_ker_ops; + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + element->hw.init = &init; + element->lock = lock; + element->dppre_shift = dppre_shift; + + hw = &element->hw; + err = clk_hw_register(dev, hw); + + if (err) { + kfree(element); + return ERR_PTR(err); + } + + return hw; +} + +static const struct clk_div_table d1cpre_div_table[] = { + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, + { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1}, + { 8, 2 }, { 9, 4 }, { 10, 8 }, { 11, 16 }, + { 12, 64 }, { 13, 128 }, { 14, 256 }, + { 15, 512 }, + { 0 }, +}; + +static const struct clk_div_table ppre_div_table[] = { + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, + { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 }, + { 0 }, +}; + +static void register_core_and_bus_clocks(void) +{ + /* CORE AND BUS */ + hws[SYS_D1CPRE] = clk_hw_register_divider_table(NULL, "d1cpre", + "sys_ck", CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 8, 4, 0, + d1cpre_div_table, &stm32rcc_lock); + + hws[HCLK] = clk_hw_register_divider_table(NULL, "hclk", "d1cpre", + CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 0, 4, 0, + d1cpre_div_table, &stm32rcc_lock); + + /* D1 DOMAIN */ + /* * CPU Systick */ + hws[CPU_SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", + "d1cpre", 0, 1, 8); + + /* * APB3 peripheral */ + hws[PCLK3] = clk_hw_register_divider_table(NULL, "pclk3", "hclk", 0, + base + RCC_D1CFGR, 4, 3, 0, + ppre_div_table, &stm32rcc_lock); + + /* D2 DOMAIN */ + /* * APB1 peripheral */ + hws[PCLK1] = clk_hw_register_divider_table(NULL, "pclk1", "hclk", 0, + base + RCC_D2CFGR, 4, 3, 0, + ppre_div_table, &stm32rcc_lock); + + /* Timers prescaler clocks */ + clk_register_stm32_timer_ker(NULL, "tim1_ker", "pclk1", 0, + 4, &stm32rcc_lock); + + /* * APB2 peripheral */ + hws[PCLK2] = clk_hw_register_divider_table(NULL, "pclk2", "hclk", 0, + base + RCC_D2CFGR, 8, 3, 0, ppre_div_table, + &stm32rcc_lock); + + clk_register_stm32_timer_ker(NULL, "tim2_ker", "pclk2", 0, 8, + &stm32rcc_lock); + + /* D3 DOMAIN */ + /* * APB4 peripheral */ + hws[PCLK4] = clk_hw_register_divider_table(NULL, "pclk4", "hclk", 0, + base + RCC_D3CFGR, 4, 3, 0, + ppre_div_table, &stm32rcc_lock); +} + +/* MUX clock configuration */ +struct stm32_mux_clk { + const char *name; + const char * const *parents; + u8 num_parents; + u32 offset; + u8 shift; + u8 width; + u32 flags; +}; + +#define M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, _flags)\ +{\ + .name = _name,\ + .parents = _parents,\ + .num_parents = ARRAY_SIZE(_parents),\ + .offset = _mux_offset,\ + .shift = _mux_shift,\ + .width = _mux_width,\ + .flags = _flags,\ +} + +#define M_MCLOC(_name, _parents, _mux_offset, _mux_shift, _mux_width)\ + M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, 0)\ + +static const struct stm32_mux_clk stm32_mclk[] __initconst = { + M_MCLOC("per_ck", per_src, RCC_D1CCIPR, 28, 3), + M_MCLOC("pllsrc", pll_src, RCC_PLLCKSELR, 0, 3), + M_MCLOC("sys_ck", sys_src, RCC_CFGR, 0, 3), + M_MCLOC("tracein_ck", tracein_src, RCC_CFGR, 0, 3), +}; + +/* Oscillary clock configuration */ +struct stm32_osc_clk { + const char *name; + const char *parent; + u32 gate_offset; + u8 bit_idx; + u8 bit_rdy; + u32 flags; +}; + +#define OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, _flags)\ +{\ + .name = _name,\ + .parent = _parent,\ + .gate_offset = _gate_offset,\ + .bit_idx = _bit_idx,\ + .bit_rdy = _bit_rdy,\ + .flags = _flags,\ +} + +#define OSC_CLK(_name, _parent, _gate_offset, _bit_idx, _bit_rdy)\ + OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, 0) + +static const struct stm32_osc_clk stm32_oclk[] __initconst = { + OSC_CLKF("hsi_ck", "hsidiv", RCC_CR, 0, 2, CLK_IGNORE_UNUSED), + OSC_CLKF("hsi_ker", "hsidiv", RCC_CR, 1, 2, CLK_IGNORE_UNUSED), + OSC_CLKF("csi_ck", "clk-csi", RCC_CR, 7, 8, CLK_IGNORE_UNUSED), + OSC_CLKF("csi_ker", "clk-csi", RCC_CR, 9, 8, CLK_IGNORE_UNUSED), + OSC_CLKF("rc48_ck", "clk-rc48", RCC_CR, 12, 13, CLK_IGNORE_UNUSED), + OSC_CLKF("lsi_ck", "clk-lsi", RCC_CSR, 0, 1, CLK_IGNORE_UNUSED), +}; + +/* PLL configuration */ +struct st32h7_pll_cfg { + u8 bit_idx; + u32 offset_divr; + u8 bit_frac_en; + u32 offset_frac; + u8 divm; +}; + +struct stm32_pll_data { + const char *name; + const char *parent_name; + unsigned long flags; + const struct st32h7_pll_cfg *cfg; +}; + +static const struct st32h7_pll_cfg stm32h7_pll1 = { + .bit_idx = 24, + .offset_divr = RCC_PLL1DIVR, + .bit_frac_en = 0, + .offset_frac = RCC_PLL1FRACR, + .divm = 4, +}; + +static const struct st32h7_pll_cfg stm32h7_pll2 = { + .bit_idx = 26, + .offset_divr = RCC_PLL2DIVR, + .bit_frac_en = 4, + .offset_frac = RCC_PLL2FRACR, + .divm = 12, +}; + +static const struct st32h7_pll_cfg stm32h7_pll3 = { + .bit_idx = 28, + .offset_divr = RCC_PLL3DIVR, + .bit_frac_en = 8, + .offset_frac = RCC_PLL3FRACR, + .divm = 20, +}; + +static const struct stm32_pll_data stm32_pll[] = { + { "vco1", "pllsrc", CLK_IGNORE_UNUSED, &stm32h7_pll1 }, + { "vco2", "pllsrc", 0, &stm32h7_pll2 }, + { "vco3", "pllsrc", 0, &stm32h7_pll3 }, +}; + +struct stm32_fractional_divider { + void __iomem *mreg; + u8 mshift; + u8 mwidth; + u32 mmask; + + void __iomem *nreg; + u8 nshift; + u8 nwidth; + + void __iomem *freg_status; + u8 freg_bit; + void __iomem *freg_value; + u8 fshift; + u8 fwidth; + + u8 flags; + struct clk_hw hw; + spinlock_t *lock; +}; + +struct stm32_pll_obj { + spinlock_t *lock; + struct stm32_fractional_divider div; + struct stm32_ready_gate rgate; + struct clk_hw hw; +}; + +#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) + +static int pll_is_enabled(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; + + __clk_hw_set_clk(_hw, hw); + + return ready_gate_clk_ops.is_enabled(_hw); +} + +static int pll_enable(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; + + __clk_hw_set_clk(_hw, hw); + + return ready_gate_clk_ops.enable(_hw); +} + +static void pll_disable(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; + + __clk_hw_set_clk(_hw, hw); + + ready_gate_clk_ops.disable(_hw); +} + +static int pll_frac_is_enabled(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct stm32_fractional_divider *fd = &clk_elem->div; + + return (readl(fd->freg_status) >> fd->freg_bit) & 0x01; +} + +static unsigned long pll_read_frac(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct stm32_fractional_divider *fd = &clk_elem->div; + + return (readl(fd->freg_value) >> fd->fshift) & + GENMASK(fd->fwidth - 1, 0); +} + +static unsigned long pll_fd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct stm32_fractional_divider *fd = &clk_elem->div; + unsigned long m, n; + u32 val, mask; + u64 rate, rate1 = 0; + + val = readl(fd->mreg); + mask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; + m = (val & mask) >> fd->mshift; + + val = readl(fd->nreg); + mask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; + n = ((val & mask) >> fd->nshift) + 1; + + if (!n || !m) + return parent_rate; + + rate = (u64)parent_rate * n; + do_div(rate, m); + + if (pll_frac_is_enabled(hw)) { + val = pll_read_frac(hw); + rate1 = (u64)parent_rate * (u64)val; + do_div(rate1, (m * 8191)); + } + + return rate + rate1; +} + +static const struct clk_ops pll_ops = { + .enable = pll_enable, + .disable = pll_disable, + .is_enabled = pll_is_enabled, + .recalc_rate = pll_fd_recalc_rate, +}; + +static struct clk_hw *clk_register_stm32_pll(struct device *dev, + const char *name, + const char *parent, + unsigned long flags, + const struct st32h7_pll_cfg *cfg, + spinlock_t *lock) +{ + struct stm32_pll_obj *pll; + struct clk_init_data init = { NULL }; + struct clk_hw *hw; + int ret; + struct stm32_fractional_divider *div = NULL; + struct stm32_ready_gate *rgate; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &pll_ops; + init.flags = flags; + init.parent_names = &parent; + init.num_parents = 1; + pll->hw.init = &init; + + hw = &pll->hw; + rgate = &pll->rgate; + + rgate->bit_rdy = cfg->bit_idx + 1; + rgate->gate.lock = lock; + rgate->gate.reg = base + RCC_CR; + rgate->gate.bit_idx = cfg->bit_idx; + + div = &pll->div; + div->flags = 0; + div->mreg = base + RCC_PLLCKSELR; + div->mshift = cfg->divm; + div->mwidth = 6; + div->nreg = base + cfg->offset_divr; + div->nshift = 0; + div->nwidth = 9; + + div->freg_status = base + RCC_PLLCFGR; + div->freg_bit = cfg->bit_frac_en; + div->freg_value = base + cfg->offset_frac; + div->fshift = 3; + div->fwidth = 13; + + div->lock = lock; + + ret = clk_hw_register(dev, hw); + if (ret) { + kfree(pll); + hw = ERR_PTR(ret); + } + + return hw; +} + +/* ODF CLOCKS */ +static unsigned long odf_divider_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return clk_divider_ops.recalc_rate(hw, parent_rate); +} + +static long odf_divider_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return clk_divider_ops.round_rate(hw, rate, prate); +} + +static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_hw *hwp; + int pll_status; + int ret; + + hwp = clk_hw_get_parent(hw); + + pll_status = pll_is_enabled(hwp); + + if (pll_status) + pll_disable(hwp); + + ret = clk_divider_ops.set_rate(hw, rate, parent_rate); + + if (pll_status) + pll_enable(hwp); + + return ret; +} + +static const struct clk_ops odf_divider_ops = { + .recalc_rate = odf_divider_recalc_rate, + .round_rate = odf_divider_round_rate, + .set_rate = odf_divider_set_rate, +}; + +static int odf_gate_enable(struct clk_hw *hw) +{ + struct clk_hw *hwp; + int pll_status; + int ret; + + if (clk_gate_ops.is_enabled(hw)) + return 0; + + hwp = clk_hw_get_parent(hw); + + pll_status = pll_is_enabled(hwp); + + if (pll_status) + pll_disable(hwp); + + ret = clk_gate_ops.enable(hw); + + if (pll_status) + pll_enable(hwp); + + return ret; +} + +static void odf_gate_disable(struct clk_hw *hw) +{ + struct clk_hw *hwp; + int pll_status; + + if (!clk_gate_ops.is_enabled(hw)) + return; + + hwp = clk_hw_get_parent(hw); + + pll_status = pll_is_enabled(hwp); + + if (pll_status) + pll_disable(hwp); + + clk_gate_ops.disable(hw); + + if (pll_status) + pll_enable(hwp); +} + +static const struct clk_ops odf_gate_ops = { + .enable = odf_gate_enable, + .disable = odf_gate_disable, + .is_enabled = clk_gate_is_enabled, +}; + +static struct composite_clk_gcfg odf_clk_gcfg = { + M_CFG_DIV(&odf_divider_ops, 0), + M_CFG_GATE(&odf_gate_ops, 0), +}; + +#define M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ + _rate_shift, _rate_width, _flags)\ +{\ + .mux = NULL,\ + .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx },\ + .name = _name,\ + .parent_name = &(const char *) {_parent},\ + .num_parents = 1,\ + .flags = _flags,\ +} + +#define M_ODF(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ + _rate_shift, _rate_width)\ +M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ + _rate_shift, _rate_width, 0)\ + +static const struct composite_clk_cfg stm32_odf[3][3] = { + { + M_ODF_F("pll1_p", "vco1", RCC_PLLCFGR, 16, RCC_PLL1DIVR, 9, 7, + CLK_IGNORE_UNUSED), + M_ODF_F("pll1_q", "vco1", RCC_PLLCFGR, 17, RCC_PLL1DIVR, 16, 7, + CLK_IGNORE_UNUSED), + M_ODF_F("pll1_r", "vco1", RCC_PLLCFGR, 18, RCC_PLL1DIVR, 24, 7, + CLK_IGNORE_UNUSED), + }, + + { + M_ODF("pll2_p", "vco2", RCC_PLLCFGR, 19, RCC_PLL2DIVR, 9, 7), + M_ODF("pll2_q", "vco2", RCC_PLLCFGR, 20, RCC_PLL2DIVR, 16, 7), + M_ODF("pll2_r", "vco2", RCC_PLLCFGR, 21, RCC_PLL2DIVR, 24, 7), + }, + { + M_ODF("pll3_p", "vco3", RCC_PLLCFGR, 22, RCC_PLL3DIVR, 9, 7), + M_ODF("pll3_q", "vco3", RCC_PLLCFGR, 23, RCC_PLL3DIVR, 16, 7), + M_ODF("pll3_r", "vco3", RCC_PLLCFGR, 24, RCC_PLL3DIVR, 24, 7), + } +}; + +/* PERIF CLOCKS */ +struct pclk_t { + u32 gate_offset; + u8 bit_idx; + const char *name; + const char *parent; + u32 flags; +}; + +#define PER_CLKF(_gate_offset, _bit_idx, _name, _parent, _flags)\ +{\ + .gate_offset = _gate_offset,\ + .bit_idx = _bit_idx,\ + .name = _name,\ + .parent = _parent,\ + .flags = _flags,\ +} + +#define PER_CLK(_gate_offset, _bit_idx, _name, _parent)\ + PER_CLKF(_gate_offset, _bit_idx, _name, _parent, 0) + +static const struct pclk_t pclk[] = { + PER_CLK(RCC_AHB3ENR, 31, "d1sram1", "hclk"), + PER_CLK(RCC_AHB3ENR, 30, "itcm", "hclk"), + PER_CLK(RCC_AHB3ENR, 29, "dtcm2", "hclk"), + PER_CLK(RCC_AHB3ENR, 28, "dtcm1", "hclk"), + PER_CLK(RCC_AHB3ENR, 8, "flitf", "hclk"), + PER_CLK(RCC_AHB3ENR, 5, "jpgdec", "hclk"), + PER_CLK(RCC_AHB3ENR, 4, "dma2d", "hclk"), + PER_CLK(RCC_AHB3ENR, 0, "mdma", "hclk"), + PER_CLK(RCC_AHB1ENR, 28, "usb2ulpi", "hclk"), + PER_CLK(RCC_AHB1ENR, 26, "usb1ulpi", "hclk"), + PER_CLK(RCC_AHB1ENR, 17, "eth1rx", "hclk"), + PER_CLK(RCC_AHB1ENR, 16, "eth1tx", "hclk"), + PER_CLK(RCC_AHB1ENR, 15, "eth1mac", "hclk"), + PER_CLK(RCC_AHB1ENR, 14, "art", "hclk"), + PER_CLK(RCC_AHB1ENR, 1, "dma2", "hclk"), + PER_CLK(RCC_AHB1ENR, 0, "dma1", "hclk"), + PER_CLK(RCC_AHB2ENR, 31, "d2sram3", "hclk"), + PER_CLK(RCC_AHB2ENR, 30, "d2sram2", "hclk"), + PER_CLK(RCC_AHB2ENR, 29, "d2sram1", "hclk"), + PER_CLK(RCC_AHB2ENR, 5, "hash", "hclk"), + PER_CLK(RCC_AHB2ENR, 4, "crypt", "hclk"), + PER_CLK(RCC_AHB2ENR, 0, "camitf", "hclk"), + PER_CLK(RCC_AHB4ENR, 28, "bkpram", "hclk"), + PER_CLK(RCC_AHB4ENR, 25, "hsem", "hclk"), + PER_CLK(RCC_AHB4ENR, 21, "bdma", "hclk"), + PER_CLK(RCC_AHB4ENR, 19, "crc", "hclk"), + PER_CLK(RCC_AHB4ENR, 10, "gpiok", "hclk"), + PER_CLK(RCC_AHB4ENR, 9, "gpioj", "hclk"), + PER_CLK(RCC_AHB4ENR, 8, "gpioi", "hclk"), + PER_CLK(RCC_AHB4ENR, 7, "gpioh", "hclk"), + PER_CLK(RCC_AHB4ENR, 6, "gpiog", "hclk"), + PER_CLK(RCC_AHB4ENR, 5, "gpiof", "hclk"), + PER_CLK(RCC_AHB4ENR, 4, "gpioe", "hclk"), + PER_CLK(RCC_AHB4ENR, 3, "gpiod", "hclk"), + PER_CLK(RCC_AHB4ENR, 2, "gpioc", "hclk"), + PER_CLK(RCC_AHB4ENR, 1, "gpiob", "hclk"), + PER_CLK(RCC_AHB4ENR, 0, "gpioa", "hclk"), + PER_CLK(RCC_APB3ENR, 6, "wwdg1", "pclk3"), + PER_CLK(RCC_APB1LENR, 29, "dac12", "pclk1"), + PER_CLK(RCC_APB1LENR, 11, "wwdg2", "pclk1"), + PER_CLK(RCC_APB1LENR, 8, "tim14", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 7, "tim13", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 6, "tim12", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 5, "tim7", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 4, "tim6", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 3, "tim5", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 2, "tim4", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 1, "tim3", "tim1_ker"), + PER_CLK(RCC_APB1LENR, 0, "tim2", "tim1_ker"), + PER_CLK(RCC_APB1HENR, 5, "mdios", "pclk1"), + PER_CLK(RCC_APB1HENR, 4, "opamp", "pclk1"), + PER_CLK(RCC_APB1HENR, 1, "crs", "pclk1"), + PER_CLK(RCC_APB2ENR, 18, "tim17", "tim2_ker"), + PER_CLK(RCC_APB2ENR, 17, "tim16", "tim2_ker"), + PER_CLK(RCC_APB2ENR, 16, "tim15", "tim2_ker"), + PER_CLK(RCC_APB2ENR, 1, "tim8", "tim2_ker"), + PER_CLK(RCC_APB2ENR, 0, "tim1", "tim2_ker"), + PER_CLK(RCC_APB4ENR, 26, "tmpsens", "pclk4"), + PER_CLK(RCC_APB4ENR, 16, "rtcapb", "pclk4"), + PER_CLK(RCC_APB4ENR, 15, "vref", "pclk4"), + PER_CLK(RCC_APB4ENR, 14, "comp12", "pclk4"), + PER_CLK(RCC_APB4ENR, 1, "syscfg", "pclk4"), +}; + +/* KERNEL CLOCKS */ +#define KER_CLKF(_gate_offset, _bit_idx,\ + _mux_offset, _mux_shift, _mux_width,\ + _name, _parent_name,\ + _flags) \ +{ \ + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ + .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ + .name = _name, \ + .parent_name = _parent_name, \ + .num_parents = ARRAY_SIZE(_parent_name),\ + .flags = _flags,\ +} + +#define KER_CLK(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ + _name, _parent_name) \ +KER_CLKF(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ + _name, _parent_name, 0)\ + +#define KER_CLKF_NOMUX(_gate_offset, _bit_idx,\ + _name, _parent_name,\ + _flags) \ +{ \ + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ + .mux = NULL,\ + .name = _name, \ + .parent_name = _parent_name, \ + .num_parents = 1,\ + .flags = _flags,\ +} + +static const struct composite_clk_cfg kclk[] = { + KER_CLK(RCC_AHB3ENR, 16, RCC_D1CCIPR, 16, 1, "sdmmc1", sdmmc_src), + KER_CLKF(RCC_AHB3ENR, 14, RCC_D1CCIPR, 4, 2, "quadspi", qspi_src, + CLK_IGNORE_UNUSED), + KER_CLKF(RCC_AHB3ENR, 12, RCC_D1CCIPR, 0, 2, "fmc", fmc_src, + CLK_IGNORE_UNUSED), + KER_CLK(RCC_AHB1ENR, 27, RCC_D2CCIP2R, 20, 2, "usb2otg", usbotg_src), + KER_CLK(RCC_AHB1ENR, 25, RCC_D2CCIP2R, 20, 2, "usb1otg", usbotg_src), + KER_CLK(RCC_AHB1ENR, 5, RCC_D3CCIPR, 16, 2, "adc12", adc_src), + KER_CLK(RCC_AHB2ENR, 9, RCC_D1CCIPR, 16, 1, "sdmmc2", sdmmc_src), + KER_CLK(RCC_AHB2ENR, 6, RCC_D2CCIP2R, 8, 2, "rng", rng_src), + KER_CLK(RCC_AHB4ENR, 24, RCC_D3CCIPR, 16, 2, "adc3", adc_src), + KER_CLKF(RCC_APB3ENR, 4, RCC_D1CCIPR, 8, 1, "dsi", dsi_src, + CLK_SET_RATE_PARENT), + KER_CLKF_NOMUX(RCC_APB3ENR, 3, "ltdc", ltdc_src, CLK_SET_RATE_PARENT), + KER_CLK(RCC_APB1LENR, 31, RCC_D2CCIP2R, 0, 3, "usart8", usart_src2), + KER_CLK(RCC_APB1LENR, 30, RCC_D2CCIP2R, 0, 3, "usart7", usart_src2), + KER_CLK(RCC_APB1LENR, 27, RCC_D2CCIP2R, 22, 2, "hdmicec", cec_src), + KER_CLK(RCC_APB1LENR, 23, RCC_D2CCIP2R, 12, 2, "i2c3", i2c_src1), + KER_CLK(RCC_APB1LENR, 22, RCC_D2CCIP2R, 12, 2, "i2c2", i2c_src1), + KER_CLK(RCC_APB1LENR, 21, RCC_D2CCIP2R, 12, 2, "i2c1", i2c_src1), + KER_CLK(RCC_APB1LENR, 20, RCC_D2CCIP2R, 0, 3, "uart5", usart_src2), + KER_CLK(RCC_APB1LENR, 19, RCC_D2CCIP2R, 0, 3, "uart4", usart_src2), + KER_CLK(RCC_APB1LENR, 18, RCC_D2CCIP2R, 0, 3, "usart3", usart_src2), + KER_CLK(RCC_APB1LENR, 17, RCC_D2CCIP2R, 0, 3, "usart2", usart_src2), + KER_CLK(RCC_APB1LENR, 16, RCC_D2CCIP1R, 20, 2, "spdifrx", spdifrx_src), + KER_CLK(RCC_APB1LENR, 15, RCC_D2CCIP1R, 16, 3, "spi3", spi_src1), + KER_CLK(RCC_APB1LENR, 14, RCC_D2CCIP1R, 16, 3, "spi2", spi_src1), + KER_CLK(RCC_APB1LENR, 9, RCC_D2CCIP2R, 28, 3, "lptim1", lptim_src1), + KER_CLK(RCC_APB1HENR, 8, RCC_D2CCIP1R, 28, 2, "fdcan", fdcan_src), + KER_CLK(RCC_APB1HENR, 2, RCC_D2CCIP1R, 31, 1, "swp", swp_src), + KER_CLK(RCC_APB2ENR, 29, RCC_CFGR, 14, 1, "hrtim", hrtim_src), + KER_CLK(RCC_APB2ENR, 28, RCC_D2CCIP1R, 24, 1, "dfsdm1", dfsdm1_src), + KER_CLKF(RCC_APB2ENR, 24, RCC_D2CCIP1R, 6, 3, "sai3", sai_src, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), + KER_CLKF(RCC_APB2ENR, 23, RCC_D2CCIP1R, 6, 3, "sai2", sai_src, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), + KER_CLKF(RCC_APB2ENR, 22, RCC_D2CCIP1R, 0, 3, "sai1", sai_src, + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), + KER_CLK(RCC_APB2ENR, 20, RCC_D2CCIP1R, 16, 3, "spi5", spi_src2), + KER_CLK(RCC_APB2ENR, 13, RCC_D2CCIP1R, 16, 3, "spi4", spi_src2), + KER_CLK(RCC_APB2ENR, 12, RCC_D2CCIP1R, 16, 3, "spi1", spi_src1), + KER_CLK(RCC_APB2ENR, 5, RCC_D2CCIP2R, 3, 3, "usart6", usart_src1), + KER_CLK(RCC_APB2ENR, 4, RCC_D2CCIP2R, 3, 3, "usart1", usart_src1), + KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 24, 3, "sai4b", sai_src), + KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 21, 3, "sai4a", sai_src), + KER_CLK(RCC_APB4ENR, 12, RCC_D3CCIPR, 13, 3, "lptim5", lptim_src2), + KER_CLK(RCC_APB4ENR, 11, RCC_D3CCIPR, 13, 3, "lptim4", lptim_src2), + KER_CLK(RCC_APB4ENR, 10, RCC_D3CCIPR, 13, 3, "lptim3", lptim_src2), + KER_CLK(RCC_APB4ENR, 9, RCC_D3CCIPR, 10, 3, "lptim2", lptim_src2), + KER_CLK(RCC_APB4ENR, 7, RCC_D3CCIPR, 8, 2, "i2c4", i2c_src2), + KER_CLK(RCC_APB4ENR, 5, RCC_D3CCIPR, 28, 3, "spi6", spi_src3), + KER_CLK(RCC_APB4ENR, 3, RCC_D3CCIPR, 0, 3, "lpuart1", lpuart1_src), +}; + +static struct composite_clk_gcfg kernel_clk_cfg = { + M_CFG_MUX(NULL, 0), + M_CFG_GATE(NULL, 0), +}; + +/* RTC clock */ +/* + * RTC & LSE registers are protected against parasitic write access. + * PWR_CR_DBP bit must be set to enable write access to RTC registers. + */ +/* STM32_PWR_CR */ +#define PWR_CR 0x00 +/* STM32_PWR_CR bit field */ +#define PWR_CR_DBP BIT(8) + +static struct composite_clk_gcfg rtc_clk_cfg = { + M_CFG_MUX(NULL, 0), + M_CFG_GATE(NULL, 0), +}; + +static const struct composite_clk_cfg rtc_clk = + KER_CLK(RCC_BDCR, 15, RCC_BDCR, 8, 2, "rtc_ck", rtc_src); + +/* Micro-controller output clock */ +static struct composite_clk_gcfg mco_clk_cfg = { + M_CFG_MUX(NULL, 0), + M_CFG_DIV(NULL, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), +}; + +#define M_MCO_F(_name, _parents, _mux_offset, _mux_shift, _mux_width,\ + _rate_offset, _rate_shift, _rate_width,\ + _flags)\ +{\ + .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ + .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ + .gate = NULL,\ + .name = _name,\ + .parent_name = _parents,\ + .num_parents = ARRAY_SIZE(_parents),\ + .flags = _flags,\ +} + +static const struct composite_clk_cfg mco_clk[] = { + M_MCO_F("mco1", mco_src1, RCC_CFGR, 22, 4, RCC_CFGR, 18, 4, 0), + M_MCO_F("mco2", mco_src2, RCC_CFGR, 29, 3, RCC_CFGR, 25, 4, 0), +}; + +static void __init stm32h7_rcc_init(struct device_node *np) +{ + struct clk_hw_onecell_data *clk_data; + struct composite_cfg c_cfg; + int n; + const char *hse_clk, *lse_clk, *i2s_clk; + struct regmap *pdrm; + + clk_data = kzalloc(sizeof(*clk_data) + + sizeof(*clk_data->hws) * STM32H7_MAX_CLKS, + GFP_KERNEL); + if (!clk_data) + return; + + clk_data->num = STM32H7_MAX_CLKS; + + hws = clk_data->hws; + + for (n = 0; n < STM32H7_MAX_CLKS; n++) + hws[n] = ERR_PTR(-ENOENT); + + /* get RCC base @ from DT */ + base = of_iomap(np, 0); + if (!base) { + pr_err("%s: unable to map resource", np->name); + goto err_free_clks; + } + + pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(pdrm)) + pr_warn("%s: Unable to get syscfg\n", __func__); + else + /* In any case disable backup domain write protection + * and will never be enabled. + * Needed by LSE & RTC clocks. + */ + regmap_update_bits(pdrm, PWR_CR, PWR_CR_DBP, PWR_CR_DBP); + + /* Put parent names from DT */ + hse_clk = of_clk_get_parent_name(np, 0); + lse_clk = of_clk_get_parent_name(np, 1); + i2s_clk = of_clk_get_parent_name(np, 2); + + sai_src[3] = i2s_clk; + spi_src1[3] = i2s_clk; + + /* Register Internal oscillators */ + clk_hw_register_fixed_rate(NULL, "clk-hsi", NULL, 0, 64000000); + clk_hw_register_fixed_rate(NULL, "clk-csi", NULL, 0, 4000000); + clk_hw_register_fixed_rate(NULL, "clk-lsi", NULL, 0, 32000); + clk_hw_register_fixed_rate(NULL, "clk-rc48", NULL, 0, 48000); + + /* This clock is coming from outside. Frequencies unknown */ + hws[CK_DSI_PHY] = clk_hw_register_fixed_rate(NULL, "ck_dsi_phy", NULL, + 0, 0); + + hws[HSI_DIV] = clk_hw_register_divider(NULL, "hsidiv", "clk-hsi", 0, + base + RCC_CR, 3, 2, CLK_DIVIDER_POWER_OF_TWO, + &stm32rcc_lock); + + hws[HSE_1M] = clk_hw_register_divider(NULL, "hse_1M", "hse_ck", 0, + base + RCC_CFGR, 8, 6, CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ALLOW_ZERO, + &stm32rcc_lock); + + /* Mux system clocks */ + for (n = 0; n < ARRAY_SIZE(stm32_mclk); n++) + hws[MCLK_BANK + n] = clk_hw_register_mux(NULL, + stm32_mclk[n].name, + stm32_mclk[n].parents, + stm32_mclk[n].num_parents, + stm32_mclk[n].flags, + stm32_mclk[n].offset + base, + stm32_mclk[n].shift, + stm32_mclk[n].width, + 0, + &stm32rcc_lock); + + register_core_and_bus_clocks(); + + /* Oscillary clocks */ + for (n = 0; n < ARRAY_SIZE(stm32_oclk); n++) + hws[OSC_BANK + n] = clk_register_ready_gate(NULL, + stm32_oclk[n].name, + stm32_oclk[n].parent, + stm32_oclk[n].gate_offset + base, + stm32_oclk[n].bit_idx, + stm32_oclk[n].bit_rdy, + stm32_oclk[n].flags, + &stm32rcc_lock); + + hws[HSE_CK] = clk_register_ready_gate(NULL, + "hse_ck", + hse_clk, + RCC_CR + base, + 16, 17, + 0, + &stm32rcc_lock); + + hws[LSE_CK] = clk_register_ready_gate(NULL, + "lse_ck", + lse_clk, + RCC_BDCR + base, + 0, 1, + 0, + &stm32rcc_lock); + + hws[CSI_KER_DIV122 + n] = clk_hw_register_fixed_factor(NULL, + "csi_ker_div122", "csi_ker", 0, 1, 122); + + /* PLLs */ + for (n = 0; n < ARRAY_SIZE(stm32_pll); n++) { + int odf; + + /* Register the VCO */ + clk_register_stm32_pll(NULL, stm32_pll[n].name, + stm32_pll[n].parent_name, stm32_pll[n].flags, + stm32_pll[n].cfg, + &stm32rcc_lock); + + /* Register the 3 output dividers */ + for (odf = 0; odf < 3; odf++) { + int idx = n * 3 + odf; + + get_cfg_composite_div(&odf_clk_gcfg, &stm32_odf[n][odf], + &c_cfg, &stm32rcc_lock); + + hws[ODF_BANK + idx] = clk_hw_register_composite(NULL, + stm32_odf[n][odf].name, + stm32_odf[n][odf].parent_name, + stm32_odf[n][odf].num_parents, + c_cfg.mux_hw, c_cfg.mux_ops, + c_cfg.div_hw, c_cfg.div_ops, + c_cfg.gate_hw, c_cfg.gate_ops, + stm32_odf[n][odf].flags); + } + } + + /* Peripheral clocks */ + for (n = 0; n < ARRAY_SIZE(pclk); n++) + hws[PERIF_BANK + n] = clk_hw_register_gate(NULL, pclk[n].name, + pclk[n].parent, + pclk[n].flags, base + pclk[n].gate_offset, + pclk[n].bit_idx, pclk[n].flags, &stm32rcc_lock); + + /* Kernel clocks */ + for (n = 0; n < ARRAY_SIZE(kclk); n++) { + get_cfg_composite_div(&kernel_clk_cfg, &kclk[n], &c_cfg, + &stm32rcc_lock); + + hws[KERN_BANK + n] = clk_hw_register_composite(NULL, + kclk[n].name, + kclk[n].parent_name, + kclk[n].num_parents, + c_cfg.mux_hw, c_cfg.mux_ops, + c_cfg.div_hw, c_cfg.div_ops, + c_cfg.gate_hw, c_cfg.gate_ops, + kclk[n].flags); + } + + /* RTC clock (default state is off) */ + clk_hw_register_fixed_rate(NULL, "off", NULL, 0, 0); + + get_cfg_composite_div(&rtc_clk_cfg, &rtc_clk, &c_cfg, &stm32rcc_lock); + + hws[RTC_CK] = clk_hw_register_composite(NULL, + rtc_clk.name, + rtc_clk.parent_name, + rtc_clk.num_parents, + c_cfg.mux_hw, c_cfg.mux_ops, + c_cfg.div_hw, c_cfg.div_ops, + c_cfg.gate_hw, c_cfg.gate_ops, + rtc_clk.flags); + + /* Micro-controller clocks */ + for (n = 0; n < ARRAY_SIZE(mco_clk); n++) { + get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg, + &stm32rcc_lock); + + hws[MCO_BANK + n] = clk_hw_register_composite(NULL, + mco_clk[n].name, + mco_clk[n].parent_name, + mco_clk[n].num_parents, + c_cfg.mux_hw, c_cfg.mux_ops, + c_cfg.div_hw, c_cfg.div_ops, + c_cfg.gate_hw, c_cfg.gate_ops, + mco_clk[n].flags); + } + + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); + + return; + +err_free_clks: + kfree(clk_data); +} + +/* The RCC node is a clock and reset controller, and these + * functionalities are supported by different drivers that + * matches the same compatible strings. + */ +CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init); diff --git a/include/dt-bindings/clock/stm32h7-clks.h b/include/dt-bindings/clock/stm32h7-clks.h new file mode 100644 index 000000000000..6637272b3242 --- /dev/null +++ b/include/dt-bindings/clock/stm32h7-clks.h @@ -0,0 +1,165 @@ +/* SYS, CORE AND BUS CLOCKS */ +#define SYS_D1CPRE 0 +#define HCLK 1 +#define PCLK1 2 +#define PCLK2 3 +#define PCLK3 4 +#define PCLK4 5 +#define HSI_DIV 6 +#define HSE_1M 7 +#define I2S_CKIN 8 +#define CK_DSI_PHY 9 +#define HSE_CK 10 +#define LSE_CK 11 +#define CSI_KER_DIV122 12 +#define RTC_CK 13 +#define CPU_SYSTICK 14 + +/* OSCILLATOR BANK */ +#define OSC_BANK 18 +#define HSI_CK 18 +#define HSI_KER_CK 19 +#define CSI_CK 20 +#define CSI_KER_CK 21 +#define RC48_CK 22 +#define LSI_CK 23 + +/* MCLOCK BANK */ +#define MCLK_BANK 28 +#define PER_CK 28 +#define PLLSRC 29 +#define SYS_CK 30 +#define TRACEIN_CK 31 + +/* ODF BANK */ +#define ODF_BANK 32 +#define PLL1_P 32 +#define PLL1_Q 33 +#define PLL1_R 34 +#define PLL2_P 35 +#define PLL2_Q 36 +#define PLL2_R 37 +#define PLL3_P 38 +#define PLL3_Q 39 +#define PLL3_R 40 + +/* MCO BANK */ +#define MCO_BANK 41 +#define MCO1 41 +#define MCO2 42 + +/* PERIF BANK */ +#define PERIF_BANK 50 +#define D1SRAM1_CK 50 +#define ITCM_CK 51 +#define DTCM2_CK 52 +#define DTCM1_CK 53 +#define FLITF_CK 54 +#define JPGDEC_CK 55 +#define DMA2D_CK 56 +#define MDMA_CK 57 +#define USB2ULPI_CK 58 +#define USB1ULPI_CK 59 +#define ETH1RX_CK 60 +#define ETH1TX_CK 61 +#define ETH1MAC_CK 62 +#define ART_CK 63 +#define DMA2_CK 64 +#define DMA1_CK 65 +#define D2SRAM3_CK 66 +#define D2SRAM2_CK 67 +#define D2SRAM1_CK 68 +#define HASH_CK 69 +#define CRYPT_CK 70 +#define CAMITF_CK 71 +#define BKPRAM_CK 72 +#define HSEM_CK 73 +#define BDMA_CK 74 +#define CRC_CK 75 +#define GPIOK_CK 76 +#define GPIOJ_CK 77 +#define GPIOI_CK 78 +#define GPIOH_CK 79 +#define GPIOG_CK 80 +#define GPIOF_CK 81 +#define GPIOE_CK 82 +#define GPIOD_CK 83 +#define GPIOC_CK 84 +#define GPIOB_CK 85 +#define GPIOA_CK 86 +#define WWDG1_CK 87 +#define DAC12_CK 88 +#define WWDG2_CK 89 +#define TIM14_CK 90 +#define TIM13_CK 91 +#define TIM12_CK 92 +#define TIM7_CK 93 +#define TIM6_CK 94 +#define TIM5_CK 95 +#define TIM4_CK 96 +#define TIM3_CK 97 +#define TIM2_CK 98 +#define MDIOS_CK 99 +#define OPAMP_CK 100 +#define CRS_CK 101 +#define TIM17_CK 102 +#define TIM16_CK 103 +#define TIM15_CK 104 +#define TIM8_CK 105 +#define TIM1_CK 106 +#define TMPSENS_CK 107 +#define RTCAPB_CK 108 +#define VREF_CK 109 +#define COMP12_CK 110 +#define SYSCFG_CK 111 + +/* KERNEL BANK */ +#define KERN_BANK 120 +#define SDMMC1_CK 120 +#define QUADSPI_CK 121 +#define FMC_CK 122 +#define USB2OTG_CK 123 +#define USB1OTG_CK 124 +#define ADC12_CK 125 +#define SDMMC2_CK 126 +#define RNG_CK 127 +#define ADC3_CK 128 +#define DSI_CK 129 +#define LTDC_CK 130 +#define USART8_CK 131 +#define USART7_CK 132 +#define HDMICEC_CK 133 +#define I2C3_CK 134 +#define I2C2_CK 135 +#define I2C1_CK 136 +#define UART5_CK 137 +#define UART4_CK 138 +#define USART3_CK 139 +#define USART2_CK 140 +#define SPDIFRX_CK 141 +#define SPI3_CK 142 +#define SPI2_CK 143 +#define LPTIM1_CK 144 +#define FDCAN_CK 145 +#define SWP_CK 146 +#define HRTIM_CK 147 +#define DFSDM1_CK 148 +#define SAI3_CK 149 +#define SAI2_CK 150 +#define SAI1_CK 151 +#define SPI5_CK 152 +#define SPI4_CK 153 +#define SPI1_CK 154 +#define USART6_CK 155 +#define USART1_CK 156 +#define SAI4B_CK 157 +#define SAI4A_CK 158 +#define LPTIM5_CK 159 +#define LPTIM4_CK 160 +#define LPTIM3_CK 161 +#define LPTIM2_CK 162 +#define I2C4_CK 163 +#define SPI6_CK 164 +#define LPUART1_CK 165 + +#define STM32H7_MAX_CLKS 166 diff --git a/include/dt-bindings/mfd/stm32h7-rcc.h b/include/dt-bindings/mfd/stm32h7-rcc.h new file mode 100644 index 000000000000..461a8e04453a --- /dev/null +++ b/include/dt-bindings/mfd/stm32h7-rcc.h @@ -0,0 +1,136 @@ +/* + * This header provides constants for the STM32H7 RCC IP + */ + +#ifndef _DT_BINDINGS_MFD_STM32H7_RCC_H +#define _DT_BINDINGS_MFD_STM32H7_RCC_H + +/* AHB3 */ +#define STM32H7_RCC_AHB3_MDMA 0 +#define STM32H7_RCC_AHB3_DMA2D 4 +#define STM32H7_RCC_AHB3_JPGDEC 5 +#define STM32H7_RCC_AHB3_FMC 12 +#define STM32H7_RCC_AHB3_QUADSPI 14 +#define STM32H7_RCC_AHB3_SDMMC1 16 +#define STM32H7_RCC_AHB3_CPU 31 + +#define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8)) + +/* AHB1 */ +#define STM32H7_RCC_AHB1_DMA1 0 +#define STM32H7_RCC_AHB1_DMA2 1 +#define STM32H7_RCC_AHB1_ADC12 5 +#define STM32H7_RCC_AHB1_ART 14 +#define STM32H7_RCC_AHB1_ETH1MAC 15 +#define STM32H7_RCC_AHB1_USB1OTG 25 +#define STM32H7_RCC_AHB1_USB2OTG 27 + +#define STM32H7_AHB1_RESET(bit) (STM32H7_RCC_AHB1_##bit + (0x80 * 8)) + +/* AHB2 */ +#define STM32H7_RCC_AHB2_CAMITF 0 +#define STM32H7_RCC_AHB2_CRYPT 4 +#define STM32H7_RCC_AHB2_HASH 5 +#define STM32H7_RCC_AHB2_RNG 6 +#define STM32H7_RCC_AHB2_SDMMC2 9 + +#define STM32H7_AHB2_RESET(bit) (STM32H7_RCC_AHB2_##bit + (0x84 * 8)) + +/* AHB4 */ +#define STM32H7_RCC_AHB4_GPIOA 0 +#define STM32H7_RCC_AHB4_GPIOB 1 +#define STM32H7_RCC_AHB4_GPIOC 2 +#define STM32H7_RCC_AHB4_GPIOD 3 +#define STM32H7_RCC_AHB4_GPIOE 4 +#define STM32H7_RCC_AHB4_GPIOF 5 +#define STM32H7_RCC_AHB4_GPIOG 6 +#define STM32H7_RCC_AHB4_GPIOH 7 +#define STM32H7_RCC_AHB4_GPIOI 8 +#define STM32H7_RCC_AHB4_GPIOJ 9 +#define STM32H7_RCC_AHB4_GPIOK 10 +#define STM32H7_RCC_AHB4_CRC 19 +#define STM32H7_RCC_AHB4_BDMA 21 +#define STM32H7_RCC_AHB4_ADC3 24 +#define STM32H7_RCC_AHB4_HSEM 25 + +#define STM32H7_AHB4_RESET(bit) (STM32H7_RCC_AHB4_##bit + (0x88 * 8)) + +/* APB3 */ +#define STM32H7_RCC_APB3_LTDC 3 +#define STM32H7_RCC_APB3_DSI 4 + +#define STM32H7_APB3_RESET(bit) (STM32H7_RCC_APB3_##bit + (0x8C * 8)) + +/* APB1L */ +#define STM32H7_RCC_APB1L_TIM2 0 +#define STM32H7_RCC_APB1L_TIM3 1 +#define STM32H7_RCC_APB1L_TIM4 2 +#define STM32H7_RCC_APB1L_TIM5 3 +#define STM32H7_RCC_APB1L_TIM6 4 +#define STM32H7_RCC_APB1L_TIM7 5 +#define STM32H7_RCC_APB1L_TIM12 6 +#define STM32H7_RCC_APB1L_TIM13 7 +#define STM32H7_RCC_APB1L_TIM14 8 +#define STM32H7_RCC_APB1L_LPTIM1 9 +#define STM32H7_RCC_APB1L_SPI2 14 +#define STM32H7_RCC_APB1L_SPI3 15 +#define STM32H7_RCC_APB1L_SPDIF_RX 16 +#define STM32H7_RCC_APB1L_USART2 17 +#define STM32H7_RCC_APB1L_USART3 18 +#define STM32H7_RCC_APB1L_UART4 19 +#define STM32H7_RCC_APB1L_UART5 20 +#define STM32H7_RCC_APB1L_I2C1 21 +#define STM32H7_RCC_APB1L_I2C2 22 +#define STM32H7_RCC_APB1L_I2C3 23 +#define STM32H7_RCC_APB1L_HDMICEC 27 +#define STM32H7_RCC_APB1L_DAC12 29 +#define STM32H7_RCC_APB1L_USART7 30 +#define STM32H7_RCC_APB1L_USART8 31 + +#define STM32H7_APB1L_RESET(bit) (STM32H7_RCC_APB1L_##bit + (0x90 * 8)) + +/* APB1H */ +#define STM32H7_RCC_APB1H_CRS 1 +#define STM32H7_RCC_APB1H_SWP 2 +#define STM32H7_RCC_APB1H_OPAMP 4 +#define STM32H7_RCC_APB1H_MDIOS 5 +#define STM32H7_RCC_APB1H_FDCAN 8 + +#define STM32H7_APB1H_RESET(bit) (STM32H7_RCC_APB1H_##bit + (0x94 * 8)) + +/* APB2 */ +#define STM32H7_RCC_APB2_TIM1 0 +#define STM32H7_RCC_APB2_TIM8 1 +#define STM32H7_RCC_APB2_USART1 4 +#define STM32H7_RCC_APB2_USART6 5 +#define STM32H7_RCC_APB2_SPI1 12 +#define STM32H7_RCC_APB2_SPI4 13 +#define STM32H7_RCC_APB2_TIM15 16 +#define STM32H7_RCC_APB2_TIM16 17 +#define STM32H7_RCC_APB2_TIM17 18 +#define STM32H7_RCC_APB2_SPI5 20 +#define STM32H7_RCC_APB2_SAI1 22 +#define STM32H7_RCC_APB2_SAI2 23 +#define STM32H7_RCC_APB2_SAI3 24 +#define STM32H7_RCC_APB2_DFSDM1 28 +#define STM32H7_RCC_APB2_HRTIM 29 + +#define STM32H7_APB2_RESET(bit) (STM32H7_RCC_APB2_##bit + (0x98 * 8)) + +/* APB4 */ +#define STM32H7_RCC_APB4_SYSCFG 1 +#define STM32H7_RCC_APB4_LPUART1 3 +#define STM32H7_RCC_APB4_SPI6 5 +#define STM32H7_RCC_APB4_I2C4 7 +#define STM32H7_RCC_APB4_LPTIM2 9 +#define STM32H7_RCC_APB4_LPTIM3 10 +#define STM32H7_RCC_APB4_LPTIM4 11 +#define STM32H7_RCC_APB4_LPTIM5 12 +#define STM32H7_RCC_APB4_COMP12 14 +#define STM32H7_RCC_APB4_VREF 15 +#define STM32H7_RCC_APB4_SAI4 21 +#define STM32H7_RCC_APB4_TMPSENS 26 + +#define STM32H7_APB4_RESET(bit) (STM32H7_RCC_APB4_##bit + (0x9C * 8)) + +#endif /* _DT_BINDINGS_MFD_STM32H7_RCC_H */ -- cgit v1.2.3