^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2014 Marvell Technology Group Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Alexandre Belloni <alexandre.belloni@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <dt-bindings/clock/berlin2q.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "berlin2-div.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "berlin2-pll.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define REG_PINMUX0 0x0018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define REG_PINMUX5 0x002c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define REG_SYSPLLCTL0 0x0030
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define REG_SYSPLLCTL4 0x0040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define REG_CLKENABLE 0x00e8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define REG_CLKSELECT0 0x00ec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define REG_CLKSELECT1 0x00f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define REG_CLKSELECT2 0x00f4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define REG_CLKSWITCH0 0x00f8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define REG_CLKSWITCH1 0x00fc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define REG_SW_GENERIC0 0x0110
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define REG_SW_GENERIC3 0x011c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define REG_SDIO0XIN_CLKCTL 0x0158
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define REG_SDIO1XIN_CLKCTL 0x015c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MAX_CLKS 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct clk_hw_onecell_data *clk_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static DEFINE_SPINLOCK(lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static void __iomem *gbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static void __iomem *cpupll_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) REFCLK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) SYSPLL, CPUPLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static const char *clk_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) [REFCLK] = "refclk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [SYSPLL] = "syspll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [CPUPLL] = "cpupll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [AVPLL_B1] = "avpll_b1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) [AVPLL_B2] = "avpll_b2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [AVPLL_B3] = "avpll_b3",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) [AVPLL_B4] = "avpll_b4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [AVPLL_B5] = "avpll_b5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) [AVPLL_B6] = "avpll_b6",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [AVPLL_B7] = "avpll_b7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) [AVPLL_B8] = "avpll_b8",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static const struct berlin2_pll_map bg2q_pll_map __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .vcodiv = {1, 0, 2, 0, 3, 4, 0, 6, 8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .mult = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .fbdiv_shift = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .rfdiv_shift = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .divsel_shift = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const u8 default_parent_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct berlin2_div_data bg2q_divs[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .name = "sys",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .flags = CLK_IGNORE_UNUSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .name = "drmfigo",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .name = "cfg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .name = "gfx2d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .name = "zsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .name = "perif",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .flags = CLK_IGNORE_UNUSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .name = "pcube",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .name = "vscope",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .name = "nfc_ecc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .name = "vpp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .name = "app",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .name = "sdio0xin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .name = "sdio1xin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .parent_ids = default_parent_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .num_parents = ARRAY_SIZE(default_parent_ids),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static const struct berlin2_gate_data bg2q_gates[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) { "gfx2daxi", "perif", 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) { "geth0", "perif", 8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) { "sata", "perif", 9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) { "usb0", "perif", 11 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) { "usb1", "perif", 12 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) { "usb2", "perif", 13 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) { "usb3", "perif", 14 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) { "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) { "sdio", "perif", 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) { "nfc", "perif", 18 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) { "pcie", "perif", 22 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static void __init berlin2q_clock_setup(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct device_node *parent_np = of_get_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) const char *parent_names[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct clk_hw **hws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int n, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (!clk_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) clk_data->num = MAX_CLKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) hws = clk_data->hws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) gbase = of_iomap(parent_np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (!gbase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) pr_err("%pOF: Unable to map global base\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* BG2Q CPU PLL is not part of global registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) cpupll_base = of_iomap(parent_np, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (!cpupll_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pr_err("%pOF: Unable to map cpupll base\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) iounmap(gbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* overwrite default clock names with DT provided ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) clk = of_clk_get_by_name(np, clk_names[REFCLK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) clk_names[REFCLK] = __clk_get_name(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) clk_put(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* simple register PLLs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) clk_names[SYSPLL], clk_names[REFCLK], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto bg2q_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) clk_names[CPUPLL], clk_names[REFCLK], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) goto bg2q_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* TODO: add BG2Q AVPLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * TODO: add reference clock bypass switches:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* clock divider cells */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) const struct berlin2_div_data *dd = &bg2q_divs[n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) for (k = 0; k < dd->num_parents; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) parent_names[k] = clk_names[dd->parent_ids[k]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) dd->name, dd->div_flags, parent_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) dd->num_parents, dd->flags, &lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* clock gate cells */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) const struct berlin2_gate_data *gd = &bg2q_gates[n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) gd->bit_idx, 0, &lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /* cpuclk divider is fixed to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) hws[CLKID_CPU] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) /* twdclk is derived from cpu/3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) hws[CLKID_TWD] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* check for errors on leaf clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) for (n = 0; n < MAX_CLKS; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (!IS_ERR(hws[n]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto bg2q_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* register clk-provider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) bg2q_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) iounmap(cpupll_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) iounmap(gbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) CLK_OF_DECLARE(berlin2q_clk, "marvell,berlin2q-clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) berlin2q_clock_setup);