^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2015 Altera Corporation. All rights reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* Clock Manager offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CLK_MGR_PLL_CLK_SRC_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define CLK_MGR_PLL_CLK_SRC_MASK 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Clock bypass bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define SOCFPGA_PLL_BG_PWRDWN 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define SOCFPGA_PLL_PWR_DOWN 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SOCFPGA_PLL_EXT_ENA 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SOCFPGA_PLL_DIVF_MASK 0x00001FFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SOCFPGA_PLL_DIVF_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SOCFPGA_PLL_DIVQ_SHIFT 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SOCFGPA_MAX_PARENTS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SOCFPGA_MAIN_PLL_CLK "main_pll"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SOCFPGA_PERIP_PLL_CLK "periph_pll"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) void __iomem *clk_mgr_a10_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) unsigned long divf, divq, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned long long vco_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* read VCO1 reg for numerator and denominator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) reg = readl(socfpgaclk->hw.reg + 0x4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) vco_freq = (unsigned long long)parent_rate * (divf + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) do_div(vco_freq, (1 + divq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return (unsigned long)vco_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static u8 clk_pll_get_parent(struct clk_hw *hwclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 pll_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pll_src = readl(socfpgaclk->hw.reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) CLK_MGR_PLL_CLK_SRC_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static const struct clk_ops clk_pll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .recalc_rate = clk_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .get_parent = clk_pll_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static struct clk * __init __socfpga_pll_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) const struct clk_ops *ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct socfpga_pll *pll_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) const char *clk_name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const char *parent_name[SOCFGPA_MAX_PARENTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct device_node *clkmgr_np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) of_property_read_u32(node, "reg", ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (WARN_ON(!pll_clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) of_node_put(clkmgr_np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) BUG_ON(!clk_mgr_a10_base_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pll_clk->hw.reg = clk_mgr_a10_base_addr + reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) of_property_read_string(node, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) init.name = clk_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) init.ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) of_clk_get_parent_name(node, i)) != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) init.num_parents = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) init.parent_names = parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) pll_clk->hw.hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) clk = clk_register(NULL, &pll_clk->hw.hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (WARN_ON(IS_ERR(clk))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kfree(pll_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) void __init socfpga_a10_pll_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) __socfpga_pll_init(node, &clk_pll_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }