linux/drivers/clk/hisilicon/clk-hi3559a.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Hisilicon Hi3559A clock driver
   4 *
   5 * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd.
   6 *
   7 * Author: Dongjiu Geng <gengdongjiu@huawei.com>
   8 */
   9
  10#include <linux/clk-provider.h>
  11#include <linux/module.h>
  12#include <linux/of_device.h>
  13#include <linux/platform_device.h>
  14#include <linux/slab.h>
  15
  16#include <dt-bindings/clock/hi3559av100-clock.h>
  17
  18#include "clk.h"
  19#include "crg.h"
  20#include "reset.h"
  21
  22#define CRG_BASE_ADDR  0x18020000
  23#define PLL_MASK_WIDTH 24
  24
  25struct hi3559av100_pll_clock {
  26        u32     id;
  27        const char      *name;
  28        const char      *parent_name;
  29        const u32       ctrl_reg1;
  30        const u8        frac_shift;
  31        const u8        frac_width;
  32        const u8        postdiv1_shift;
  33        const u8        postdiv1_width;
  34        const u8        postdiv2_shift;
  35        const u8        postdiv2_width;
  36        const u32       ctrl_reg2;
  37        const u8        fbdiv_shift;
  38        const u8        fbdiv_width;
  39        const u8        refdiv_shift;
  40        const u8        refdiv_width;
  41};
  42
  43struct hi3559av100_clk_pll {
  44        struct clk_hw   hw;
  45        u32     id;
  46        void __iomem    *ctrl_reg1;
  47        u8      frac_shift;
  48        u8      frac_width;
  49        u8      postdiv1_shift;
  50        u8      postdiv1_width;
  51        u8      postdiv2_shift;
  52        u8      postdiv2_width;
  53        void __iomem    *ctrl_reg2;
  54        u8      fbdiv_shift;
  55        u8      fbdiv_width;
  56        u8      refdiv_shift;
  57        u8      refdiv_width;
  58};
  59
  60/* soc clk config */
  61static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = {
  62        { HI3559AV100_FIXED_1188M, "1188m", NULL, 0, 1188000000, },
  63        { HI3559AV100_FIXED_1000M, "1000m", NULL, 0, 1000000000, },
  64        { HI3559AV100_FIXED_842M, "842m", NULL, 0, 842000000, },
  65        { HI3559AV100_FIXED_792M, "792m", NULL, 0, 792000000, },
  66        { HI3559AV100_FIXED_750M, "750m", NULL, 0, 750000000, },
  67        { HI3559AV100_FIXED_710M, "710m", NULL, 0, 710000000, },
  68        { HI3559AV100_FIXED_680M, "680m", NULL, 0, 680000000, },
  69        { HI3559AV100_FIXED_667M, "667m", NULL, 0, 667000000, },
  70        { HI3559AV100_FIXED_631M, "631m", NULL, 0, 631000000, },
  71        { HI3559AV100_FIXED_600M, "600m", NULL, 0, 600000000, },
  72        { HI3559AV100_FIXED_568M, "568m", NULL, 0, 568000000, },
  73        { HI3559AV100_FIXED_500M, "500m", NULL, 0, 500000000, },
  74        { HI3559AV100_FIXED_475M, "475m", NULL, 0, 475000000, },
  75        { HI3559AV100_FIXED_428M, "428m", NULL, 0, 428000000, },
  76        { HI3559AV100_FIXED_400M, "400m", NULL, 0, 400000000, },
  77        { HI3559AV100_FIXED_396M, "396m", NULL, 0, 396000000, },
  78        { HI3559AV100_FIXED_300M, "300m", NULL, 0, 300000000, },
  79        { HI3559AV100_FIXED_250M, "250m", NULL, 0, 250000000, },
  80        { HI3559AV100_FIXED_200M, "200m", NULL, 0, 200000000, },
  81        { HI3559AV100_FIXED_198M, "198m", NULL, 0, 198000000, },
  82        { HI3559AV100_FIXED_187p5M, "187p5m", NULL, 0, 187500000, },
  83        { HI3559AV100_FIXED_150M, "150m", NULL, 0, 150000000, },
  84        { HI3559AV100_FIXED_148p5M, "148p5m", NULL, 0, 1485000000, },
  85        { HI3559AV100_FIXED_125M, "125m", NULL, 0, 125000000, },
  86        { HI3559AV100_FIXED_107M, "107m", NULL, 0, 107000000, },
  87        { HI3559AV100_FIXED_100M, "100m", NULL, 0, 100000000, },
  88        { HI3559AV100_FIXED_99M, "99m", NULL, 0, 99000000, },
  89        { HI3559AV100_FIXED_75M, "75m", NULL, 0, 75000000, },
  90        { HI3559AV100_FIXED_74p25M, "74p25m", NULL, 0, 74250000, },
  91        { HI3559AV100_FIXED_72M, "72m", NULL, 0, 72000000, },
  92        { HI3559AV100_FIXED_60M, "60m", NULL, 0, 60000000, },
  93        { HI3559AV100_FIXED_54M, "54m", NULL, 0, 54000000, },
  94        { HI3559AV100_FIXED_50M, "50m", NULL, 0, 50000000, },
  95        { HI3559AV100_FIXED_49p5M, "49p5m", NULL, 0, 49500000, },
  96        { HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, },
  97        { HI3559AV100_FIXED_36M, "36m", NULL, 0, 36000000, },
  98        { HI3559AV100_FIXED_32p4M, "32p4m", NULL, 0, 32400000, },
  99        { HI3559AV100_FIXED_27M, "27m", NULL, 0, 27000000, },
 100        { HI3559AV100_FIXED_25M, "25m", NULL, 0, 25000000, },
 101        { HI3559AV100_FIXED_24M, "24m", NULL, 0, 24000000, },
 102        { HI3559AV100_FIXED_12M, "12m", NULL, 0, 12000000, },
 103        { HI3559AV100_FIXED_3M,  "3m", NULL, 0, 3000000, },
 104        { HI3559AV100_FIXED_1p6M, "1p6m", NULL, 0, 1600000, },
 105        { HI3559AV100_FIXED_400K, "400k", NULL, 0, 400000, },
 106        { HI3559AV100_FIXED_100K, "100k", NULL, 0, 100000, },
 107};
 108
 109
 110static const char *fmc_mux_p[] = {
 111        "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m"
 112};
 113
 114static const char *mmc_mux_p[] = {
 115        "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k"
 116};
 117
 118static const char *sysapb_mux_p[] = {
 119        "24m", "50m",
 120};
 121
 122static const char *sysbus_mux_p[] = {
 123        "24m", "300m"
 124};
 125
 126static const char *uart_mux_p[] = { "50m", "24m", "3m" };
 127
 128static const char *a73_clksel_mux_p[] = {
 129        "24m", "apll", "1000m"
 130};
 131
 132static const u32 fmc_mux_table[]        = { 0, 1, 2, 3, 4, 5, 6, 7 };
 133static const u32 mmc_mux_table[]        = { 0, 1, 2, 3, 4, 5, 6, 7 };
 134static const u32 sysapb_mux_table[]     = { 0, 1 };
 135static const u32 sysbus_mux_table[]     = { 0, 1 };
 136static const u32 uart_mux_table[]       = { 0, 1, 2 };
 137static const u32 a73_clksel_mux_table[] = { 0, 1, 2 };
 138
 139static struct hisi_mux_clock hi3559av100_mux_clks_crg[] = {
 140        {
 141                HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
 142                CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table,
 143        },
 144        {
 145                HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
 146                CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table,
 147        },
 148        {
 149                HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
 150                CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table,
 151        },
 152
 153        {
 154                HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
 155                CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table,
 156        },
 157
 158        {
 159                HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
 160                CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table,
 161        },
 162
 163        {
 164                HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p),
 165                CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table
 166        },
 167
 168        {
 169                HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p),
 170                CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table
 171        },
 172
 173        {
 174                HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
 175                CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table
 176        },
 177
 178        {
 179                HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p),
 180                CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table
 181        },
 182};
 183
 184static struct hisi_gate_clock hi3559av100_gate_clks[] = {
 185        {
 186                HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux",
 187                CLK_SET_RATE_PARENT, 0x170, 1, 0,
 188        },
 189        {
 190                HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux",
 191                CLK_SET_RATE_PARENT, 0x1a8, 28, 0,
 192        },
 193        {
 194                HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux",
 195                CLK_SET_RATE_PARENT, 0x1ec, 28, 0,
 196        },
 197        {
 198                HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux",
 199                CLK_SET_RATE_PARENT, 0x214, 28, 0,
 200        },
 201        {
 202                HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux",
 203                CLK_SET_RATE_PARENT, 0x23c, 28, 0,
 204        },
 205        {
 206                HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux",
 207                CLK_SET_RATE_PARENT, 0x198, 23, 0,
 208        },
 209        {
 210                HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux",
 211                CLK_SET_RATE_PARENT, 0x198, 24, 0,
 212        },
 213        {
 214                HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux",
 215                CLK_SET_RATE_PARENT, 0x198, 25, 0,
 216        },
 217        {
 218                HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux",
 219                CLK_SET_RATE_PARENT, 0x198, 26, 0,
 220        },
 221        {
 222                HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux",
 223                CLK_SET_RATE_PARENT, 0x198, 27, 0,
 224        },
 225        {
 226                HI3559AV100_ETH_CLK, "clk_eth", NULL,
 227                CLK_SET_RATE_PARENT, 0x0174, 1, 0,
 228        },
 229        {
 230                HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL,
 231                CLK_SET_RATE_PARENT, 0x0174, 5, 0,
 232        },
 233        {
 234                HI3559AV100_ETH1_CLK, "clk_eth1", NULL,
 235                CLK_SET_RATE_PARENT, 0x0174, 3, 0,
 236        },
 237        {
 238                HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL,
 239                CLK_SET_RATE_PARENT, 0x0174, 7, 0,
 240        },
 241        {
 242                HI3559AV100_I2C0_CLK, "clk_i2c0", "50m",
 243                CLK_SET_RATE_PARENT, 0x01a0, 16, 0,
 244        },
 245        {
 246                HI3559AV100_I2C1_CLK, "clk_i2c1", "50m",
 247                CLK_SET_RATE_PARENT, 0x01a0, 17, 0,
 248        },
 249        {
 250                HI3559AV100_I2C2_CLK, "clk_i2c2", "50m",
 251                CLK_SET_RATE_PARENT, 0x01a0, 18, 0,
 252        },
 253        {
 254                HI3559AV100_I2C3_CLK, "clk_i2c3", "50m",
 255                CLK_SET_RATE_PARENT, 0x01a0, 19, 0,
 256        },
 257        {
 258                HI3559AV100_I2C4_CLK, "clk_i2c4", "50m",
 259                CLK_SET_RATE_PARENT, 0x01a0, 20, 0,
 260        },
 261        {
 262                HI3559AV100_I2C5_CLK, "clk_i2c5", "50m",
 263                CLK_SET_RATE_PARENT, 0x01a0, 21, 0,
 264        },
 265        {
 266                HI3559AV100_I2C6_CLK, "clk_i2c6", "50m",
 267                CLK_SET_RATE_PARENT, 0x01a0, 22, 0,
 268        },
 269        {
 270                HI3559AV100_I2C7_CLK, "clk_i2c7", "50m",
 271                CLK_SET_RATE_PARENT, 0x01a0, 23, 0,
 272        },
 273        {
 274                HI3559AV100_I2C8_CLK, "clk_i2c8", "50m",
 275                CLK_SET_RATE_PARENT, 0x01a0, 24, 0,
 276        },
 277        {
 278                HI3559AV100_I2C9_CLK, "clk_i2c9", "50m",
 279                CLK_SET_RATE_PARENT, 0x01a0, 25, 0,
 280        },
 281        {
 282                HI3559AV100_I2C10_CLK, "clk_i2c10", "50m",
 283                CLK_SET_RATE_PARENT, 0x01a0, 26, 0,
 284        },
 285        {
 286                HI3559AV100_I2C11_CLK, "clk_i2c11", "50m",
 287                CLK_SET_RATE_PARENT, 0x01a0, 27, 0,
 288        },
 289        {
 290                HI3559AV100_SPI0_CLK, "clk_spi0", "100m",
 291                CLK_SET_RATE_PARENT, 0x0198, 16, 0,
 292        },
 293        {
 294                HI3559AV100_SPI1_CLK, "clk_spi1", "100m",
 295                CLK_SET_RATE_PARENT, 0x0198, 17, 0,
 296        },
 297        {
 298                HI3559AV100_SPI2_CLK, "clk_spi2", "100m",
 299                CLK_SET_RATE_PARENT, 0x0198, 18, 0,
 300        },
 301        {
 302                HI3559AV100_SPI3_CLK, "clk_spi3", "100m",
 303                CLK_SET_RATE_PARENT, 0x0198, 19, 0,
 304        },
 305        {
 306                HI3559AV100_SPI4_CLK, "clk_spi4", "100m",
 307                CLK_SET_RATE_PARENT, 0x0198, 20, 0,
 308        },
 309        {
 310                HI3559AV100_SPI5_CLK, "clk_spi5", "100m",
 311                CLK_SET_RATE_PARENT, 0x0198, 21, 0,
 312        },
 313        {
 314                HI3559AV100_SPI6_CLK, "clk_spi6", "100m",
 315                CLK_SET_RATE_PARENT, 0x0198, 22, 0,
 316        },
 317        {
 318                HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL,
 319                CLK_SET_RATE_PARENT, 0x16c, 6, 0,
 320        },
 321        {
 322                HI3559AV100_EDMAC_CLK, "clk_edmac", NULL,
 323                CLK_SET_RATE_PARENT, 0x16c, 5, 0,
 324        },
 325        {
 326                HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL,
 327                CLK_SET_RATE_PARENT, 0x16c, 9, 0,
 328        },
 329        {
 330                HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL,
 331                CLK_SET_RATE_PARENT, 0x16c, 8, 0,
 332        },
 333        {
 334                HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL,
 335                CLK_SET_RATE_PARENT, 0x14c, 5, 0,
 336        },
 337};
 338
 339static struct hi3559av100_pll_clock hi3559av100_pll_clks[] = {
 340        {
 341                HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3,
 342                0x4, 0, 12, 12, 6
 343        },
 344        {
 345                HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3,
 346                0x24, 0, 12, 12, 6
 347        },
 348};
 349
 350#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw)
 351static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val,
 352                                 u32 *postdiv2_val,
 353                                 u32 *fbdiv_val, u32 *refdiv_val, u64 rate)
 354{
 355        u64 rem;
 356
 357        *postdiv1_val = 2;
 358        *postdiv2_val = 1;
 359
 360        rate = rate * ((*postdiv1_val) * (*postdiv2_val));
 361
 362        *frac_val = 0;
 363        rem = do_div(rate, 1000000);
 364        rem = do_div(rate, PLL_MASK_WIDTH);
 365        *fbdiv_val = rate;
 366        *refdiv_val = 1;
 367        rem = rem * (1 << PLL_MASK_WIDTH);
 368        do_div(rem, PLL_MASK_WIDTH);
 369        *frac_val = rem;
 370}
 371
 372static int clk_pll_set_rate(struct clk_hw *hw,
 373                            unsigned long rate,
 374                            unsigned long parent_rate)
 375{
 376        struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
 377        u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val;
 378        u32 val;
 379
 380        postdiv1_val = postdiv2_val = 0;
 381
 382        hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val,
 383                             &fbdiv_val, &refdiv_val, (u64)rate);
 384
 385        val = readl_relaxed(clk->ctrl_reg1);
 386        val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
 387        val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
 388        val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift);
 389
 390        val |= frac_val << clk->frac_shift;
 391        val |= postdiv1_val << clk->postdiv1_shift;
 392        val |= postdiv2_val << clk->postdiv2_shift;
 393        writel_relaxed(val, clk->ctrl_reg1);
 394
 395        val = readl_relaxed(clk->ctrl_reg2);
 396        val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
 397        val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
 398
 399        val |= fbdiv_val << clk->fbdiv_shift;
 400        val |= refdiv_val << clk->refdiv_shift;
 401        writel_relaxed(val, clk->ctrl_reg2);
 402
 403        return 0;
 404}
 405
 406static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 407                unsigned long parent_rate)
 408{
 409        struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
 410        u64 frac_val, fbdiv_val, refdiv_val;
 411        u32 postdiv1_val, postdiv2_val;
 412        u32 val;
 413        u64 tmp, rate;
 414
 415        val = readl_relaxed(clk->ctrl_reg1);
 416        val = val >> clk->frac_shift;
 417        val &= ((1 << clk->frac_width) - 1);
 418        frac_val = val;
 419
 420        val = readl_relaxed(clk->ctrl_reg1);
 421        val = val >> clk->postdiv1_shift;
 422        val &= ((1 << clk->postdiv1_width) - 1);
 423        postdiv1_val = val;
 424
 425        val = readl_relaxed(clk->ctrl_reg1);
 426        val = val >> clk->postdiv2_shift;
 427        val &= ((1 << clk->postdiv2_width) - 1);
 428        postdiv2_val = val;
 429
 430        val = readl_relaxed(clk->ctrl_reg2);
 431        val = val >> clk->fbdiv_shift;
 432        val &= ((1 << clk->fbdiv_width) - 1);
 433        fbdiv_val = val;
 434
 435        val = readl_relaxed(clk->ctrl_reg2);
 436        val = val >> clk->refdiv_shift;
 437        val &= ((1 << clk->refdiv_width) - 1);
 438        refdiv_val = val;
 439
 440        /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv  */
 441        rate = 0;
 442        tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24);
 443        rate += tmp;
 444        do_div(rate, refdiv_val);
 445        do_div(rate, postdiv1_val * postdiv2_val);
 446
 447        return rate;
 448}
 449
 450static const struct clk_ops hisi_clk_pll_ops = {
 451        .set_rate = clk_pll_set_rate,
 452        .recalc_rate = clk_pll_recalc_rate,
 453};
 454
 455static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
 456                           int nums, struct hisi_clock_data *data, struct device *dev)
 457{
 458        void __iomem *base = data->base;
 459        struct hi3559av100_clk_pll *p_clk = NULL;
 460        struct clk *clk = NULL;
 461        struct clk_init_data init;
 462        int i;
 463
 464        p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL);
 465
 466        if (!p_clk)
 467                return;
 468
 469        for (i = 0; i < nums; i++) {
 470                init.name = clks[i].name;
 471                init.flags = 0;
 472                init.parent_names =
 473                        (clks[i].parent_name ? &clks[i].parent_name : NULL);
 474                init.num_parents = (clks[i].parent_name ? 1 : 0);
 475                init.ops = &hisi_clk_pll_ops;
 476
 477                p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1;
 478                p_clk->frac_shift = clks[i].frac_shift;
 479                p_clk->frac_width = clks[i].frac_width;
 480                p_clk->postdiv1_shift = clks[i].postdiv1_shift;
 481                p_clk->postdiv1_width = clks[i].postdiv1_width;
 482                p_clk->postdiv2_shift = clks[i].postdiv2_shift;
 483                p_clk->postdiv2_width = clks[i].postdiv2_width;
 484
 485                p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2;
 486                p_clk->fbdiv_shift = clks[i].fbdiv_shift;
 487                p_clk->fbdiv_width = clks[i].fbdiv_width;
 488                p_clk->refdiv_shift = clks[i].refdiv_shift;
 489                p_clk->refdiv_width = clks[i].refdiv_width;
 490                p_clk->hw.init = &init;
 491
 492                clk = clk_register(NULL, &p_clk->hw);
 493                if (IS_ERR(clk)) {
 494                        devm_kfree(dev, p_clk);
 495                        dev_err(dev, "%s: failed to register clock %s\n",
 496                               __func__, clks[i].name);
 497                        continue;
 498                }
 499
 500                data->clk_data.clks[clks[i].id] = clk;
 501                p_clk++;
 502        }
 503}
 504
 505static struct hisi_clock_data *hi3559av100_clk_register(
 506        struct platform_device *pdev)
 507{
 508        struct hisi_clock_data *clk_data;
 509        int ret;
 510
 511        clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS);
 512        if (!clk_data)
 513                return ERR_PTR(-ENOMEM);
 514
 515        ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg,
 516                                           ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
 517        if (ret)
 518                return ERR_PTR(ret);
 519
 520        hisi_clk_register_pll(hi3559av100_pll_clks,
 521                              ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev);
 522
 523        ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg,
 524                                    ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
 525        if (ret)
 526                goto unregister_fixed_rate;
 527
 528        ret = hisi_clk_register_gate(hi3559av100_gate_clks,
 529                                     ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
 530        if (ret)
 531                goto unregister_mux;
 532
 533        ret = of_clk_add_provider(pdev->dev.of_node,
 534                                  of_clk_src_onecell_get, &clk_data->clk_data);
 535        if (ret)
 536                goto unregister_gate;
 537
 538        return clk_data;
 539
 540unregister_gate:
 541        hisi_clk_unregister_gate(hi3559av100_gate_clks,
 542                                 ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
 543unregister_mux:
 544        hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
 545                                ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
 546unregister_fixed_rate:
 547        hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
 548                                       ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
 549        return ERR_PTR(ret);
 550}
 551
 552static void hi3559av100_clk_unregister(struct platform_device *pdev)
 553{
 554        struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
 555
 556        of_clk_del_provider(pdev->dev.of_node);
 557
 558        hisi_clk_unregister_gate(hi3559av100_gate_clks,
 559                                 ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data);
 560        hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
 561                                ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data);
 562        hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
 563                                       ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data);
 564}
 565
 566static const struct hisi_crg_funcs hi3559av100_crg_funcs = {
 567        .register_clks = hi3559av100_clk_register,
 568        .unregister_clks = hi3559av100_clk_unregister,
 569};
 570
 571static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] = {
 572        { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, },
 573        { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, },
 574        { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, },
 575        { HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, },
 576        { HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, },
 577        { HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, },
 578        { HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, },
 579        { HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, },
 580        { HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, },
 581        { HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, },
 582        { HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, },
 583        { HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, },
 584        { HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, },
 585};
 586
 587/* shub mux clk */
 588static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3};
 589static const char *shub_source_clk_mux_p[] = {
 590        "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL"
 591};
 592
 593static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3};
 594static const char *shub_uart_source_clk_mux_p[] = {
 595        "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M"
 596};
 597
 598static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = {
 599        {
 600                HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p,
 601                ARRAY_SIZE(shub_source_clk_mux_p),
 602                0, 0x0, 0, 2, 0, shub_source_clk_mux_table,
 603        },
 604
 605        {
 606                HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk",
 607                shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p),
 608                0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table,
 609        },
 610};
 611
 612
 613/* shub div clk */
 614static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}};
 615static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}};
 616
 617static struct hisi_divider_clock hi3559av100_shub_div_clks[] = {
 618        { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2,
 619          CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table,
 620        },
 621        { HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2,
 622          CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table,
 623        },
 624};
 625
 626/* shub gate clk */
 627static struct hisi_gate_clock hi3559av100_shub_gate_clks[] = {
 628        {
 629                HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk",
 630                0, 0x20, 1, 0,
 631        },
 632        {
 633                HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk",
 634                0, 0x20, 5, 0,
 635        },
 636        {
 637                HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk",
 638                0, 0x20, 9, 0,
 639        },
 640
 641        {
 642                HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk",
 643                0, 0x1c, 1, 0,
 644        },
 645        {
 646                HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk",
 647                0, 0x1c, 5, 0,
 648        },
 649        {
 650                HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk",
 651                0, 0x1c, 9, 0,
 652        },
 653        {
 654                HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk",
 655                0, 0x1c, 13, 0,
 656        },
 657        {
 658                HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk",
 659                0, 0x1c, 17, 0,
 660        },
 661        {
 662                HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk",
 663                0, 0x1c, 21, 0,
 664        },
 665        {
 666                HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk",
 667                0, 0x1c, 25, 0,
 668        },
 669
 670        {
 671                HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk",
 672                0, 0x24, 4, 0,
 673        },
 674};
 675
 676static int hi3559av100_shub_default_clk_set(void)
 677{
 678        void __iomem *crg_base;
 679        unsigned int val;
 680
 681        crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
 682
 683        /* SSP: 192M/2 */
 684        val = readl_relaxed(crg_base + 0x20);
 685        val |= (0x2 << 24);
 686        writel_relaxed(val, crg_base + 0x20);
 687
 688        /* UART: 192M/8 */
 689        val = readl_relaxed(crg_base + 0x1C);
 690        val |= (0x1 << 28);
 691        writel_relaxed(val, crg_base + 0x1C);
 692
 693        iounmap(crg_base);
 694        crg_base = NULL;
 695
 696        return 0;
 697}
 698
 699static struct hisi_clock_data *hi3559av100_shub_clk_register(
 700        struct platform_device *pdev)
 701{
 702        struct hisi_clock_data *clk_data = NULL;
 703        int ret;
 704
 705        hi3559av100_shub_default_clk_set();
 706
 707        clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS);
 708        if (!clk_data)
 709                return ERR_PTR(-ENOMEM);
 710
 711        ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks,
 712                                           ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
 713        if (ret)
 714                return ERR_PTR(ret);
 715
 716        ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks,
 717                                    ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
 718        if (ret)
 719                goto unregister_fixed_rate;
 720
 721        ret = hisi_clk_register_divider(hi3559av100_shub_div_clks,
 722                                        ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
 723        if (ret)
 724                goto unregister_mux;
 725
 726        ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks,
 727                                     ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
 728        if (ret)
 729                goto unregister_factor;
 730
 731        ret = of_clk_add_provider(pdev->dev.of_node,
 732                                  of_clk_src_onecell_get, &clk_data->clk_data);
 733        if (ret)
 734                goto unregister_gate;
 735
 736        return clk_data;
 737
 738unregister_gate:
 739        hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
 740                                 ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
 741unregister_factor:
 742        hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
 743                                    ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
 744unregister_mux:
 745        hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
 746                                ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
 747unregister_fixed_rate:
 748        hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
 749                                       ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
 750        return ERR_PTR(ret);
 751}
 752
 753static void hi3559av100_shub_clk_unregister(struct platform_device *pdev)
 754{
 755        struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
 756
 757        of_clk_del_provider(pdev->dev.of_node);
 758
 759        hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
 760                                 ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data);
 761        hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
 762                                    ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data);
 763        hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
 764                                ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data);
 765        hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
 766                                       ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data);
 767}
 768
 769static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = {
 770        .register_clks = hi3559av100_shub_clk_register,
 771        .unregister_clks = hi3559av100_shub_clk_unregister,
 772};
 773
 774static const struct of_device_id hi3559av100_crg_match_table[] = {
 775        {
 776                .compatible = "hisilicon,hi3559av100-clock",
 777                .data = &hi3559av100_crg_funcs
 778        },
 779        {
 780                .compatible = "hisilicon,hi3559av100-shub-clock",
 781                .data = &hi3559av100_shub_crg_funcs
 782        },
 783        { }
 784};
 785MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table);
 786
 787static int hi3559av100_crg_probe(struct platform_device *pdev)
 788{
 789        struct hisi_crg_dev *crg;
 790
 791        crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
 792        if (!crg)
 793                return -ENOMEM;
 794
 795        crg->funcs = of_device_get_match_data(&pdev->dev);
 796        if (!crg->funcs)
 797                return -ENOENT;
 798
 799        crg->rstc = hisi_reset_init(pdev);
 800        if (!crg->rstc)
 801                return -ENOMEM;
 802
 803        crg->clk_data = crg->funcs->register_clks(pdev);
 804        if (IS_ERR(crg->clk_data)) {
 805                hisi_reset_exit(crg->rstc);
 806                return PTR_ERR(crg->clk_data);
 807        }
 808
 809        platform_set_drvdata(pdev, crg);
 810        return 0;
 811}
 812
 813static int hi3559av100_crg_remove(struct platform_device *pdev)
 814{
 815        struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
 816
 817        hisi_reset_exit(crg->rstc);
 818        crg->funcs->unregister_clks(pdev);
 819        return 0;
 820}
 821
 822static struct platform_driver hi3559av100_crg_driver = {
 823        .probe          = hi3559av100_crg_probe,
 824        .remove         = hi3559av100_crg_remove,
 825        .driver         = {
 826                .name   = "hi3559av100-clock",
 827                .of_match_table = hi3559av100_crg_match_table,
 828        },
 829};
 830
 831static int __init hi3559av100_crg_init(void)
 832{
 833        return platform_driver_register(&hi3559av100_crg_driver);
 834}
 835core_initcall(hi3559av100_crg_init);
 836
 837static void __exit hi3559av100_crg_exit(void)
 838{
 839        platform_driver_unregister(&hi3559av100_crg_driver);
 840}
 841module_exit(hi3559av100_crg_exit);
 842
 843
 844MODULE_LICENSE("GPL v2");
 845MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver");
 846