uboot/arch/arm/cpu/armv7/bcm281xx/clk-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2013 Broadcom Corporation.
   4 */
   5
   6/*
   7 *
   8 * bcm281xx architecture clock framework
   9 *
  10 */
  11
  12#include <common.h>
  13#include <asm/io.h>
  14#include <linux/errno.h>
  15#include <bitfield.h>
  16#include <asm/arch/sysmap.h>
  17#include <asm/kona-common/clk.h>
  18#include "clk-core.h"
  19
  20#define CLK_WR_ACCESS_PASSWORD  0x00a5a501
  21#define WR_ACCESS_OFFSET        0       /* common to all clock blocks */
  22#define POLICY_CTL_GO           1       /* Load and refresh policy masks */
  23#define POLICY_CTL_GO_ATL       4       /* Active Load */
  24
  25/* Helper function */
  26int clk_get_and_enable(char *clkstr)
  27{
  28        int ret = 0;
  29        struct clk *c;
  30
  31        debug("%s: %s\n", __func__, clkstr);
  32
  33        c = clk_get(clkstr);
  34        if (c) {
  35                ret = clk_enable(c);
  36                if (ret)
  37                        return ret;
  38        } else {
  39                printf("%s: Couldn't find %s\n", __func__, clkstr);
  40                return -EINVAL;
  41        }
  42        return ret;
  43}
  44
  45/*
  46 * Poll a register in a CCU's address space, returning when the
  47 * specified bit in that register's value is set (or clear).  Delay
  48 * a microsecond after each read of the register.  Returns true if
  49 * successful, or false if we gave up trying.
  50 *
  51 * Caller must ensure the CCU lock is held.
  52 */
  53#define CLK_GATE_DELAY_USEC 2000
  54static inline int wait_bit(void *base, u32 offset, u32 bit, bool want)
  55{
  56        unsigned int tries;
  57        u32 bit_mask = 1 << bit;
  58
  59        for (tries = 0; tries < CLK_GATE_DELAY_USEC; tries++) {
  60                u32 val;
  61                bool bit_val;
  62
  63                val = readl(base + offset);
  64                bit_val = (val & bit_mask) ? 1 : 0;
  65                if (bit_val == want)
  66                        return 0;       /* success */
  67                udelay(1);
  68        }
  69
  70        debug("%s: timeout on addr 0x%p, waiting for bit %d to go to %d\n",
  71              __func__, base + offset, bit, want);
  72
  73        return -ETIMEDOUT;
  74}
  75
  76/* Enable a peripheral clock */
  77static int peri_clk_enable(struct clk *c, int enable)
  78{
  79        int ret = 0;
  80        u32 reg;
  81        struct peri_clock *peri_clk = to_peri_clk(c);
  82        struct peri_clk_data *cd = peri_clk->data;
  83        struct bcm_clk_gate *gate = &cd->gate;
  84        void *base = (void *)c->ccu_clk_mgr_base;
  85
  86
  87        debug("%s: %s\n", __func__, c->name);
  88
  89        clk_get_rate(c);        /* Make sure rate and sel are filled in */
  90
  91        /* enable access */
  92        writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
  93
  94        if (enable) {
  95                debug("%s %s set rate %lu div %lu sel %d parent %lu\n",
  96                      __func__, c->name, c->rate, c->div, c->sel,
  97                      c->parent->rate);
  98
  99                /*
 100                 * clkgate - only software controllable gates are
 101                 * supported by u-boot which includes all clocks
 102                 * that matter. This avoids bringing in a lot of extra
 103                 * complexity as done in the kernel framework.
 104                 */
 105                if (gate_exists(gate)) {
 106                        reg = readl(base + cd->gate.offset);
 107                        reg |= (1 << cd->gate.en_bit);
 108                        writel(reg, base + cd->gate.offset);
 109                }
 110
 111                /* div and pll select */
 112                if (divider_exists(&cd->div)) {
 113                        reg = readl(base + cd->div.offset);
 114                        bitfield_replace(reg, cd->div.shift, cd->div.width,
 115                                         c->div - 1);
 116                        writel(reg, base + cd->div.offset);
 117                }
 118
 119                /* frequency selector */
 120                if (selector_exists(&cd->sel)) {
 121                        reg = readl(base + cd->sel.offset);
 122                        bitfield_replace(reg, cd->sel.shift, cd->sel.width,
 123                                         c->sel);
 124                        writel(reg, base + cd->sel.offset);
 125                }
 126
 127                /* trigger */
 128                if (trigger_exists(&cd->trig)) {
 129                        writel((1 << cd->trig.bit), base + cd->trig.offset);
 130
 131                        /* wait for trigger status bit to go to 0 */
 132                        ret = wait_bit(base, cd->trig.offset, cd->trig.bit, 0);
 133                        if (ret)
 134                                return ret;
 135                }
 136
 137                /* wait for running (status_bit = 1) */
 138                ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 1);
 139                if (ret)
 140                        return ret;
 141        } else {
 142                debug("%s disable clock %s\n", __func__, c->name);
 143
 144                /* clkgate */
 145                reg = readl(base + cd->gate.offset);
 146                reg &= ~(1 << cd->gate.en_bit);
 147                writel(reg, base + cd->gate.offset);
 148
 149                /* wait for stop (status_bit = 0) */
 150                ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit, 0);
 151        }
 152
 153        /* disable access */
 154        writel(0, base + WR_ACCESS_OFFSET);
 155
 156        return ret;
 157}
 158
 159/* Set the rate of a peripheral clock */
 160static int peri_clk_set_rate(struct clk *c, unsigned long rate)
 161{
 162        int ret = 0;
 163        int i;
 164        unsigned long diff;
 165        unsigned long new_rate = 0, div = 1;
 166        struct peri_clock *peri_clk = to_peri_clk(c);
 167        struct peri_clk_data *cd = peri_clk->data;
 168        const char **clock;
 169
 170        debug("%s: %s\n", __func__, c->name);
 171        diff = rate;
 172
 173        i = 0;
 174        for (clock = cd->clocks; *clock; clock++, i++) {
 175                struct refclk *ref = refclk_str_to_clk(*clock);
 176                if (!ref) {
 177                        printf("%s: Lookup of %s failed\n", __func__, *clock);
 178                        return -EINVAL;
 179                }
 180
 181                /* round to the new rate */
 182                div = ref->clk.rate / rate;
 183                if (div == 0)
 184                        div = 1;
 185
 186                new_rate = ref->clk.rate / div;
 187
 188                /* get the min diff */
 189                if (abs(new_rate - rate) < diff) {
 190                        diff = abs(new_rate - rate);
 191                        c->sel = i;
 192                        c->parent = &ref->clk;
 193                        c->rate = new_rate;
 194                        c->div = div;
 195                }
 196        }
 197
 198        debug("%s %s set rate %lu div %lu sel %d parent %lu\n", __func__,
 199              c->name, c->rate, c->div, c->sel, c->parent->rate);
 200        return ret;
 201}
 202
 203/* Get the rate of a peripheral clock */
 204static unsigned long peri_clk_get_rate(struct clk *c)
 205{
 206        struct peri_clock *peri_clk = to_peri_clk(c);
 207        struct peri_clk_data *cd = peri_clk->data;
 208        void *base = (void *)c->ccu_clk_mgr_base;
 209        int div = 1;
 210        const char **clock;
 211        struct refclk *ref;
 212        u32 reg;
 213
 214        debug("%s: %s\n", __func__, c->name);
 215        if (selector_exists(&cd->sel)) {
 216                reg = readl(base + cd->sel.offset);
 217                c->sel = bitfield_extract(reg, cd->sel.shift, cd->sel.width);
 218        } else {
 219                /*
 220                 * For peri clocks that don't have a selector, the single
 221                 * reference clock will always exist at index 0.
 222                 */
 223                c->sel = 0;
 224        }
 225
 226        if (divider_exists(&cd->div)) {
 227                reg = readl(base + cd->div.offset);
 228                div = bitfield_extract(reg, cd->div.shift, cd->div.width);
 229                div += 1;
 230        }
 231
 232        clock = cd->clocks;
 233        ref = refclk_str_to_clk(clock[c->sel]);
 234        if (!ref) {
 235                printf("%s: Can't lookup %s\n", __func__, clock[c->sel]);
 236                return 0;
 237        }
 238
 239        c->parent = &ref->clk;
 240        c->div = div;
 241        c->rate = c->parent->rate / c->div;
 242        debug("%s parent rate %lu div %d sel %d rate %lu\n", __func__,
 243              c->parent->rate, div, c->sel, c->rate);
 244
 245        return c->rate;
 246}
 247
 248/* Peripheral clock operations */
 249struct clk_ops peri_clk_ops = {
 250        .enable = peri_clk_enable,
 251        .set_rate = peri_clk_set_rate,
 252        .get_rate = peri_clk_get_rate,
 253};
 254
 255/* Enable a CCU clock */
 256static int ccu_clk_enable(struct clk *c, int enable)
 257{
 258        struct ccu_clock *ccu_clk = to_ccu_clk(c);
 259        void *base = (void *)c->ccu_clk_mgr_base;
 260        int ret = 0;
 261        u32 reg;
 262
 263        debug("%s: %s\n", __func__, c->name);
 264        if (!enable)
 265                return -EINVAL; /* CCU clock cannot shutdown */
 266
 267        /* enable access */
 268        writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
 269
 270        /* config enable for policy engine */
 271        writel(1, base + ccu_clk->lvm_en_offset);
 272
 273        /* wait for bit to go to 0 */
 274        ret = wait_bit(base, ccu_clk->lvm_en_offset, 0, 0);
 275        if (ret)
 276                return ret;
 277
 278        /* freq ID */
 279        if (!ccu_clk->freq_bit_shift)
 280                ccu_clk->freq_bit_shift = 8;
 281
 282        /* Set frequency id for each of the 4 policies */
 283        reg = ccu_clk->freq_id |
 284            (ccu_clk->freq_id << (ccu_clk->freq_bit_shift)) |
 285            (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 2)) |
 286            (ccu_clk->freq_id << (ccu_clk->freq_bit_shift * 3));
 287        writel(reg, base + ccu_clk->policy_freq_offset);
 288
 289        /* enable all clock mask */
 290        writel(0x7fffffff, base + ccu_clk->policy0_mask_offset);
 291        writel(0x7fffffff, base + ccu_clk->policy1_mask_offset);
 292        writel(0x7fffffff, base + ccu_clk->policy2_mask_offset);
 293        writel(0x7fffffff, base + ccu_clk->policy3_mask_offset);
 294
 295        if (ccu_clk->num_policy_masks == 2) {
 296                writel(0x7fffffff, base + ccu_clk->policy0_mask2_offset);
 297                writel(0x7fffffff, base + ccu_clk->policy1_mask2_offset);
 298                writel(0x7fffffff, base + ccu_clk->policy2_mask2_offset);
 299                writel(0x7fffffff, base + ccu_clk->policy3_mask2_offset);
 300        }
 301
 302        /* start policy engine */
 303        reg = readl(base + ccu_clk->policy_ctl_offset);
 304        reg |= (POLICY_CTL_GO + POLICY_CTL_GO_ATL);
 305        writel(reg, base + ccu_clk->policy_ctl_offset);
 306
 307        /* wait till started */
 308        ret = wait_bit(base, ccu_clk->policy_ctl_offset, 0, 0);
 309        if (ret)
 310                return ret;
 311
 312        /* disable access */
 313        writel(0, base + WR_ACCESS_OFFSET);
 314
 315        return ret;
 316}
 317
 318/* Get the CCU clock rate */
 319static unsigned long ccu_clk_get_rate(struct clk *c)
 320{
 321        struct ccu_clock *ccu_clk = to_ccu_clk(c);
 322        debug("%s: %s\n", __func__, c->name);
 323        c->rate = ccu_clk->freq_tbl[ccu_clk->freq_id];
 324        return c->rate;
 325}
 326
 327/* CCU clock operations */
 328struct clk_ops ccu_clk_ops = {
 329        .enable = ccu_clk_enable,
 330        .get_rate = ccu_clk_get_rate,
 331};
 332
 333/* Enable a bus clock */
 334static int bus_clk_enable(struct clk *c, int enable)
 335{
 336        struct bus_clock *bus_clk = to_bus_clk(c);
 337        struct bus_clk_data *cd = bus_clk->data;
 338        void *base = (void *)c->ccu_clk_mgr_base;
 339        int ret = 0;
 340        u32 reg;
 341
 342        debug("%s: %s\n", __func__, c->name);
 343        /* enable access */
 344        writel(CLK_WR_ACCESS_PASSWORD, base + WR_ACCESS_OFFSET);
 345
 346        /* enable gating */
 347        reg = readl(base + cd->gate.offset);
 348        if (!!(reg & (1 << cd->gate.status_bit)) == !!enable)
 349                debug("%s already %s\n", c->name,
 350                      enable ? "enabled" : "disabled");
 351        else {
 352                int want = (enable) ? 1 : 0;
 353                reg |= (1 << cd->gate.hw_sw_sel_bit);
 354
 355                if (enable)
 356                        reg |= (1 << cd->gate.en_bit);
 357                else
 358                        reg &= ~(1 << cd->gate.en_bit);
 359
 360                writel(reg, base + cd->gate.offset);
 361                ret = wait_bit(base, cd->gate.offset, cd->gate.status_bit,
 362                               want);
 363                if (ret)
 364                        return ret;
 365        }
 366
 367        /* disable access */
 368        writel(0, base + WR_ACCESS_OFFSET);
 369
 370        return ret;
 371}
 372
 373/* Get the rate of a bus clock */
 374static unsigned long bus_clk_get_rate(struct clk *c)
 375{
 376        struct bus_clock *bus_clk = to_bus_clk(c);
 377        struct ccu_clock *ccu_clk;
 378
 379        debug("%s: %s\n", __func__, c->name);
 380        ccu_clk = to_ccu_clk(c->parent);
 381
 382        c->rate = bus_clk->freq_tbl[ccu_clk->freq_id];
 383        c->div = ccu_clk->freq_tbl[ccu_clk->freq_id] / c->rate;
 384        return c->rate;
 385}
 386
 387/* Bus clock operations */
 388struct clk_ops bus_clk_ops = {
 389        .enable = bus_clk_enable,
 390        .get_rate = bus_clk_get_rate,
 391};
 392
 393/* Enable a reference clock */
 394static int ref_clk_enable(struct clk *c, int enable)
 395{
 396        debug("%s: %s\n", __func__, c->name);
 397        return 0;
 398}
 399
 400/* Reference clock operations */
 401struct clk_ops ref_clk_ops = {
 402        .enable = ref_clk_enable,
 403};
 404
 405/*
 406 * clk.h implementation follows
 407 */
 408
 409/* Initialize the clock framework */
 410int clk_init(void)
 411{
 412        debug("%s:\n", __func__);
 413        return 0;
 414}
 415
 416/* Get a clock handle, give a name string */
 417struct clk *clk_get(const char *con_id)
 418{
 419        int i;
 420        struct clk_lookup *clk_tblp;
 421
 422        debug("%s: %s\n", __func__, con_id);
 423
 424        clk_tblp = arch_clk_tbl;
 425        for (i = 0; i < arch_clk_tbl_array_size; i++, clk_tblp++) {
 426                if (clk_tblp->con_id) {
 427                        if (!con_id || strcmp(clk_tblp->con_id, con_id))
 428                                continue;
 429                        return clk_tblp->clk;
 430                }
 431        }
 432        return NULL;
 433}
 434
 435/* Enable a clock */
 436int clk_enable(struct clk *c)
 437{
 438        int ret = 0;
 439
 440        debug("%s: %s\n", __func__, c->name);
 441        if (!c->ops || !c->ops->enable)
 442                return -1;
 443
 444        /* enable parent clock first */
 445        if (c->parent)
 446                ret = clk_enable(c->parent);
 447
 448        if (ret)
 449                return ret;
 450
 451        if (!c->use_cnt) {
 452                c->use_cnt++;
 453                ret = c->ops->enable(c, 1);
 454        }
 455
 456        return ret;
 457}
 458
 459/* Disable a clock */
 460void clk_disable(struct clk *c)
 461{
 462        debug("%s: %s\n", __func__, c->name);
 463        if (!c->ops || !c->ops->enable)
 464                return;
 465
 466        if (c->use_cnt) {
 467                c->use_cnt--;
 468                c->ops->enable(c, 0);
 469        }
 470
 471        /* disable parent */
 472        if (c->parent)
 473                clk_disable(c->parent);
 474}
 475
 476/* Get the clock rate */
 477unsigned long clk_get_rate(struct clk *c)
 478{
 479        unsigned long rate;
 480
 481        if (!c || !c->ops || !c->ops->get_rate)
 482                return 0;
 483        debug("%s: %s\n", __func__, c->name);
 484
 485        rate = c->ops->get_rate(c);
 486        debug("%s: rate = %ld\n", __func__, rate);
 487        return rate;
 488}
 489
 490/* Set the clock rate */
 491int clk_set_rate(struct clk *c, unsigned long rate)
 492{
 493        int ret;
 494
 495        if (!c || !c->ops || !c->ops->set_rate)
 496                return -EINVAL;
 497        debug("%s: %s rate=%ld\n", __func__, c->name, rate);
 498
 499        if (c->use_cnt)
 500                return -EINVAL;
 501
 502        ret = c->ops->set_rate(c, rate);
 503
 504        return ret;
 505}
 506
 507/* Not required for this arch */
 508/*
 509long clk_round_rate(struct clk *clk, unsigned long rate);
 510int clk_set_parent(struct clk *clk, struct clk *parent);
 511struct clk *clk_get_parent(struct clk *clk);
 512*/
 513