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_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
 179                unsigned long best_parent = rate / mult;
 180
 181                *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
 182        }
 183
 184        return *prate * mult;
 185}
 186
 187static int clk_apb_mul_set_rate(struct clk_hw *hw, unsigned long rate,
 188                                unsigned long parent_rate)
 189{
 190        /*
 191         * We must report success but we can do so unconditionally because
 192         * clk_apb_mul_round_rate returns values that ensure this call is a
 193         * nop.
 194         */
 195
 196        return 0;
 197}
 198
 199static const struct clk_ops clk_apb_mul_factor_ops = {
 200        .round_rate = clk_apb_mul_round_rate,
 201        .set_rate = clk_apb_mul_set_rate,
 202        .recalc_rate = clk_apb_mul_recalc_rate,
 203};
 204
 205static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
 206                                        const char *parent_name,
 207                                        unsigned long flags, u8 bit_idx)
 208{
 209        struct clk_apb_mul *am;
 210        struct clk_init_data init;
 211        struct clk *clk;
 212
 213        am = kzalloc(sizeof(*am), GFP_KERNEL);
 214        if (!am)
 215                return ERR_PTR(-ENOMEM);
 216
 217        am->bit_idx = bit_idx;
 218        am->hw.init = &init;
 219
 220        init.name = name;
 221        init.ops = &clk_apb_mul_factor_ops;
 222        init.flags = flags;
 223        init.parent_names = &parent_name;
 224        init.num_parents = 1;
 225
 226        clk = clk_register(dev, &am->hw);
 227
 228        if (IS_ERR(clk))
 229                kfree(am);
 230
 231        return clk;
 232}
 233
 234/*
 235 * Decode current PLL state and (statically) model the state we inherit from
 236 * the bootloader.
 237 */
 238static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
 239{
 240        unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
 241
 242        unsigned long pllm   = pllcfgr & 0x3f;
 243        unsigned long plln   = (pllcfgr >> 6) & 0x1ff;
 244        unsigned long pllp   = BIT(((pllcfgr >> 16) & 3) + 1);
 245        const char   *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
 246        unsigned long pllq   = (pllcfgr >> 24) & 0xf;
 247
 248        clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
 249        clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
 250        clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
 251}
 252
 253/*
 254 * Converts the primary and secondary indices (as they appear in DT) to an
 255 * offset into our struct clock array.
 256 */
 257static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
 258{
 259        u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
 260
 261        if (primary == 1) {
 262                if (WARN_ON(secondary > FCLK))
 263                        return -EINVAL;
 264                return secondary;
 265        }
 266
 267        memcpy(table, stm32f42xx_gate_map, sizeof(table));
 268
 269        /* only bits set in table can be used as indices */
 270        if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
 271                    0 == (table[BIT_ULL_WORD(secondary)] &
 272                          BIT_ULL_MASK(secondary))))
 273                return -EINVAL;
 274
 275        /* mask out bits above our current index */
 276        table[BIT_ULL_WORD(secondary)] &=
 277            GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
 278
 279        return FCLK + hweight64(table[0]) +
 280               (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
 281               (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
 282}
 283
 284static struct clk *
 285stm32f4_rcc_lookup_clk(struct of_phandle_args *clkspec, void *data)
 286{
 287        int i = stm32f4_rcc_lookup_clk_idx(clkspec->args[0], clkspec->args[1]);
 288
 289        if (i < 0)
 290                return ERR_PTR(-EINVAL);
 291
 292        return clks[i];
 293}
 294
 295static const char *sys_parents[] __initdata =   { "hsi", NULL, "pll" };
 296
 297static const struct clk_div_table ahb_div_table[] = {
 298        { 0x0,   1 }, { 0x1,   1 }, { 0x2,   1 }, { 0x3,   1 },
 299        { 0x4,   1 }, { 0x5,   1 }, { 0x6,   1 }, { 0x7,   1 },
 300        { 0x8,   2 }, { 0x9,   4 }, { 0xa,   8 }, { 0xb,  16 },
 301        { 0xc,  64 }, { 0xd, 128 }, { 0xe, 256 }, { 0xf, 512 },
 302        { 0 },
 303};
 304
 305static const struct clk_div_table apb_div_table[] = {
 306        { 0,  1 }, { 0,  1 }, { 0,  1 }, { 0,  1 },
 307        { 4,  2 }, { 5,  4 }, { 6,  8 }, { 7, 16 },
 308        { 0 },
 309};
 310
 311static void __init stm32f4_rcc_init(struct device_node *np)
 312{
 313        const char *hse_clk;
 314        int n;
 315
 316        base = of_iomap(np, 0);
 317        if (!base) {
 318                pr_err("%s: unable to map resource", np->name);
 319                return;
 320        }
 321
 322        hse_clk = of_clk_get_parent_name(np, 0);
 323
 324        clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
 325                        16000000, 160000);
 326        stm32f4_rcc_register_pll(hse_clk, "hsi");
 327
 328        sys_parents[1] = hse_clk;
 329        clk_register_mux_table(
 330            NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
 331            base + STM32F4_RCC_CFGR, 0, 3, 0, NULL, &stm32f4_clk_lock);
 332
 333        clk_register_divider_table(NULL, "ahb_div", "sys",
 334                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 335                                   4, 4, 0, ahb_div_table, &stm32f4_clk_lock);
 336
 337        clk_register_divider_table(NULL, "apb1_div", "ahb_div",
 338                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 339                                   10, 3, 0, apb_div_table, &stm32f4_clk_lock);
 340        clk_register_apb_mul(NULL, "apb1_mul", "apb1_div",
 341                             CLK_SET_RATE_PARENT, 12);
 342
 343        clk_register_divider_table(NULL, "apb2_div", "ahb_div",
 344                                   CLK_SET_RATE_PARENT, base + STM32F4_RCC_CFGR,
 345                                   13, 3, 0, apb_div_table, &stm32f4_clk_lock);
 346        clk_register_apb_mul(NULL, "apb2_mul", "apb2_div",
 347                             CLK_SET_RATE_PARENT, 15);
 348
 349        clks[SYSTICK] = clk_register_fixed_factor(NULL, "systick", "ahb_div",
 350                                                  0, 1, 8);
 351        clks[FCLK] = clk_register_fixed_factor(NULL, "fclk", "ahb_div",
 352                                               0, 1, 1);
 353
 354        for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
 355                const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
 356                unsigned int secondary =
 357                    8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
 358                int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
 359
 360                if (idx < 0)
 361                        goto fail;
 362
 363                clks[idx] = clk_register_gate(
 364                    NULL, gd->name, gd->parent_name, gd->flags,
 365                    base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock);
 366
 367                if (IS_ERR(clks[n])) {
 368                        pr_err("%s: Unable to register leaf clock %s\n",
 369                               np->full_name, gd->name);
 370                        goto fail;
 371                }
 372        }
 373
 374        of_clk_add_provider(np, stm32f4_rcc_lookup_clk, NULL);
 375        return;
 376fail:
 377        iounmap(base);
 378}
 379CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
 380