linux/drivers/clk/socfpga/clk.c
<<
>>
Prefs
   1/*
   2 *  Copyright 2011-2012 Calxeda, Inc.
   3 *  Copyright (C) 2012-2013 Altera Corporation <www.altera.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * Based from clk-highbank.c
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20#include <linux/clk.h>
  21#include <linux/clkdev.h>
  22#include <linux/clk-provider.h>
  23#include <linux/io.h>
  24#include <linux/of.h>
  25
  26/* Clock Manager offsets */
  27#define CLKMGR_CTRL     0x0
  28#define CLKMGR_BYPASS   0x4
  29#define CLKMGR_L4SRC    0x70
  30#define CLKMGR_PERPLL_SRC       0xAC
  31
  32/* Clock bypass bits */
  33#define MAINPLL_BYPASS          (1<<0)
  34#define SDRAMPLL_BYPASS         (1<<1)
  35#define SDRAMPLL_SRC_BYPASS     (1<<2)
  36#define PERPLL_BYPASS           (1<<3)
  37#define PERPLL_SRC_BYPASS       (1<<4)
  38
  39#define SOCFPGA_PLL_BG_PWRDWN           0
  40#define SOCFPGA_PLL_EXT_ENA             1
  41#define SOCFPGA_PLL_PWR_DOWN            2
  42#define SOCFPGA_PLL_DIVF_MASK           0x0000FFF8
  43#define SOCFPGA_PLL_DIVF_SHIFT  3
  44#define SOCFPGA_PLL_DIVQ_MASK           0x003F0000
  45#define SOCFPGA_PLL_DIVQ_SHIFT  16
  46#define SOCFGPA_MAX_PARENTS     3
  47
  48#define SOCFPGA_L4_MP_CLK               "l4_mp_clk"
  49#define SOCFPGA_L4_SP_CLK               "l4_sp_clk"
  50#define SOCFPGA_NAND_CLK                "nand_clk"
  51#define SOCFPGA_NAND_X_CLK              "nand_x_clk"
  52#define SOCFPGA_MMC_CLK                 "sdmmc_clk"
  53#define SOCFPGA_DB_CLK                  "gpio_db_clk"
  54
  55#define div_mask(width) ((1 << (width)) - 1)
  56#define streq(a, b) (strcmp((a), (b)) == 0)
  57
  58extern void __iomem *clk_mgr_base_addr;
  59
  60struct socfpga_clk {
  61        struct clk_gate hw;
  62        char *parent_name;
  63        char *clk_name;
  64        u32 fixed_div;
  65        void __iomem *div_reg;
  66        u32 width;      /* only valid if div_reg != 0 */
  67        u32 shift;      /* only valid if div_reg != 0 */
  68};
  69#define to_socfpga_clk(p) container_of(p, struct socfpga_clk, hw.hw)
  70
  71static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
  72                                         unsigned long parent_rate)
  73{
  74        struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
  75        unsigned long divf, divq, vco_freq, reg;
  76        unsigned long bypass;
  77
  78        reg = readl(socfpgaclk->hw.reg);
  79        bypass = readl(clk_mgr_base_addr + CLKMGR_BYPASS);
  80        if (bypass & MAINPLL_BYPASS)
  81                return parent_rate;
  82
  83        divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT;
  84        divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT;
  85        vco_freq = parent_rate * (divf + 1);
  86        return vco_freq / (1 + divq);
  87}
  88
  89
  90static struct clk_ops clk_pll_ops = {
  91        .recalc_rate = clk_pll_recalc_rate,
  92};
  93
  94static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
  95                                             unsigned long parent_rate)
  96{
  97        struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
  98        u32 div;
  99
 100        if (socfpgaclk->fixed_div)
 101                div = socfpgaclk->fixed_div;
 102        else
 103                div = ((readl(socfpgaclk->hw.reg) & 0x1ff) + 1);
 104
 105        return parent_rate / div;
 106}
 107
 108static const struct clk_ops periclk_ops = {
 109        .recalc_rate = clk_periclk_recalc_rate,
 110};
 111
 112static __init struct clk *socfpga_clk_init(struct device_node *node,
 113        const struct clk_ops *ops)
 114{
 115        u32 reg;
 116        struct clk *clk;
 117        struct socfpga_clk *socfpga_clk;
 118        const char *clk_name = node->name;
 119        const char *parent_name;
 120        struct clk_init_data init;
 121        int rc;
 122        u32 fixed_div;
 123
 124        rc = of_property_read_u32(node, "reg", &reg);
 125        if (WARN_ON(rc))
 126                return NULL;
 127
 128        socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
 129        if (WARN_ON(!socfpga_clk))
 130                return NULL;
 131
 132        socfpga_clk->hw.reg = clk_mgr_base_addr + reg;
 133
 134        rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
 135        if (rc)
 136                socfpga_clk->fixed_div = 0;
 137        else
 138                socfpga_clk->fixed_div = fixed_div;
 139
 140        of_property_read_string(node, "clock-output-names", &clk_name);
 141
 142        init.name = clk_name;
 143        init.ops = ops;
 144        init.flags = 0;
 145        parent_name = of_clk_get_parent_name(node, 0);
 146        init.parent_names = &parent_name;
 147        init.num_parents = 1;
 148
 149        socfpga_clk->hw.hw.init = &init;
 150
 151        if (streq(clk_name, "main_pll") ||
 152                streq(clk_name, "periph_pll") ||
 153                streq(clk_name, "sdram_pll")) {
 154                socfpga_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA;
 155                clk_pll_ops.enable = clk_gate_ops.enable;
 156                clk_pll_ops.disable = clk_gate_ops.disable;
 157        }
 158
 159        clk = clk_register(NULL, &socfpga_clk->hw.hw);
 160        if (WARN_ON(IS_ERR(clk))) {
 161                kfree(socfpga_clk);
 162                return NULL;
 163        }
 164        rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
 165        return clk;
 166}
 167
 168static u8 socfpga_clk_get_parent(struct clk_hw *hwclk)
 169{
 170        u32 l4_src;
 171        u32 perpll_src;
 172
 173        if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
 174                l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
 175                return l4_src &= 0x1;
 176        }
 177        if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
 178                l4_src = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
 179                return !!(l4_src & 2);
 180        }
 181
 182        perpll_src = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
 183        if (streq(hwclk->init->name, SOCFPGA_MMC_CLK))
 184                return perpll_src &= 0x3;
 185        if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
 186                        streq(hwclk->init->name, SOCFPGA_NAND_X_CLK))
 187                        return (perpll_src >> 2) & 3;
 188
 189        /* QSPI clock */
 190        return (perpll_src >> 4) & 3;
 191
 192}
 193
 194static int socfpga_clk_set_parent(struct clk_hw *hwclk, u8 parent)
 195{
 196        u32 src_reg;
 197
 198        if (streq(hwclk->init->name, SOCFPGA_L4_MP_CLK)) {
 199                src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
 200                src_reg &= ~0x1;
 201                src_reg |= parent;
 202                writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
 203        } else if (streq(hwclk->init->name, SOCFPGA_L4_SP_CLK)) {
 204                src_reg = readl(clk_mgr_base_addr + CLKMGR_L4SRC);
 205                src_reg &= ~0x2;
 206                src_reg |= (parent << 1);
 207                writel(src_reg, clk_mgr_base_addr + CLKMGR_L4SRC);
 208        } else {
 209                src_reg = readl(clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
 210                if (streq(hwclk->init->name, SOCFPGA_MMC_CLK)) {
 211                        src_reg &= ~0x3;
 212                        src_reg |= parent;
 213                } else if (streq(hwclk->init->name, SOCFPGA_NAND_CLK) ||
 214                        streq(hwclk->init->name, SOCFPGA_NAND_X_CLK)) {
 215                        src_reg &= ~0xC;
 216                        src_reg |= (parent << 2);
 217                } else {/* QSPI clock */
 218                        src_reg &= ~0x30;
 219                        src_reg |= (parent << 4);
 220                }
 221                writel(src_reg, clk_mgr_base_addr + CLKMGR_PERPLL_SRC);
 222        }
 223
 224        return 0;
 225}
 226
 227static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
 228        unsigned long parent_rate)
 229{
 230        struct socfpga_clk *socfpgaclk = to_socfpga_clk(hwclk);
 231        u32 div = 1, val;
 232
 233        if (socfpgaclk->fixed_div)
 234                div = socfpgaclk->fixed_div;
 235        else if (socfpgaclk->div_reg) {
 236                val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
 237                val &= div_mask(socfpgaclk->width);
 238                if (streq(hwclk->init->name, SOCFPGA_DB_CLK))
 239                        div = val + 1;
 240                else
 241                        div = (1 << val);
 242        }
 243
 244        return parent_rate / div;
 245}
 246
 247static struct clk_ops gateclk_ops = {
 248        .recalc_rate = socfpga_clk_recalc_rate,
 249        .get_parent = socfpga_clk_get_parent,
 250        .set_parent = socfpga_clk_set_parent,
 251};
 252
 253static void __init socfpga_gate_clk_init(struct device_node *node,
 254        const struct clk_ops *ops)
 255{
 256        u32 clk_gate[2];
 257        u32 div_reg[3];
 258        u32 fixed_div;
 259        struct clk *clk;
 260        struct socfpga_clk *socfpga_clk;
 261        const char *clk_name = node->name;
 262        const char *parent_name[SOCFGPA_MAX_PARENTS];
 263        struct clk_init_data init;
 264        int rc;
 265        int i = 0;
 266
 267        socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
 268        if (WARN_ON(!socfpga_clk))
 269                return;
 270
 271        rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
 272        if (rc)
 273                clk_gate[0] = 0;
 274
 275        if (clk_gate[0]) {
 276                socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0];
 277                socfpga_clk->hw.bit_idx = clk_gate[1];
 278
 279                gateclk_ops.enable = clk_gate_ops.enable;
 280                gateclk_ops.disable = clk_gate_ops.disable;
 281        }
 282
 283        rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
 284        if (rc)
 285                socfpga_clk->fixed_div = 0;
 286        else
 287                socfpga_clk->fixed_div = fixed_div;
 288
 289        rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
 290        if (!rc) {
 291                socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0];
 292                socfpga_clk->shift = div_reg[1];
 293                socfpga_clk->width = div_reg[2];
 294        } else {
 295                socfpga_clk->div_reg = 0;
 296        }
 297
 298        of_property_read_string(node, "clock-output-names", &clk_name);
 299
 300        init.name = clk_name;
 301        init.ops = ops;
 302        init.flags = 0;
 303        while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] =
 304                        of_clk_get_parent_name(node, i)) != NULL)
 305                i++;
 306
 307        init.parent_names = parent_name;
 308        init.num_parents = i;
 309        socfpga_clk->hw.hw.init = &init;
 310
 311        clk = clk_register(NULL, &socfpga_clk->hw.hw);
 312        if (WARN_ON(IS_ERR(clk))) {
 313                kfree(socfpga_clk);
 314                return;
 315        }
 316        rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
 317        if (WARN_ON(rc))
 318                return;
 319}
 320
 321static void __init socfpga_pll_init(struct device_node *node)
 322{
 323        socfpga_clk_init(node, &clk_pll_ops);
 324}
 325CLK_OF_DECLARE(socfpga_pll, "altr,socfpga-pll-clock", socfpga_pll_init);
 326
 327static void __init socfpga_periph_init(struct device_node *node)
 328{
 329        socfpga_clk_init(node, &periclk_ops);
 330}
 331CLK_OF_DECLARE(socfpga_periph, "altr,socfpga-perip-clk", socfpga_periph_init);
 332
 333static void __init socfpga_gate_init(struct device_node *node)
 334{
 335        socfpga_gate_clk_init(node, &gateclk_ops);
 336}
 337CLK_OF_DECLARE(socfpga_gate, "altr,socfpga-gate-clk", socfpga_gate_init);
 338
 339void __init socfpga_init_clocks(void)
 340{
 341        struct clk *clk;
 342        int ret;
 343
 344        clk = clk_register_fixed_factor(NULL, "smp_twd", "mpuclk", 0, 1, 4);
 345        ret = clk_register_clkdev(clk, NULL, "smp_twd");
 346        if (ret)
 347                pr_err("smp_twd alias not registered\n");
 348}
 349