linux/drivers/clk/at91/clk-master.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/of.h>
  10#include <linux/mfd/syscon.h>
  11#include <linux/regmap.h>
  12
  13#include "pmc.h"
  14
  15#define MASTER_PRES_MASK        0x7
  16#define MASTER_PRES_MAX         MASTER_PRES_MASK
  17#define MASTER_DIV_SHIFT        8
  18#define MASTER_DIV_MASK         0x7
  19
  20#define PMC_MCR                 0x30
  21#define PMC_MCR_ID_MSK          GENMASK(3, 0)
  22#define PMC_MCR_CMD             BIT(7)
  23#define PMC_MCR_DIV             GENMASK(10, 8)
  24#define PMC_MCR_CSS             GENMASK(20, 16)
  25#define PMC_MCR_CSS_SHIFT       (16)
  26#define PMC_MCR_EN              BIT(28)
  27
  28#define PMC_MCR_ID(x)           ((x) & PMC_MCR_ID_MSK)
  29
  30#define MASTER_MAX_ID           4
  31
  32#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
  33
  34struct clk_master {
  35        struct clk_hw hw;
  36        struct regmap *regmap;
  37        spinlock_t *lock;
  38        const struct clk_master_layout *layout;
  39        const struct clk_master_characteristics *characteristics;
  40        u32 *mux_table;
  41        u32 mckr;
  42        int chg_pid;
  43        u8 id;
  44        u8 parent;
  45        u8 div;
  46};
  47
  48static inline bool clk_master_ready(struct clk_master *master)
  49{
  50        unsigned int bit = master->id ? AT91_PMC_MCKXRDY : AT91_PMC_MCKRDY;
  51        unsigned int status;
  52
  53        regmap_read(master->regmap, AT91_PMC_SR, &status);
  54
  55        return !!(status & bit);
  56}
  57
  58static int clk_master_prepare(struct clk_hw *hw)
  59{
  60        struct clk_master *master = to_clk_master(hw);
  61        unsigned long flags;
  62
  63        spin_lock_irqsave(master->lock, flags);
  64
  65        while (!clk_master_ready(master))
  66                cpu_relax();
  67
  68        spin_unlock_irqrestore(master->lock, flags);
  69
  70        return 0;
  71}
  72
  73static int clk_master_is_prepared(struct clk_hw *hw)
  74{
  75        struct clk_master *master = to_clk_master(hw);
  76        unsigned long flags;
  77        bool status;
  78
  79        spin_lock_irqsave(master->lock, flags);
  80        status = clk_master_ready(master);
  81        spin_unlock_irqrestore(master->lock, flags);
  82
  83        return status;
  84}
  85
  86static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
  87                                                unsigned long parent_rate)
  88{
  89        u8 div;
  90        unsigned long flags, rate = parent_rate;
  91        struct clk_master *master = to_clk_master(hw);
  92        const struct clk_master_layout *layout = master->layout;
  93        const struct clk_master_characteristics *characteristics =
  94                                                master->characteristics;
  95        unsigned int mckr;
  96
  97        spin_lock_irqsave(master->lock, flags);
  98        regmap_read(master->regmap, master->layout->offset, &mckr);
  99        spin_unlock_irqrestore(master->lock, flags);
 100
 101        mckr &= layout->mask;
 102
 103        div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
 104
 105        rate /= characteristics->divisors[div];
 106
 107        if (rate < characteristics->output.min)
 108                pr_warn("master clk div is underclocked");
 109        else if (rate > characteristics->output.max)
 110                pr_warn("master clk div is overclocked");
 111
 112        return rate;
 113}
 114
 115static const struct clk_ops master_div_ops = {
 116        .prepare = clk_master_prepare,
 117        .is_prepared = clk_master_is_prepared,
 118        .recalc_rate = clk_master_div_recalc_rate,
 119};
 120
 121static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
 122                                   unsigned long parent_rate)
 123{
 124        struct clk_master *master = to_clk_master(hw);
 125        const struct clk_master_characteristics *characteristics =
 126                                                master->characteristics;
 127        unsigned long flags;
 128        int div, i;
 129
 130        div = DIV_ROUND_CLOSEST(parent_rate, rate);
 131        if (div > ARRAY_SIZE(characteristics->divisors))
 132                return -EINVAL;
 133
 134        for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
 135                if (!characteristics->divisors[i])
 136                        break;
 137
 138                if (div == characteristics->divisors[i]) {
 139                        div = i;
 140                        break;
 141                }
 142        }
 143
 144        if (i == ARRAY_SIZE(characteristics->divisors))
 145                return -EINVAL;
 146
 147        spin_lock_irqsave(master->lock, flags);
 148        regmap_update_bits(master->regmap, master->layout->offset,
 149                           (MASTER_DIV_MASK << MASTER_DIV_SHIFT),
 150                           (div << MASTER_DIV_SHIFT));
 151        while (!clk_master_ready(master))
 152                cpu_relax();
 153        spin_unlock_irqrestore(master->lock, flags);
 154
 155        return 0;
 156}
 157
 158static int clk_master_div_determine_rate(struct clk_hw *hw,
 159                                         struct clk_rate_request *req)
 160{
 161        struct clk_master *master = to_clk_master(hw);
 162        const struct clk_master_characteristics *characteristics =
 163                                                master->characteristics;
 164        struct clk_hw *parent;
 165        unsigned long parent_rate, tmp_rate, best_rate = 0;
 166        int i, best_diff = INT_MIN, tmp_diff;
 167
 168        parent = clk_hw_get_parent(hw);
 169        if (!parent)
 170                return -EINVAL;
 171
 172        parent_rate = clk_hw_get_rate(parent);
 173        if (!parent_rate)
 174                return -EINVAL;
 175
 176        for (i = 0; i < ARRAY_SIZE(characteristics->divisors); i++) {
 177                if (!characteristics->divisors[i])
 178                        break;
 179
 180                tmp_rate = DIV_ROUND_CLOSEST_ULL(parent_rate,
 181                                                 characteristics->divisors[i]);
 182                tmp_diff = abs(tmp_rate - req->rate);
 183
 184                if (!best_rate || best_diff > tmp_diff) {
 185                        best_diff = tmp_diff;
 186                        best_rate = tmp_rate;
 187                }
 188
 189                if (!best_diff)
 190                        break;
 191        }
 192
 193        req->best_parent_rate = best_rate;
 194        req->best_parent_hw = parent;
 195        req->rate = best_rate;
 196
 197        return 0;
 198}
 199
 200static const struct clk_ops master_div_ops_chg = {
 201        .prepare = clk_master_prepare,
 202        .is_prepared = clk_master_is_prepared,
 203        .recalc_rate = clk_master_div_recalc_rate,
 204        .determine_rate = clk_master_div_determine_rate,
 205        .set_rate = clk_master_div_set_rate,
 206};
 207
 208static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
 209                                         struct clk_hw *parent,
 210                                         unsigned long parent_rate,
 211                                         long *best_rate,
 212                                         long *best_diff,
 213                                         u32 div)
 214{
 215        unsigned long tmp_rate, tmp_diff;
 216
 217        if (div == MASTER_PRES_MAX)
 218                tmp_rate = parent_rate / 3;
 219        else
 220                tmp_rate = parent_rate >> div;
 221
 222        tmp_diff = abs(req->rate - tmp_rate);
 223
 224        if (*best_diff < 0 || *best_diff >= tmp_diff) {
 225                *best_rate = tmp_rate;
 226                *best_diff = tmp_diff;
 227                req->best_parent_rate = parent_rate;
 228                req->best_parent_hw = parent;
 229        }
 230}
 231
 232static int clk_master_pres_determine_rate(struct clk_hw *hw,
 233                                          struct clk_rate_request *req)
 234{
 235        struct clk_master *master = to_clk_master(hw);
 236        struct clk_rate_request req_parent = *req;
 237        const struct clk_master_characteristics *characteristics =
 238                                                        master->characteristics;
 239        struct clk_hw *parent;
 240        long best_rate = LONG_MIN, best_diff = LONG_MIN;
 241        u32 pres;
 242        int i;
 243
 244        if (master->chg_pid < 0)
 245                return -EOPNOTSUPP;
 246
 247        parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
 248        if (!parent)
 249                return -EOPNOTSUPP;
 250
 251        for (i = 0; i <= MASTER_PRES_MAX; i++) {
 252                if (characteristics->have_div3_pres && i == MASTER_PRES_MAX)
 253                        pres = 3;
 254                else
 255                        pres = 1 << i;
 256
 257                req_parent.rate = req->rate * pres;
 258                if (__clk_determine_rate(parent, &req_parent))
 259                        continue;
 260
 261                clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
 262                                             &best_diff, &best_rate, pres);
 263                if (!best_diff)
 264                        break;
 265        }
 266
 267        return 0;
 268}
 269
 270static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate,
 271                                    unsigned long parent_rate)
 272{
 273        struct clk_master *master = to_clk_master(hw);
 274        unsigned long flags;
 275        unsigned int pres;
 276
 277        pres = DIV_ROUND_CLOSEST(parent_rate, rate);
 278        if (pres > MASTER_PRES_MAX)
 279                return -EINVAL;
 280
 281        else if (pres == 3)
 282                pres = MASTER_PRES_MAX;
 283        else
 284                pres = ffs(pres) - 1;
 285
 286        spin_lock_irqsave(master->lock, flags);
 287        regmap_update_bits(master->regmap, master->layout->offset,
 288                           (MASTER_PRES_MASK << master->layout->pres_shift),
 289                           (pres << master->layout->pres_shift));
 290
 291        while (!clk_master_ready(master))
 292                cpu_relax();
 293        spin_unlock_irqrestore(master->lock, flags);
 294
 295        return 0;
 296}
 297
 298static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
 299                                                 unsigned long parent_rate)
 300{
 301        struct clk_master *master = to_clk_master(hw);
 302        const struct clk_master_characteristics *characteristics =
 303                                                master->characteristics;
 304        unsigned long flags;
 305        unsigned int val, pres;
 306
 307        spin_lock_irqsave(master->lock, flags);
 308        regmap_read(master->regmap, master->layout->offset, &val);
 309        spin_unlock_irqrestore(master->lock, flags);
 310
 311        pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
 312        if (pres == 3 && characteristics->have_div3_pres)
 313                pres = 3;
 314        else
 315                pres = (1 << pres);
 316
 317        return DIV_ROUND_CLOSEST_ULL(parent_rate, pres);
 318}
 319
 320static u8 clk_master_pres_get_parent(struct clk_hw *hw)
 321{
 322        struct clk_master *master = to_clk_master(hw);
 323        unsigned long flags;
 324        unsigned int mckr;
 325
 326        spin_lock_irqsave(master->lock, flags);
 327        regmap_read(master->regmap, master->layout->offset, &mckr);
 328        spin_unlock_irqrestore(master->lock, flags);
 329
 330        return mckr & AT91_PMC_CSS;
 331}
 332
 333static const struct clk_ops master_pres_ops = {
 334        .prepare = clk_master_prepare,
 335        .is_prepared = clk_master_is_prepared,
 336        .recalc_rate = clk_master_pres_recalc_rate,
 337        .get_parent = clk_master_pres_get_parent,
 338};
 339
 340static const struct clk_ops master_pres_ops_chg = {
 341        .prepare = clk_master_prepare,
 342        .is_prepared = clk_master_is_prepared,
 343        .determine_rate = clk_master_pres_determine_rate,
 344        .recalc_rate = clk_master_pres_recalc_rate,
 345        .get_parent = clk_master_pres_get_parent,
 346        .set_rate = clk_master_pres_set_rate,
 347};
 348
 349static struct clk_hw * __init
 350at91_clk_register_master_internal(struct regmap *regmap,
 351                const char *name, int num_parents,
 352                const char **parent_names,
 353                const struct clk_master_layout *layout,
 354                const struct clk_master_characteristics *characteristics,
 355                const struct clk_ops *ops, spinlock_t *lock, u32 flags,
 356                int chg_pid)
 357{
 358        struct clk_master *master;
 359        struct clk_init_data init;
 360        struct clk_hw *hw;
 361        int ret;
 362
 363        if (!name || !num_parents || !parent_names || !lock)
 364                return ERR_PTR(-EINVAL);
 365
 366        master = kzalloc(sizeof(*master), GFP_KERNEL);
 367        if (!master)
 368                return ERR_PTR(-ENOMEM);
 369
 370        init.name = name;
 371        init.ops = ops;
 372        init.parent_names = parent_names;
 373        init.num_parents = num_parents;
 374        init.flags = flags;
 375
 376        master->hw.init = &init;
 377        master->layout = layout;
 378        master->characteristics = characteristics;
 379        master->regmap = regmap;
 380        master->chg_pid = chg_pid;
 381        master->lock = lock;
 382
 383        hw = &master->hw;
 384        ret = clk_hw_register(NULL, &master->hw);
 385        if (ret) {
 386                kfree(master);
 387                hw = ERR_PTR(ret);
 388        }
 389
 390        return hw;
 391}
 392
 393struct clk_hw * __init
 394at91_clk_register_master_pres(struct regmap *regmap,
 395                const char *name, int num_parents,
 396                const char **parent_names,
 397                const struct clk_master_layout *layout,
 398                const struct clk_master_characteristics *characteristics,
 399                spinlock_t *lock, u32 flags, int chg_pid)
 400{
 401        const struct clk_ops *ops;
 402
 403        if (flags & CLK_SET_RATE_GATE)
 404                ops = &master_pres_ops;
 405        else
 406                ops = &master_pres_ops_chg;
 407
 408        return at91_clk_register_master_internal(regmap, name, num_parents,
 409                                                 parent_names, layout,
 410                                                 characteristics, ops,
 411                                                 lock, flags, chg_pid);
 412}
 413
 414struct clk_hw * __init
 415at91_clk_register_master_div(struct regmap *regmap,
 416                const char *name, const char *parent_name,
 417                const struct clk_master_layout *layout,
 418                const struct clk_master_characteristics *characteristics,
 419                spinlock_t *lock, u32 flags)
 420{
 421        const struct clk_ops *ops;
 422
 423        if (flags & CLK_SET_RATE_GATE)
 424                ops = &master_div_ops;
 425        else
 426                ops = &master_div_ops_chg;
 427
 428        return at91_clk_register_master_internal(regmap, name, 1,
 429                                                 &parent_name, layout,
 430                                                 characteristics, ops,
 431                                                 lock, flags, -EINVAL);
 432}
 433
 434static unsigned long
 435clk_sama7g5_master_recalc_rate(struct clk_hw *hw,
 436                               unsigned long parent_rate)
 437{
 438        struct clk_master *master = to_clk_master(hw);
 439
 440        return DIV_ROUND_CLOSEST_ULL(parent_rate, (1 << master->div));
 441}
 442
 443static int clk_sama7g5_master_determine_rate(struct clk_hw *hw,
 444                                             struct clk_rate_request *req)
 445{
 446        struct clk_master *master = to_clk_master(hw);
 447        struct clk_rate_request req_parent = *req;
 448        struct clk_hw *parent;
 449        long best_rate = LONG_MIN, best_diff = LONG_MIN;
 450        unsigned long parent_rate;
 451        unsigned int div, i;
 452
 453        /* First: check the dividers of MCR. */
 454        for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
 455                parent = clk_hw_get_parent_by_index(hw, i);
 456                if (!parent)
 457                        continue;
 458
 459                parent_rate = clk_hw_get_rate(parent);
 460                if (!parent_rate)
 461                        continue;
 462
 463                for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
 464                        clk_sama7g5_master_best_diff(req, parent, parent_rate,
 465                                                     &best_rate, &best_diff,
 466                                                     div);
 467                        if (!best_diff)
 468                                break;
 469                }
 470
 471                if (!best_diff)
 472                        break;
 473        }
 474
 475        /* Second: try to request rate form changeable parent. */
 476        if (master->chg_pid < 0)
 477                goto end;
 478
 479        parent = clk_hw_get_parent_by_index(hw, master->chg_pid);
 480        if (!parent)
 481                goto end;
 482
 483        for (div = 0; div < MASTER_PRES_MAX + 1; div++) {
 484                if (div == MASTER_PRES_MAX)
 485                        req_parent.rate = req->rate * 3;
 486                else
 487                        req_parent.rate = req->rate << div;
 488
 489                if (__clk_determine_rate(parent, &req_parent))
 490                        continue;
 491
 492                clk_sama7g5_master_best_diff(req, parent, req_parent.rate,
 493                                             &best_rate, &best_diff, div);
 494
 495                if (!best_diff)
 496                        break;
 497        }
 498
 499end:
 500        pr_debug("MCK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
 501                 __func__, best_rate,
 502                 __clk_get_name((req->best_parent_hw)->clk),
 503                req->best_parent_rate);
 504
 505        if (best_rate < 0)
 506                return -EINVAL;
 507
 508        req->rate = best_rate;
 509
 510        return 0;
 511}
 512
 513static u8 clk_sama7g5_master_get_parent(struct clk_hw *hw)
 514{
 515        struct clk_master *master = to_clk_master(hw);
 516        unsigned long flags;
 517        u8 index;
 518
 519        spin_lock_irqsave(master->lock, flags);
 520        index = clk_mux_val_to_index(&master->hw, master->mux_table, 0,
 521                                     master->parent);
 522        spin_unlock_irqrestore(master->lock, flags);
 523
 524        return index;
 525}
 526
 527static int clk_sama7g5_master_set_parent(struct clk_hw *hw, u8 index)
 528{
 529        struct clk_master *master = to_clk_master(hw);
 530        unsigned long flags;
 531
 532        if (index >= clk_hw_get_num_parents(hw))
 533                return -EINVAL;
 534
 535        spin_lock_irqsave(master->lock, flags);
 536        master->parent = clk_mux_index_to_val(master->mux_table, 0, index);
 537        spin_unlock_irqrestore(master->lock, flags);
 538
 539        return 0;
 540}
 541
 542static int clk_sama7g5_master_enable(struct clk_hw *hw)
 543{
 544        struct clk_master *master = to_clk_master(hw);
 545        unsigned long flags;
 546        unsigned int val, cparent;
 547
 548        spin_lock_irqsave(master->lock, flags);
 549
 550        regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
 551        regmap_read(master->regmap, PMC_MCR, &val);
 552        regmap_update_bits(master->regmap, PMC_MCR,
 553                           PMC_MCR_EN | PMC_MCR_CSS | PMC_MCR_DIV |
 554                           PMC_MCR_CMD | PMC_MCR_ID_MSK,
 555                           PMC_MCR_EN | (master->parent << PMC_MCR_CSS_SHIFT) |
 556                           (master->div << MASTER_DIV_SHIFT) |
 557                           PMC_MCR_CMD | PMC_MCR_ID(master->id));
 558
 559        cparent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
 560
 561        /* Wait here only if parent is being changed. */
 562        while ((cparent != master->parent) && !clk_master_ready(master))
 563                cpu_relax();
 564
 565        spin_unlock_irqrestore(master->lock, flags);
 566
 567        return 0;
 568}
 569
 570static void clk_sama7g5_master_disable(struct clk_hw *hw)
 571{
 572        struct clk_master *master = to_clk_master(hw);
 573        unsigned long flags;
 574
 575        spin_lock_irqsave(master->lock, flags);
 576
 577        regmap_write(master->regmap, PMC_MCR, master->id);
 578        regmap_update_bits(master->regmap, PMC_MCR,
 579                           PMC_MCR_EN | PMC_MCR_CMD | PMC_MCR_ID_MSK,
 580                           PMC_MCR_CMD | PMC_MCR_ID(master->id));
 581
 582        spin_unlock_irqrestore(master->lock, flags);
 583}
 584
 585static int clk_sama7g5_master_is_enabled(struct clk_hw *hw)
 586{
 587        struct clk_master *master = to_clk_master(hw);
 588        unsigned long flags;
 589        unsigned int val;
 590
 591        spin_lock_irqsave(master->lock, flags);
 592
 593        regmap_write(master->regmap, PMC_MCR, master->id);
 594        regmap_read(master->regmap, PMC_MCR, &val);
 595
 596        spin_unlock_irqrestore(master->lock, flags);
 597
 598        return !!(val & PMC_MCR_EN);
 599}
 600
 601static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
 602                                       unsigned long parent_rate)
 603{
 604        struct clk_master *master = to_clk_master(hw);
 605        unsigned long div, flags;
 606
 607        div = DIV_ROUND_CLOSEST(parent_rate, rate);
 608        if ((div > (1 << (MASTER_PRES_MAX - 1))) || (div & (div - 1)))
 609                return -EINVAL;
 610
 611        if (div == 3)
 612                div = MASTER_PRES_MAX;
 613        else
 614                div = ffs(div) - 1;
 615
 616        spin_lock_irqsave(master->lock, flags);
 617        master->div = div;
 618        spin_unlock_irqrestore(master->lock, flags);
 619
 620        return 0;
 621}
 622
 623static const struct clk_ops sama7g5_master_ops = {
 624        .enable = clk_sama7g5_master_enable,
 625        .disable = clk_sama7g5_master_disable,
 626        .is_enabled = clk_sama7g5_master_is_enabled,
 627        .recalc_rate = clk_sama7g5_master_recalc_rate,
 628        .determine_rate = clk_sama7g5_master_determine_rate,
 629        .set_rate = clk_sama7g5_master_set_rate,
 630        .get_parent = clk_sama7g5_master_get_parent,
 631        .set_parent = clk_sama7g5_master_set_parent,
 632};
 633
 634struct clk_hw * __init
 635at91_clk_sama7g5_register_master(struct regmap *regmap,
 636                                 const char *name, int num_parents,
 637                                 const char **parent_names,
 638                                 u32 *mux_table,
 639                                 spinlock_t *lock, u8 id,
 640                                 bool critical, int chg_pid)
 641{
 642        struct clk_master *master;
 643        struct clk_hw *hw;
 644        struct clk_init_data init;
 645        unsigned long flags;
 646        unsigned int val;
 647        int ret;
 648
 649        if (!name || !num_parents || !parent_names || !mux_table ||
 650            !lock || id > MASTER_MAX_ID)
 651                return ERR_PTR(-EINVAL);
 652
 653        master = kzalloc(sizeof(*master), GFP_KERNEL);
 654        if (!master)
 655                return ERR_PTR(-ENOMEM);
 656
 657        init.name = name;
 658        init.ops = &sama7g5_master_ops;
 659        init.parent_names = parent_names;
 660        init.num_parents = num_parents;
 661        init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
 662        if (chg_pid >= 0)
 663                init.flags |= CLK_SET_RATE_PARENT;
 664        if (critical)
 665                init.flags |= CLK_IS_CRITICAL;
 666
 667        master->hw.init = &init;
 668        master->regmap = regmap;
 669        master->id = id;
 670        master->chg_pid = chg_pid;
 671        master->lock = lock;
 672        master->mux_table = mux_table;
 673
 674        spin_lock_irqsave(master->lock, flags);
 675        regmap_write(master->regmap, PMC_MCR, master->id);
 676        regmap_read(master->regmap, PMC_MCR, &val);
 677        master->parent = (val & PMC_MCR_CSS) >> PMC_MCR_CSS_SHIFT;
 678        master->div = (val & PMC_MCR_DIV) >> MASTER_DIV_SHIFT;
 679        spin_unlock_irqrestore(master->lock, flags);
 680
 681        hw = &master->hw;
 682        ret = clk_hw_register(NULL, &master->hw);
 683        if (ret) {
 684                kfree(master);
 685                hw = ERR_PTR(ret);
 686        }
 687
 688        return hw;
 689}
 690
 691const struct clk_master_layout at91rm9200_master_layout = {
 692        .mask = 0x31F,
 693        .pres_shift = 2,
 694        .offset = AT91_PMC_MCKR,
 695};
 696
 697const struct clk_master_layout at91sam9x5_master_layout = {
 698        .mask = 0x373,
 699        .pres_shift = 4,
 700        .offset = AT91_PMC_MCKR,
 701};
 702