linux/drivers/clk/clk-stm32f4.c
<<
>>
Prefs
   1/*
   2 * Author: Daniel Thompson <daniel.thompson@linaro.org>
   3 *
   4 * Inspired by clk-asm9260.c .
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 *
  15 * You should have received a copy of the GNU General Public License along with
  16 * this program.  If not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#include <linux/clk-provider.h>
  20#include <linux/err.h>
  21#include <linux/io.h>
  22#include <linux/slab.h>
  23#include <linux/spinlock.h>
  24#include <linux/of.h>
  25#include <linux/of_address.h>
  26
  27#define STM32F4_RCC_PLLCFGR             0x04
  28#define STM32F4_RCC_CFGR                0x08
  29#define STM32F4_RCC_AHB1ENR             0x30
  30#define STM32F4_RCC_AHB2ENR             0x34
  31#define STM32F4_RCC_AHB3ENR             0x38
  32#define STM32F4_RCC_APB1ENR             0x40
  33#define STM32F4_RCC_APB2ENR             0x44
  34
  35struct stm32f4_gate_data {
  36        u8      offset;
  37        u8      bit_idx;
  38        const char *name;
  39        const char *parent_name;
  40        unsigned long flags;
  41};
  42
  43static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
  44        { STM32F4_RCC_AHB1ENR,  0,      "gpioa",        "ahb_div" },
  45        { STM32F4_RCC_AHB1ENR,  1,      "gpiob",        "ahb_div" },
  46        { STM32F4_RCC_AHB1ENR,  2,      "gpioc",        "ahb_div" },
  47        { STM32F4_RCC_AHB1ENR,  3,      "gpiod",        "ahb_div" },
  48        { STM32F4_RCC_AHB1ENR,  4,      "gpioe",        "ahb_div" },
  49        { STM32F4_RCC_AHB1ENR,  5,      "gpiof",        "ahb_div" },
  50        { STM32F4_RCC_AHB1ENR,  6,      "gpiog",        "ahb_div" },
  51        { STM32F4_RCC_AHB1ENR,  7,      "gpioh",        "ahb_div" },
  52        { STM32F4_RCC_AHB1ENR,  8,      "gpioi",        "ahb_div" },
  53        { STM32F4_RCC_AHB1ENR,  9,      "gpioj",        "ahb_div" },
  54        { STM32F4_RCC_AHB1ENR, 10,      "gpiok",        "ahb_div" },
  55        { STM32F4_RCC_AHB1ENR, 12,      "crc",          "ahb_div" },
  56        { STM32F4_RCC_AHB1ENR, 18,      "bkpsra",       "ahb_div" },
  57        { STM32F4_RCC_AHB1ENR, 20,      "ccmdatam",     "ahb_div" },
  58        { STM32F4_RCC_AHB1ENR, 21,      "dma1",         "ahb_div" },
  59        { STM32F4_RCC_AHB1ENR, 22,      "dma2",         "ahb_div" },
  60        { STM32F4_RCC_AHB1ENR, 23,      "dma2d",        "ahb_div" },
  61        { STM32F4_RCC_AHB1ENR, 25,      "ethmac",       "ahb_div" },
  62        { STM32F4_RCC_AHB1ENR, 26,      "ethmactx",     "ahb_div" },
  63        { STM32F4_RCC_AHB1ENR, 27,      "ethmacrx",     "ahb_div" },
  64        { STM32F4_RCC_AHB1ENR, 28,      "ethmacptp",    "ahb_div" },
  65        { STM32F4_RCC_AHB1ENR, 29,      "otghs",        "ahb_div" },
  66        { STM32F4_RCC_AHB1ENR, 30,      "otghsulpi",    "ahb_div" },
  67
  68        { STM32F4_RCC_AHB2ENR,  0,      "dcmi",         "ahb_div" },
  69        { STM32F4_RCC_AHB2ENR,  4,      "cryp",         "ahb_div" },
  70        { STM32F4_RCC_AHB2ENR,  5,      "hash",         "ahb_div" },
  71        { STM32F4_RCC_AHB2ENR,  6,      "rng",          "pll48" },
  72        { STM32F4_RCC_AHB2ENR,  7,      "otgfs",        "pll48" },
  73
  74        { STM32F4_RCC_AHB3ENR,  0,      "fmc",          "ahb_div",
  75                CLK_IGNORE_UNUSED },
  76
  77        { STM32F4_RCC_APB1ENR,  0,      "tim2",         "apb1_mul" },
  78        { STM32F4_RCC_APB1ENR,  1,      "tim3",         "apb1_mul" },
  79        { STM32F4_RCC_APB1ENR,  2,      "tim4",         "apb1_mul" },
  80        { STM32F4_RCC_APB1ENR,  3,      "tim5",         "apb1_mul" },
  81        { STM32F4_RCC_APB1ENR,  4,      "tim6",         "apb1_mul" },
  82        { STM32F4_RCC_APB1ENR,  5,      "tim7",         "apb1_mul" },
  83        { STM32F4_RCC_APB1ENR,  6,      "tim12",        "apb1_mul" },
  84        { STM32F4_RCC_APB1ENR,  7,      "tim13",        "apb1_mul" },
  85        { STM32F4_RCC_APB1ENR,  8,      "tim14",        "apb1_mul" },
  86        { STM32F4_RCC_APB1ENR, 11,      "wwdg",         "apb1_div" },
  87        { STM32F4_RCC_APB1ENR, 14,      "spi2",         "apb1_div" },
  88        { STM32F4_RCC_APB1ENR, 15,      "spi3",         "apb1_div" },
  89        { STM32F4_RCC_APB1ENR, 17,      "uart2",        "apb1_div" },
  90        { STM32F4_RCC_APB1ENR, 18,      "uart3",        "apb1_div" },
  91        { STM32F4_RCC_APB1ENR, 19,      "uart4",        "apb1_div" },
  92        { STM32F4_RCC_APB1ENR, 20,      "uart5",        "apb1_div" },
  93        { STM32F4_RCC_APB1ENR, 21,      "i2c1",         "apb1_div" },
  94        { STM32F4_RCC_APB1ENR, 22,      "i2c2",         "apb1_div" },
  95        { STM32F4_RCC_APB1ENR, 23,      "i2c3",         "apb1_div" },
  96        { STM32F4_RCC_APB1ENR, 25,      "can1",         "apb1_div" },
  97        { STM32F4_RCC_APB1ENR, 26,      "can2",         "apb1_div" },
  98        { STM32F4_RCC_APB1ENR, 28,      "pwr",          "apb1_div" },
  99        { STM32F4_RCC_APB1ENR, 29,      "dac",          "apb1_div" },
 100        { STM32F4_RCC_APB1ENR, 30,      "uart7",        "apb1_div" },
 101        { STM32F4_RCC_APB1ENR, 31,      "uart8",        "apb1_div" },
 102
 103        { STM32F4_RCC_APB2ENR,  0,      "tim1",         "apb2_mul" },
 104        { STM32F4_RCC_APB2ENR,  1,      "tim8",         "apb2_mul" },
 105        { STM32F4_RCC_APB2ENR,  4,      "usart1",       "apb2_div" },
 106        { STM32F4_RCC_APB2ENR,  5,      "usart6",       "apb2_div" },
 107        { STM32F4_RCC_APB2ENR,  8,      "adc1",         "apb2_div" },
 108        { STM32F4_RCC_APB2ENR,  9,      "adc2",         "apb2_div" },
 109        { STM32F4_RCC_APB2ENR, 10,      "adc3",         "apb2_div" },
 110        { STM32F4_RCC_APB2ENR, 11,      "sdio",         "pll48" },
 111        { STM32F4_RCC_APB2ENR, 12,      "spi1",         "apb2_div" },
 112        { STM32F4_RCC_APB2ENR, 13,      "spi4",         "apb2_div" },
 113        { STM32F4_RCC_APB2ENR, 14,      "syscfg",       "apb2_div" },
 114        { STM32F4_RCC_APB2ENR, 16,      "tim9",         "apb2_mul" },
 115        { STM32F4_RCC_APB2ENR, 17,      "tim10",        "apb2_mul" },
 116        { STM32F4_RCC_APB2ENR, 18,      "tim11",        "apb2_mul" },
 117        { STM32F4_RCC_APB2ENR, 20,      "spi5",         "apb2_div" },
 118        { STM32F4_RCC_APB2ENR, 21,      "spi6",         "apb2_div" },
 119        { STM32F4_RCC_APB2ENR, 22,      "sai1",         "apb2_div" },
 120        { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
 121};
 122
 123/*
 124 * MAX_CLKS is the maximum value in the enumeration below plus the combined
 125 * hweight of stm32f42xx_gate_map (plus one).
 126 */
 127#define MAX_CLKS 74
 128
 129enum { SYSTICK, FCLK };
 130
 131/*
 132 * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
 133 * have gate bits associated with them. Its combined hweight is 71.
 134 */
 135static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
 136                                           0x0000000000000001ull,
 137                                           0x04777f33f6fec9ffull };
 138
 139static struct clk *clks[MAX_CLKS];
 140static DEFINE_SPINLOCK(stm32f4_clk_lock);
 141static void __iomem *base;
 142
 143/*
 144 * "Multiplier" device for APBx clocks.
 145 *
 146 * The APBx dividers are power-of-two dividers and, if *not* running in 1:1
 147 * mode, they also tap out the one of the low order state bits to run the
 148 * timers. ST datasheets represent this feature as a (conditional) clock
 149 * multiplier.
 150 */
 151struct clk_apb_mul {
 152        struct clk_hw hw;
 153        u8 bit_idx;
 154};
 155
 156#define to_clk_apb_mul(_hw) container_of(_hw, struct clk_apb_mul, hw)
 157
 158static unsigned long clk_apb_mul_recalc_rate(struct clk_hw *hw,
 159                                             unsigned long parent_rate)
 160{
 161        struct clk_apb_mul *am = to_clk_apb_mul(hw);
 162
 163        if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
 164                return parent_rate * 2;
 165
 166        return parent_rate;
 167}
 168
 169static long clk_apb_mul_round_rate(struct clk_hw *hw, unsigned long rate,
 170                                   unsigned long *prate)
 171{
 172        struct clk_apb_mul *am = to_clk_apb_mul(hw);
 173        unsigned long mult = 1;
 174
 175        if (readl(base + STM32F4_RCC_CFGR) & BIT(am->bit_idx))
 176                mult = 2;
 177
 178        if (__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT) {
 179                unsigned long best_parent = rate / mult;
 180
 181                *prate =
 182                    __clk_round_rate(__clk_get_parent(hw->clk), best_parent);
 183        }
 184
 185        return *prate * mult;
 186}
 187
 188static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
 189                                unsigned long parent_rate)
 190{
 191        /*
 192         * We must report success but we can do so unconditionally because
 193         * clk_apb_mul_round_rate returns values that ensure this call is a
 194         * nop.
 195         */
 196
 197        return 0;
 198}
 199
 200static const struct clk_ops clk_apb_mul_factor_ops = {
 201        .round_rate = clk_apb_mul_round_rate,
 202        .set_rate = clk_apb_mul_set_rate,
 203        .recalc_rate = clk_apb_mul_recalc_rate,
 204};
 205
 206static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
 207                                        const char *parent_name,
 208                                        unsigned long flags, u8 bit_idx)
 209{
 210        struct clk_apb_mul *am;
 211        struct clk_init_data init;
 212        struct clk *clk;
 213
 214        am = kzalloc(sizeof(*am), GFP_KERNEL);
 215        if (!am)
 216                return ERR_PTR(-ENOMEM);
 217
 218        am->bit_idx = bit_idx;
 219        am->hw.init = &init;
 220
 221        init.name = name;
 222        init.ops = &clk_apb_mul_factor_ops;
 223        init.flags = flags;
 224        init.parent_names = &parent_name;
 225        init.num_parents = 1;
 226
 227        clk = clk_register(dev, &am->hw);
 228
 229        if (IS_ERR(clk))
 230                kfree(am);
 231
 232        return clk;
 233}
 234
 235/*
 236 * Decode current PLL state and (statically) model the state we inherit from
 237 * the bootloader.
 238 */
 239static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
 240{
 241        unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
 242
 243        unsigned long pllm   = pllcfgr & 0x3f;
 244        unsigned long plln   = (pllcfgr >> 6) & 0x1ff;
 245        unsigned long pllp   = BIT(((pllcfgr >> 16) & 3) + 1);
 246        const char   *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
 247        unsigned long pllq   = (pllcfgr >> 24) & 0xf;
 248
 249        clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
 250        clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
 251        clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
 252}
 253
 254/*
 255 * Converts the primary and secondary indices (as they appear in DT) to an
 256 * offset into our struct clock array.
 257 */
 258static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
 259{
 260        u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
 261
 262        if (primary == 1) {
 263                if (WARN_ON(secondary > FCLK))
 264                        return -EINVAL;
 265                return secondary;
 266        }
 267
 268        memcpy(table, stm32f42xx_gate_map, sizeof(table));
 269
 270        /* only bits set in table can be used as indices */
 271        if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
 272                    0 == (table[BIT_ULL_WORD(secondary)] &
 273                          BIT_ULL_MASK(secondary))))
 274                return -EINVAL;
 275
 276        /* mask out bits above our current index */
 277        table[BIT_ULL_WORD(secondary)] &=
 278            GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
 279
 280        return FCLK + hweight64(table[0]) +
 281               (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
 282               (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
 283}
 284
 285static struct clk *
 286stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
 287{
 288        int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
 289
 290        if (i < 0)
 291                return ERR_PTR(-EINVAL);
 292
 293        return clks[i];
 294}
 295
 296static const char *sys_parents[] __initdata =   { "hsi", NULL, "pll" };
 297
 298static const struct clk_div_table ahb_div_table[] = {
 299        { 0x0,   1 }, { 0x1,   1 }, { 0x2,   1 }, { 0x3,   1 },
 300        { 0x4,   1 }, { 0x5,   1 }, { 0x6,   1 }, { 0x7,   1 },
 301        { 0x8,   2 }, { 0x9,   4 }, { 0xa,   8 }, { 0xb,  16 },
 302        { 0xc,  64 }, { 0xd, 128 }, { 0xe, 256 }, { 0xf, 512 },
 303        { 0 },
 304};
 305
 306static const struct clk_div_table apb_div_table[] = {
 307        { 0,  1 }, { 0,  1 }, { 0,  1 }, { 0,  1 },
 308        { 4,  2 }, { 5,  4 }, { 6,  8 }, { 7, 16 },
 309        { 0 },
 310};
 311
 312static void __init stm32f4_rcc_init(struct device_node *np)
 313{
 314        const char *hse_clk;
 315        int n;
 316
 317        base = of_iomap(np, 0);
 318        if (!base) {
 319                pr_err("%s: unable to map resource", np->name);
 320                return;
 321        }
 322
 323        hse_clk = of_clk_get_parent_name(np, 0);
 324
 325        clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
 326                        16000000, 160000);
 327        stm32f4_rcc_register_pll(hse_clk, "hsi");
 328
 329        sys_parents[1] = hse_clk;
 330        clk_register_mux_table(
 331            NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
 332            base + STM32F4_RCC_CFGR, 0, 3, 0, NULL, &stm32f4_clk_lock);
 333
 334        clk_register_divider_table(NULL, "ahb_div", "sys",
 335                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 336                                   4, 4, 0, ahb_div_table, &stm32f4_clk_lock);
 337
 338        clk_register_divider_table(NULL, "apb1_div", "ahb_div",
 339                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 340                                   10, 3, 0, apb_div_table, &stm32f4_clk_lock);
 341        clk_register_apb_mul(NULL, "apb1_mul", "apb1_div",
 342                             CLK_SET_RATE_PARENT, 12);
 343
 344        clk_register_divider_table(NULL, "apb2_div", "ahb_div",
 345                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 346                                   13, 3, 0, apb_div_table, &stm32f4_clk_lock);
 347        clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
 348                             CLK_SET_RATE_PARENT, 15);
 349
 350        clks[SYSTICK] = clk_register_fixed_factor(NULL, "systick", "ahb_div",
 351                                                  0, 1, 8);
 352        clks[FCLK] = clk_register_fixed_factor(NULL, "fclk", "ahb_div",
 353                                               0, 1, 1);
 354
 355        for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
 356                const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
 357                unsigned int secondary =
 358                    8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
 359                int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
 360
 361                if (idx < 0)
 362                        goto fail;
 363
 364                clks[idx] = clk_register_gate(
 365                    NULL, gd->name, gd->parent_name, gd->flags,
 366                    base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
 367
 368                if (IS_ERR(clks[n])) {
 369                        pr_err("%s: Unable to register leaf clock %s\n",
 370                               np->full_name, gd->name);
 371                        goto fail;
 372                }
 373        }
 374
 375        of_clk_add_provider(np, stm32f4_rcc_lookup_clk, NULL);
 376        return;
 377fail:
 378        iounmap(base);
 379}
 380CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
 381