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