linux/drivers/clk/rockchip/clk.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2014 MundoReader S.L.
   3 * Author: Heiko Stuebner <heiko@sntech.de>
   4 *
   5 * based on
   6 *
   7 * samsung/clk.h
   8 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
   9 * Copyright (c) 2013 Linaro Ltd.
  10 * Author: Thomas Abraham <thomas.ab@samsung.com>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 */
  22
  23#ifndef CLK_ROCKCHIP_CLK_H
  24#define CLK_ROCKCHIP_CLK_H
  25
  26#include <linux/io.h>
  27#include <linux/clk.h>
  28#include <linux/clk-provider.h>
  29
  30#define HIWORD_UPDATE(val, mask, shift) \
  31                ((val) << (shift) | (mask) << ((shift) + 16))
  32
  33/* register positions shared by RK2928, RK3066 and RK3188 */
  34#define RK2928_PLL_CON(x)               (x * 0x4)
  35#define RK2928_MODE_CON         0x40
  36#define RK2928_CLKSEL_CON(x)    (x * 0x4 + 0x44)
  37#define RK2928_CLKGATE_CON(x)   (x * 0x4 + 0xd0)
  38#define RK2928_GLB_SRST_FST             0x100
  39#define RK2928_GLB_SRST_SND             0x104
  40#define RK2928_SOFTRST_CON(x)   (x * 0x4 + 0x110)
  41#define RK2928_MISC_CON         0x134
  42
  43#define RK3288_PLL_CON(x)               RK2928_PLL_CON(x)
  44#define RK3288_MODE_CON                 0x50
  45#define RK3288_CLKSEL_CON(x)            (x * 0x4 + 0x60)
  46#define RK3288_CLKGATE_CON(x)           (x * 0x4 + 0x160)
  47#define RK3288_GLB_SRST_FST             0x1b0
  48#define RK3288_GLB_SRST_SND             0x1b4
  49#define RK3288_SOFTRST_CON(x)           (x * 0x4 + 0x1b8)
  50#define RK3288_MISC_CON                 0x1e8
  51#define RK3288_SDMMC_CON0               0x200
  52#define RK3288_SDMMC_CON1               0x204
  53#define RK3288_SDIO0_CON0               0x208
  54#define RK3288_SDIO0_CON1               0x20c
  55#define RK3288_SDIO1_CON0               0x210
  56#define RK3288_SDIO1_CON1               0x214
  57#define RK3288_EMMC_CON0                0x218
  58#define RK3288_EMMC_CON1                0x21c
  59
  60enum rockchip_pll_type {
  61        pll_rk3066,
  62};
  63
  64#define RK3066_PLL_RATE(_rate, _nr, _nf, _no)   \
  65{                                               \
  66        .rate   = _rate##U,                     \
  67        .nr = _nr,                              \
  68        .nf = _nf,                              \
  69        .no = _no,                              \
  70        .bwadj = (_nf >> 1),                    \
  71}
  72
  73#define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw)        \
  74{                                                               \
  75        .rate   = _rate##U,                                     \
  76        .nr = _nr,                                              \
  77        .nf = _nf,                                              \
  78        .no = _no,                                              \
  79        .bwadj = _bw,                                           \
  80}
  81
  82struct rockchip_pll_rate_table {
  83        unsigned long rate;
  84        unsigned int nr;
  85        unsigned int nf;
  86        unsigned int no;
  87        unsigned int bwadj;
  88};
  89
  90/**
  91 * struct rockchip_pll_clock: information about pll clock
  92 * @id: platform specific id of the clock.
  93 * @name: name of this pll clock.
  94 * @parent_name: name of the parent clock.
  95 * @flags: optional flags for basic clock.
  96 * @con_offset: offset of the register for configuring the PLL.
  97 * @mode_offset: offset of the register for configuring the PLL-mode.
  98 * @mode_shift: offset inside the mode-register for the mode of this pll.
  99 * @lock_shift: offset inside the lock register for the lock status.
 100 * @type: Type of PLL to be registered.
 101 * @pll_flags: hardware-specific flags
 102 * @rate_table: Table of usable pll rates
 103 *
 104 * Flags:
 105 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
 106 *      rate_table parameters and ajust them if necessary.
 107 */
 108struct rockchip_pll_clock {
 109        unsigned int            id;
 110        const char              *name;
 111        const char              **parent_names;
 112        u8                      num_parents;
 113        unsigned long           flags;
 114        int                     con_offset;
 115        int                     mode_offset;
 116        int                     mode_shift;
 117        int                     lock_shift;
 118        enum rockchip_pll_type  type;
 119        u8                      pll_flags;
 120        struct rockchip_pll_rate_table *rate_table;
 121};
 122
 123#define ROCKCHIP_PLL_SYNC_RATE          BIT(0)
 124
 125#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift,   \
 126                _lshift, _pflags, _rtable)                              \
 127        {                                                               \
 128                .id             = _id,                                  \
 129                .type           = _type,                                \
 130                .name           = _name,                                \
 131                .parent_names   = _pnames,                              \
 132                .num_parents    = ARRAY_SIZE(_pnames),                  \
 133                .flags          = CLK_GET_RATE_NOCACHE | _flags,        \
 134                .con_offset     = _con,                                 \
 135                .mode_offset    = _mode,                                \
 136                .mode_shift     = _mshift,                              \
 137                .lock_shift     = _lshift,                              \
 138                .pll_flags      = _pflags,                              \
 139                .rate_table     = _rtable,                              \
 140        }
 141
 142struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 143                const char *name, const char **parent_names, u8 num_parents,
 144                void __iomem *base, int con_offset, int grf_lock_offset,
 145                int lock_shift, int reg_mode, int mode_shift,
 146                struct rockchip_pll_rate_table *rate_table,
 147                u8 clk_pll_flags, spinlock_t *lock);
 148
 149struct rockchip_cpuclk_clksel {
 150        int reg;
 151        u32 val;
 152};
 153
 154#define ROCKCHIP_CPUCLK_NUM_DIVIDERS    2
 155struct rockchip_cpuclk_rate_table {
 156        unsigned long prate;
 157        struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
 158};
 159
 160/**
 161 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
 162 * @core_reg:           register offset of the core settings register
 163 * @div_core_shift:     core divider offset used to divide the pll value
 164 * @div_core_mask:      core divider mask
 165 * @mux_core_shift:     offset of the core multiplexer
 166 */
 167struct rockchip_cpuclk_reg_data {
 168        int             core_reg;
 169        u8              div_core_shift;
 170        u32             div_core_mask;
 171        int             mux_core_reg;
 172        u8              mux_core_shift;
 173};
 174
 175struct clk *rockchip_clk_register_cpuclk(const char *name,
 176                        const char **parent_names, u8 num_parents,
 177                        const struct rockchip_cpuclk_reg_data *reg_data,
 178                        const struct rockchip_cpuclk_rate_table *rates,
 179                        int nrates, void __iomem *reg_base, spinlock_t *lock);
 180
 181struct clk *rockchip_clk_register_mmc(const char *name,
 182                                const char **parent_names, u8 num_parents,
 183                                void __iomem *reg, int shift);
 184
 185#define PNAME(x) static const char *x[] __initconst
 186
 187enum rockchip_clk_branch_type {
 188        branch_composite,
 189        branch_mux,
 190        branch_divider,
 191        branch_fraction_divider,
 192        branch_gate,
 193        branch_mmc,
 194};
 195
 196struct rockchip_clk_branch {
 197        unsigned int                    id;
 198        enum rockchip_clk_branch_type   branch_type;
 199        const char                      *name;
 200        const char                      **parent_names;
 201        u8                              num_parents;
 202        unsigned long                   flags;
 203        int                             muxdiv_offset;
 204        u8                              mux_shift;
 205        u8                              mux_width;
 206        u8                              mux_flags;
 207        u8                              div_shift;
 208        u8                              div_width;
 209        u8                              div_flags;
 210        struct clk_div_table            *div_table;
 211        int                             gate_offset;
 212        u8                              gate_shift;
 213        u8                              gate_flags;
 214};
 215
 216#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
 217                  df, go, gs, gf)                               \
 218        {                                                       \
 219                .id             = _id,                          \
 220                .branch_type    = branch_composite,             \
 221                .name           = cname,                        \
 222                .parent_names   = pnames,                       \
 223                .num_parents    = ARRAY_SIZE(pnames),           \
 224                .flags          = f,                            \
 225                .muxdiv_offset  = mo,                           \
 226                .mux_shift      = ms,                           \
 227                .mux_width      = mw,                           \
 228                .mux_flags      = mf,                           \
 229                .div_shift      = ds,                           \
 230                .div_width      = dw,                           \
 231                .div_flags      = df,                           \
 232                .gate_offset    = go,                           \
 233                .gate_shift     = gs,                           \
 234                .gate_flags     = gf,                           \
 235        }
 236
 237#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,   \
 238                        go, gs, gf)                             \
 239        {                                                       \
 240                .id             = _id,                          \
 241                .branch_type    = branch_composite,             \
 242                .name           = cname,                        \
 243                .parent_names   = (const char *[]){ pname },    \
 244                .num_parents    = 1,                            \
 245                .flags          = f,                            \
 246                .muxdiv_offset  = mo,                           \
 247                .div_shift      = ds,                           \
 248                .div_width      = dw,                           \
 249                .div_flags      = df,                           \
 250                .gate_offset    = go,                           \
 251                .gate_shift     = gs,                           \
 252                .gate_flags     = gf,                           \
 253        }
 254
 255#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
 256                               df, dt, go, gs, gf)              \
 257        {                                                       \
 258                .id             = _id,                          \
 259                .branch_type    = branch_composite,             \
 260                .name           = cname,                        \
 261                .parent_names   = (const char *[]){ pname },    \
 262                .num_parents    = 1,                            \
 263                .flags          = f,                            \
 264                .muxdiv_offset  = mo,                           \
 265                .div_shift      = ds,                           \
 266                .div_width      = dw,                           \
 267                .div_flags      = df,                           \
 268                .div_table      = dt,                           \
 269                .gate_offset    = go,                           \
 270                .gate_shift     = gs,                           \
 271                .gate_flags     = gf,                           \
 272        }
 273
 274#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf,  \
 275                        go, gs, gf)                             \
 276        {                                                       \
 277                .id             = _id,                          \
 278                .branch_type    = branch_composite,             \
 279                .name           = cname,                        \
 280                .parent_names   = pnames,                       \
 281                .num_parents    = ARRAY_SIZE(pnames),           \
 282                .flags          = f,                            \
 283                .muxdiv_offset  = mo,                           \
 284                .mux_shift      = ms,                           \
 285                .mux_width      = mw,                           \
 286                .mux_flags      = mf,                           \
 287                .gate_offset    = go,                           \
 288                .gate_shift     = gs,                           \
 289                .gate_flags     = gf,                           \
 290        }
 291
 292#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
 293                         ds, dw, df)                            \
 294        {                                                       \
 295                .id             = _id,                          \
 296                .branch_type    = branch_composite,             \
 297                .name           = cname,                        \
 298                .parent_names   = pnames,                       \
 299                .num_parents    = ARRAY_SIZE(pnames),           \
 300                .flags          = f,                            \
 301                .muxdiv_offset  = mo,                           \
 302                .mux_shift      = ms,                           \
 303                .mux_width      = mw,                           \
 304                .mux_flags      = mf,                           \
 305                .div_shift      = ds,                           \
 306                .div_width      = dw,                           \
 307                .div_flags      = df,                           \
 308                .gate_offset    = -1,                           \
 309        }
 310
 311#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
 312        {                                                       \
 313                .id             = _id,                          \
 314                .branch_type    = branch_fraction_divider,      \
 315                .name           = cname,                        \
 316                .parent_names   = (const char *[]){ pname },    \
 317                .num_parents    = 1,                            \
 318                .flags          = f,                            \
 319                .muxdiv_offset  = mo,                           \
 320                .div_shift      = 16,                           \
 321                .div_width      = 16,                           \
 322                .div_flags      = df,                           \
 323                .gate_offset    = go,                           \
 324                .gate_shift     = gs,                           \
 325                .gate_flags     = gf,                           \
 326        }
 327
 328#define MUX(_id, cname, pnames, f, o, s, w, mf)                 \
 329        {                                                       \
 330                .id             = _id,                          \
 331                .branch_type    = branch_mux,                   \
 332                .name           = cname,                        \
 333                .parent_names   = pnames,                       \
 334                .num_parents    = ARRAY_SIZE(pnames),           \
 335                .flags          = f,                            \
 336                .muxdiv_offset  = o,                            \
 337                .mux_shift      = s,                            \
 338                .mux_width      = w,                            \
 339                .mux_flags      = mf,                           \
 340                .gate_offset    = -1,                           \
 341        }
 342
 343#define DIV(_id, cname, pname, f, o, s, w, df)                  \
 344        {                                                       \
 345                .id             = _id,                          \
 346                .branch_type    = branch_divider,               \
 347                .name           = cname,                        \
 348                .parent_names   = (const char *[]){ pname },    \
 349                .num_parents    = 1,                            \
 350                .flags          = f,                            \
 351                .muxdiv_offset  = o,                            \
 352                .div_shift      = s,                            \
 353                .div_width      = w,                            \
 354                .div_flags      = df,                           \
 355                .gate_offset    = -1,                           \
 356        }
 357
 358#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt)           \
 359        {                                                       \
 360                .id             = _id,                          \
 361                .branch_type    = branch_divider,               \
 362                .name           = cname,                        \
 363                .parent_names   = (const char *[]){ pname },    \
 364                .num_parents    = 1,                            \
 365                .flags          = f,                            \
 366                .muxdiv_offset  = o,                            \
 367                .div_shift      = s,                            \
 368                .div_width      = w,                            \
 369                .div_flags      = df,                           \
 370                .div_table      = dt,                           \
 371        }
 372
 373#define GATE(_id, cname, pname, f, o, b, gf)                    \
 374        {                                                       \
 375                .id             = _id,                          \
 376                .branch_type    = branch_gate,                  \
 377                .name           = cname,                        \
 378                .parent_names   = (const char *[]){ pname },    \
 379                .num_parents    = 1,                            \
 380                .flags          = f,                            \
 381                .gate_offset    = o,                            \
 382                .gate_shift     = b,                            \
 383                .gate_flags     = gf,                           \
 384        }
 385
 386#define MMC(_id, cname, pname, offset, shift)                   \
 387        {                                                       \
 388                .id             = _id,                          \
 389                .branch_type    = branch_mmc,                   \
 390                .name           = cname,                        \
 391                .parent_names   = (const char *[]){ pname },    \
 392                .num_parents    = 1,                            \
 393                .muxdiv_offset  = offset,                       \
 394                .div_shift      = shift,                        \
 395        }
 396
 397void rockchip_clk_init(struct device_node *np, void __iomem *base,
 398                       unsigned long nr_clks);
 399struct regmap *rockchip_clk_get_grf(void);
 400void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
 401void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
 402                                    unsigned int nr_clk);
 403void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
 404                                unsigned int nr_pll, int grf_lock_offset);
 405void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
 406                        const char **parent_names, u8 num_parents,
 407                        const struct rockchip_cpuclk_reg_data *reg_data,
 408                        const struct rockchip_cpuclk_rate_table *rates,
 409                        int nrates);
 410void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
 411void rockchip_register_restart_notifier(unsigned int reg);
 412
 413#define ROCKCHIP_SOFTRST_HIWORD_MASK    BIT(0)
 414
 415#ifdef CONFIG_RESET_CONTROLLER
 416void rockchip_register_softrst(struct device_node *np,
 417                               unsigned int num_regs,
 418                               void __iomem *base, u8 flags);
 419#else
 420static inline void rockchip_register_softrst(struct device_node *np,
 421                               unsigned int num_regs,
 422                               void __iomem *base, u8 flags)
 423{
 424}
 425#endif
 426
 427#endif
 428