^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * clk-xgene.c - AppliedMicro X-Gene Clock Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2013, Applied Micro Circuits Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Loc Ho <lho@apm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk-provider.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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Register SCU_PCPPLL bit fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define N_DIV_RD(src) ((src) & 0x000001ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define SC_N_DIV_RD(src) ((src) & 0x0000007f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SC_OUTDIV2(src) (((src) & 0x00000100) >> 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Register SCU_SOCPLL bit fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define CLKR_RD(src) (((src) & 0x07000000)>>24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define CLKOD_RD(src) (((src) & 0x00300000)>>20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define REGSPEC_RESET_F1_MASK 0x00010000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define CLKF_RD(src) (((src) & 0x000001ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define XGENE_CLK_DRIVER_VER "0.1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static DEFINE_SPINLOCK(clk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static inline u32 xgene_clk_read(void __iomem *csr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return readl_relaxed(csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static inline void xgene_clk_write(u32 data, void __iomem *csr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) writel_relaxed(data, csr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* PLL Clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) enum xgene_pll_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) PLL_TYPE_PCP = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) PLL_TYPE_SOC = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct xgene_clk_pll {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) spinlock_t *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 pll_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) enum xgene_pll_type type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) pr_debug("%s pll %s\n", clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned long fref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned long fvco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 nref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 nout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u32 nfb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (pllclk->version <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (pllclk->type == PLL_TYPE_PCP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * PLL VCO = Reference clock * NF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * PCP PLL = PLL_VCO / 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) nout = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) fvco = parent_rate * (N_DIV_RD(pll) + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * Fref = Reference Clock / NREF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Fvco = Fref * NFB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Fout = Fvco / NOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) nref = CLKR_RD(pll) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) nout = CLKOD_RD(pll) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) nfb = CLKF_RD(pll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) fref = parent_rate / nref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fvco = fref * nfb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * fvco = Reference clock * FBDIVC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * PLL freq = fvco / NOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) nout = SC_OUTDIV2(pll) ? 2 : 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fvco = parent_rate * SC_N_DIV_RD(pll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) pr_debug("%s pll recalc rate %ld parent %ld version %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) clk_hw_get_name(hw), fvco / nout, parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pllclk->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return fvco / nout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static const struct clk_ops xgene_clk_pll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .is_enabled = xgene_clk_pll_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .recalc_rate = xgene_clk_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static struct clk *xgene_register_clk_pll(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) const char *name, const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned long flags, void __iomem *reg, u32 pll_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) u32 type, spinlock_t *lock, int version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct xgene_clk_pll *apmclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* allocate the APM clock structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (!apmclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) init.ops = &xgene_clk_pll_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) init.parent_names = parent_name ? &parent_name : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) init.num_parents = parent_name ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) apmclk->version = version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) apmclk->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) apmclk->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) apmclk->pll_offset = pll_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) apmclk->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) apmclk->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* Register the clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) clk = clk_register(dev, &apmclk->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pr_err("%s: could not register clk %s\n", __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) kfree(apmclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static int xgene_pllclk_version(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (of_device_is_compatible(np, "apm,xgene-socpll-clock"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (of_device_is_compatible(np, "apm,xgene-pcppll-clock"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 2;
^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) static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) const char *clk_name = np->full_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int version = xgene_pllclk_version(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) reg = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) pr_err("Unable to map CSR register for %pOF\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) of_property_read_string(np, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) clk = xgene_register_clk_pll(NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) clk_name, of_clk_get_parent_name(np, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 0, reg, 0, pll_type, &clk_lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) of_clk_add_provider(np, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) clk_register_clkdev(clk, clk_name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) pr_debug("Add %s clock PLL\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) static void xgene_socpllclk_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) xgene_pllclk_init(np, PLL_TYPE_SOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void xgene_pcppllclk_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) xgene_pllclk_init(np, PLL_TYPE_PCP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * struct xgene_clk_pmd - PMD clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * @hw: handle between common and hardware-specific interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * @reg: register containing the fractional scale multiplier (scaler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @shift: shift to the unit bit field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @denom: 1/denominator unit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @lock: register lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Flags:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * XGENE_CLK_PMD_SCALE_INVERTED - By default the scaler is the value read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * from the register plus one. For example,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * 0 for (0 + 1) / denom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * 1 for (1 + 1) / denom and etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * If this flag is set, it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * 0 for (denom - 0) / denom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * 1 for (denom - 1) / denom and etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct xgene_clk_pmd {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u8 shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) u64 denom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) spinlock_t *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define to_xgene_clk_pmd(_hw) container_of(_hw, struct xgene_clk_pmd, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #define XGENE_CLK_PMD_SCALE_INVERTED BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define XGENE_CLK_PMD_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define XGENE_CLK_PMD_WIDTH 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static unsigned long xgene_clk_pmd_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) u64 ret, scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (fd->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) spin_lock_irqsave(fd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) __acquire(fd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) val = readl(fd->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (fd->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) spin_unlock_irqrestore(fd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) __release(fd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = (u64)parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) scale = (val & fd->mask) >> fd->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) scale = fd->denom - scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) scale++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* freq = parent_rate * scaler / denom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) do_div(ret, fd->denom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ret *= scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (ret == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ret = (u64)parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static long xgene_clk_pmd_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u64 ret, scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!rate || rate >= *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return *parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* freq = parent_rate * scaler / denom */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = rate * fd->denom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) scale = DIV_ROUND_UP_ULL(ret, *parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = (u64)*parent_rate * scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) do_div(ret, fd->denom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int xgene_clk_pmd_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) u64 scale, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Compute the scaler:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * freq = parent_rate * scaler / denom, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * scaler = freq * denom / parent_rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ret = rate * fd->denom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) scale = DIV_ROUND_UP_ULL(ret, (u64)parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Check if inverted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) scale = fd->denom - scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) scale--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (fd->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) spin_lock_irqsave(fd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) __acquire(fd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) val = readl(fd->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) val &= ~fd->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val |= (scale << fd->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) writel(val, fd->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (fd->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) spin_unlock_irqrestore(fd->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) __release(fd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static const struct clk_ops xgene_clk_pmd_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .recalc_rate = xgene_clk_pmd_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .round_rate = xgene_clk_pmd_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .set_rate = xgene_clk_pmd_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) static struct clk *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) xgene_register_clk_pmd(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) const char *name, const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned long flags, void __iomem *reg, u8 shift,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) u8 width, u64 denom, u32 clk_flags, spinlock_t *lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct xgene_clk_pmd *fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) fd = kzalloc(sizeof(*fd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) init.ops = &xgene_clk_pmd_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) init.parent_names = parent_name ? &parent_name : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) init.num_parents = parent_name ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) fd->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) fd->shift = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) fd->mask = (BIT(width) - 1) << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) fd->denom = denom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) fd->flags = clk_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) fd->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) fd->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) clk = clk_register(dev, &fd->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) pr_err("%s: could not register clk %s\n", __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) kfree(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static void xgene_pmdclk_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) const char *clk_name = np->full_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) void __iomem *csr_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) u64 denom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) u32 flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Check if the entry is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!of_device_is_available(np))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* Parse the DTS register for resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) rc = of_address_to_resource(np, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) pr_err("no DTS register for %pOF\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) csr_reg = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!csr_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) pr_err("Unable to map resource for %pOF\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) of_property_read_string(np, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) denom = BIT(XGENE_CLK_PMD_WIDTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) flags |= XGENE_CLK_PMD_SCALE_INVERTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) clk = xgene_register_clk_pmd(NULL, clk_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) of_clk_get_parent_name(np, 0), 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) csr_reg, XGENE_CLK_PMD_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) XGENE_CLK_PMD_WIDTH, denom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) flags, &clk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (!IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) of_clk_add_provider(np, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) clk_register_clkdev(clk, clk_name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) pr_debug("Add %s clock\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (csr_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) iounmap(csr_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* IP Clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct xgene_dev_parameters {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) void __iomem *csr_reg; /* CSR for IP clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) u32 reg_clk_offset; /* Offset to clock enable CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) u32 reg_clk_mask; /* Mask bit for clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) u32 reg_csr_offset; /* Offset to CSR reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) u32 reg_csr_mask; /* Mask bit for disable CSR reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) void __iomem *divider_reg; /* CSR for divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) u32 reg_divider_offset; /* Offset to divider register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) u32 reg_divider_shift; /* Bit shift to divider field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) u32 reg_divider_width; /* Width of the bit to divider field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct xgene_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) spinlock_t *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct xgene_dev_parameters param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) #define to_xgene_clk(_hw) container_of(_hw, struct xgene_clk, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int xgene_clk_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) spin_lock_irqsave(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (pclk->param.csr_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) /* First enable the clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) data = xgene_clk_read(pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) pclk->param.reg_clk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) data |= pclk->param.reg_clk_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) xgene_clk_write(data, pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) pclk->param.reg_clk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) pr_debug("%s clk offset 0x%08X mask 0x%08X value 0x%08X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /* Second enable the CSR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) data = xgene_clk_read(pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) pclk->param.reg_csr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) data &= ~pclk->param.reg_csr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) xgene_clk_write(data, pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) pclk->param.reg_csr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) pr_debug("%s csr offset 0x%08X mask 0x%08X value 0x%08X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) spin_unlock_irqrestore(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void xgene_clk_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) spin_lock_irqsave(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (pclk->param.csr_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* First put the CSR in reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) data = xgene_clk_read(pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) pclk->param.reg_csr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) data |= pclk->param.reg_csr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) xgene_clk_write(data, pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) pclk->param.reg_csr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* Second disable the clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) data = xgene_clk_read(pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) pclk->param.reg_clk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) data &= ~pclk->param.reg_clk_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) xgene_clk_write(data, pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) pclk->param.reg_clk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) spin_unlock_irqrestore(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int xgene_clk_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) u32 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (pclk->param.csr_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pr_debug("%s clock checking\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) data = xgene_clk_read(pclk->param.csr_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) pclk->param.reg_clk_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) pr_debug("%s clock is %s\n", clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) data & pclk->param.reg_clk_mask ? "enabled" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!pclk->param.csr_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return data & pclk->param.reg_clk_mask ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (pclk->param.divider_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) data = xgene_clk_read(pclk->param.divider_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) pclk->param.reg_divider_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) data >>= pclk->param.reg_divider_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) data &= (1 << pclk->param.reg_divider_width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) pr_debug("%s clock recalc rate %ld parent %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) parent_rate / data, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return parent_rate / data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) pr_debug("%s clock recalc rate %ld parent %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) clk_hw_get_name(hw), parent_rate, parent_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) u32 divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) u32 divider_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) spin_lock_irqsave(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (pclk->param.divider_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) /* Let's compute the divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (rate > parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) divider_save = divider = parent_rate / rate; /* Rounded down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) divider &= (1 << pclk->param.reg_divider_width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) divider <<= pclk->param.reg_divider_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* Set new divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) data = xgene_clk_read(pclk->param.divider_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) pclk->param.reg_divider_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) data &= ~(((1 << pclk->param.reg_divider_width) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) << pclk->param.reg_divider_shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) data |= divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) xgene_clk_write(data, pclk->param.divider_reg +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) pclk->param.reg_divider_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) pr_debug("%s clock set rate %ld\n", clk_hw_get_name(hw),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) parent_rate / divider_save);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) divider_save = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (pclk->lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) spin_unlock_irqrestore(pclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return parent_rate / divider_save;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) unsigned long *prate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct xgene_clk *pclk = to_xgene_clk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) unsigned long parent_rate = *prate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) u32 divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (pclk->param.divider_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* Let's compute the divider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) if (rate > parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) divider = parent_rate / rate; /* Rounded down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) divider = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return parent_rate / divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static const struct clk_ops xgene_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) .enable = xgene_clk_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) .disable = xgene_clk_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) .is_enabled = xgene_clk_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) .recalc_rate = xgene_clk_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) .set_rate = xgene_clk_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) .round_rate = xgene_clk_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static struct clk *xgene_register_clk(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) const char *name, const char *parent_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct xgene_dev_parameters *parameters, spinlock_t *lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct xgene_clk *apmclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* allocate the APM clock structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (!apmclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) init.ops = &xgene_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) init.parent_names = parent_name ? &parent_name : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) init.num_parents = parent_name ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) apmclk->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) apmclk->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) apmclk->param = *parameters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* Register the clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) clk = clk_register(dev, &apmclk->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) pr_err("%s: could not register clk %s\n", __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) kfree(apmclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /* Register the clock for lookup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) rc = clk_register_clkdev(clk, name, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) pr_err("%s: could not register lookup clk %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) __func__, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static void __init xgene_devclk_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) const char *clk_name = np->full_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct xgene_dev_parameters parameters;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* Check if the entry is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) if (!of_device_is_available(np))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /* Parse the DTS register for resource */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) parameters.csr_reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) parameters.divider_reg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) void __iomem *map_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) rc = of_address_to_resource(np, i, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pr_err("no DTS register for %pOF\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) map_res = of_iomap(np, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) if (!map_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) pr_err("Unable to map resource %d for %pOF\n", i, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (strcmp(res.name, "div-reg") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) parameters.divider_reg = map_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) else /* if (strcmp(res->name, "csr-reg") == 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) parameters.csr_reg = map_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (of_property_read_u32(np, "csr-offset", ¶meters.reg_csr_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) parameters.reg_csr_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (of_property_read_u32(np, "csr-mask", ¶meters.reg_csr_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) parameters.reg_csr_mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (of_property_read_u32(np, "enable-offset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ¶meters.reg_clk_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) parameters.reg_clk_offset = 0x8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (of_property_read_u32(np, "enable-mask", ¶meters.reg_clk_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) parameters.reg_clk_mask = 0xF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (of_property_read_u32(np, "divider-offset",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) ¶meters.reg_divider_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) parameters.reg_divider_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (of_property_read_u32(np, "divider-width",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ¶meters.reg_divider_width))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) parameters.reg_divider_width = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (of_property_read_u32(np, "divider-shift",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ¶meters.reg_divider_shift))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) parameters.reg_divider_shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) of_property_read_string(np, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) clk = xgene_register_clk(NULL, clk_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) of_clk_get_parent_name(np, 0), ¶meters, &clk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) pr_debug("Add %s clock\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) pr_err("%s: could register provider clk %pOF\n", __func__, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (parameters.csr_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) iounmap(parameters.csr_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (parameters.divider_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) iounmap(parameters.divider_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) CLK_OF_DECLARE(xgene_pmd_clock, "apm,xgene-pmd-clock", xgene_pmdclk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) xgene_socpllclk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) xgene_pcppllclk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);