Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: keystone: add Keystone PLL clock driver

Add the driver for the PLL IPs found on Keystone 2 devices. The PLL
IP typically has a multiplier, a divider and a post-divider. The PLL IPs like
ARMPLL, DDRPLL and PAPLL are controlled by the memory mapped register where
as the Main PLL is controlled by a PLL controller and memory map registers.

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Mike Turquette <mturquette@linaro.org>

authored by

Santosh Shilimkar and committed by
Mike Turquette
b9e0d40c 938cc3a1

+389
+84
Documentation/devicetree/bindings/clock/keystone-pll.txt
··· 1 + Status: Unstable - ABI compatibility may be broken in the future 2 + 3 + Binding for keystone PLLs. The main PLL IP typically has a multiplier, 4 + a divider and a post divider. The additional PLL IPs like ARMPLL, DDRPLL 5 + and PAPLL are controlled by the memory mapped register where as the Main 6 + PLL is controlled by a PLL controller registers along with memory mapped 7 + registers. 8 + 9 + This binding uses the common clock binding[1]. 10 + 11 + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt 12 + 13 + Required properties: 14 + - #clock-cells : from common clock binding; shall be set to 0. 15 + - compatible : shall be "ti,keystone,main-pll-clock" or "ti,keystone,pll-clock" 16 + - clocks : parent clock phandle 17 + - reg - pll control0 and pll multipler registers 18 + - reg-names : control and multiplier. The multiplier is applicable only for 19 + main pll clock 20 + - fixed-postdiv : fixed post divider value 21 + 22 + Example: 23 + mainpllclk: mainpllclk@2310110 { 24 + #clock-cells = <0>; 25 + compatible = "ti,keystone,main-pll-clock"; 26 + clocks = <&refclkmain>; 27 + reg = <0x02620350 4>, <0x02310110 4>; 28 + reg-names = "control", "multiplier"; 29 + fixed-postdiv = <2>; 30 + }; 31 + 32 + papllclk: papllclk@2620358 { 33 + #clock-cells = <0>; 34 + compatible = "ti,keystone,pll-clock"; 35 + clocks = <&refclkmain>; 36 + clock-output-names = "pa-pll-clk"; 37 + reg = <0x02620358 4>; 38 + reg-names = "control"; 39 + fixed-postdiv = <6>; 40 + }; 41 + 42 + Required properties: 43 + - #clock-cells : from common clock binding; shall be set to 0. 44 + - compatible : shall be "ti,keystone,pll-mux-clock" 45 + - clocks : link phandles of parent clocks 46 + - reg - pll mux register 47 + - bit-shift : number of bits to shift the bit-mask 48 + - bit-mask : arbitrary bitmask for programming the mux 49 + 50 + Optional properties: 51 + - clock-output-names : From common clock binding. 52 + 53 + Example: 54 + mainmuxclk: mainmuxclk@2310108 { 55 + #clock-cells = <0>; 56 + compatible = "ti,keystone,pll-mux-clock"; 57 + clocks = <&mainpllclk>, <&refclkmain>; 58 + reg = <0x02310108 4>; 59 + bit-shift = <23>; 60 + bit-mask = <1>; 61 + clock-output-names = "mainmuxclk"; 62 + }; 63 + 64 + Required properties: 65 + - #clock-cells : from common clock binding; shall be set to 0. 66 + - compatible : shall be "ti,keystone,pll-divider-clock" 67 + - clocks : parent clock phandle 68 + - reg - pll mux register 69 + - bit-shift : number of bits to shift the bit-mask 70 + - bit-mask : arbitrary bitmask for programming the divider 71 + 72 + Optional properties: 73 + - clock-output-names : From common clock binding. 74 + 75 + Example: 76 + gemtraceclk: gemtraceclk@2310120 { 77 + #clock-cells = <0>; 78 + compatible = "ti,keystone,pll-divider-clock"; 79 + clocks = <&mainmuxclk>; 80 + reg = <0x02310120 4>; 81 + bit-shift = <0>; 82 + bit-mask = <8>; 83 + clock-output-names = "gemtraceclk"; 84 + };
+305
drivers/clk/keystone/pll.c
··· 1 + /* 2 + * PLL clock driver for Keystone devices 3 + * 4 + * Copyright (C) 2013 Texas Instruments Inc. 5 + * Murali Karicheri <m-karicheri2@ti.com> 6 + * Santosh Shilimkar <santosh.shilimkar@ti.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + #include <linux/clk.h> 14 + #include <linux/clk-provider.h> 15 + #include <linux/err.h> 16 + #include <linux/io.h> 17 + #include <linux/slab.h> 18 + #include <linux/of_address.h> 19 + #include <linux/of.h> 20 + #include <linux/module.h> 21 + 22 + #define PLLM_LOW_MASK 0x3f 23 + #define PLLM_HIGH_MASK 0x7ffc0 24 + #define MAIN_PLLM_HIGH_MASK 0x7f000 25 + #define PLLM_HIGH_SHIFT 6 26 + #define PLLD_MASK 0x3f 27 + 28 + /** 29 + * struct clk_pll_data - pll data structure 30 + * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm 31 + * register of pll controller, else it is in the pll_ctrl0((bit 11-6) 32 + * @phy_pllm: Physical address of PLLM in pll controller. Used when 33 + * has_pllctrl is non zero. 34 + * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of 35 + * Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL 36 + * or PA PLL available on keystone2. These PLLs are controlled by 37 + * this register. Main PLL is controlled by a PLL controller. 38 + * @pllm: PLL register map address 39 + * @pll_ctl0: PLL controller map address 40 + * @pllm_lower_mask: multiplier lower mask 41 + * @pllm_upper_mask: multiplier upper mask 42 + * @pllm_upper_shift: multiplier upper shift 43 + * @plld_mask: divider mask 44 + * @postdiv: Post divider 45 + */ 46 + struct clk_pll_data { 47 + bool has_pllctrl; 48 + u32 phy_pllm; 49 + u32 phy_pll_ctl0; 50 + void __iomem *pllm; 51 + void __iomem *pll_ctl0; 52 + u32 pllm_lower_mask; 53 + u32 pllm_upper_mask; 54 + u32 pllm_upper_shift; 55 + u32 plld_mask; 56 + u32 postdiv; 57 + }; 58 + 59 + /** 60 + * struct clk_pll - Main pll clock 61 + * @hw: clk_hw for the pll 62 + * @pll_data: PLL driver specific data 63 + */ 64 + struct clk_pll { 65 + struct clk_hw hw; 66 + struct clk_pll_data *pll_data; 67 + }; 68 + 69 + #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) 70 + 71 + static unsigned long clk_pllclk_recalc(struct clk_hw *hw, 72 + unsigned long parent_rate) 73 + { 74 + struct clk_pll *pll = to_clk_pll(hw); 75 + struct clk_pll_data *pll_data = pll->pll_data; 76 + unsigned long rate = parent_rate; 77 + u32 mult = 0, prediv, postdiv, val; 78 + 79 + /* 80 + * get bits 0-5 of multiplier from pllctrl PLLM register 81 + * if has_pllctrl is non zero 82 + */ 83 + if (pll_data->has_pllctrl) { 84 + val = readl(pll_data->pllm); 85 + mult = (val & pll_data->pllm_lower_mask); 86 + } 87 + 88 + /* bit6-12 of PLLM is in Main PLL control register */ 89 + val = readl(pll_data->pll_ctl0); 90 + mult |= ((val & pll_data->pllm_upper_mask) 91 + >> pll_data->pllm_upper_shift); 92 + prediv = (val & pll_data->plld_mask); 93 + postdiv = pll_data->postdiv; 94 + 95 + rate /= (prediv + 1); 96 + rate = (rate * (mult + 1)); 97 + rate /= postdiv; 98 + 99 + return rate; 100 + } 101 + 102 + static const struct clk_ops clk_pll_ops = { 103 + .recalc_rate = clk_pllclk_recalc, 104 + }; 105 + 106 + static struct clk *clk_register_pll(struct device *dev, 107 + const char *name, 108 + const char *parent_name, 109 + struct clk_pll_data *pll_data) 110 + { 111 + struct clk_init_data init; 112 + struct clk_pll *pll; 113 + struct clk *clk; 114 + 115 + pll = kzalloc(sizeof(*pll), GFP_KERNEL); 116 + if (!pll) 117 + return ERR_PTR(-ENOMEM); 118 + 119 + init.name = name; 120 + init.ops = &clk_pll_ops; 121 + init.flags = 0; 122 + init.parent_names = (parent_name ? &parent_name : NULL); 123 + init.num_parents = (parent_name ? 1 : 0); 124 + 125 + pll->pll_data = pll_data; 126 + pll->hw.init = &init; 127 + 128 + clk = clk_register(NULL, &pll->hw); 129 + if (IS_ERR(clk)) 130 + goto out; 131 + 132 + return clk; 133 + out: 134 + kfree(pll); 135 + return NULL; 136 + } 137 + 138 + /** 139 + * _of_clk_init - PLL initialisation via DT 140 + * @node: device tree node for this clock 141 + * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of 142 + * pll controller, else it is in the control regsiter0(bit 11-6) 143 + */ 144 + static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl) 145 + { 146 + struct clk_pll_data *pll_data; 147 + const char *parent_name; 148 + struct clk *clk; 149 + int i; 150 + 151 + pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL); 152 + if (!pll_data) { 153 + pr_err("%s: Out of memory\n", __func__); 154 + return; 155 + } 156 + 157 + parent_name = of_clk_get_parent_name(node, 0); 158 + if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) 159 + goto out; 160 + 161 + i = of_property_match_string(node, "reg-names", "control"); 162 + pll_data->pll_ctl0 = of_iomap(node, i); 163 + if (!pll_data->pll_ctl0) { 164 + pr_err("%s: ioremap failed\n", __func__); 165 + goto out; 166 + } 167 + 168 + pll_data->pllm_lower_mask = PLLM_LOW_MASK; 169 + pll_data->pllm_upper_shift = PLLM_HIGH_SHIFT; 170 + pll_data->plld_mask = PLLD_MASK; 171 + pll_data->has_pllctrl = pllctrl; 172 + if (!pll_data->has_pllctrl) { 173 + pll_data->pllm_upper_mask = PLLM_HIGH_MASK; 174 + } else { 175 + pll_data->pllm_upper_mask = MAIN_PLLM_HIGH_MASK; 176 + i = of_property_match_string(node, "reg-names", "multiplier"); 177 + pll_data->pllm = of_iomap(node, i); 178 + if (!pll_data->pllm) { 179 + iounmap(pll_data->pll_ctl0); 180 + goto out; 181 + } 182 + } 183 + 184 + clk = clk_register_pll(NULL, node->name, parent_name, pll_data); 185 + if (clk) { 186 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 187 + return; 188 + } 189 + 190 + out: 191 + pr_err("%s: error initializing pll %s\n", __func__, node->name); 192 + kfree(pll_data); 193 + } 194 + 195 + /** 196 + * of_keystone_pll_clk_init - PLL initialisation DT wrapper 197 + * @node: device tree node for this clock 198 + */ 199 + static void __init of_keystone_pll_clk_init(struct device_node *node) 200 + { 201 + _of_pll_clk_init(node, false); 202 + } 203 + CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock", 204 + of_keystone_pll_clk_init); 205 + 206 + /** 207 + * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper 208 + * @node: device tree node for this clock 209 + */ 210 + static void __init of_keystone_main_pll_clk_init(struct device_node *node) 211 + { 212 + _of_pll_clk_init(node, true); 213 + } 214 + CLK_OF_DECLARE(keystone_main_pll_clock, "ti,keystone,main-pll-clock", 215 + of_keystone_main_pll_clk_init); 216 + 217 + /** 218 + * of_pll_div_clk_init - PLL divider setup function 219 + * @node: device tree node for this clock 220 + */ 221 + static void __init of_pll_div_clk_init(struct device_node *node) 222 + { 223 + const char *parent_name; 224 + void __iomem *reg; 225 + u32 shift, mask; 226 + struct clk *clk; 227 + const char *clk_name = node->name; 228 + 229 + of_property_read_string(node, "clock-output-names", &clk_name); 230 + reg = of_iomap(node, 0); 231 + if (!reg) { 232 + pr_err("%s: ioremap failed\n", __func__); 233 + return; 234 + } 235 + 236 + parent_name = of_clk_get_parent_name(node, 0); 237 + if (!parent_name) { 238 + pr_err("%s: missing parent clock\n", __func__); 239 + return; 240 + } 241 + 242 + if (of_property_read_u32(node, "bit-shift", &shift)) { 243 + pr_err("%s: missing 'shift' property\n", __func__); 244 + return; 245 + } 246 + 247 + if (of_property_read_u32(node, "bit-mask", &mask)) { 248 + pr_err("%s: missing 'bit-mask' property\n", __func__); 249 + return; 250 + } 251 + 252 + clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift, 253 + mask, 0, NULL); 254 + if (clk) 255 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 256 + else 257 + pr_err("%s: error registering divider %s\n", __func__, clk_name); 258 + } 259 + CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init); 260 + 261 + /** 262 + * of_pll_mux_clk_init - PLL mux setup function 263 + * @node: device tree node for this clock 264 + */ 265 + static void __init of_pll_mux_clk_init(struct device_node *node) 266 + { 267 + void __iomem *reg; 268 + u32 shift, mask; 269 + struct clk *clk; 270 + const char *parents[2]; 271 + const char *clk_name = node->name; 272 + 273 + of_property_read_string(node, "clock-output-names", &clk_name); 274 + reg = of_iomap(node, 0); 275 + if (!reg) { 276 + pr_err("%s: ioremap failed\n", __func__); 277 + return; 278 + } 279 + 280 + parents[0] = of_clk_get_parent_name(node, 0); 281 + parents[1] = of_clk_get_parent_name(node, 1); 282 + if (!parents[0] || !parents[1]) { 283 + pr_err("%s: missing parent clocks\n", __func__); 284 + return; 285 + } 286 + 287 + if (of_property_read_u32(node, "bit-shift", &shift)) { 288 + pr_err("%s: missing 'shift' property\n", __func__); 289 + return; 290 + } 291 + 292 + if (of_property_read_u32(node, "bit-mask", &mask)) { 293 + pr_err("%s: missing 'bit-mask' property\n", __func__); 294 + return; 295 + } 296 + 297 + clk = clk_register_mux(NULL, clk_name, (const char **)&parents, 298 + ARRAY_SIZE(parents) , 0, reg, shift, mask, 299 + 0, NULL); 300 + if (clk) 301 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 302 + else 303 + pr_err("%s: error registering mux %s\n", __func__, clk_name); 304 + } 305 + CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);