linux/drivers/clk/at91/clk-main.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/clkdev.h>
   8#include <linux/clk/at91_pmc.h>
   9#include <linux/delay.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/regmap.h>
  12
  13#include "pmc.h"
  14
  15#define SLOW_CLOCK_FREQ         32768
  16#define MAINF_DIV               16
  17#define MAINFRDY_TIMEOUT        (((MAINF_DIV + 1) * USEC_PER_SEC) / \
  18                                 SLOW_CLOCK_FREQ)
  19#define MAINF_LOOP_MIN_WAIT     (USEC_PER_SEC / SLOW_CLOCK_FREQ)
  20#define MAINF_LOOP_MAX_WAIT     MAINFRDY_TIMEOUT
  21
  22#define MOR_KEY_MASK            (0xff << 16)
  23
  24#define clk_main_parent_select(s)       (((s) & \
  25                                        (AT91_PMC_MOSCEN | \
  26                                        AT91_PMC_OSCBYPASS)) ? 1 : 0)
  27
  28struct clk_main_osc {
  29        struct clk_hw hw;
  30        struct regmap *regmap;
  31};
  32
  33#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
  34
  35struct clk_main_rc_osc {
  36        struct clk_hw hw;
  37        struct regmap *regmap;
  38        unsigned long frequency;
  39        unsigned long accuracy;
  40};
  41
  42#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
  43
  44struct clk_rm9200_main {
  45        struct clk_hw hw;
  46        struct regmap *regmap;
  47};
  48
  49#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
  50
  51struct clk_sam9x5_main {
  52        struct clk_hw hw;
  53        struct regmap *regmap;
  54        u8 parent;
  55};
  56
  57#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
  58
  59static inline bool clk_main_osc_ready(struct regmap *regmap)
  60{
  61        unsigned int status;
  62
  63        regmap_read(regmap, AT91_PMC_SR, &status);
  64
  65        return status & AT91_PMC_MOSCS;
  66}
  67
  68static int clk_main_osc_prepare(struct clk_hw *hw)
  69{
  70        struct clk_main_osc *osc = to_clk_main_osc(hw);
  71        struct regmap *regmap = osc->regmap;
  72        u32 tmp;
  73
  74        regmap_read(regmap, AT91_CKGR_MOR, &tmp);
  75        tmp &= ~MOR_KEY_MASK;
  76
  77        if (tmp & AT91_PMC_OSCBYPASS)
  78                return 0;
  79
  80        if (!(tmp & AT91_PMC_MOSCEN)) {
  81                tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
  82                regmap_write(regmap, AT91_CKGR_MOR, tmp);
  83        }
  84
  85        while (!clk_main_osc_ready(regmap))
  86                cpu_relax();
  87
  88        return 0;
  89}
  90
  91static void clk_main_osc_unprepare(struct clk_hw *hw)
  92{
  93        struct clk_main_osc *osc = to_clk_main_osc(hw);
  94        struct regmap *regmap = osc->regmap;
  95        u32 tmp;
  96
  97        regmap_read(regmap, AT91_CKGR_MOR, &tmp);
  98        if (tmp & AT91_PMC_OSCBYPASS)
  99                return;
 100
 101        if (!(tmp & AT91_PMC_MOSCEN))
 102                return;
 103
 104        tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
 105        regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
 106}
 107
 108static int clk_main_osc_is_prepared(struct clk_hw *hw)
 109{
 110        struct clk_main_osc *osc = to_clk_main_osc(hw);
 111        struct regmap *regmap = osc->regmap;
 112        u32 tmp, status;
 113
 114        regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 115        if (tmp & AT91_PMC_OSCBYPASS)
 116                return 1;
 117
 118        regmap_read(regmap, AT91_PMC_SR, &status);
 119
 120        return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
 121}
 122
 123static const struct clk_ops main_osc_ops = {
 124        .prepare = clk_main_osc_prepare,
 125        .unprepare = clk_main_osc_unprepare,
 126        .is_prepared = clk_main_osc_is_prepared,
 127};
 128
 129struct clk_hw * __init
 130at91_clk_register_main_osc(struct regmap *regmap,
 131                           const char *name,
 132                           const char *parent_name,
 133                           bool bypass)
 134{
 135        struct clk_main_osc *osc;
 136        struct clk_init_data init;
 137        struct clk_hw *hw;
 138        int ret;
 139
 140        if (!name || !parent_name)
 141                return ERR_PTR(-EINVAL);
 142
 143        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
 144        if (!osc)
 145                return ERR_PTR(-ENOMEM);
 146
 147        init.name = name;
 148        init.ops = &main_osc_ops;
 149        init.parent_names = &parent_name;
 150        init.num_parents = 1;
 151        init.flags = CLK_IGNORE_UNUSED;
 152
 153        osc->hw.init = &init;
 154        osc->regmap = regmap;
 155
 156        if (bypass)
 157                regmap_update_bits(regmap,
 158                                   AT91_CKGR_MOR, MOR_KEY_MASK |
 159                                   AT91_PMC_OSCBYPASS,
 160                                   AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
 161
 162        hw = &osc->hw;
 163        ret = clk_hw_register(NULL, &osc->hw);
 164        if (ret) {
 165                kfree(osc);
 166                hw = ERR_PTR(ret);
 167        }
 168
 169        return hw;
 170}
 171
 172static bool clk_main_rc_osc_ready(struct regmap *regmap)
 173{
 174        unsigned int status;
 175
 176        regmap_read(regmap, AT91_PMC_SR, &status);
 177
 178        return !!(status & AT91_PMC_MOSCRCS);
 179}
 180
 181static int clk_main_rc_osc_prepare(struct clk_hw *hw)
 182{
 183        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 184        struct regmap *regmap = osc->regmap;
 185        unsigned int mor;
 186
 187        regmap_read(regmap, AT91_CKGR_MOR, &mor);
 188
 189        if (!(mor & AT91_PMC_MOSCRCEN))
 190                regmap_update_bits(regmap, AT91_CKGR_MOR,
 191                                   MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
 192                                   AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
 193
 194        while (!clk_main_rc_osc_ready(regmap))
 195                cpu_relax();
 196
 197        return 0;
 198}
 199
 200static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
 201{
 202        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 203        struct regmap *regmap = osc->regmap;
 204        unsigned int mor;
 205
 206        regmap_read(regmap, AT91_CKGR_MOR, &mor);
 207
 208        if (!(mor & AT91_PMC_MOSCRCEN))
 209                return;
 210
 211        regmap_update_bits(regmap, AT91_CKGR_MOR,
 212                           MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
 213}
 214
 215static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
 216{
 217        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 218        struct regmap *regmap = osc->regmap;
 219        unsigned int mor, status;
 220
 221        regmap_read(regmap, AT91_CKGR_MOR, &mor);
 222        regmap_read(regmap, AT91_PMC_SR, &status);
 223
 224        return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
 225}
 226
 227static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
 228                                                 unsigned long parent_rate)
 229{
 230        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 231
 232        return osc->frequency;
 233}
 234
 235static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
 236                                                     unsigned long parent_acc)
 237{
 238        struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
 239
 240        return osc->accuracy;
 241}
 242
 243static const struct clk_ops main_rc_osc_ops = {
 244        .prepare = clk_main_rc_osc_prepare,
 245        .unprepare = clk_main_rc_osc_unprepare,
 246        .is_prepared = clk_main_rc_osc_is_prepared,
 247        .recalc_rate = clk_main_rc_osc_recalc_rate,
 248        .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
 249};
 250
 251struct clk_hw * __init
 252at91_clk_register_main_rc_osc(struct regmap *regmap,
 253                              const char *name,
 254                              u32 frequency, u32 accuracy)
 255{
 256        struct clk_main_rc_osc *osc;
 257        struct clk_init_data init;
 258        struct clk_hw *hw;
 259        int ret;
 260
 261        if (!name || !frequency)
 262                return ERR_PTR(-EINVAL);
 263
 264        osc = kzalloc(sizeof(*osc), GFP_KERNEL);
 265        if (!osc)
 266                return ERR_PTR(-ENOMEM);
 267
 268        init.name = name;
 269        init.ops = &main_rc_osc_ops;
 270        init.parent_names = NULL;
 271        init.num_parents = 0;
 272        init.flags = CLK_IGNORE_UNUSED;
 273
 274        osc->hw.init = &init;
 275        osc->regmap = regmap;
 276        osc->frequency = frequency;
 277        osc->accuracy = accuracy;
 278
 279        hw = &osc->hw;
 280        ret = clk_hw_register(NULL, hw);
 281        if (ret) {
 282                kfree(osc);
 283                hw = ERR_PTR(ret);
 284        }
 285
 286        return hw;
 287}
 288
 289static int clk_main_probe_frequency(struct regmap *regmap)
 290{
 291        unsigned long prep_time, timeout;
 292        unsigned int mcfr;
 293
 294        timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
 295        do {
 296                prep_time = jiffies;
 297                regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
 298                if (mcfr & AT91_PMC_MAINRDY)
 299                        return 0;
 300                if (system_state < SYSTEM_RUNNING)
 301                        udelay(MAINF_LOOP_MIN_WAIT);
 302                else
 303                        usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
 304        } while (time_before(prep_time, timeout));
 305
 306        return -ETIMEDOUT;
 307}
 308
 309static unsigned long clk_main_recalc_rate(struct regmap *regmap,
 310                                          unsigned long parent_rate)
 311{
 312        unsigned int mcfr;
 313
 314        if (parent_rate)
 315                return parent_rate;
 316
 317        pr_warn("Main crystal frequency not set, using approximate value\n");
 318        regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
 319        if (!(mcfr & AT91_PMC_MAINRDY))
 320                return 0;
 321
 322        return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
 323}
 324
 325static int clk_rm9200_main_prepare(struct clk_hw *hw)
 326{
 327        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 328
 329        return clk_main_probe_frequency(clkmain->regmap);
 330}
 331
 332static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
 333{
 334        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 335        unsigned int status;
 336
 337        regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
 338
 339        return !!(status & AT91_PMC_MAINRDY);
 340}
 341
 342static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
 343                                                 unsigned long parent_rate)
 344{
 345        struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
 346
 347        return clk_main_recalc_rate(clkmain->regmap, parent_rate);
 348}
 349
 350static const struct clk_ops rm9200_main_ops = {
 351        .prepare = clk_rm9200_main_prepare,
 352        .is_prepared = clk_rm9200_main_is_prepared,
 353        .recalc_rate = clk_rm9200_main_recalc_rate,
 354};
 355
 356struct clk_hw * __init
 357at91_clk_register_rm9200_main(struct regmap *regmap,
 358                              const char *name,
 359                              const char *parent_name)
 360{
 361        struct clk_rm9200_main *clkmain;
 362        struct clk_init_data init;
 363        struct clk_hw *hw;
 364        int ret;
 365
 366        if (!name)
 367                return ERR_PTR(-EINVAL);
 368
 369        if (!parent_name)
 370                return ERR_PTR(-EINVAL);
 371
 372        clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
 373        if (!clkmain)
 374                return ERR_PTR(-ENOMEM);
 375
 376        init.name = name;
 377        init.ops = &rm9200_main_ops;
 378        init.parent_names = &parent_name;
 379        init.num_parents = 1;
 380        init.flags = 0;
 381
 382        clkmain->hw.init = &init;
 383        clkmain->regmap = regmap;
 384
 385        hw = &clkmain->hw;
 386        ret = clk_hw_register(NULL, &clkmain->hw);
 387        if (ret) {
 388                kfree(clkmain);
 389                hw = ERR_PTR(ret);
 390        }
 391
 392        return hw;
 393}
 394
 395static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
 396{
 397        unsigned int status;
 398
 399        regmap_read(regmap, AT91_PMC_SR, &status);
 400
 401        return !!(status & AT91_PMC_MOSCSELS);
 402}
 403
 404static int clk_sam9x5_main_prepare(struct clk_hw *hw)
 405{
 406        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 407        struct regmap *regmap = clkmain->regmap;
 408
 409        while (!clk_sam9x5_main_ready(regmap))
 410                cpu_relax();
 411
 412        return clk_main_probe_frequency(regmap);
 413}
 414
 415static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
 416{
 417        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 418
 419        return clk_sam9x5_main_ready(clkmain->regmap);
 420}
 421
 422static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
 423                                                 unsigned long parent_rate)
 424{
 425        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 426
 427        return clk_main_recalc_rate(clkmain->regmap, parent_rate);
 428}
 429
 430static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
 431{
 432        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 433        struct regmap *regmap = clkmain->regmap;
 434        unsigned int tmp;
 435
 436        if (index > 1)
 437                return -EINVAL;
 438
 439        regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 440
 441        if (index && !(tmp & AT91_PMC_MOSCSEL))
 442                tmp = AT91_PMC_MOSCSEL;
 443        else if (!index && (tmp & AT91_PMC_MOSCSEL))
 444                tmp = 0;
 445        else
 446                return 0;
 447
 448        regmap_update_bits(regmap, AT91_CKGR_MOR,
 449                           AT91_PMC_MOSCSEL | MOR_KEY_MASK,
 450                           tmp | AT91_PMC_KEY);
 451
 452        while (!clk_sam9x5_main_ready(regmap))
 453                cpu_relax();
 454
 455        return 0;
 456}
 457
 458static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
 459{
 460        struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
 461        unsigned int status;
 462
 463        regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
 464
 465        return clk_main_parent_select(status);
 466}
 467
 468static const struct clk_ops sam9x5_main_ops = {
 469        .prepare = clk_sam9x5_main_prepare,
 470        .is_prepared = clk_sam9x5_main_is_prepared,
 471        .recalc_rate = clk_sam9x5_main_recalc_rate,
 472        .set_parent = clk_sam9x5_main_set_parent,
 473        .get_parent = clk_sam9x5_main_get_parent,
 474};
 475
 476struct clk_hw * __init
 477at91_clk_register_sam9x5_main(struct regmap *regmap,
 478                              const char *name,
 479                              const char **parent_names,
 480                              int num_parents)
 481{
 482        struct clk_sam9x5_main *clkmain;
 483        struct clk_init_data init;
 484        unsigned int status;
 485        struct clk_hw *hw;
 486        int ret;
 487
 488        if (!name)
 489                return ERR_PTR(-EINVAL);
 490
 491        if (!parent_names || !num_parents)
 492                return ERR_PTR(-EINVAL);
 493
 494        clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
 495        if (!clkmain)
 496                return ERR_PTR(-ENOMEM);
 497
 498        init.name = name;
 499        init.ops = &sam9x5_main_ops;
 500        init.parent_names = parent_names;
 501        init.num_parents = num_parents;
 502        init.flags = CLK_SET_PARENT_GATE;
 503
 504        clkmain->hw.init = &init;
 505        clkmain->regmap = regmap;
 506        regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
 507        clkmain->parent = clk_main_parent_select(status);
 508
 509        hw = &clkmain->hw;
 510        ret = clk_hw_register(NULL, &clkmain->hw);
 511        if (ret) {
 512                kfree(clkmain);
 513                hw = ERR_PTR(ret);
 514        }
 515
 516        return hw;
 517}
 518