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
  28struct clk;
  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
  60#define RK3368_PLL_CON(x)               RK2928_PLL_CON(x)
  61#define RK3368_CLKSEL_CON(x)            ((x) * 0x4 + 0x100)
  62#define RK3368_CLKGATE_CON(x)           ((x) * 0x4 + 0x200)
  63#define RK3368_GLB_SRST_FST             0x280
  64#define RK3368_GLB_SRST_SND             0x284
  65#define RK3368_SOFTRST_CON(x)           ((x) * 0x4 + 0x300)
  66#define RK3368_MISC_CON                 0x380
  67#define RK3368_SDMMC_CON0               0x400
  68#define RK3368_SDMMC_CON1               0x404
  69#define RK3368_SDIO0_CON0               0x408
  70#define RK3368_SDIO0_CON1               0x40c
  71#define RK3368_SDIO1_CON0               0x410
  72#define RK3368_SDIO1_CON1               0x414
  73#define RK3368_EMMC_CON0                0x418
  74#define RK3368_EMMC_CON1                0x41c
  75
  76enum rockchip_pll_type {
  77        pll_rk3066,
  78};
  79
  80#define RK3066_PLL_RATE(_rate, _nr, _nf, _no)   \
  81{                                               \
  82        .rate   = _rate##U,                     \
  83        .nr = _nr,                              \
  84        .nf = _nf,                              \
  85        .no = _no,                              \
  86        .nb = ((_nf) < 2) ? 1 : (_nf) >> 1,     \
  87}
  88
  89#define RK3066_PLL_RATE_NB(_rate, _nr, _nf, _no, _nb)           \
  90{                                                               \
  91        .rate   = _rate##U,                                     \
  92        .nr = _nr,                                              \
  93        .nf = _nf,                                              \
  94        .no = _no,                                              \
  95        .nb = _nb,                                              \
  96}
  97
  98struct rockchip_pll_rate_table {
  99        unsigned long rate;
 100        unsigned int nr;
 101        unsigned int nf;
 102        unsigned int no;
 103        unsigned int nb;
 104};
 105
 106/**
 107 * struct rockchip_pll_clock: information about pll clock
 108 * @id: platform specific id of the clock.
 109 * @name: name of this pll clock.
 110 * @parent_name: name of the parent clock.
 111 * @flags: optional flags for basic clock.
 112 * @con_offset: offset of the register for configuring the PLL.
 113 * @mode_offset: offset of the register for configuring the PLL-mode.
 114 * @mode_shift: offset inside the mode-register for the mode of this pll.
 115 * @lock_shift: offset inside the lock register for the lock status.
 116 * @type: Type of PLL to be registered.
 117 * @pll_flags: hardware-specific flags
 118 * @rate_table: Table of usable pll rates
 119 *
 120 * Flags:
 121 * ROCKCHIP_PLL_SYNC_RATE - check rate parameters to match against the
 122 *      rate_table parameters and ajust them if necessary.
 123 */
 124struct rockchip_pll_clock {
 125        unsigned int            id;
 126        const char              *name;
 127        const char              *const *parent_names;
 128        u8                      num_parents;
 129        unsigned long           flags;
 130        int                     con_offset;
 131        int                     mode_offset;
 132        int                     mode_shift;
 133        int                     lock_shift;
 134        enum rockchip_pll_type  type;
 135        u8                      pll_flags;
 136        struct rockchip_pll_rate_table *rate_table;
 137};
 138
 139#define ROCKCHIP_PLL_SYNC_RATE          BIT(0)
 140
 141#define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift,   \
 142                _lshift, _pflags, _rtable)                              \
 143        {                                                               \
 144                .id             = _id,                                  \
 145                .type           = _type,                                \
 146                .name           = _name,                                \
 147                .parent_names   = _pnames,                              \
 148                .num_parents    = ARRAY_SIZE(_pnames),                  \
 149                .flags          = CLK_GET_RATE_NOCACHE | _flags,        \
 150                .con_offset     = _con,                                 \
 151                .mode_offset    = _mode,                                \
 152                .mode_shift     = _mshift,                              \
 153                .lock_shift     = _lshift,                              \
 154                .pll_flags      = _pflags,                              \
 155                .rate_table     = _rtable,                              \
 156        }
 157
 158struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
 159                const char *name, const char *const *parent_names,
 160                u8 num_parents, void __iomem *base, int con_offset,
 161                int grf_lock_offset, int lock_shift, int reg_mode,
 162                int mode_shift, struct rockchip_pll_rate_table *rate_table,
 163                u8 clk_pll_flags, spinlock_t *lock);
 164
 165struct rockchip_cpuclk_clksel {
 166        int reg;
 167        u32 val;
 168};
 169
 170#define ROCKCHIP_CPUCLK_NUM_DIVIDERS    2
 171struct rockchip_cpuclk_rate_table {
 172        unsigned long prate;
 173        struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
 174};
 175
 176/**
 177 * struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
 178 * @core_reg:           register offset of the core settings register
 179 * @div_core_shift:     core divider offset used to divide the pll value
 180 * @div_core_mask:      core divider mask
 181 * @mux_core_shift:     offset of the core multiplexer
 182 */
 183struct rockchip_cpuclk_reg_data {
 184        int             core_reg;
 185        u8              div_core_shift;
 186        u32             div_core_mask;
 187        int             mux_core_reg;
 188        u8              mux_core_shift;
 189};
 190
 191struct clk *rockchip_clk_register_cpuclk(const char *name,
 192                        const char *const *parent_names, u8 num_parents,
 193                        const struct rockchip_cpuclk_reg_data *reg_data,
 194                        const struct rockchip_cpuclk_rate_table *rates,
 195                        int nrates, void __iomem *reg_base, spinlock_t *lock);
 196
 197struct clk *rockchip_clk_register_mmc(const char *name,
 198                                const char *const *parent_names, u8 num_parents,
 199                                void __iomem *reg, int shift);
 200
 201#define ROCKCHIP_INVERTER_HIWORD_MASK   BIT(0)
 202
 203struct clk *rockchip_clk_register_inverter(const char *name,
 204                                const char *const *parent_names, u8 num_parents,
 205                                void __iomem *reg, int shift, int flags,
 206                                spinlock_t *lock);
 207
 208#define PNAME(x) static const char *const x[] __initconst
 209
 210enum rockchip_clk_branch_type {
 211        branch_composite,
 212        branch_mux,
 213        branch_divider,
 214        branch_fraction_divider,
 215        branch_gate,
 216        branch_mmc,
 217        branch_inverter,
 218};
 219
 220struct rockchip_clk_branch {
 221        unsigned int                    id;
 222        enum rockchip_clk_branch_type   branch_type;
 223        const char                      *name;
 224        const char                      *const *parent_names;
 225        u8                              num_parents;
 226        unsigned long                   flags;
 227        int                             muxdiv_offset;
 228        u8                              mux_shift;
 229        u8                              mux_width;
 230        u8                              mux_flags;
 231        u8                              div_shift;
 232        u8                              div_width;
 233        u8                              div_flags;
 234        struct clk_div_table            *div_table;
 235        int                             gate_offset;
 236        u8                              gate_shift;
 237        u8                              gate_flags;
 238};
 239
 240#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
 241                  df, go, gs, gf)                               \
 242        {                                                       \
 243                .id             = _id,                          \
 244                .branch_type    = branch_composite,             \
 245                .name           = cname,                        \
 246                .parent_names   = pnames,                       \
 247                .num_parents    = ARRAY_SIZE(pnames),           \
 248                .flags          = f,                            \
 249                .muxdiv_offset  = mo,                           \
 250                .mux_shift      = ms,                           \
 251                .mux_width      = mw,                           \
 252                .mux_flags      = mf,                           \
 253                .div_shift      = ds,                           \
 254                .div_width      = dw,                           \
 255                .div_flags      = df,                           \
 256                .gate_offset    = go,                           \
 257                .gate_shift     = gs,                           \
 258                .gate_flags     = gf,                           \
 259        }
 260
 261#define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df,   \
 262                        go, gs, gf)                             \
 263        {                                                       \
 264                .id             = _id,                          \
 265                .branch_type    = branch_composite,             \
 266                .name           = cname,                        \
 267                .parent_names   = (const char *[]){ pname },    \
 268                .num_parents    = 1,                            \
 269                .flags          = f,                            \
 270                .muxdiv_offset  = mo,                           \
 271                .div_shift      = ds,                           \
 272                .div_width      = dw,                           \
 273                .div_flags      = df,                           \
 274                .gate_offset    = go,                           \
 275                .gate_shift     = gs,                           \
 276                .gate_flags     = gf,                           \
 277        }
 278
 279#define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\
 280                               df, dt, go, gs, gf)              \
 281        {                                                       \
 282                .id             = _id,                          \
 283                .branch_type    = branch_composite,             \
 284                .name           = cname,                        \
 285                .parent_names   = (const char *[]){ pname },    \
 286                .num_parents    = 1,                            \
 287                .flags          = f,                            \
 288                .muxdiv_offset  = mo,                           \
 289                .div_shift      = ds,                           \
 290                .div_width      = dw,                           \
 291                .div_flags      = df,                           \
 292                .div_table      = dt,                           \
 293                .gate_offset    = go,                           \
 294                .gate_shift     = gs,                           \
 295                .gate_flags     = gf,                           \
 296        }
 297
 298#define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf,  \
 299                        go, gs, gf)                             \
 300        {                                                       \
 301                .id             = _id,                          \
 302                .branch_type    = branch_composite,             \
 303                .name           = cname,                        \
 304                .parent_names   = pnames,                       \
 305                .num_parents    = ARRAY_SIZE(pnames),           \
 306                .flags          = f,                            \
 307                .muxdiv_offset  = mo,                           \
 308                .mux_shift      = ms,                           \
 309                .mux_width      = mw,                           \
 310                .mux_flags      = mf,                           \
 311                .gate_offset    = go,                           \
 312                .gate_shift     = gs,                           \
 313                .gate_flags     = gf,                           \
 314        }
 315
 316#define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \
 317                         ds, dw, df)                            \
 318        {                                                       \
 319                .id             = _id,                          \
 320                .branch_type    = branch_composite,             \
 321                .name           = cname,                        \
 322                .parent_names   = pnames,                       \
 323                .num_parents    = ARRAY_SIZE(pnames),           \
 324                .flags          = f,                            \
 325                .muxdiv_offset  = mo,                           \
 326                .mux_shift      = ms,                           \
 327                .mux_width      = mw,                           \
 328                .mux_flags      = mf,                           \
 329                .div_shift      = ds,                           \
 330                .div_width      = dw,                           \
 331                .div_flags      = df,                           \
 332                .gate_offset    = -1,                           \
 333        }
 334
 335#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms,  \
 336                                mw, mf, ds, dw, df, dt)         \
 337        {                                                       \
 338                .id             = _id,                          \
 339                .branch_type    = branch_composite,             \
 340                .name           = cname,                        \
 341                .parent_names   = pnames,                       \
 342                .num_parents    = ARRAY_SIZE(pnames),           \
 343                .flags          = f,                            \
 344                .muxdiv_offset  = mo,                           \
 345                .mux_shift      = ms,                           \
 346                .mux_width      = mw,                           \
 347                .mux_flags      = mf,                           \
 348                .div_shift      = ds,                           \
 349                .div_width      = dw,                           \
 350                .div_flags      = df,                           \
 351                .div_table      = dt,                           \
 352                .gate_offset    = -1,                           \
 353        }
 354
 355#define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
 356        {                                                       \
 357                .id             = _id,                          \
 358                .branch_type    = branch_fraction_divider,      \
 359                .name           = cname,                        \
 360                .parent_names   = (const char *[]){ pname },    \
 361                .num_parents    = 1,                            \
 362                .flags          = f,                            \
 363                .muxdiv_offset  = mo,                           \
 364                .div_shift      = 16,                           \
 365                .div_width      = 16,                           \
 366                .div_flags      = df,                           \
 367                .gate_offset    = go,                           \
 368                .gate_shift     = gs,                           \
 369                .gate_flags     = gf,                           \
 370        }
 371
 372#define MUX(_id, cname, pnames, f, o, s, w, mf)                 \
 373        {                                                       \
 374                .id             = _id,                          \
 375                .branch_type    = branch_mux,                   \
 376                .name           = cname,                        \
 377                .parent_names   = pnames,                       \
 378                .num_parents    = ARRAY_SIZE(pnames),           \
 379                .flags          = f,                            \
 380                .muxdiv_offset  = o,                            \
 381                .mux_shift      = s,                            \
 382                .mux_width      = w,                            \
 383                .mux_flags      = mf,                           \
 384                .gate_offset    = -1,                           \
 385        }
 386
 387#define DIV(_id, cname, pname, f, o, s, w, df)                  \
 388        {                                                       \
 389                .id             = _id,                          \
 390                .branch_type    = branch_divider,               \
 391                .name           = cname,                        \
 392                .parent_names   = (const char *[]){ pname },    \
 393                .num_parents    = 1,                            \
 394                .flags          = f,                            \
 395                .muxdiv_offset  = o,                            \
 396                .div_shift      = s,                            \
 397                .div_width      = w,                            \
 398                .div_flags      = df,                           \
 399                .gate_offset    = -1,                           \
 400        }
 401
 402#define DIVTBL(_id, cname, pname, f, o, s, w, df, dt)           \
 403        {                                                       \
 404                .id             = _id,                          \
 405                .branch_type    = branch_divider,               \
 406                .name           = cname,                        \
 407                .parent_names   = (const char *[]){ pname },    \
 408                .num_parents    = 1,                            \
 409                .flags          = f,                            \
 410                .muxdiv_offset  = o,                            \
 411                .div_shift      = s,                            \
 412                .div_width      = w,                            \
 413                .div_flags      = df,                           \
 414                .div_table      = dt,                           \
 415        }
 416
 417#define GATE(_id, cname, pname, f, o, b, gf)                    \
 418        {                                                       \
 419                .id             = _id,                          \
 420                .branch_type    = branch_gate,                  \
 421                .name           = cname,                        \
 422                .parent_names   = (const char *[]){ pname },    \
 423                .num_parents    = 1,                            \
 424                .flags          = f,                            \
 425                .gate_offset    = o,                            \
 426                .gate_shift     = b,                            \
 427                .gate_flags     = gf,                           \
 428        }
 429
 430#define MMC(_id, cname, pname, offset, shift)                   \
 431        {                                                       \
 432                .id             = _id,                          \
 433                .branch_type    = branch_mmc,                   \
 434                .name           = cname,                        \
 435                .parent_names   = (const char *[]){ pname },    \
 436                .num_parents    = 1,                            \
 437                .muxdiv_offset  = offset,                       \
 438                .div_shift      = shift,                        \
 439        }
 440
 441#define INVERTER(_id, cname, pname, io, is, if)                 \
 442        {                                                       \
 443                .id             = _id,                          \
 444                .branch_type    = branch_inverter,              \
 445                .name           = cname,                        \
 446                .parent_names   = (const char *[]){ pname },    \
 447                .num_parents    = 1,                            \
 448                .muxdiv_offset  = io,                           \
 449                .div_shift      = is,                           \
 450                .div_flags      = if,                           \
 451        }
 452
 453void rockchip_clk_init(struct device_node *np, void __iomem *base,
 454                       unsigned long nr_clks);
 455struct regmap *rockchip_clk_get_grf(void);
 456void rockchip_clk_add_lookup(struct clk *clk, unsigned int id);
 457void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
 458                                    unsigned int nr_clk);
 459void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
 460                                unsigned int nr_pll, int grf_lock_offset);
 461void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
 462                        const char *const *parent_names, u8 num_parents,
 463                        const struct rockchip_cpuclk_reg_data *reg_data,
 464                        const struct rockchip_cpuclk_rate_table *rates,
 465                        int nrates);
 466void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
 467void rockchip_register_restart_notifier(unsigned int reg);
 468
 469#define ROCKCHIP_SOFTRST_HIWORD_MASK    BIT(0)
 470
 471#ifdef CONFIG_RESET_CONTROLLER
 472void rockchip_register_softrst(struct device_node *np,
 473                               unsigned int num_regs,
 474                               void __iomem *base, u8 flags);
 475#else
 476static inline void rockchip_register_softrst(struct device_node *np,
 477                               unsigned int num_regs,
 478                               void __iomem *base, u8 flags)
 479{
 480}
 481#endif
 482
 483#endif
 484