linux/drivers/clk/tegra/clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
   4 */
   5
   6#include <linux/clkdev.h>
   7#include <linux/clk.h>
   8#include <linux/clk-provider.h>
   9#include <linux/delay.h>
  10#include <linux/io.h>
  11#include <linux/of.h>
  12#include <linux/clk/tegra.h>
  13#include <linux/reset-controller.h>
  14
  15#include <soc/tegra/fuse.h>
  16
  17#include "clk.h"
  18
  19#define CLK_OUT_ENB_L                   0x010
  20#define CLK_OUT_ENB_H                   0x014
  21#define CLK_OUT_ENB_U                   0x018
  22#define CLK_OUT_ENB_V                   0x360
  23#define CLK_OUT_ENB_W                   0x364
  24#define CLK_OUT_ENB_X                   0x280
  25#define CLK_OUT_ENB_Y                   0x298
  26#define CLK_OUT_ENB_SET_L               0x320
  27#define CLK_OUT_ENB_CLR_L               0x324
  28#define CLK_OUT_ENB_SET_H               0x328
  29#define CLK_OUT_ENB_CLR_H               0x32c
  30#define CLK_OUT_ENB_SET_U               0x330
  31#define CLK_OUT_ENB_CLR_U               0x334
  32#define CLK_OUT_ENB_SET_V               0x440
  33#define CLK_OUT_ENB_CLR_V               0x444
  34#define CLK_OUT_ENB_SET_W               0x448
  35#define CLK_OUT_ENB_CLR_W               0x44c
  36#define CLK_OUT_ENB_SET_X               0x284
  37#define CLK_OUT_ENB_CLR_X               0x288
  38#define CLK_OUT_ENB_SET_Y               0x29c
  39#define CLK_OUT_ENB_CLR_Y               0x2a0
  40
  41#define RST_DEVICES_L                   0x004
  42#define RST_DEVICES_H                   0x008
  43#define RST_DEVICES_U                   0x00C
  44#define RST_DEVICES_V                   0x358
  45#define RST_DEVICES_W                   0x35C
  46#define RST_DEVICES_X                   0x28C
  47#define RST_DEVICES_Y                   0x2a4
  48#define RST_DEVICES_SET_L               0x300
  49#define RST_DEVICES_CLR_L               0x304
  50#define RST_DEVICES_SET_H               0x308
  51#define RST_DEVICES_CLR_H               0x30c
  52#define RST_DEVICES_SET_U               0x310
  53#define RST_DEVICES_CLR_U               0x314
  54#define RST_DEVICES_SET_V               0x430
  55#define RST_DEVICES_CLR_V               0x434
  56#define RST_DEVICES_SET_W               0x438
  57#define RST_DEVICES_CLR_W               0x43c
  58#define RST_DEVICES_SET_X               0x290
  59#define RST_DEVICES_CLR_X               0x294
  60#define RST_DEVICES_SET_Y               0x2a8
  61#define RST_DEVICES_CLR_Y               0x2ac
  62
  63/* Global data of Tegra CPU CAR ops */
  64static struct tegra_cpu_car_ops dummy_car_ops;
  65struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
  66
  67int *periph_clk_enb_refcnt;
  68static int periph_banks;
  69static struct clk **clks;
  70static int clk_num;
  71static struct clk_onecell_data clk_data;
  72
  73/* Handlers for SoC-specific reset lines */
  74static int (*special_reset_assert)(unsigned long);
  75static int (*special_reset_deassert)(unsigned long);
  76static unsigned int num_special_reset;
  77
  78static const struct tegra_clk_periph_regs periph_regs[] = {
  79        [0] = {
  80                .enb_reg = CLK_OUT_ENB_L,
  81                .enb_set_reg = CLK_OUT_ENB_SET_L,
  82                .enb_clr_reg = CLK_OUT_ENB_CLR_L,
  83                .rst_reg = RST_DEVICES_L,
  84                .rst_set_reg = RST_DEVICES_SET_L,
  85                .rst_clr_reg = RST_DEVICES_CLR_L,
  86        },
  87        [1] = {
  88                .enb_reg = CLK_OUT_ENB_H,
  89                .enb_set_reg = CLK_OUT_ENB_SET_H,
  90                .enb_clr_reg = CLK_OUT_ENB_CLR_H,
  91                .rst_reg = RST_DEVICES_H,
  92                .rst_set_reg = RST_DEVICES_SET_H,
  93                .rst_clr_reg = RST_DEVICES_CLR_H,
  94        },
  95        [2] = {
  96                .enb_reg = CLK_OUT_ENB_U,
  97                .enb_set_reg = CLK_OUT_ENB_SET_U,
  98                .enb_clr_reg = CLK_OUT_ENB_CLR_U,
  99                .rst_reg = RST_DEVICES_U,
 100                .rst_set_reg = RST_DEVICES_SET_U,
 101                .rst_clr_reg = RST_DEVICES_CLR_U,
 102        },
 103        [3] = {
 104                .enb_reg = CLK_OUT_ENB_V,
 105                .enb_set_reg = CLK_OUT_ENB_SET_V,
 106                .enb_clr_reg = CLK_OUT_ENB_CLR_V,
 107                .rst_reg = RST_DEVICES_V,
 108                .rst_set_reg = RST_DEVICES_SET_V,
 109                .rst_clr_reg = RST_DEVICES_CLR_V,
 110        },
 111        [4] = {
 112                .enb_reg = CLK_OUT_ENB_W,
 113                .enb_set_reg = CLK_OUT_ENB_SET_W,
 114                .enb_clr_reg = CLK_OUT_ENB_CLR_W,
 115                .rst_reg = RST_DEVICES_W,
 116                .rst_set_reg = RST_DEVICES_SET_W,
 117                .rst_clr_reg = RST_DEVICES_CLR_W,
 118        },
 119        [5] = {
 120                .enb_reg = CLK_OUT_ENB_X,
 121                .enb_set_reg = CLK_OUT_ENB_SET_X,
 122                .enb_clr_reg = CLK_OUT_ENB_CLR_X,
 123                .rst_reg = RST_DEVICES_X,
 124                .rst_set_reg = RST_DEVICES_SET_X,
 125                .rst_clr_reg = RST_DEVICES_CLR_X,
 126        },
 127        [6] = {
 128                .enb_reg = CLK_OUT_ENB_Y,
 129                .enb_set_reg = CLK_OUT_ENB_SET_Y,
 130                .enb_clr_reg = CLK_OUT_ENB_CLR_Y,
 131                .rst_reg = RST_DEVICES_Y,
 132                .rst_set_reg = RST_DEVICES_SET_Y,
 133                .rst_clr_reg = RST_DEVICES_CLR_Y,
 134        },
 135};
 136
 137static void __iomem *clk_base;
 138
 139static int tegra_clk_rst_assert(struct reset_controller_dev *rcdev,
 140                unsigned long id)
 141{
 142        /*
 143         * If peripheral is on the APB bus then we must read the APB bus to
 144         * flush the write operation in apb bus. This will avoid peripheral
 145         * access after disabling clock. Since the reset driver has no
 146         * knowledge of which reset IDs represent which devices, simply do
 147         * this all the time.
 148         */
 149        tegra_read_chipid();
 150
 151        if (id < periph_banks * 32) {
 152                writel_relaxed(BIT(id % 32),
 153                               clk_base + periph_regs[id / 32].rst_set_reg);
 154                return 0;
 155        } else if (id < periph_banks * 32 + num_special_reset) {
 156                return special_reset_assert(id);
 157        }
 158
 159        return -EINVAL;
 160}
 161
 162static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
 163                unsigned long id)
 164{
 165        if (id < periph_banks * 32) {
 166                writel_relaxed(BIT(id % 32),
 167                               clk_base + periph_regs[id / 32].rst_clr_reg);
 168                return 0;
 169        } else if (id < periph_banks * 32 + num_special_reset) {
 170                return special_reset_deassert(id);
 171        }
 172
 173        return -EINVAL;
 174}
 175
 176static int tegra_clk_rst_reset(struct reset_controller_dev *rcdev,
 177                unsigned long id)
 178{
 179        int err;
 180
 181        err = tegra_clk_rst_assert(rcdev, id);
 182        if (err)
 183                return err;
 184
 185        udelay(1);
 186
 187        return tegra_clk_rst_deassert(rcdev, id);
 188}
 189
 190const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
 191{
 192        int reg_bank = clkid / 32;
 193
 194        if (reg_bank < periph_banks)
 195                return &periph_regs[reg_bank];
 196        else {
 197                WARN_ON(1);
 198                return NULL;
 199        }
 200}
 201
 202struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
 203{
 204        clk_base = regs;
 205
 206        if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
 207                return NULL;
 208
 209        periph_clk_enb_refcnt = kcalloc(32 * banks,
 210                                        sizeof(*periph_clk_enb_refcnt),
 211                                        GFP_KERNEL);
 212        if (!periph_clk_enb_refcnt)
 213                return NULL;
 214
 215        periph_banks = banks;
 216
 217        clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL);
 218        if (!clks)
 219                kfree(periph_clk_enb_refcnt);
 220
 221        clk_num = num;
 222
 223        return clks;
 224}
 225
 226void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
 227                                struct clk *clks[], int clk_max)
 228{
 229        struct clk *clk;
 230
 231        for (; dup_list->clk_id < clk_max; dup_list++) {
 232                clk = clks[dup_list->clk_id];
 233                dup_list->lookup.clk = clk;
 234                clkdev_add(&dup_list->lookup);
 235        }
 236}
 237
 238void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
 239                                  struct clk *clks[], int clk_max)
 240{
 241        struct clk *clk;
 242
 243        for (; tbl->clk_id < clk_max; tbl++) {
 244                clk = clks[tbl->clk_id];
 245                if (IS_ERR_OR_NULL(clk)) {
 246                        pr_err("%s: invalid entry %ld in clks array for id %d\n",
 247                               __func__, PTR_ERR(clk), tbl->clk_id);
 248                        WARN_ON(1);
 249
 250                        continue;
 251                }
 252
 253                if (tbl->parent_id < clk_max) {
 254                        struct clk *parent = clks[tbl->parent_id];
 255                        if (clk_set_parent(clk, parent)) {
 256                                pr_err("%s: Failed to set parent %s of %s\n",
 257                                       __func__, __clk_get_name(parent),
 258                                       __clk_get_name(clk));
 259                                WARN_ON(1);
 260                        }
 261                }
 262
 263                if (tbl->rate)
 264                        if (clk_set_rate(clk, tbl->rate)) {
 265                                pr_err("%s: Failed to set rate %lu of %s\n",
 266                                       __func__, tbl->rate,
 267                                       __clk_get_name(clk));
 268                                WARN_ON(1);
 269                        }
 270
 271                if (tbl->state)
 272                        if (clk_prepare_enable(clk)) {
 273                                pr_err("%s: Failed to enable %s\n", __func__,
 274                                       __clk_get_name(clk));
 275                                WARN_ON(1);
 276                        }
 277        }
 278}
 279
 280static const struct reset_control_ops rst_ops = {
 281        .assert = tegra_clk_rst_assert,
 282        .deassert = tegra_clk_rst_deassert,
 283        .reset = tegra_clk_rst_reset,
 284};
 285
 286static struct reset_controller_dev rst_ctlr = {
 287        .ops = &rst_ops,
 288        .owner = THIS_MODULE,
 289        .of_reset_n_cells = 1,
 290};
 291
 292void __init tegra_add_of_provider(struct device_node *np,
 293                                  void *clk_src_onecell_get)
 294{
 295        int i;
 296
 297        for (i = 0; i < clk_num; i++) {
 298                if (IS_ERR(clks[i])) {
 299                        pr_err
 300                            ("Tegra clk %d: register failed with %ld\n",
 301                             i, PTR_ERR(clks[i]));
 302                }
 303                if (!clks[i])
 304                        clks[i] = ERR_PTR(-EINVAL);
 305        }
 306
 307        clk_data.clks = clks;
 308        clk_data.clk_num = clk_num;
 309        of_clk_add_provider(np, clk_src_onecell_get, &clk_data);
 310
 311        rst_ctlr.of_node = np;
 312        rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
 313        reset_controller_register(&rst_ctlr);
 314}
 315
 316void __init tegra_init_special_resets(unsigned int num,
 317                                      int (*assert)(unsigned long),
 318                                      int (*deassert)(unsigned long))
 319{
 320        num_special_reset = num;
 321        special_reset_assert = assert;
 322        special_reset_deassert = deassert;
 323}
 324
 325void __init tegra_register_devclks(struct tegra_devclk *dev_clks, int num)
 326{
 327        int i;
 328
 329        for (i = 0; i < num; i++, dev_clks++)
 330                clk_register_clkdev(clks[dev_clks->dt_id], dev_clks->con_id,
 331                                dev_clks->dev_id);
 332
 333        for (i = 0; i < clk_num; i++) {
 334                if (!IS_ERR_OR_NULL(clks[i]))
 335                        clk_register_clkdev(clks[i], __clk_get_name(clks[i]),
 336                                "tegra-clk-debug");
 337        }
 338}
 339
 340struct clk ** __init tegra_lookup_dt_id(int clk_id,
 341                                        struct tegra_clk *tegra_clk)
 342{
 343        if (tegra_clk[clk_id].present)
 344                return &clks[tegra_clk[clk_id].dt_id];
 345        else
 346                return NULL;
 347}
 348
 349tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
 350
 351static int __init tegra_clocks_apply_init_table(void)
 352{
 353        if (!tegra_clk_apply_init_table)
 354                return 0;
 355
 356        tegra_clk_apply_init_table();
 357
 358        return 0;
 359}
 360arch_initcall(tegra_clocks_apply_init_table);
 361