root/drivers/clk/tegra/clk.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tegra_clk_rst_assert
  2. tegra_clk_rst_deassert
  3. tegra_clk_rst_reset
  4. get_reg_bank
  5. tegra_clk_init
  6. tegra_init_dup_clks
  7. tegra_init_from_table
  8. tegra_add_of_provider
  9. tegra_init_special_resets
  10. tegra_register_devclks
  11. tegra_lookup_dt_id
  12. tegra_clocks_apply_init_table

   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 */
  64 static struct tegra_cpu_car_ops dummy_car_ops;
  65 struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
  66 
  67 int *periph_clk_enb_refcnt;
  68 static int periph_banks;
  69 static struct clk **clks;
  70 static int clk_num;
  71 static struct clk_onecell_data clk_data;
  72 
  73 /* Handlers for SoC-specific reset lines */
  74 static int (*special_reset_assert)(unsigned long);
  75 static int (*special_reset_deassert)(unsigned long);
  76 static unsigned int num_special_reset;
  77 
  78 static 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 
 137 static void __iomem *clk_base;
 138 
 139 static 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 
 162 static 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 
 176 static 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 
 190 const 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 
 202 struct 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 
 226 void __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 
 238 void __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 
 280 static 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 
 286 static struct reset_controller_dev rst_ctlr = {
 287         .ops = &rst_ops,
 288         .owner = THIS_MODULE,
 289         .of_reset_n_cells = 1,
 290 };
 291 
 292 void __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 
 316 void __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 
 325 void __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 
 340 struct 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 
 349 tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
 350 
 351 static 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 }
 360 arch_initcall(tegra_clocks_apply_init_table);

/* [<][>][^][v][top][bottom][index][help] */