uboot/drivers/clk/meson/gxbb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2018 - Beniamino Galvani <b.galvani@gmail.com>
   4 * (C) Copyright 2018 - BayLibre, SAS
   5 * Author: Neil Armstrong <narmstrong@baylibre.com>
   6 */
   7
   8#include <common.h>
   9#include <asm/arch/clock-gx.h>
  10#include <asm/io.h>
  11#include <clk-uclass.h>
  12#include <div64.h>
  13#include <dm.h>
  14#include <regmap.h>
  15#include <syscon.h>
  16#include <dt-bindings/clock/gxbb-clkc.h>
  17#include "clk_meson.h"
  18
  19/* This driver support only basic clock tree operations :
  20 * - Can calculate clock frequency on a limited tree
  21 * - Can Read muxes and basic dividers (0-based only)
  22 * - Can enable/disable gates with limited propagation
  23 * - Can reparent without propagation, only on muxes
  24 * - Can set rates without reparenting
  25 * This driver is adapted to what is actually supported by U-Boot
  26 */
  27
  28/* Only the clocks ids we don't want to expose, such as the internal muxes
  29 * and dividers of composite clocks, will remain defined here.
  30 */
  31#define CLKID_MPEG_SEL            10
  32#define CLKID_MPEG_DIV            11
  33#define CLKID_SAR_ADC_DIV         99
  34#define CLKID_MALI_0_DIV          101
  35#define CLKID_MALI_1_DIV          104
  36#define CLKID_CTS_AMCLK_SEL       108
  37#define CLKID_CTS_AMCLK_DIV       109
  38#define CLKID_CTS_MCLK_I958_SEL   111
  39#define CLKID_CTS_MCLK_I958_DIV   112
  40#define CLKID_32K_CLK_SEL         115
  41#define CLKID_32K_CLK_DIV         116
  42#define CLKID_SD_EMMC_A_CLK0_SEL  117
  43#define CLKID_SD_EMMC_A_CLK0_DIV  118
  44#define CLKID_SD_EMMC_B_CLK0_SEL  120
  45#define CLKID_SD_EMMC_B_CLK0_DIV  121
  46#define CLKID_SD_EMMC_C_CLK0_SEL  123
  47#define CLKID_SD_EMMC_C_CLK0_DIV  124
  48#define CLKID_VPU_0_DIV           127
  49#define CLKID_VPU_1_DIV           130
  50#define CLKID_VAPB_0_DIV          134
  51#define CLKID_VAPB_1_DIV          137
  52#define CLKID_HDMI_PLL_PRE_MULT   141
  53#define CLKID_MPLL0_DIV           142
  54#define CLKID_MPLL1_DIV           143
  55#define CLKID_MPLL2_DIV           144
  56#define CLKID_MPLL_PREDIV         145
  57#define CLKID_FCLK_DIV2_DIV       146
  58#define CLKID_FCLK_DIV3_DIV       147
  59#define CLKID_FCLK_DIV4_DIV       148
  60#define CLKID_FCLK_DIV5_DIV       149
  61#define CLKID_FCLK_DIV7_DIV       150
  62#define CLKID_VDEC_1_SEL          151
  63#define CLKID_VDEC_1_DIV          152
  64#define CLKID_VDEC_HEVC_SEL       154
  65#define CLKID_VDEC_HEVC_DIV       155
  66
  67#define XTAL_RATE 24000000
  68
  69struct meson_clk {
  70        struct regmap *map;
  71};
  72
  73static ulong meson_div_get_rate(struct clk *clk, unsigned long id);
  74static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
  75                                ulong current_rate);
  76static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
  77                                  unsigned long parent_id);
  78static ulong meson_mux_get_rate(struct clk *clk, unsigned long id);
  79static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
  80                                      ulong rate, ulong current_rate);
  81static ulong meson_mux_get_parent(struct clk *clk, unsigned long id);
  82static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id);
  83
  84static struct meson_gate gates[] = {
  85        /* Everything Else (EE) domain gates */
  86        MESON_GATE(CLKID_DDR, HHI_GCLK_MPEG0, 0),
  87        MESON_GATE(CLKID_DOS, HHI_GCLK_MPEG0, 1),
  88        MESON_GATE(CLKID_ISA, HHI_GCLK_MPEG0, 5),
  89        MESON_GATE(CLKID_PL301, HHI_GCLK_MPEG0, 6),
  90        MESON_GATE(CLKID_PERIPHS, HHI_GCLK_MPEG0, 7),
  91        MESON_GATE(CLKID_SPICC, HHI_GCLK_MPEG0, 8),
  92        MESON_GATE(CLKID_I2C, HHI_GCLK_MPEG0, 9),
  93        MESON_GATE(CLKID_SAR_ADC, HHI_GCLK_MPEG0, 10),
  94        MESON_GATE(CLKID_SMART_CARD, HHI_GCLK_MPEG0, 11),
  95        MESON_GATE(CLKID_RNG0, HHI_GCLK_MPEG0, 12),
  96        MESON_GATE(CLKID_UART0, HHI_GCLK_MPEG0, 13),
  97        MESON_GATE(CLKID_SDHC, HHI_GCLK_MPEG0, 14),
  98        MESON_GATE(CLKID_STREAM, HHI_GCLK_MPEG0, 15),
  99        MESON_GATE(CLKID_ASYNC_FIFO, HHI_GCLK_MPEG0, 16),
 100        MESON_GATE(CLKID_SDIO, HHI_GCLK_MPEG0, 17),
 101        MESON_GATE(CLKID_ABUF, HHI_GCLK_MPEG0, 18),
 102        MESON_GATE(CLKID_HIU_IFACE, HHI_GCLK_MPEG0, 19),
 103        MESON_GATE(CLKID_ASSIST_MISC, HHI_GCLK_MPEG0, 23),
 104        MESON_GATE(CLKID_SD_EMMC_A, HHI_GCLK_MPEG0, 24),
 105        MESON_GATE(CLKID_SD_EMMC_B, HHI_GCLK_MPEG0, 25),
 106        MESON_GATE(CLKID_SD_EMMC_C, HHI_GCLK_MPEG0, 26),
 107        MESON_GATE(CLKID_SPI, HHI_GCLK_MPEG0, 30),
 108
 109        MESON_GATE(CLKID_I2S_SPDIF, HHI_GCLK_MPEG1, 2),
 110        MESON_GATE(CLKID_ETH, HHI_GCLK_MPEG1, 3),
 111        MESON_GATE(CLKID_DEMUX, HHI_GCLK_MPEG1, 4),
 112        MESON_GATE(CLKID_AIU_GLUE, HHI_GCLK_MPEG1, 6),
 113        MESON_GATE(CLKID_IEC958, HHI_GCLK_MPEG1, 7),
 114        MESON_GATE(CLKID_I2S_OUT, HHI_GCLK_MPEG1, 8),
 115        MESON_GATE(CLKID_AMCLK, HHI_GCLK_MPEG1, 9),
 116        MESON_GATE(CLKID_AIFIFO2, HHI_GCLK_MPEG1, 10),
 117        MESON_GATE(CLKID_MIXER, HHI_GCLK_MPEG1, 11),
 118        MESON_GATE(CLKID_MIXER_IFACE, HHI_GCLK_MPEG1, 12),
 119        MESON_GATE(CLKID_ADC, HHI_GCLK_MPEG1, 13),
 120        MESON_GATE(CLKID_BLKMV, HHI_GCLK_MPEG1, 14),
 121        MESON_GATE(CLKID_AIU, HHI_GCLK_MPEG1, 15),
 122        MESON_GATE(CLKID_UART1, HHI_GCLK_MPEG1, 16),
 123        MESON_GATE(CLKID_G2D, HHI_GCLK_MPEG1, 20),
 124        MESON_GATE(CLKID_USB0, HHI_GCLK_MPEG1, 21),
 125        MESON_GATE(CLKID_USB1, HHI_GCLK_MPEG1, 22),
 126        MESON_GATE(CLKID_RESET, HHI_GCLK_MPEG1, 23),
 127        MESON_GATE(CLKID_NAND, HHI_GCLK_MPEG1, 24),
 128        MESON_GATE(CLKID_DOS_PARSER, HHI_GCLK_MPEG1, 25),
 129        MESON_GATE(CLKID_USB, HHI_GCLK_MPEG1, 26),
 130        MESON_GATE(CLKID_VDIN1, HHI_GCLK_MPEG1, 28),
 131        MESON_GATE(CLKID_AHB_ARB0, HHI_GCLK_MPEG1, 29),
 132        MESON_GATE(CLKID_EFUSE, HHI_GCLK_MPEG1, 30),
 133        MESON_GATE(CLKID_BOOT_ROM, HHI_GCLK_MPEG1, 31),
 134
 135        MESON_GATE(CLKID_AHB_DATA_BUS, HHI_GCLK_MPEG2, 1),
 136        MESON_GATE(CLKID_AHB_CTRL_BUS, HHI_GCLK_MPEG2, 2),
 137        MESON_GATE(CLKID_HDMI_INTR_SYNC, HHI_GCLK_MPEG2, 3),
 138        MESON_GATE(CLKID_HDMI_PCLK, HHI_GCLK_MPEG2, 4),
 139        MESON_GATE(CLKID_USB1_DDR_BRIDGE, HHI_GCLK_MPEG2, 8),
 140        MESON_GATE(CLKID_USB0_DDR_BRIDGE, HHI_GCLK_MPEG2, 9),
 141        MESON_GATE(CLKID_MMC_PCLK, HHI_GCLK_MPEG2, 11),
 142        MESON_GATE(CLKID_DVIN, HHI_GCLK_MPEG2, 12),
 143        MESON_GATE(CLKID_UART2, HHI_GCLK_MPEG2, 15),
 144        MESON_GATE(CLKID_SANA, HHI_GCLK_MPEG2, 22),
 145        MESON_GATE(CLKID_VPU_INTR, HHI_GCLK_MPEG2, 25),
 146        MESON_GATE(CLKID_SEC_AHB_AHB3_BRIDGE, HHI_GCLK_MPEG2, 26),
 147        MESON_GATE(CLKID_CLK81_A53, HHI_GCLK_MPEG2, 29),
 148
 149        MESON_GATE(CLKID_VCLK2_VENCI0, HHI_GCLK_OTHER, 1),
 150        MESON_GATE(CLKID_VCLK2_VENCI1, HHI_GCLK_OTHER, 2),
 151        MESON_GATE(CLKID_VCLK2_VENCP0, HHI_GCLK_OTHER, 3),
 152        MESON_GATE(CLKID_VCLK2_VENCP1, HHI_GCLK_OTHER, 4),
 153        MESON_GATE(CLKID_GCLK_VENCI_INT0, HHI_GCLK_OTHER, 8),
 154        MESON_GATE(CLKID_DAC_CLK, HHI_GCLK_OTHER, 10),
 155        MESON_GATE(CLKID_AOCLK_GATE, HHI_GCLK_OTHER, 14),
 156        MESON_GATE(CLKID_IEC958_GATE, HHI_GCLK_OTHER, 16),
 157        MESON_GATE(CLKID_ENC480P, HHI_GCLK_OTHER, 20),
 158        MESON_GATE(CLKID_RNG1, HHI_GCLK_OTHER, 21),
 159        MESON_GATE(CLKID_GCLK_VENCI_INT1, HHI_GCLK_OTHER, 22),
 160        MESON_GATE(CLKID_VCLK2_VENCLMCC, HHI_GCLK_OTHER, 24),
 161        MESON_GATE(CLKID_VCLK2_VENCL, HHI_GCLK_OTHER, 25),
 162        MESON_GATE(CLKID_VCLK_OTHER, HHI_GCLK_OTHER, 26),
 163        MESON_GATE(CLKID_EDP, HHI_GCLK_OTHER, 31),
 164
 165        /* Always On (AO) domain gates */
 166        MESON_GATE(CLKID_AO_MEDIA_CPU, HHI_GCLK_AO, 0),
 167        MESON_GATE(CLKID_AO_AHB_SRAM, HHI_GCLK_AO, 1),
 168        MESON_GATE(CLKID_AO_AHB_BUS, HHI_GCLK_AO, 2),
 169        MESON_GATE(CLKID_AO_IFACE, HHI_GCLK_AO, 3),
 170        MESON_GATE(CLKID_AO_I2C, HHI_GCLK_AO, 4),
 171
 172        /* PLL Gates */
 173        /* CLKID_FCLK_DIV2 is critical for the SCPI Processor */
 174        MESON_GATE(CLKID_FCLK_DIV3, HHI_MPLL_CNTL6, 28),
 175        MESON_GATE(CLKID_FCLK_DIV4, HHI_MPLL_CNTL6, 29),
 176        MESON_GATE(CLKID_FCLK_DIV5, HHI_MPLL_CNTL6, 30),
 177        MESON_GATE(CLKID_FCLK_DIV7, HHI_MPLL_CNTL6, 31),
 178        MESON_GATE(CLKID_MPLL0, HHI_MPLL_CNTL7, 14),
 179        MESON_GATE(CLKID_MPLL1, HHI_MPLL_CNTL8, 14),
 180        MESON_GATE(CLKID_MPLL2, HHI_MPLL_CNTL9, 14),
 181        /* CLKID_CLK81 is critical for the system */
 182
 183        /* Peripheral Gates */
 184        MESON_GATE(CLKID_SAR_ADC_CLK, HHI_SAR_CLK_CNTL, 8),
 185        MESON_GATE(CLKID_SD_EMMC_A_CLK0, HHI_SD_EMMC_CLK_CNTL, 7),
 186        MESON_GATE(CLKID_SD_EMMC_B_CLK0, HHI_SD_EMMC_CLK_CNTL, 23),
 187        MESON_GATE(CLKID_SD_EMMC_C_CLK0, HHI_NAND_CLK_CNTL, 7),
 188        MESON_GATE(CLKID_VPU_0, HHI_VPU_CLK_CNTL, 8),
 189        MESON_GATE(CLKID_VPU_1, HHI_VPU_CLK_CNTL, 24),
 190        MESON_GATE(CLKID_VAPB_0, HHI_VAPBCLK_CNTL, 8),
 191        MESON_GATE(CLKID_VAPB_1, HHI_VAPBCLK_CNTL, 24),
 192        MESON_GATE(CLKID_VAPB, HHI_VAPBCLK_CNTL, 30),
 193};
 194
 195static int meson_set_gate_by_id(struct clk *clk, unsigned long id, bool on)
 196{
 197        struct meson_clk *priv = dev_get_priv(clk->dev);
 198        struct meson_gate *gate;
 199
 200        debug("%s: %sabling %ld\n", __func__, on ? "en" : "dis", id);
 201
 202        /* Propagate through muxes */
 203        switch (id) {
 204        case CLKID_VPU:
 205                return meson_set_gate_by_id(clk,
 206                                meson_mux_get_parent(clk, CLKID_VPU), on);
 207        case CLKID_VAPB_SEL:
 208                return meson_set_gate_by_id(clk,
 209                                meson_mux_get_parent(clk, CLKID_VAPB_SEL), on);
 210        }
 211
 212        if (id >= ARRAY_SIZE(gates))
 213                return -ENOENT;
 214
 215        gate = &gates[id];
 216
 217        if (gate->reg == 0)
 218                return 0;
 219
 220        debug("%s: really %sabling %ld\n", __func__, on ? "en" : "dis", id);
 221
 222        regmap_update_bits(priv->map, gate->reg,
 223                           BIT(gate->bit), on ? BIT(gate->bit) : 0);
 224
 225        /* Propagate to next gate(s) */
 226        switch (id) {
 227        case CLKID_VAPB:
 228                return meson_set_gate_by_id(clk, CLKID_VAPB_SEL, on);
 229        }
 230
 231        return 0;
 232}
 233
 234static int meson_clk_enable(struct clk *clk)
 235{
 236        return meson_set_gate_by_id(clk, clk->id, true);
 237}
 238
 239static int meson_clk_disable(struct clk *clk)
 240{
 241        return meson_set_gate_by_id(clk, clk->id, false);
 242}
 243
 244static struct parm meson_vpu_0_div_parm = {
 245        HHI_VPU_CLK_CNTL, 0, 7,
 246};
 247
 248int meson_vpu_0_div_parent = CLKID_VPU_0_SEL;
 249
 250static struct parm meson_vpu_1_div_parm = {
 251        HHI_VPU_CLK_CNTL, 16, 7,
 252};
 253
 254int meson_vpu_1_div_parent = CLKID_VPU_1_SEL;
 255
 256static struct parm meson_vapb_0_div_parm = {
 257        HHI_VAPBCLK_CNTL, 0, 7,
 258};
 259
 260int meson_vapb_0_div_parent = CLKID_VAPB_0_SEL;
 261
 262static struct parm meson_vapb_1_div_parm = {
 263        HHI_VAPBCLK_CNTL, 16, 7,
 264};
 265
 266int meson_vapb_1_div_parent = CLKID_VAPB_1_SEL;
 267
 268static ulong meson_div_get_rate(struct clk *clk, unsigned long id)
 269{
 270        struct meson_clk *priv = dev_get_priv(clk->dev);
 271        unsigned int rate, parent_rate;
 272        struct parm *parm;
 273        int parent;
 274        uint reg;
 275
 276        switch (id) {
 277        case CLKID_VPU_0_DIV:
 278                parm = &meson_vpu_0_div_parm;
 279                parent = meson_vpu_0_div_parent;
 280                break;
 281        case CLKID_VPU_1_DIV:
 282                parm = &meson_vpu_1_div_parm;
 283                parent = meson_vpu_1_div_parent;
 284                break;
 285        case CLKID_VAPB_0_DIV:
 286                parm = &meson_vapb_0_div_parm;
 287                parent = meson_vapb_0_div_parent;
 288                break;
 289        case CLKID_VAPB_1_DIV:
 290                parm = &meson_vapb_1_div_parm;
 291                parent = meson_vapb_1_div_parent;
 292                break;
 293        default:
 294                return -ENOENT;
 295        }
 296
 297        regmap_read(priv->map, parm->reg_off, &reg);
 298        reg = PARM_GET(parm->width, parm->shift, reg);
 299
 300        debug("%s: div of %ld is %d\n", __func__, id, reg + 1);
 301
 302        parent_rate = meson_clk_get_rate_by_id(clk, parent);
 303        if (IS_ERR_VALUE(parent_rate))
 304                return parent_rate;
 305
 306        debug("%s: parent rate of %ld is %d\n", __func__, id, parent_rate);
 307
 308        rate = parent_rate / (reg + 1);
 309
 310        debug("%s: rate of %ld is %d\n", __func__, id, rate);
 311
 312        return rate;
 313}
 314
 315static ulong meson_div_set_rate(struct clk *clk, unsigned long id, ulong rate,
 316                                ulong current_rate)
 317{
 318        struct meson_clk *priv = dev_get_priv(clk->dev);
 319        unsigned int new_div = -EINVAL;
 320        unsigned long parent_rate;
 321        struct parm *parm;
 322        int parent;
 323        int ret;
 324
 325        if (current_rate == rate)
 326                return 0;
 327
 328        debug("%s: setting rate of %ld from %ld to %ld\n",
 329              __func__, id, current_rate, rate);
 330
 331        switch (id) {
 332        case CLKID_VPU_0_DIV:
 333                parm = &meson_vpu_0_div_parm;
 334                parent = meson_vpu_0_div_parent;
 335                break;
 336        case CLKID_VPU_1_DIV:
 337                parm = &meson_vpu_1_div_parm;
 338                parent = meson_vpu_1_div_parent;
 339                break;
 340        case CLKID_VAPB_0_DIV:
 341                parm = &meson_vapb_0_div_parm;
 342                parent = meson_vapb_0_div_parent;
 343                break;
 344        case CLKID_VAPB_1_DIV:
 345                parm = &meson_vapb_1_div_parm;
 346                parent = meson_vapb_1_div_parent;
 347                break;
 348        default:
 349                return -ENOENT;
 350        }
 351
 352        parent_rate = meson_clk_get_rate_by_id(clk, parent);
 353        if (IS_ERR_VALUE(parent_rate))
 354                return parent_rate;
 355
 356        debug("%s: parent rate of %ld is %ld\n", __func__, id, parent_rate);
 357
 358        /* If can't divide, set parent instead */
 359        if (!parent_rate || rate > parent_rate)
 360                return meson_clk_set_rate_by_id(clk, parent, rate,
 361                                                current_rate);
 362
 363        new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
 364
 365        debug("%s: new div of %ld is %d\n", __func__, id, new_div);
 366
 367        /* If overflow, try to set parent rate and retry */
 368        if (!new_div || new_div > (1 << parm->width)) {
 369                ret = meson_clk_set_rate_by_id(clk, parent, rate, current_rate);
 370                if (IS_ERR_VALUE(ret))
 371                        return ret;
 372
 373                parent_rate = meson_clk_get_rate_by_id(clk, parent);
 374                if (IS_ERR_VALUE(parent_rate))
 375                        return parent_rate;
 376
 377                new_div = DIV_ROUND_CLOSEST(parent_rate, rate);
 378
 379                debug("%s: new new div of %ld is %d\n", __func__, id, new_div);
 380
 381                if (!new_div || new_div > (1 << parm->width))
 382                        return -EINVAL;
 383        }
 384
 385        debug("%s: setting div of %ld to %d\n", __func__, id, new_div);
 386
 387        regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
 388                           (new_div - 1) << parm->shift);
 389
 390        debug("%s: new rate of %ld is %ld\n",
 391              __func__, id, meson_div_get_rate(clk, id));
 392
 393        return 0;
 394}
 395
 396static struct parm meson_vpu_mux_parm = {
 397        HHI_VPU_CLK_CNTL, 31, 1,
 398};
 399
 400int meson_vpu_mux_parents[] = {
 401        CLKID_VPU_0,
 402        CLKID_VPU_1,
 403};
 404
 405static struct parm meson_vpu_0_mux_parm = {
 406        HHI_VPU_CLK_CNTL, 9, 2,
 407};
 408
 409static struct parm meson_vpu_1_mux_parm = {
 410        HHI_VPU_CLK_CNTL, 25, 2,
 411};
 412
 413static int meson_vpu_0_1_mux_parents[] = {
 414        CLKID_FCLK_DIV4,
 415        CLKID_FCLK_DIV3,
 416        CLKID_FCLK_DIV5,
 417        CLKID_FCLK_DIV7,
 418};
 419
 420static struct parm meson_vapb_sel_mux_parm = {
 421        HHI_VAPBCLK_CNTL, 31, 1,
 422};
 423
 424int meson_vapb_sel_mux_parents[] = {
 425        CLKID_VAPB_0,
 426        CLKID_VAPB_1,
 427};
 428
 429static struct parm meson_vapb_0_mux_parm = {
 430        HHI_VAPBCLK_CNTL, 9, 2,
 431};
 432
 433static struct parm meson_vapb_1_mux_parm = {
 434        HHI_VAPBCLK_CNTL, 25, 2,
 435};
 436
 437static int meson_vapb_0_1_mux_parents[] = {
 438        CLKID_FCLK_DIV4,
 439        CLKID_FCLK_DIV3,
 440        CLKID_FCLK_DIV5,
 441        CLKID_FCLK_DIV7,
 442};
 443
 444static ulong meson_mux_get_parent(struct clk *clk, unsigned long id)
 445{
 446        struct meson_clk *priv = dev_get_priv(clk->dev);
 447        struct parm *parm;
 448        int *parents;
 449        uint reg;
 450
 451        switch (id) {
 452        case CLKID_VPU:
 453                parm = &meson_vpu_mux_parm;
 454                parents = meson_vpu_mux_parents;
 455                break;
 456        case CLKID_VPU_0_SEL:
 457                parm = &meson_vpu_0_mux_parm;
 458                parents = meson_vpu_0_1_mux_parents;
 459                break;
 460        case CLKID_VPU_1_SEL:
 461                parm = &meson_vpu_1_mux_parm;
 462                parents = meson_vpu_0_1_mux_parents;
 463                break;
 464        case CLKID_VAPB_SEL:
 465                parm = &meson_vapb_sel_mux_parm;
 466                parents = meson_vapb_sel_mux_parents;
 467                break;
 468        case CLKID_VAPB_0_SEL:
 469                parm = &meson_vapb_0_mux_parm;
 470                parents = meson_vapb_0_1_mux_parents;
 471                break;
 472        case CLKID_VAPB_1_SEL:
 473                parm = &meson_vapb_1_mux_parm;
 474                parents = meson_vapb_0_1_mux_parents;
 475                break;
 476        default:
 477                return -ENOENT;
 478        }
 479
 480        regmap_read(priv->map, parm->reg_off, &reg);
 481        reg = PARM_GET(parm->width, parm->shift, reg);
 482
 483        debug("%s: parent of %ld is %d (%d)\n",
 484              __func__, id, parents[reg], reg);
 485
 486        return parents[reg];
 487}
 488
 489static ulong meson_mux_set_parent(struct clk *clk, unsigned long id,
 490                                  unsigned long parent_id)
 491{
 492        unsigned long cur_parent = meson_mux_get_parent(clk, id);
 493        struct meson_clk *priv = dev_get_priv(clk->dev);
 494        unsigned int new_index = -EINVAL;
 495        struct parm *parm;
 496        int *parents;
 497        int i;
 498
 499        if (IS_ERR_VALUE(cur_parent))
 500                return cur_parent;
 501
 502        debug("%s: setting parent of %ld from %ld to %ld\n",
 503              __func__, id, cur_parent, parent_id);
 504
 505        if (cur_parent == parent_id)
 506                return 0;
 507
 508        switch (id) {
 509        case CLKID_VPU:
 510                parm = &meson_vpu_mux_parm;
 511                parents = meson_vpu_mux_parents;
 512                break;
 513        case CLKID_VPU_0_SEL:
 514                parm = &meson_vpu_0_mux_parm;
 515                parents = meson_vpu_0_1_mux_parents;
 516                break;
 517        case CLKID_VPU_1_SEL:
 518                parm = &meson_vpu_1_mux_parm;
 519                parents = meson_vpu_0_1_mux_parents;
 520                break;
 521        case CLKID_VAPB_SEL:
 522                parm = &meson_vapb_sel_mux_parm;
 523                parents = meson_vapb_sel_mux_parents;
 524                break;
 525        case CLKID_VAPB_0_SEL:
 526                parm = &meson_vapb_0_mux_parm;
 527                parents = meson_vapb_0_1_mux_parents;
 528                break;
 529        case CLKID_VAPB_1_SEL:
 530                parm = &meson_vapb_1_mux_parm;
 531                parents = meson_vapb_0_1_mux_parents;
 532                break;
 533        default:
 534                /* Not a mux */
 535                return -ENOENT;
 536        }
 537
 538        for (i = 0 ; i < (1 << parm->width) ; ++i) {
 539                if (parents[i] == parent_id)
 540                        new_index = i;
 541        }
 542
 543        if (IS_ERR_VALUE(new_index))
 544                return new_index;
 545
 546        debug("%s: new index of %ld is %d\n", __func__, id, new_index);
 547
 548        regmap_update_bits(priv->map, parm->reg_off, SETPMASK(parm->width, parm->shift),
 549                           new_index << parm->shift);
 550
 551        debug("%s: new parent of %ld is %ld\n",
 552              __func__, id, meson_mux_get_parent(clk, id));
 553
 554        return 0;
 555}
 556
 557static ulong meson_mux_get_rate(struct clk *clk, unsigned long id)
 558{
 559        int parent = meson_mux_get_parent(clk, id);
 560
 561        if (IS_ERR_VALUE(parent))
 562                return parent;
 563
 564        return meson_clk_get_rate_by_id(clk, parent);
 565}
 566
 567static unsigned long meson_clk81_get_rate(struct clk *clk)
 568{
 569        struct meson_clk *priv = dev_get_priv(clk->dev);
 570        unsigned long parent_rate;
 571        uint reg;
 572        int parents[] = {
 573                -1,
 574                -1,
 575                CLKID_FCLK_DIV7,
 576                CLKID_MPLL1,
 577                CLKID_MPLL2,
 578                CLKID_FCLK_DIV4,
 579                CLKID_FCLK_DIV3,
 580                CLKID_FCLK_DIV5
 581        };
 582
 583        /* mux */
 584        regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
 585        reg = (reg >> 12) & 7;
 586
 587        switch (reg) {
 588        case 0:
 589                parent_rate = XTAL_RATE;
 590                break;
 591        case 1:
 592                return -ENOENT;
 593        default:
 594                parent_rate = meson_clk_get_rate_by_id(clk, parents[reg]);
 595        }
 596
 597        /* divider */
 598        regmap_read(priv->map, HHI_MPEG_CLK_CNTL, &reg);
 599        reg = reg & ((1 << 7) - 1);
 600
 601        /* clk81 divider is zero based */
 602        return parent_rate / (reg + 1);
 603}
 604
 605static long mpll_rate_from_params(unsigned long parent_rate,
 606                                  unsigned long sdm,
 607                                  unsigned long n2)
 608{
 609        unsigned long divisor = (SDM_DEN * n2) + sdm;
 610
 611        if (n2 < N2_MIN)
 612                return -EINVAL;
 613
 614        return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
 615}
 616
 617static struct parm meson_mpll0_parm[3] = {
 618        {HHI_MPLL_CNTL7, 0, 14}, /* psdm */
 619        {HHI_MPLL_CNTL7, 16, 9}, /* pn2 */
 620};
 621
 622static struct parm meson_mpll1_parm[3] = {
 623        {HHI_MPLL_CNTL8, 0, 14}, /* psdm */
 624        {HHI_MPLL_CNTL8, 16, 9}, /* pn2 */
 625};
 626
 627static struct parm meson_mpll2_parm[3] = {
 628        {HHI_MPLL_CNTL9, 0, 14}, /* psdm */
 629        {HHI_MPLL_CNTL9, 16, 9}, /* pn2 */
 630};
 631
 632/*
 633 * MultiPhase Locked Loops are outputs from a PLL with additional frequency
 634 * scaling capabilities. MPLL rates are calculated as:
 635 *
 636 * f(N2_integer, SDM_IN ) = 2.0G/(N2_integer + SDM_IN/16384)
 637 */
 638static ulong meson_mpll_get_rate(struct clk *clk, unsigned long id)
 639{
 640        struct meson_clk *priv = dev_get_priv(clk->dev);
 641        struct parm *psdm, *pn2;
 642        unsigned long sdm, n2;
 643        unsigned long parent_rate;
 644        uint reg;
 645
 646        switch (id) {
 647        case CLKID_MPLL0:
 648                psdm = &meson_mpll0_parm[0];
 649                pn2 = &meson_mpll0_parm[1];
 650                break;
 651        case CLKID_MPLL1:
 652                psdm = &meson_mpll1_parm[0];
 653                pn2 = &meson_mpll1_parm[1];
 654                break;
 655        case CLKID_MPLL2:
 656                psdm = &meson_mpll2_parm[0];
 657                pn2 = &meson_mpll2_parm[1];
 658                break;
 659        default:
 660                return -ENOENT;
 661        }
 662
 663        parent_rate = meson_clk_get_rate_by_id(clk, CLKID_FIXED_PLL);
 664        if (IS_ERR_VALUE(parent_rate))
 665                return parent_rate;
 666
 667        regmap_read(priv->map, psdm->reg_off, &reg);
 668        sdm = PARM_GET(psdm->width, psdm->shift, reg);
 669
 670        regmap_read(priv->map, pn2->reg_off, &reg);
 671        n2 = PARM_GET(pn2->width, pn2->shift, reg);
 672
 673        return mpll_rate_from_params(parent_rate, sdm, n2);
 674}
 675
 676static struct parm meson_fixed_pll_parm[3] = {
 677        {HHI_MPLL_CNTL, 0, 9}, /* pm */
 678        {HHI_MPLL_CNTL, 9, 5}, /* pn */
 679        {HHI_MPLL_CNTL, 16, 2}, /* pod */
 680};
 681
 682static struct parm meson_sys_pll_parm[3] = {
 683        {HHI_SYS_PLL_CNTL, 0, 9}, /* pm */
 684        {HHI_SYS_PLL_CNTL, 9, 5}, /* pn */
 685        {HHI_SYS_PLL_CNTL, 10, 2}, /* pod */
 686};
 687
 688static ulong meson_pll_get_rate(struct clk *clk, unsigned long id)
 689{
 690        struct meson_clk *priv = dev_get_priv(clk->dev);
 691        struct parm *pm, *pn, *pod;
 692        unsigned long parent_rate_mhz = XTAL_RATE / 1000000;
 693        u16 n, m, od;
 694        uint reg;
 695
 696        switch (id) {
 697        case CLKID_FIXED_PLL:
 698                pm = &meson_fixed_pll_parm[0];
 699                pn = &meson_fixed_pll_parm[1];
 700                pod = &meson_fixed_pll_parm[2];
 701                break;
 702        case CLKID_SYS_PLL:
 703                pm = &meson_sys_pll_parm[0];
 704                pn = &meson_sys_pll_parm[1];
 705                pod = &meson_sys_pll_parm[2];
 706                break;
 707        default:
 708                return -ENOENT;
 709        }
 710
 711        regmap_read(priv->map, pn->reg_off, &reg);
 712        n = PARM_GET(pn->width, pn->shift, reg);
 713
 714        regmap_read(priv->map, pm->reg_off, &reg);
 715        m = PARM_GET(pm->width, pm->shift, reg);
 716
 717        regmap_read(priv->map, pod->reg_off, &reg);
 718        od = PARM_GET(pod->width, pod->shift, reg);
 719
 720        return ((parent_rate_mhz * m / n) >> od) * 1000000;
 721}
 722
 723static ulong meson_clk_get_rate_by_id(struct clk *clk, unsigned long id)
 724{
 725        ulong rate;
 726
 727        switch (id) {
 728        case CLKID_FIXED_PLL:
 729        case CLKID_SYS_PLL:
 730                rate = meson_pll_get_rate(clk, id);
 731                break;
 732        case CLKID_FCLK_DIV2:
 733                rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 2;
 734                break;
 735        case CLKID_FCLK_DIV3:
 736                rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 3;
 737                break;
 738        case CLKID_FCLK_DIV4:
 739                rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 4;
 740                break;
 741        case CLKID_FCLK_DIV5:
 742                rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 5;
 743                break;
 744        case CLKID_FCLK_DIV7:
 745                rate = meson_pll_get_rate(clk, CLKID_FIXED_PLL) / 7;
 746                break;
 747        case CLKID_MPLL0:
 748        case CLKID_MPLL1:
 749        case CLKID_MPLL2:
 750                rate = meson_mpll_get_rate(clk, id);
 751                break;
 752        case CLKID_CLK81:
 753                rate = meson_clk81_get_rate(clk);
 754                break;
 755        case CLKID_VPU_0:
 756                rate = meson_div_get_rate(clk, CLKID_VPU_0_DIV);
 757                break;
 758        case CLKID_VPU_1:
 759                rate = meson_div_get_rate(clk, CLKID_VPU_1_DIV);
 760                break;
 761        case CLKID_VAPB:
 762                rate = meson_mux_get_rate(clk, CLKID_VAPB_SEL);
 763                break;
 764        case CLKID_VAPB_0:
 765                rate = meson_div_get_rate(clk, CLKID_VAPB_0_DIV);
 766                break;
 767        case CLKID_VAPB_1:
 768                rate = meson_div_get_rate(clk, CLKID_VAPB_1_DIV);
 769                break;
 770        case CLKID_VPU_0_DIV:
 771        case CLKID_VPU_1_DIV:
 772        case CLKID_VAPB_0_DIV:
 773        case CLKID_VAPB_1_DIV:
 774                rate = meson_div_get_rate(clk, id);
 775                break;
 776        case CLKID_VPU:
 777        case CLKID_VPU_0_SEL:
 778        case CLKID_VPU_1_SEL:
 779        case CLKID_VAPB_SEL:
 780        case CLKID_VAPB_0_SEL:
 781        case CLKID_VAPB_1_SEL:
 782                rate = meson_mux_get_rate(clk, id);
 783                break;
 784        default:
 785                if (gates[id].reg != 0) {
 786                        /* a clock gate */
 787                        rate = meson_clk81_get_rate(clk);
 788                        break;
 789                }
 790                return -ENOENT;
 791        }
 792
 793        debug("clock %lu has rate %lu\n", id, rate);
 794        return rate;
 795}
 796
 797static ulong meson_clk_get_rate(struct clk *clk)
 798{
 799        return meson_clk_get_rate_by_id(clk, clk->id);
 800}
 801
 802static int meson_clk_set_parent(struct clk *clk, struct clk *parent)
 803{
 804        return meson_mux_set_parent(clk, clk->id, parent->id);
 805}
 806
 807static ulong meson_clk_set_rate_by_id(struct clk *clk, unsigned long id,
 808                                      ulong rate, ulong current_rate)
 809{
 810        if (current_rate == rate)
 811                return 0;
 812
 813        switch (id) {
 814        /* Fixed clocks */
 815        case CLKID_FIXED_PLL:
 816        case CLKID_SYS_PLL:
 817        case CLKID_FCLK_DIV2:
 818        case CLKID_FCLK_DIV3:
 819        case CLKID_FCLK_DIV4:
 820        case CLKID_FCLK_DIV5:
 821        case CLKID_FCLK_DIV7:
 822        case CLKID_MPLL0:
 823        case CLKID_MPLL1:
 824        case CLKID_MPLL2:
 825        case CLKID_CLK81:
 826                return -EINVAL;
 827        case CLKID_VPU:
 828                return meson_clk_set_rate_by_id(clk,
 829                                meson_mux_get_parent(clk, CLKID_VPU), rate,
 830                                                     current_rate);
 831        case CLKID_VAPB:
 832        case CLKID_VAPB_SEL:
 833                return meson_clk_set_rate_by_id(clk,
 834                                meson_mux_get_parent(clk, CLKID_VAPB_SEL),
 835                                rate, current_rate);
 836        case CLKID_VPU_0:
 837                return meson_div_set_rate(clk, CLKID_VPU_0_DIV, rate,
 838                                          current_rate);
 839        case CLKID_VPU_1:
 840                return meson_div_set_rate(clk, CLKID_VPU_1_DIV, rate,
 841                                          current_rate);
 842        case CLKID_VAPB_0:
 843                return meson_div_set_rate(clk, CLKID_VAPB_0_DIV, rate,
 844                                          current_rate);
 845        case CLKID_VAPB_1:
 846                return meson_div_set_rate(clk, CLKID_VAPB_1_DIV, rate,
 847                                          current_rate);
 848        case CLKID_VPU_0_DIV:
 849        case CLKID_VPU_1_DIV:
 850        case CLKID_VAPB_0_DIV:
 851        case CLKID_VAPB_1_DIV:
 852                return meson_div_set_rate(clk, id, rate, current_rate);
 853        default:
 854                return -ENOENT;
 855        }
 856
 857        return -EINVAL;
 858}
 859
 860static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
 861{
 862        ulong current_rate = meson_clk_get_rate_by_id(clk, clk->id);
 863        int ret;
 864
 865        if (IS_ERR_VALUE(current_rate))
 866                return current_rate;
 867
 868        debug("%s: setting rate of %ld from %ld to %ld\n",
 869              __func__, clk->id, current_rate, rate);
 870
 871        ret = meson_clk_set_rate_by_id(clk, clk->id, rate, current_rate);
 872        if (IS_ERR_VALUE(ret))
 873                return ret;
 874
 875        debug("clock %lu has new rate %lu\n", clk->id,
 876              meson_clk_get_rate_by_id(clk, clk->id));
 877
 878        return 0;
 879}
 880
 881static int meson_clk_probe(struct udevice *dev)
 882{
 883        struct meson_clk *priv = dev_get_priv(dev);
 884
 885        priv->map = syscon_node_to_regmap(dev_get_parent(dev)->node);
 886        if (IS_ERR(priv->map))
 887                return PTR_ERR(priv->map);
 888
 889        debug("meson-clk: probed\n");
 890
 891        return 0;
 892}
 893
 894static struct clk_ops meson_clk_ops = {
 895        .disable        = meson_clk_disable,
 896        .enable         = meson_clk_enable,
 897        .get_rate       = meson_clk_get_rate,
 898        .set_parent     = meson_clk_set_parent,
 899        .set_rate       = meson_clk_set_rate,
 900};
 901
 902static const struct udevice_id meson_clk_ids[] = {
 903        { .compatible = "amlogic,gxbb-clkc" },
 904        { .compatible = "amlogic,gxl-clkc" },
 905        { }
 906};
 907
 908U_BOOT_DRIVER(meson_clk) = {
 909        .name           = "meson_clk",
 910        .id             = UCLASS_CLK,
 911        .of_match       = meson_clk_ids,
 912        .priv_auto_alloc_size = sizeof(struct meson_clk),
 913        .ops            = &meson_clk_ops,
 914        .probe          = meson_clk_probe,
 915};
 916