linux/drivers/clk/keystone/pll.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * PLL clock driver for Keystone devices
   4 *
   5 * Copyright (C) 2013 Texas Instruments Inc.
   6 *      Murali Karicheri <m-karicheri2@ti.com>
   7 *      Santosh Shilimkar <santosh.shilimkar@ti.com>
   8 */
   9#include <linux/clk-provider.h>
  10#include <linux/err.h>
  11#include <linux/io.h>
  12#include <linux/slab.h>
  13#include <linux/of_address.h>
  14#include <linux/of.h>
  15#include <linux/module.h>
  16
  17#define PLLM_LOW_MASK           0x3f
  18#define PLLM_HIGH_MASK          0x7ffc0
  19#define MAIN_PLLM_HIGH_MASK     0x7f000
  20#define PLLM_HIGH_SHIFT         6
  21#define PLLD_MASK               0x3f
  22#define CLKOD_MASK              0x780000
  23#define CLKOD_SHIFT             19
  24
  25/**
  26 * struct clk_pll_data - pll data structure
  27 * @has_pllctrl: If set to non zero, lower 6 bits of multiplier is in pllm
  28 *      register of pll controller, else it is in the pll_ctrl0((bit 11-6)
  29 * @phy_pllm: Physical address of PLLM in pll controller. Used when
  30 *      has_pllctrl is non zero.
  31 * @phy_pll_ctl0: Physical address of PLL ctrl0. This could be that of
  32 *      Main PLL or any other PLLs in the device such as ARM PLL, DDR PLL
  33 *      or PA PLL available on keystone2. These PLLs are controlled by
  34 *      this register. Main PLL is controlled by a PLL controller.
  35 * @pllm: PLL register map address for multiplier bits
  36 * @pllod: PLL register map address for post divider bits
  37 * @pll_ctl0: PLL controller map address
  38 * @pllm_lower_mask: multiplier lower mask
  39 * @pllm_upper_mask: multiplier upper mask
  40 * @pllm_upper_shift: multiplier upper shift
  41 * @plld_mask: divider mask
  42 * @clkod_mask: output divider mask
  43 * @clkod_shift: output divider shift
  44 * @plld_mask: divider mask
  45 * @postdiv: Fixed post divider
  46 */
  47struct clk_pll_data {
  48        bool has_pllctrl;
  49        u32 phy_pllm;
  50        u32 phy_pll_ctl0;
  51        void __iomem *pllm;
  52        void __iomem *pllod;
  53        void __iomem *pll_ctl0;
  54        u32 pllm_lower_mask;
  55        u32 pllm_upper_mask;
  56        u32 pllm_upper_shift;
  57        u32 plld_mask;
  58        u32 clkod_mask;
  59        u32 clkod_shift;
  60        u32 postdiv;
  61};
  62
  63/**
  64 * struct clk_pll - Main pll clock
  65 * @hw: clk_hw for the pll
  66 * @pll_data: PLL driver specific data
  67 */
  68struct clk_pll {
  69        struct clk_hw hw;
  70        struct clk_pll_data *pll_data;
  71};
  72
  73#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
  74
  75static unsigned long clk_pllclk_recalc(struct clk_hw *hw,
  76                                        unsigned long parent_rate)
  77{
  78        struct clk_pll *pll = to_clk_pll(hw);
  79        struct clk_pll_data *pll_data = pll->pll_data;
  80        unsigned long rate = parent_rate;
  81        u32  mult = 0, prediv, postdiv, val;
  82
  83        /*
  84         * get bits 0-5 of multiplier from pllctrl PLLM register
  85         * if has_pllctrl is non zero
  86         */
  87        if (pll_data->has_pllctrl) {
  88                val = readl(pll_data->pllm);
  89                mult = (val & pll_data->pllm_lower_mask);
  90        }
  91
  92        /* bit6-12 of PLLM is in Main PLL control register */
  93        val = readl(pll_data->pll_ctl0);
  94        mult |= ((val & pll_data->pllm_upper_mask)
  95                        >> pll_data->pllm_upper_shift);
  96        prediv = (val & pll_data->plld_mask);
  97
  98        if (!pll_data->has_pllctrl)
  99                /* read post divider from od bits*/
 100                postdiv = ((val & pll_data->clkod_mask) >>
 101                                 pll_data->clkod_shift) + 1;
 102        else if (pll_data->pllod) {
 103                postdiv = readl(pll_data->pllod);
 104                postdiv = ((postdiv & pll_data->clkod_mask) >>
 105                                pll_data->clkod_shift) + 1;
 106        } else
 107                postdiv = pll_data->postdiv;
 108
 109        rate /= (prediv + 1);
 110        rate = (rate * (mult + 1));
 111        rate /= postdiv;
 112
 113        return rate;
 114}
 115
 116static const struct clk_ops clk_pll_ops = {
 117        .recalc_rate = clk_pllclk_recalc,
 118};
 119
 120static struct clk *clk_register_pll(struct device *dev,
 121                        const char *name,
 122                        const char *parent_name,
 123                        struct clk_pll_data *pll_data)
 124{
 125        struct clk_init_data init;
 126        struct clk_pll *pll;
 127        struct clk *clk;
 128
 129        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 130        if (!pll)
 131                return ERR_PTR(-ENOMEM);
 132
 133        init.name = name;
 134        init.ops = &clk_pll_ops;
 135        init.flags = 0;
 136        init.parent_names = (parent_name ? &parent_name : NULL);
 137        init.num_parents = (parent_name ? 1 : 0);
 138
 139        pll->pll_data   = pll_data;
 140        pll->hw.init = &init;
 141
 142        clk = clk_register(NULL, &pll->hw);
 143        if (IS_ERR(clk))
 144                goto out;
 145
 146        return clk;
 147out:
 148        kfree(pll);
 149        return NULL;
 150}
 151
 152/**
 153 * _of_pll_clk_init - PLL initialisation via DT
 154 * @node: device tree node for this clock
 155 * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
 156 *              pll controller, else it is in the control register0(bit 11-6)
 157 */
 158static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
 159{
 160        struct clk_pll_data *pll_data;
 161        const char *parent_name;
 162        struct clk *clk;
 163        int i;
 164
 165        pll_data = kzalloc(sizeof(*pll_data), GFP_KERNEL);
 166        if (!pll_data) {
 167                pr_err("%s: Out of memory\n", __func__);
 168                return;
 169        }
 170
 171        parent_name = of_clk_get_parent_name(node, 0);
 172        if (of_property_read_u32(node, "fixed-postdiv", &pll_data->postdiv)) {
 173                /* assume the PLL has output divider register bits */
 174                pll_data->clkod_mask = CLKOD_MASK;
 175                pll_data->clkod_shift = CLKOD_SHIFT;
 176
 177                /*
 178                 * Check if there is an post-divider register. If not
 179                 * assume od bits are part of control register.
 180                 */
 181                i = of_property_match_string(node, "reg-names",
 182                                             "post-divider");
 183                pll_data->pllod = of_iomap(node, i);
 184        }
 185
 186        i = of_property_match_string(node, "reg-names", "control");
 187        pll_data->pll_ctl0 = of_iomap(node, i);
 188        if (!pll_data->pll_ctl0) {
 189                pr_err("%s: ioremap failed\n", __func__);
 190                iounmap(pll_data->pllod);
 191                goto out;
 192        }
 193
 194        pll_data->pllm_lower_mask = PLLM_LOW_MASK;
 195        pll_data->pllm_upper_shift = PLLM_HIGH_SHIFT;
 196        pll_data->plld_mask = PLLD_MASK;
 197        pll_data->has_pllctrl = pllctrl;
 198        if (!pll_data->has_pllctrl) {
 199                pll_data->pllm_upper_mask = PLLM_HIGH_MASK;
 200        } else {
 201                pll_data->pllm_upper_mask = MAIN_PLLM_HIGH_MASK;
 202                i = of_property_match_string(node, "reg-names", "multiplier");
 203                pll_data->pllm = of_iomap(node, i);
 204                if (!pll_data->pllm) {
 205                        iounmap(pll_data->pll_ctl0);
 206                        iounmap(pll_data->pllod);
 207                        goto out;
 208                }
 209        }
 210
 211        clk = clk_register_pll(NULL, node->name, parent_name, pll_data);
 212        if (clk) {
 213                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 214                return;
 215        }
 216
 217out:
 218        pr_err("%s: error initializing pll %pOFn\n", __func__, node);
 219        kfree(pll_data);
 220}
 221
 222/**
 223 * of_keystone_pll_clk_init - PLL initialisation DT wrapper
 224 * @node: device tree node for this clock
 225 */
 226static void __init of_keystone_pll_clk_init(struct device_node *node)
 227{
 228        _of_pll_clk_init(node, false);
 229}
 230CLK_OF_DECLARE(keystone_pll_clock, "ti,keystone,pll-clock",
 231                                        of_keystone_pll_clk_init);
 232
 233/**
 234 * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper
 235 * @node: device tree node for this clock
 236 */
 237static void __init of_keystone_main_pll_clk_init(struct device_node *node)
 238{
 239        _of_pll_clk_init(node, true);
 240}
 241CLK_OF_DECLARE(keystone_main_pll_clock, "ti,keystone,main-pll-clock",
 242                                                of_keystone_main_pll_clk_init);
 243
 244/**
 245 * of_pll_div_clk_init - PLL divider setup function
 246 * @node: device tree node for this clock
 247 */
 248static void __init of_pll_div_clk_init(struct device_node *node)
 249{
 250        const char *parent_name;
 251        void __iomem *reg;
 252        u32 shift, mask;
 253        struct clk *clk;
 254        const char *clk_name = node->name;
 255
 256        of_property_read_string(node, "clock-output-names", &clk_name);
 257        reg = of_iomap(node, 0);
 258        if (!reg) {
 259                pr_err("%s: ioremap failed\n", __func__);
 260                return;
 261        }
 262
 263        parent_name = of_clk_get_parent_name(node, 0);
 264        if (!parent_name) {
 265                pr_err("%s: missing parent clock\n", __func__);
 266                iounmap(reg);
 267                return;
 268        }
 269
 270        if (of_property_read_u32(node, "bit-shift", &shift)) {
 271                pr_err("%s: missing 'shift' property\n", __func__);
 272                iounmap(reg);
 273                return;
 274        }
 275
 276        if (of_property_read_u32(node, "bit-mask", &mask)) {
 277                pr_err("%s: missing 'bit-mask' property\n", __func__);
 278                iounmap(reg);
 279                return;
 280        }
 281
 282        clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
 283                                 mask, 0, NULL);
 284        if (clk) {
 285                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 286        } else {
 287                pr_err("%s: error registering divider %s\n", __func__, clk_name);
 288                iounmap(reg);
 289        }
 290}
 291CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
 292
 293/**
 294 * of_pll_mux_clk_init - PLL mux setup function
 295 * @node: device tree node for this clock
 296 */
 297static void __init of_pll_mux_clk_init(struct device_node *node)
 298{
 299        void __iomem *reg;
 300        u32 shift, mask;
 301        struct clk *clk;
 302        const char *parents[2];
 303        const char *clk_name = node->name;
 304
 305        of_property_read_string(node, "clock-output-names", &clk_name);
 306        reg = of_iomap(node, 0);
 307        if (!reg) {
 308                pr_err("%s: ioremap failed\n", __func__);
 309                return;
 310        }
 311
 312        of_clk_parent_fill(node, parents, 2);
 313        if (!parents[0] || !parents[1]) {
 314                pr_err("%s: missing parent clocks\n", __func__);
 315                return;
 316        }
 317
 318        if (of_property_read_u32(node, "bit-shift", &shift)) {
 319                pr_err("%s: missing 'shift' property\n", __func__);
 320                return;
 321        }
 322
 323        if (of_property_read_u32(node, "bit-mask", &mask)) {
 324                pr_err("%s: missing 'bit-mask' property\n", __func__);
 325                return;
 326        }
 327
 328        clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
 329                                ARRAY_SIZE(parents) , 0, reg, shift, mask,
 330                                0, NULL);
 331        if (clk)
 332                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 333        else
 334                pr_err("%s: error registering mux %s\n", __func__, clk_name);
 335}
 336CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
 337
 338MODULE_LICENSE("GPL");
 339MODULE_DESCRIPTION("PLL clock driver for Keystone devices");
 340MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
 341MODULE_AUTHOR("Santosh Shilimkar <santosh.shilimkar@ti.com>");
 342