1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2011-2012 Calxeda, Inc. 4 * Copyright (C) 2012-2013 Altera Corporation <www.altera.com> 5 * 6 * Based from clk-highbank.c 7 */ 8 #include <linux/slab.h> 9 #include <linux/clk-provider.h> 10 #include <linux/io.h> 11 #include <linux/of.h> 12 #include <linux/of_address.h> 13 14 #include "clk.h" 15 16 /* Clock bypass bits */ 17 #define MAINPLL_BYPASS (1<<0) 18 #define SDRAMPLL_BYPASS (1<<1) 19 #define SDRAMPLL_SRC_BYPASS (1<<2) 20 #define PERPLL_BYPASS (1<<3) 21 #define PERPLL_SRC_BYPASS (1<<4) 22 23 #define SOCFPGA_PLL_BG_PWRDWN 0 24 #define SOCFPGA_PLL_EXT_ENA 1 25 #define SOCFPGA_PLL_PWR_DOWN 2 26 #define SOCFPGA_PLL_DIVF_MASK 0x0000FFF8 27 #define SOCFPGA_PLL_DIVF_SHIFT 3 28 #define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 29 #define SOCFPGA_PLL_DIVQ_SHIFT 16 30 31 #define CLK_MGR_PLL_CLK_SRC_SHIFT 22 32 #define CLK_MGR_PLL_CLK_SRC_MASK 0x3 33 34 #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) 35 36 void __iomem *clk_mgr_base_addr; 37 38 static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, 39 unsigned long parent_rate) 40 { 41 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 42 unsigned long divf, divq, reg; 43 unsigned long long vco_freq; 44 unsigned long bypass; 45 46 reg = readl(socfpgaclk->hw.reg); 47 bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS); 48 if (bypass & MAINPLL_BYPASS) 49 return parent_rate; 50 51 divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; 52 divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; 53 vco_freq = (unsigned long long)parent_rate * (divf + 1); 54 do_div(vco_freq, (1 + divq)); 55 return (unsigned long)vco_freq; 56 } 57 58 static u8 clk_pll_get_parent(struct clk_hw *hwclk) 59 { 60 u32 pll_src; 61 struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); 62 63 pll_src = readl(socfpgaclk->hw.reg); 64 return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) & 65 CLK_MGR_PLL_CLK_SRC_MASK; 66 } 67 68 static const struct clk_ops clk_pll_ops = { 69 .recalc_rate = clk_pll_recalc_rate, 70 .get_parent = clk_pll_get_parent, 71 }; 72 73 static __init struct clk_hw *__socfpga_pll_init(struct device_node *node, 74 const struct clk_ops *ops) 75 { 76 u32 reg; 77 struct clk_hw *hw_clk; 78 struct socfpga_pll *pll_clk; 79 const char *clk_name = node->name; 80 const char *parent_name[SOCFPGA_MAX_PARENTS]; 81 struct clk_init_data init; 82 struct device_node *clkmgr_np; 83 int rc; 84 int err; 85 86 of_property_read_u32(node, "reg", ®); 87 88 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); 89 if (WARN_ON(!pll_clk)) 90 return NULL; 91 92 clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); 93 clk_mgr_base_addr = of_iomap(clkmgr_np, 0); 94 of_node_put(clkmgr_np); 95 BUG_ON(!clk_mgr_base_addr); 96 pll_clk->hw.reg = clk_mgr_base_addr + reg; 97 98 of_property_read_string(node, "clock-output-names", &clk_name); 99 100 init.name = clk_name; 101 init.ops = ops; 102 init.flags = 0; 103 104 init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS); 105 init.parent_names = parent_name; 106 pll_clk->hw.hw.init = &init; 107 108 pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; 109 110 hw_clk = &pll_clk->hw.hw; 111 112 err = clk_hw_register(NULL, hw_clk); 113 if (err) { 114 kfree(pll_clk); 115 return ERR_PTR(err); 116 } 117 rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk); 118 return hw_clk; 119 } 120 121 void __init socfpga_pll_init(struct device_node *node) 122 { 123 __socfpga_pll_init(node, &clk_pll_ops); 124 } 125