Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/io.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_device.h>
0010 
0011 #include "ccu_common.h"
0012 #include "ccu_reset.h"
0013 
0014 #include "ccu_div.h"
0015 #include "ccu_gate.h"
0016 #include "ccu_mp.h"
0017 #include "ccu_nkmp.h"
0018 #include "ccu_nm.h"
0019 #include "ccu_phase.h"
0020 
0021 #include "ccu-sun9i-a80.h"
0022 
0023 #define CCU_SUN9I_LOCK_REG  0x09c
0024 
0025 /*
0026  * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
0027  * P should only be used for output frequencies lower than 228 MHz.
0028  * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
0029  *
0030  * For now we can just model it as a multiplier clock, and force P to /1.
0031  */
0032 #define SUN9I_A80_PLL_C0CPUX_REG    0x000
0033 #define SUN9I_A80_PLL_C1CPUX_REG    0x004
0034 
0035 static struct ccu_mult pll_c0cpux_clk = {
0036     .enable     = BIT(31),
0037     .lock       = BIT(0),
0038     .mult       = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0039     .common     = {
0040         .reg        = SUN9I_A80_PLL_C0CPUX_REG,
0041         .lock_reg   = CCU_SUN9I_LOCK_REG,
0042         .features   = CCU_FEATURE_LOCK_REG,
0043         .hw.init    = CLK_HW_INIT("pll-c0cpux", "osc24M",
0044                           &ccu_mult_ops,
0045                           CLK_SET_RATE_UNGATE),
0046     },
0047 };
0048 
0049 static struct ccu_mult pll_c1cpux_clk = {
0050     .enable     = BIT(31),
0051     .lock       = BIT(1),
0052     .mult       = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0053     .common     = {
0054         .reg        = SUN9I_A80_PLL_C1CPUX_REG,
0055         .lock_reg   = CCU_SUN9I_LOCK_REG,
0056         .features   = CCU_FEATURE_LOCK_REG,
0057         .hw.init    = CLK_HW_INIT("pll-c1cpux", "osc24M",
0058                           &ccu_mult_ops,
0059                           CLK_SET_RATE_UNGATE),
0060     },
0061 };
0062 
0063 /*
0064  * The Audio PLL has d1, d2 dividers in addition to the usual N, M
0065  * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
0066  * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
0067  */
0068 #define SUN9I_A80_PLL_AUDIO_REG 0x008
0069 
0070 static struct ccu_nm pll_audio_clk = {
0071     .enable     = BIT(31),
0072     .lock       = BIT(2),
0073     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0074     .m      = _SUNXI_CCU_DIV_OFFSET(0, 6, 0),
0075     .common     = {
0076         .reg        = 0x008,
0077         .lock_reg   = CCU_SUN9I_LOCK_REG,
0078         .features   = CCU_FEATURE_LOCK_REG,
0079         .hw.init    = CLK_HW_INIT("pll-audio", "osc24M",
0080                           &ccu_nm_ops, CLK_SET_RATE_UNGATE),
0081     },
0082 };
0083 
0084 /* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */
0085 static struct ccu_nkmp pll_periph0_clk = {
0086     .enable     = BIT(31),
0087     .lock       = BIT(3),
0088     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0089     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0090     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0091     .common     = {
0092         .reg        = 0x00c,
0093         .lock_reg   = CCU_SUN9I_LOCK_REG,
0094         .features   = CCU_FEATURE_LOCK_REG,
0095         .hw.init    = CLK_HW_INIT("pll-periph0", "osc24M",
0096                           &ccu_nkmp_ops,
0097                           CLK_SET_RATE_UNGATE),
0098     },
0099 };
0100 
0101 static struct ccu_nkmp pll_ve_clk = {
0102     .enable     = BIT(31),
0103     .lock       = BIT(4),
0104     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0105     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0106     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0107     .common     = {
0108         .reg        = 0x010,
0109         .lock_reg   = CCU_SUN9I_LOCK_REG,
0110         .features   = CCU_FEATURE_LOCK_REG,
0111         .hw.init    = CLK_HW_INIT("pll-ve", "osc24M",
0112                           &ccu_nkmp_ops,
0113                           CLK_SET_RATE_UNGATE),
0114     },
0115 };
0116 
0117 static struct ccu_nkmp pll_ddr_clk = {
0118     .enable     = BIT(31),
0119     .lock       = BIT(5),
0120     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0121     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0122     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0123     .common     = {
0124         .reg        = 0x014,
0125         .lock_reg   = CCU_SUN9I_LOCK_REG,
0126         .features   = CCU_FEATURE_LOCK_REG,
0127         .hw.init    = CLK_HW_INIT("pll-ddr", "osc24M",
0128                           &ccu_nkmp_ops,
0129                           CLK_SET_RATE_UNGATE),
0130     },
0131 };
0132 
0133 static struct ccu_nm pll_video0_clk = {
0134     .enable     = BIT(31),
0135     .lock       = BIT(6),
0136     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0137     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0138     .common     = {
0139         .reg        = 0x018,
0140         .lock_reg   = CCU_SUN9I_LOCK_REG,
0141         .features   = CCU_FEATURE_LOCK_REG,
0142         .hw.init    = CLK_HW_INIT("pll-video0", "osc24M",
0143                           &ccu_nm_ops,
0144                           CLK_SET_RATE_UNGATE),
0145     },
0146 };
0147 
0148 static struct ccu_nkmp pll_video1_clk = {
0149     .enable     = BIT(31),
0150     .lock       = BIT(7),
0151     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0152     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0153     .p      = _SUNXI_CCU_DIV(0, 2), /* external divider p */
0154     .common     = {
0155         .reg        = 0x01c,
0156         .lock_reg   = CCU_SUN9I_LOCK_REG,
0157         .features   = CCU_FEATURE_LOCK_REG,
0158         .hw.init    = CLK_HW_INIT("pll-video1", "osc24M",
0159                           &ccu_nkmp_ops,
0160                           CLK_SET_RATE_UNGATE),
0161     },
0162 };
0163 
0164 static struct ccu_nkmp pll_gpu_clk = {
0165     .enable     = BIT(31),
0166     .lock       = BIT(8),
0167     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0168     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0169     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0170     .common     = {
0171         .reg        = 0x020,
0172         .lock_reg   = CCU_SUN9I_LOCK_REG,
0173         .features   = CCU_FEATURE_LOCK_REG,
0174         .hw.init    = CLK_HW_INIT("pll-gpu", "osc24M",
0175                           &ccu_nkmp_ops,
0176                           CLK_SET_RATE_UNGATE),
0177     },
0178 };
0179 
0180 static struct ccu_nkmp pll_de_clk = {
0181     .enable     = BIT(31),
0182     .lock       = BIT(9),
0183     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0184     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0185     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0186     .common     = {
0187         .reg        = 0x024,
0188         .lock_reg   = CCU_SUN9I_LOCK_REG,
0189         .features   = CCU_FEATURE_LOCK_REG,
0190         .hw.init    = CLK_HW_INIT("pll-de", "osc24M",
0191                           &ccu_nkmp_ops,
0192                           CLK_SET_RATE_UNGATE),
0193     },
0194 };
0195 
0196 static struct ccu_nkmp pll_isp_clk = {
0197     .enable     = BIT(31),
0198     .lock       = BIT(10),
0199     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0200     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0201     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0202     .common     = {
0203         .reg        = 0x028,
0204         .lock_reg   = CCU_SUN9I_LOCK_REG,
0205         .features   = CCU_FEATURE_LOCK_REG,
0206         .hw.init    = CLK_HW_INIT("pll-isp", "osc24M",
0207                           &ccu_nkmp_ops,
0208                           CLK_SET_RATE_UNGATE),
0209     },
0210 };
0211 
0212 static struct ccu_nkmp pll_periph1_clk = {
0213     .enable     = BIT(31),
0214     .lock       = BIT(11),
0215     .n      = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
0216     .m      = _SUNXI_CCU_DIV(16, 1), /* input divider */
0217     .p      = _SUNXI_CCU_DIV(18, 1), /* output divider */
0218     .common     = {
0219         .reg        = 0x028,
0220         .lock_reg   = CCU_SUN9I_LOCK_REG,
0221         .features   = CCU_FEATURE_LOCK_REG,
0222         .hw.init    = CLK_HW_INIT("pll-periph1", "osc24M",
0223                           &ccu_nkmp_ops,
0224                           CLK_SET_RATE_UNGATE),
0225     },
0226 };
0227 
0228 static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
0229 static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
0230              0x50, 0, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
0231 
0232 static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
0233 static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
0234              0x50, 8, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
0235 
0236 static struct clk_div_table axi_div_table[] = {
0237     { .val = 0, .div = 1 },
0238     { .val = 1, .div = 2 },
0239     { .val = 2, .div = 3 },
0240     { .val = 3, .div = 4 },
0241     { .val = 4, .div = 4 },
0242     { .val = 5, .div = 4 },
0243     { .val = 6, .div = 4 },
0244     { .val = 7, .div = 4 },
0245     { /* Sentinel */ },
0246 };
0247 
0248 static SUNXI_CCU_M(atb0_clk, "atb0", "c0cpux", 0x054, 8, 2, 0);
0249 
0250 static SUNXI_CCU_DIV_TABLE(axi0_clk, "axi0", "c0cpux",
0251                0x054, 0, 3, axi_div_table, 0);
0252 
0253 static SUNXI_CCU_M(atb1_clk, "atb1", "c1cpux", 0x058, 8, 2, 0);
0254 
0255 static SUNXI_CCU_DIV_TABLE(axi1_clk, "axi1", "c1cpux",
0256                0x058, 0, 3, axi_div_table, 0);
0257 
0258 static const char * const gtbus_parents[] = { "osc24M", "pll-periph0",
0259                           "pll-periph1", "pll-periph1" };
0260 static SUNXI_CCU_M_WITH_MUX(gtbus_clk, "gtbus", gtbus_parents,
0261                 0x05c, 0, 2, 24, 2, CLK_IS_CRITICAL);
0262 
0263 static const char * const ahb_parents[] = { "gtbus", "pll-periph0",
0264                         "pll-periph1", "pll-periph1" };
0265 static struct ccu_div ahb0_clk = {
0266     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0267     .mux        = _SUNXI_CCU_MUX(24, 2),
0268     .common     = {
0269         .reg        = 0x060,
0270         .hw.init    = CLK_HW_INIT_PARENTS("ahb0",
0271                               ahb_parents,
0272                               &ccu_div_ops,
0273                               0),
0274     },
0275 };
0276 
0277 static struct ccu_div ahb1_clk = {
0278     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0279     .mux        = _SUNXI_CCU_MUX(24, 2),
0280     .common     = {
0281         .reg        = 0x064,
0282         .hw.init    = CLK_HW_INIT_PARENTS("ahb1",
0283                               ahb_parents,
0284                               &ccu_div_ops,
0285                               0),
0286     },
0287 };
0288 
0289 static struct ccu_div ahb2_clk = {
0290     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0291     .mux        = _SUNXI_CCU_MUX(24, 2),
0292     .common     = {
0293         .reg        = 0x068,
0294         .hw.init    = CLK_HW_INIT_PARENTS("ahb2",
0295                               ahb_parents,
0296                               &ccu_div_ops,
0297                               0),
0298     },
0299 };
0300 
0301 static const char * const apb_parents[] = { "osc24M", "pll-periph0" };
0302 
0303 static struct ccu_div apb0_clk = {
0304     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0305     .mux        = _SUNXI_CCU_MUX(24, 1),
0306     .common     = {
0307         .reg        = 0x070,
0308         .hw.init    = CLK_HW_INIT_PARENTS("apb0",
0309                               apb_parents,
0310                               &ccu_div_ops,
0311                               0),
0312     },
0313 };
0314 
0315 static struct ccu_div apb1_clk = {
0316     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0317     .mux        = _SUNXI_CCU_MUX(24, 1),
0318     .common     = {
0319         .reg        = 0x074,
0320         .hw.init    = CLK_HW_INIT_PARENTS("apb1",
0321                               apb_parents,
0322                               &ccu_div_ops,
0323                               0),
0324     },
0325 };
0326 
0327 static struct ccu_div cci400_clk = {
0328     .div        = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
0329     .mux        = _SUNXI_CCU_MUX(24, 2),
0330     .common     = {
0331         .reg        = 0x078,
0332         .hw.init    = CLK_HW_INIT_PARENTS("cci400",
0333                               ahb_parents,
0334                               &ccu_div_ops,
0335                               CLK_IS_CRITICAL),
0336     },
0337 };
0338 
0339 static SUNXI_CCU_M_WITH_MUX_GATE(ats_clk, "ats", apb_parents,
0340                  0x080, 0, 3, 24, 2, BIT(31), 0);
0341 
0342 static SUNXI_CCU_M_WITH_MUX_GATE(trace_clk, "trace", apb_parents,
0343                  0x084, 0, 3, 24, 2, BIT(31), 0);
0344 
0345 static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" };
0346 static const struct ccu_mux_fixed_prediv out_prediv = {
0347     .index = 0, .div = 750
0348 };
0349 
0350 static struct ccu_mp out_a_clk = {
0351     .enable     = BIT(31),
0352     .m      = _SUNXI_CCU_DIV(8, 5),
0353     .p      = _SUNXI_CCU_DIV(20, 2),
0354     .mux        = {
0355         .shift      = 24,
0356         .width      = 4,
0357         .fixed_predivs  = &out_prediv,
0358         .n_predivs  = 1,
0359     },
0360     .common     = {
0361         .reg        = 0x180,
0362         .features   = CCU_FEATURE_FIXED_PREDIV,
0363         .hw.init    = CLK_HW_INIT_PARENTS("out-a",
0364                               out_parents,
0365                               &ccu_mp_ops,
0366                               0),
0367     },
0368 };
0369 
0370 static struct ccu_mp out_b_clk = {
0371     .enable     = BIT(31),
0372     .m      = _SUNXI_CCU_DIV(8, 5),
0373     .p      = _SUNXI_CCU_DIV(20, 2),
0374     .mux        = {
0375         .shift      = 24,
0376         .width      = 4,
0377         .fixed_predivs  = &out_prediv,
0378         .n_predivs  = 1,
0379     },
0380     .common     = {
0381         .reg        = 0x184,
0382         .features   = CCU_FEATURE_FIXED_PREDIV,
0383         .hw.init    = CLK_HW_INIT_PARENTS("out-b",
0384                               out_parents,
0385                               &ccu_mp_ops,
0386                               0),
0387     },
0388 };
0389 
0390 static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0" };
0391 
0392 static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_0_clk, "nand0-0", mod0_default_parents,
0393                   0x400,
0394                   0, 4,     /* M */
0395                   16, 2,    /* P */
0396                   24, 4,    /* mux */
0397                   BIT(31),  /* gate */
0398                   0);
0399 
0400 static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_1_clk, "nand0-1", mod0_default_parents,
0401                   0x404,
0402                   0, 4,     /* M */
0403                   16, 2,    /* P */
0404                   24, 4,    /* mux */
0405                   BIT(31),  /* gate */
0406                   0);
0407 
0408 static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_0_clk, "nand1-0", mod0_default_parents,
0409                   0x408,
0410                   0, 4,     /* M */
0411                   16, 2,    /* P */
0412                   24, 4,    /* mux */
0413                   BIT(31),  /* gate */
0414                   0);
0415 
0416 static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_1_clk, "nand1-1", mod0_default_parents,
0417                   0x40c,
0418                   0, 4,     /* M */
0419                   16, 2,    /* P */
0420                   24, 4,    /* mux */
0421                   BIT(31),  /* gate */
0422                   0);
0423 
0424 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
0425                   0x410,
0426                   0, 4,     /* M */
0427                   16, 2,    /* P */
0428                   24, 4,    /* mux */
0429                   BIT(31),  /* gate */
0430                   0);
0431 
0432 static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
0433                0x410, 20, 3, 0);
0434 static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
0435                0x410, 8, 3, 0);
0436 
0437 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
0438                   0x414,
0439                   0, 4,     /* M */
0440                   16, 2,    /* P */
0441                   24, 4,    /* mux */
0442                   BIT(31),  /* gate */
0443                   0);
0444 
0445 static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
0446                0x414, 20, 3, 0);
0447 static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
0448                0x414, 8, 3, 0);
0449 
0450 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
0451                   0x418,
0452                   0, 4,     /* M */
0453                   16, 2,    /* P */
0454                   24, 4,    /* mux */
0455                   BIT(31),  /* gate */
0456                   0);
0457 
0458 static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
0459                0x418, 20, 3, 0);
0460 static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
0461                0x418, 8, 3, 0);
0462 
0463 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents,
0464                   0x41c,
0465                   0, 4,     /* M */
0466                   16, 2,    /* P */
0467                   24, 4,    /* mux */
0468                   BIT(31),  /* gate */
0469                   0);
0470 
0471 static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3-sample", "mmc3",
0472                0x41c, 20, 3, 0);
0473 static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3-output", "mmc3",
0474                0x41c, 8, 3, 0);
0475 
0476 static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents,
0477                   0x428,
0478                   0, 4,     /* M */
0479                   16, 2,    /* P */
0480                   24, 4,    /* mux */
0481                   BIT(31),  /* gate */
0482                   0);
0483 
0484 static const char * const ss_parents[] = { "osc24M", "pll-periph",
0485                        "pll-periph1" };
0486 static const u8 ss_table[] = { 0, 1, 13 };
0487 static struct ccu_mp ss_clk = {
0488     .enable     = BIT(31),
0489     .m      = _SUNXI_CCU_DIV(0, 4),
0490     .p      = _SUNXI_CCU_DIV(16, 2),
0491     .mux        = _SUNXI_CCU_MUX_TABLE(24, 4, ss_table),
0492     .common     = {
0493         .reg        = 0x42c,
0494         .hw.init    = CLK_HW_INIT_PARENTS("ss",
0495                               ss_parents,
0496                               &ccu_mp_ops,
0497                               0),
0498     },
0499 };
0500 
0501 static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
0502                   0x430,
0503                   0, 4,     /* M */
0504                   16, 2,    /* P */
0505                   24, 4,    /* mux */
0506                   BIT(31),  /* gate */
0507                   0);
0508 
0509 static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
0510                   0x434,
0511                   0, 4,     /* M */
0512                   16, 2,    /* P */
0513                   24, 4,    /* mux */
0514                   BIT(31),  /* gate */
0515                   0);
0516 
0517 static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents,
0518                   0x438,
0519                   0, 4,     /* M */
0520                   16, 2,    /* P */
0521                   24, 4,    /* mux */
0522                   BIT(31),  /* gate */
0523                   0);
0524 
0525 static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents,
0526                   0x43c,
0527                   0, 4,     /* M */
0528                   16, 2,    /* P */
0529                   24, 4,    /* mux */
0530                   BIT(31),  /* gate */
0531                   0);
0532 
0533 static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
0534                  0x440, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
0535 static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
0536                  0x444, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
0537 static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
0538                  0x44c, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
0539 
0540 static const char * const sdram_parents[] = { "pll-periph0", "pll-ddr" };
0541 static const u8 sdram_table[] = { 0, 3 };
0542 
0543 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(sdram_clk, "sdram",
0544                        sdram_parents, sdram_table,
0545                        0x484,
0546                        8, 4,    /* M */
0547                        12, 4,   /* mux */
0548                        0,   /* no gate */
0549                        CLK_IS_CRITICAL);
0550 
0551 static SUNXI_CCU_M_WITH_GATE(de_clk, "de", "pll-de", 0x490,
0552                  0, 4, BIT(31), CLK_SET_RATE_PARENT);
0553 
0554 static SUNXI_CCU_GATE(edp_clk, "edp", "osc24M", 0x494, BIT(31), 0);
0555 
0556 static const char * const mp_parents[] = { "pll-video1", "pll-gpu", "pll-de" };
0557 static const u8 mp_table[] = { 9, 10, 11 };
0558 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mp_clk, "mp", mp_parents, mp_table,
0559                        0x498,
0560                        0, 4,    /* M */
0561                        24, 4,   /* mux */
0562                        BIT(31), /* gate */
0563                        0);
0564 
0565 static const char * const display_parents[] = { "pll-video0", "pll-video1" };
0566 static const u8 display_table[] = { 8, 9 };
0567 
0568 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd0_clk, "lcd0",
0569                        display_parents, display_table,
0570                        0x49c,
0571                        0, 4,    /* M */
0572                        24, 4,   /* mux */
0573                        BIT(31), /* gate */
0574                        CLK_SET_RATE_NO_REPARENT |
0575                        CLK_SET_RATE_PARENT);
0576 
0577 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd1_clk, "lcd1",
0578                        display_parents, display_table,
0579                        0x4a0,
0580                        0, 4,    /* M */
0581                        24, 4,   /* mux */
0582                        BIT(31), /* gate */
0583                        CLK_SET_RATE_NO_REPARENT |
0584                        CLK_SET_RATE_PARENT);
0585 
0586 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
0587                        display_parents, display_table,
0588                        0x4a8,
0589                        0, 4,    /* M */
0590                        24, 4,   /* mux */
0591                        BIT(31), /* gate */
0592                        CLK_SET_RATE_PARENT);
0593 
0594 static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video1" };
0595 static const u8 mipi_dsi1_table[] = { 0, 9 };
0596 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
0597                        mipi_dsi1_parents, mipi_dsi1_table,
0598                        0x4ac,
0599                        0, 4,    /* M */
0600                        24, 4,   /* mux */
0601                        BIT(31), /* gate */
0602                        CLK_SET_RATE_PARENT);
0603 
0604 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi",
0605                        display_parents, display_table,
0606                        0x4b0,
0607                        0, 4,    /* M */
0608                        24, 4,   /* mux */
0609                        BIT(31), /* gate */
0610                        CLK_SET_RATE_NO_REPARENT |
0611                        CLK_SET_RATE_PARENT);
0612 
0613 static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x4b4, BIT(31), 0);
0614 
0615 static SUNXI_CCU_M_WITH_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x4bc,
0616                  0, 4, BIT(31), 0);
0617 
0618 static SUNXI_CCU_M_WITH_GATE(csi_isp_clk, "csi-isp", "pll-isp", 0x4c0,
0619                  0, 4, BIT(31), CLK_SET_RATE_PARENT);
0620 
0621 static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x4c0, BIT(16), 0);
0622 
0623 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_mclk_clk, "csi0-mclk",
0624                        mipi_dsi1_parents, mipi_dsi1_table,
0625                        0x4c4,
0626                        0, 4,    /* M */
0627                        24, 4,   /* mux */
0628                        BIT(31), /* gate */
0629                        CLK_SET_RATE_PARENT);
0630 
0631 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_mclk_clk, "csi1-mclk",
0632                        mipi_dsi1_parents, mipi_dsi1_table,
0633                        0x4c8,
0634                        0, 4,    /* M */
0635                        24, 4,   /* mux */
0636                        BIT(31), /* gate */
0637                        CLK_SET_RATE_PARENT);
0638 
0639 static const char * const fd_parents[] = { "pll-periph0", "pll-isp" };
0640 static const u8 fd_table[] = { 1, 12 };
0641 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(fd_clk, "fd", fd_parents, fd_table,
0642                        0x4cc,
0643                        0, 4,    /* M */
0644                        24, 4,   /* mux */
0645                        BIT(31), /* gate */
0646                        0);
0647 static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x4d0,
0648                  16, 3, BIT(31), CLK_SET_RATE_PARENT);
0649 
0650 static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x4d4, BIT(31), 0);
0651 
0652 static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x4f0,
0653                  0, 3, BIT(31), CLK_SET_RATE_PARENT);
0654 static SUNXI_CCU_M_WITH_GATE(gpu_memory_clk, "gpu-memory", "pll-gpu", 0x4f4,
0655                  0, 3, BIT(31), CLK_SET_RATE_PARENT);
0656 
0657 static const char * const gpu_axi_parents[] = { "pll-periph0", "pll-gpu" };
0658 static const u8 gpu_axi_table[] = { 1, 10 };
0659 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_axi_clk, "gpu-axi",
0660                        gpu_axi_parents, gpu_axi_table,
0661                        0x4f8,
0662                        0, 4,    /* M */
0663                        24, 4,   /* mux */
0664                        BIT(31), /* gate */
0665                        CLK_SET_RATE_PARENT);
0666 
0667 static SUNXI_CCU_M_WITH_GATE(sata_clk, "sata", "pll-periph0", 0x500,
0668                  0, 4, BIT(31), 0);
0669 
0670 static SUNXI_CCU_M_WITH_GATE(ac97_clk, "ac97", "pll-audio",
0671                  0x504, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
0672 
0673 static SUNXI_CCU_M_WITH_MUX_GATE(mipi_hsi_clk, "mipi-hsi",
0674                  mod0_default_parents, 0x508,
0675                  0, 4,      /* M */
0676                  24, 4,     /* mux */
0677                  BIT(31),   /* gate */
0678                  0);
0679 
0680 static const char * const gpadc_parents[] = { "osc24M", "pll-audio", "osc32k" };
0681 static const u8 gpadc_table[] = { 0, 4, 7 };
0682 static struct ccu_mp gpadc_clk = {
0683     .enable     = BIT(31),
0684     .m      = _SUNXI_CCU_DIV(0, 4),
0685     .p      = _SUNXI_CCU_DIV(16, 2),
0686     .mux        = _SUNXI_CCU_MUX_TABLE(24, 4, gpadc_table),
0687     .common     = {
0688         .reg        = 0x50c,
0689         .hw.init    = CLK_HW_INIT_PARENTS("gpadc",
0690                               gpadc_parents,
0691                               &ccu_mp_ops,
0692                               0),
0693     },
0694 };
0695 
0696 static const char * const cir_tx_parents[] = { "osc24M", "osc32k" };
0697 static const u8 cir_tx_table[] = { 0, 7 };
0698 static struct ccu_mp cir_tx_clk = {
0699     .enable     = BIT(31),
0700     .m      = _SUNXI_CCU_DIV(0, 4),
0701     .p      = _SUNXI_CCU_DIV(16, 2),
0702     .mux        = _SUNXI_CCU_MUX_TABLE(24, 4, cir_tx_table),
0703     .common     = {
0704         .reg        = 0x510,
0705         .hw.init    = CLK_HW_INIT_PARENTS("cir-tx",
0706                               cir_tx_parents,
0707                               &ccu_mp_ops,
0708                               0),
0709     },
0710 };
0711 
0712 /* AHB0 bus gates */
0713 static SUNXI_CCU_GATE(bus_fd_clk,   "bus-fd",   "ahb0",
0714               0x580, BIT(0), 0);
0715 static SUNXI_CCU_GATE(bus_ve_clk,   "bus-ve",   "ahb0",
0716               0x580, BIT(1), 0);
0717 static SUNXI_CCU_GATE(bus_gpu_ctrl_clk, "bus-gpu-ctrl", "ahb0",
0718               0x580, BIT(3), 0);
0719 static SUNXI_CCU_GATE(bus_ss_clk,   "bus-ss",   "ahb0",
0720               0x580, BIT(5), 0);
0721 static SUNXI_CCU_GATE(bus_mmc_clk,  "bus-mmc",  "ahb0",
0722               0x580, BIT(8), 0);
0723 static SUNXI_CCU_GATE(bus_nand0_clk,    "bus-nand0",    "ahb0",
0724               0x580, BIT(12), 0);
0725 static SUNXI_CCU_GATE(bus_nand1_clk,    "bus-nand1",    "ahb0",
0726               0x580, BIT(13), 0);
0727 static SUNXI_CCU_GATE(bus_sdram_clk,    "bus-sdram",    "ahb0",
0728               0x580, BIT(14), 0);
0729 static SUNXI_CCU_GATE(bus_mipi_hsi_clk, "bus-mipi-hsi", "ahb0",
0730               0x580, BIT(15), 0);
0731 static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata", "ahb0",
0732               0x580, BIT(16), 0);
0733 static SUNXI_CCU_GATE(bus_ts_clk,   "bus-ts",   "ahb0",
0734               0x580, BIT(18), 0);
0735 static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb0",
0736               0x580, BIT(20), 0);
0737 static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb0",
0738               0x580, BIT(21), 0);
0739 static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb0",
0740               0x580, BIT(22), 0);
0741 static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3", "ahb0",
0742               0x580, BIT(23), 0);
0743 
0744 /* AHB1 bus gates */
0745 static SUNXI_CCU_GATE(bus_otg_clk,  "bus-otg",  "ahb1",
0746               0x584, BIT(0), 0);
0747 static SUNXI_CCU_GATE(bus_usb_clk,  "bus-usb",  "ahb1",
0748               0x584, BIT(1), 0);
0749 static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac", "ahb1",
0750               0x584, BIT(17), 0);
0751 static SUNXI_CCU_GATE(bus_msgbox_clk,   "bus-msgbox",   "ahb1",
0752               0x584, BIT(21), 0);
0753 static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1",
0754               0x584, BIT(22), 0);
0755 static SUNXI_CCU_GATE(bus_hstimer_clk,  "bus-hstimer",  "ahb1",
0756               0x584, BIT(23), 0);
0757 static SUNXI_CCU_GATE(bus_dma_clk,  "bus-dma",  "ahb1",
0758               0x584, BIT(24), 0);
0759 
0760 /* AHB2 bus gates */
0761 static SUNXI_CCU_GATE(bus_lcd0_clk, "bus-lcd0", "ahb2",
0762               0x588, BIT(0), 0);
0763 static SUNXI_CCU_GATE(bus_lcd1_clk, "bus-lcd1", "ahb2",
0764               0x588, BIT(1), 0);
0765 static SUNXI_CCU_GATE(bus_edp_clk,  "bus-edp",  "ahb2",
0766               0x588, BIT(2), 0);
0767 static SUNXI_CCU_GATE(bus_csi_clk,  "bus-csi",  "ahb2",
0768               0x588, BIT(4), 0);
0769 static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb2",
0770               0x588, BIT(5), 0);
0771 static SUNXI_CCU_GATE(bus_de_clk,   "bus-de",   "ahb2",
0772               0x588, BIT(7), 0);
0773 static SUNXI_CCU_GATE(bus_mp_clk,   "bus-mp",   "ahb2",
0774               0x588, BIT(8), 0);
0775 static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb2",
0776               0x588, BIT(11), 0);
0777 
0778 /* APB0 bus gates */
0779 static SUNXI_CCU_GATE(bus_spdif_clk,    "bus-spdif",    "apb0",
0780               0x590, BIT(1), 0);
0781 static SUNXI_CCU_GATE(bus_pio_clk,  "bus-pio",  "apb0",
0782               0x590, BIT(5), 0);
0783 static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97", "apb0",
0784               0x590, BIT(11), 0);
0785 static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb0",
0786               0x590, BIT(12), 0);
0787 static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb0",
0788               0x590, BIT(13), 0);
0789 static SUNXI_CCU_GATE(bus_lradc_clk,    "bus-lradc",    "apb0",
0790               0x590, BIT(15), 0);
0791 static SUNXI_CCU_GATE(bus_gpadc_clk,    "bus-gpadc",    "apb0",
0792               0x590, BIT(17), 0);
0793 static SUNXI_CCU_GATE(bus_twd_clk,  "bus-twd",  "apb0",
0794               0x590, BIT(18), 0);
0795 static SUNXI_CCU_GATE(bus_cir_tx_clk,   "bus-cir-tx",   "apb0",
0796               0x590, BIT(19), 0);
0797 
0798 /* APB1 bus gates */
0799 static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb1",
0800               0x594, BIT(0), 0);
0801 static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb1",
0802               0x594, BIT(1), 0);
0803 static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb1",
0804               0x594, BIT(2), 0);
0805 static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb1",
0806               0x594, BIT(3), 0);
0807 static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb1",
0808               0x594, BIT(4), 0);
0809 static SUNXI_CCU_GATE(bus_uart0_clk,    "bus-uart0",    "apb1",
0810               0x594, BIT(16), 0);
0811 static SUNXI_CCU_GATE(bus_uart1_clk,    "bus-uart1",    "apb1",
0812               0x594, BIT(17), 0);
0813 static SUNXI_CCU_GATE(bus_uart2_clk,    "bus-uart2",    "apb1",
0814               0x594, BIT(18), 0);
0815 static SUNXI_CCU_GATE(bus_uart3_clk,    "bus-uart3",    "apb1",
0816               0x594, BIT(19), 0);
0817 static SUNXI_CCU_GATE(bus_uart4_clk,    "bus-uart4",    "apb1",
0818               0x594, BIT(20), 0);
0819 static SUNXI_CCU_GATE(bus_uart5_clk,    "bus-uart5",    "apb1",
0820               0x594, BIT(21), 0);
0821 
0822 static struct ccu_common *sun9i_a80_ccu_clks[] = {
0823     &pll_c0cpux_clk.common,
0824     &pll_c1cpux_clk.common,
0825     &pll_audio_clk.common,
0826     &pll_periph0_clk.common,
0827     &pll_ve_clk.common,
0828     &pll_ddr_clk.common,
0829     &pll_video0_clk.common,
0830     &pll_video1_clk.common,
0831     &pll_gpu_clk.common,
0832     &pll_de_clk.common,
0833     &pll_isp_clk.common,
0834     &pll_periph1_clk.common,
0835     &c0cpux_clk.common,
0836     &c1cpux_clk.common,
0837     &atb0_clk.common,
0838     &axi0_clk.common,
0839     &atb1_clk.common,
0840     &axi1_clk.common,
0841     &gtbus_clk.common,
0842     &ahb0_clk.common,
0843     &ahb1_clk.common,
0844     &ahb2_clk.common,
0845     &apb0_clk.common,
0846     &apb1_clk.common,
0847     &cci400_clk.common,
0848     &ats_clk.common,
0849     &trace_clk.common,
0850 
0851     &out_a_clk.common,
0852     &out_b_clk.common,
0853 
0854     /* module clocks */
0855     &nand0_0_clk.common,
0856     &nand0_1_clk.common,
0857     &nand1_0_clk.common,
0858     &nand1_1_clk.common,
0859     &mmc0_clk.common,
0860     &mmc0_sample_clk.common,
0861     &mmc0_output_clk.common,
0862     &mmc1_clk.common,
0863     &mmc1_sample_clk.common,
0864     &mmc1_output_clk.common,
0865     &mmc2_clk.common,
0866     &mmc2_sample_clk.common,
0867     &mmc2_output_clk.common,
0868     &mmc3_clk.common,
0869     &mmc3_sample_clk.common,
0870     &mmc3_output_clk.common,
0871     &ts_clk.common,
0872     &ss_clk.common,
0873     &spi0_clk.common,
0874     &spi1_clk.common,
0875     &spi2_clk.common,
0876     &spi3_clk.common,
0877     &i2s0_clk.common,
0878     &i2s1_clk.common,
0879     &spdif_clk.common,
0880     &sdram_clk.common,
0881     &de_clk.common,
0882     &edp_clk.common,
0883     &mp_clk.common,
0884     &lcd0_clk.common,
0885     &lcd1_clk.common,
0886     &mipi_dsi0_clk.common,
0887     &mipi_dsi1_clk.common,
0888     &hdmi_clk.common,
0889     &hdmi_slow_clk.common,
0890     &mipi_csi_clk.common,
0891     &csi_isp_clk.common,
0892     &csi_misc_clk.common,
0893     &csi0_mclk_clk.common,
0894     &csi1_mclk_clk.common,
0895     &fd_clk.common,
0896     &ve_clk.common,
0897     &avs_clk.common,
0898     &gpu_core_clk.common,
0899     &gpu_memory_clk.common,
0900     &gpu_axi_clk.common,
0901     &sata_clk.common,
0902     &ac97_clk.common,
0903     &mipi_hsi_clk.common,
0904     &gpadc_clk.common,
0905     &cir_tx_clk.common,
0906 
0907     /* AHB0 bus gates */
0908     &bus_fd_clk.common,
0909     &bus_ve_clk.common,
0910     &bus_gpu_ctrl_clk.common,
0911     &bus_ss_clk.common,
0912     &bus_mmc_clk.common,
0913     &bus_nand0_clk.common,
0914     &bus_nand1_clk.common,
0915     &bus_sdram_clk.common,
0916     &bus_mipi_hsi_clk.common,
0917     &bus_sata_clk.common,
0918     &bus_ts_clk.common,
0919     &bus_spi0_clk.common,
0920     &bus_spi1_clk.common,
0921     &bus_spi2_clk.common,
0922     &bus_spi3_clk.common,
0923 
0924     /* AHB1 bus gates */
0925     &bus_otg_clk.common,
0926     &bus_usb_clk.common,
0927     &bus_gmac_clk.common,
0928     &bus_msgbox_clk.common,
0929     &bus_spinlock_clk.common,
0930     &bus_hstimer_clk.common,
0931     &bus_dma_clk.common,
0932 
0933     /* AHB2 bus gates */
0934     &bus_lcd0_clk.common,
0935     &bus_lcd1_clk.common,
0936     &bus_edp_clk.common,
0937     &bus_csi_clk.common,
0938     &bus_hdmi_clk.common,
0939     &bus_de_clk.common,
0940     &bus_mp_clk.common,
0941     &bus_mipi_dsi_clk.common,
0942 
0943     /* APB0 bus gates */
0944     &bus_spdif_clk.common,
0945     &bus_pio_clk.common,
0946     &bus_ac97_clk.common,
0947     &bus_i2s0_clk.common,
0948     &bus_i2s1_clk.common,
0949     &bus_lradc_clk.common,
0950     &bus_gpadc_clk.common,
0951     &bus_twd_clk.common,
0952     &bus_cir_tx_clk.common,
0953 
0954     /* APB1 bus gates */
0955     &bus_i2c0_clk.common,
0956     &bus_i2c1_clk.common,
0957     &bus_i2c2_clk.common,
0958     &bus_i2c3_clk.common,
0959     &bus_i2c4_clk.common,
0960     &bus_uart0_clk.common,
0961     &bus_uart1_clk.common,
0962     &bus_uart2_clk.common,
0963     &bus_uart3_clk.common,
0964     &bus_uart4_clk.common,
0965     &bus_uart5_clk.common,
0966 };
0967 
0968 static struct clk_hw_onecell_data sun9i_a80_hw_clks = {
0969     .hws    = {
0970         [CLK_PLL_C0CPUX]    = &pll_c0cpux_clk.common.hw,
0971         [CLK_PLL_C1CPUX]    = &pll_c1cpux_clk.common.hw,
0972         [CLK_PLL_AUDIO]     = &pll_audio_clk.common.hw,
0973         [CLK_PLL_PERIPH0]   = &pll_periph0_clk.common.hw,
0974         [CLK_PLL_VE]        = &pll_ve_clk.common.hw,
0975         [CLK_PLL_DDR]       = &pll_ddr_clk.common.hw,
0976         [CLK_PLL_VIDEO0]    = &pll_video0_clk.common.hw,
0977         [CLK_PLL_VIDEO1]    = &pll_video1_clk.common.hw,
0978         [CLK_PLL_GPU]       = &pll_gpu_clk.common.hw,
0979         [CLK_PLL_DE]        = &pll_de_clk.common.hw,
0980         [CLK_PLL_ISP]       = &pll_isp_clk.common.hw,
0981         [CLK_PLL_PERIPH1]   = &pll_periph1_clk.common.hw,
0982         [CLK_C0CPUX]        = &c0cpux_clk.common.hw,
0983         [CLK_C1CPUX]        = &c1cpux_clk.common.hw,
0984         [CLK_ATB0]      = &atb0_clk.common.hw,
0985         [CLK_AXI0]      = &axi0_clk.common.hw,
0986         [CLK_ATB1]      = &atb1_clk.common.hw,
0987         [CLK_AXI1]      = &axi1_clk.common.hw,
0988         [CLK_GTBUS]     = &gtbus_clk.common.hw,
0989         [CLK_AHB0]      = &ahb0_clk.common.hw,
0990         [CLK_AHB1]      = &ahb1_clk.common.hw,
0991         [CLK_AHB2]      = &ahb2_clk.common.hw,
0992         [CLK_APB0]      = &apb0_clk.common.hw,
0993         [CLK_APB1]      = &apb1_clk.common.hw,
0994         [CLK_CCI400]        = &cci400_clk.common.hw,
0995         [CLK_ATS]       = &ats_clk.common.hw,
0996         [CLK_TRACE]     = &trace_clk.common.hw,
0997 
0998         [CLK_OUT_A]     = &out_a_clk.common.hw,
0999         [CLK_OUT_B]     = &out_b_clk.common.hw,
1000 
1001         [CLK_NAND0_0]       = &nand0_0_clk.common.hw,
1002         [CLK_NAND0_1]       = &nand0_1_clk.common.hw,
1003         [CLK_NAND1_0]       = &nand1_0_clk.common.hw,
1004         [CLK_NAND1_1]       = &nand1_1_clk.common.hw,
1005         [CLK_MMC0]      = &mmc0_clk.common.hw,
1006         [CLK_MMC0_SAMPLE]   = &mmc0_sample_clk.common.hw,
1007         [CLK_MMC0_OUTPUT]   = &mmc0_output_clk.common.hw,
1008         [CLK_MMC1]      = &mmc1_clk.common.hw,
1009         [CLK_MMC1_SAMPLE]   = &mmc1_sample_clk.common.hw,
1010         [CLK_MMC1_OUTPUT]   = &mmc1_output_clk.common.hw,
1011         [CLK_MMC2]      = &mmc2_clk.common.hw,
1012         [CLK_MMC2_SAMPLE]   = &mmc2_sample_clk.common.hw,
1013         [CLK_MMC2_OUTPUT]   = &mmc2_output_clk.common.hw,
1014         [CLK_MMC3]      = &mmc3_clk.common.hw,
1015         [CLK_MMC3_SAMPLE]   = &mmc3_sample_clk.common.hw,
1016         [CLK_MMC3_OUTPUT]   = &mmc3_output_clk.common.hw,
1017         [CLK_TS]        = &ts_clk.common.hw,
1018         [CLK_SS]        = &ss_clk.common.hw,
1019         [CLK_SPI0]      = &spi0_clk.common.hw,
1020         [CLK_SPI1]      = &spi1_clk.common.hw,
1021         [CLK_SPI2]      = &spi2_clk.common.hw,
1022         [CLK_SPI3]      = &spi3_clk.common.hw,
1023         [CLK_I2S0]      = &i2s0_clk.common.hw,
1024         [CLK_I2S1]      = &i2s1_clk.common.hw,
1025         [CLK_SPDIF]     = &spdif_clk.common.hw,
1026         [CLK_SDRAM]     = &sdram_clk.common.hw,
1027         [CLK_DE]        = &de_clk.common.hw,
1028         [CLK_EDP]       = &edp_clk.common.hw,
1029         [CLK_MP]        = &mp_clk.common.hw,
1030         [CLK_LCD0]      = &lcd0_clk.common.hw,
1031         [CLK_LCD1]      = &lcd1_clk.common.hw,
1032         [CLK_MIPI_DSI0]     = &mipi_dsi0_clk.common.hw,
1033         [CLK_MIPI_DSI1]     = &mipi_dsi1_clk.common.hw,
1034         [CLK_HDMI]      = &hdmi_clk.common.hw,
1035         [CLK_HDMI_SLOW]     = &hdmi_slow_clk.common.hw,
1036         [CLK_MIPI_CSI]      = &mipi_csi_clk.common.hw,
1037         [CLK_CSI_ISP]       = &csi_isp_clk.common.hw,
1038         [CLK_CSI_MISC]      = &csi_misc_clk.common.hw,
1039         [CLK_CSI0_MCLK]     = &csi0_mclk_clk.common.hw,
1040         [CLK_CSI1_MCLK]     = &csi1_mclk_clk.common.hw,
1041         [CLK_FD]        = &fd_clk.common.hw,
1042         [CLK_VE]        = &ve_clk.common.hw,
1043         [CLK_AVS]       = &avs_clk.common.hw,
1044         [CLK_GPU_CORE]      = &gpu_core_clk.common.hw,
1045         [CLK_GPU_MEMORY]    = &gpu_memory_clk.common.hw,
1046         [CLK_GPU_AXI]       = &gpu_axi_clk.common.hw,
1047         [CLK_SATA]      = &sata_clk.common.hw,
1048         [CLK_AC97]      = &ac97_clk.common.hw,
1049         [CLK_MIPI_HSI]      = &mipi_hsi_clk.common.hw,
1050         [CLK_GPADC]     = &gpadc_clk.common.hw,
1051         [CLK_CIR_TX]        = &cir_tx_clk.common.hw,
1052 
1053         [CLK_BUS_FD]        = &bus_fd_clk.common.hw,
1054         [CLK_BUS_VE]        = &bus_ve_clk.common.hw,
1055         [CLK_BUS_GPU_CTRL]  = &bus_gpu_ctrl_clk.common.hw,
1056         [CLK_BUS_SS]        = &bus_ss_clk.common.hw,
1057         [CLK_BUS_MMC]       = &bus_mmc_clk.common.hw,
1058         [CLK_BUS_NAND0]     = &bus_nand0_clk.common.hw,
1059         [CLK_BUS_NAND1]     = &bus_nand1_clk.common.hw,
1060         [CLK_BUS_SDRAM]     = &bus_sdram_clk.common.hw,
1061         [CLK_BUS_MIPI_HSI]  = &bus_mipi_hsi_clk.common.hw,
1062         [CLK_BUS_SATA]      = &bus_sata_clk.common.hw,
1063         [CLK_BUS_TS]        = &bus_ts_clk.common.hw,
1064         [CLK_BUS_SPI0]      = &bus_spi0_clk.common.hw,
1065         [CLK_BUS_SPI1]      = &bus_spi1_clk.common.hw,
1066         [CLK_BUS_SPI2]      = &bus_spi2_clk.common.hw,
1067         [CLK_BUS_SPI3]      = &bus_spi3_clk.common.hw,
1068 
1069         [CLK_BUS_OTG]       = &bus_otg_clk.common.hw,
1070         [CLK_BUS_USB]       = &bus_usb_clk.common.hw,
1071         [CLK_BUS_GMAC]      = &bus_gmac_clk.common.hw,
1072         [CLK_BUS_MSGBOX]    = &bus_msgbox_clk.common.hw,
1073         [CLK_BUS_SPINLOCK]  = &bus_spinlock_clk.common.hw,
1074         [CLK_BUS_HSTIMER]   = &bus_hstimer_clk.common.hw,
1075         [CLK_BUS_DMA]       = &bus_dma_clk.common.hw,
1076 
1077         [CLK_BUS_LCD0]      = &bus_lcd0_clk.common.hw,
1078         [CLK_BUS_LCD1]      = &bus_lcd1_clk.common.hw,
1079         [CLK_BUS_EDP]       = &bus_edp_clk.common.hw,
1080         [CLK_BUS_CSI]       = &bus_csi_clk.common.hw,
1081         [CLK_BUS_HDMI]      = &bus_hdmi_clk.common.hw,
1082         [CLK_BUS_DE]        = &bus_de_clk.common.hw,
1083         [CLK_BUS_MP]        = &bus_mp_clk.common.hw,
1084         [CLK_BUS_MIPI_DSI]  = &bus_mipi_dsi_clk.common.hw,
1085 
1086         [CLK_BUS_SPDIF]     = &bus_spdif_clk.common.hw,
1087         [CLK_BUS_PIO]       = &bus_pio_clk.common.hw,
1088         [CLK_BUS_AC97]      = &bus_ac97_clk.common.hw,
1089         [CLK_BUS_I2S0]      = &bus_i2s0_clk.common.hw,
1090         [CLK_BUS_I2S1]      = &bus_i2s1_clk.common.hw,
1091         [CLK_BUS_LRADC]     = &bus_lradc_clk.common.hw,
1092         [CLK_BUS_GPADC]     = &bus_gpadc_clk.common.hw,
1093         [CLK_BUS_TWD]       = &bus_twd_clk.common.hw,
1094         [CLK_BUS_CIR_TX]    = &bus_cir_tx_clk.common.hw,
1095 
1096         [CLK_BUS_I2C0]      = &bus_i2c0_clk.common.hw,
1097         [CLK_BUS_I2C1]      = &bus_i2c1_clk.common.hw,
1098         [CLK_BUS_I2C2]      = &bus_i2c2_clk.common.hw,
1099         [CLK_BUS_I2C3]      = &bus_i2c3_clk.common.hw,
1100         [CLK_BUS_I2C4]      = &bus_i2c4_clk.common.hw,
1101         [CLK_BUS_UART0]     = &bus_uart0_clk.common.hw,
1102         [CLK_BUS_UART1]     = &bus_uart1_clk.common.hw,
1103         [CLK_BUS_UART2]     = &bus_uart2_clk.common.hw,
1104         [CLK_BUS_UART3]     = &bus_uart3_clk.common.hw,
1105         [CLK_BUS_UART4]     = &bus_uart4_clk.common.hw,
1106         [CLK_BUS_UART5]     = &bus_uart5_clk.common.hw,
1107     },
1108     .num    = CLK_NUMBER,
1109 };
1110 
1111 static struct ccu_reset_map sun9i_a80_ccu_resets[] = {
1112     /* AHB0 reset controls */
1113     [RST_BUS_FD]        = { 0x5a0, BIT(0) },
1114     [RST_BUS_VE]        = { 0x5a0, BIT(1) },
1115     [RST_BUS_GPU_CTRL]  = { 0x5a0, BIT(3) },
1116     [RST_BUS_SS]        = { 0x5a0, BIT(5) },
1117     [RST_BUS_MMC]       = { 0x5a0, BIT(8) },
1118     [RST_BUS_NAND0]     = { 0x5a0, BIT(12) },
1119     [RST_BUS_NAND1]     = { 0x5a0, BIT(13) },
1120     [RST_BUS_SDRAM]     = { 0x5a0, BIT(14) },
1121     [RST_BUS_SATA]      = { 0x5a0, BIT(16) },
1122     [RST_BUS_TS]        = { 0x5a0, BIT(18) },
1123     [RST_BUS_SPI0]      = { 0x5a0, BIT(20) },
1124     [RST_BUS_SPI1]      = { 0x5a0, BIT(21) },
1125     [RST_BUS_SPI2]      = { 0x5a0, BIT(22) },
1126     [RST_BUS_SPI3]      = { 0x5a0, BIT(23) },
1127 
1128     /* AHB1 reset controls */
1129     [RST_BUS_OTG]       = { 0x5a4, BIT(0) },
1130     [RST_BUS_OTG_PHY]   = { 0x5a4, BIT(1) },
1131     [RST_BUS_MIPI_HSI]  = { 0x5a4, BIT(9) },
1132     [RST_BUS_GMAC]      = { 0x5a4, BIT(17) },
1133     [RST_BUS_MSGBOX]    = { 0x5a4, BIT(21) },
1134     [RST_BUS_SPINLOCK]  = { 0x5a4, BIT(22) },
1135     [RST_BUS_HSTIMER]   = { 0x5a4, BIT(23) },
1136     [RST_BUS_DMA]       = { 0x5a4, BIT(24) },
1137 
1138     /* AHB2 reset controls */
1139     [RST_BUS_LCD0]      = { 0x5a8, BIT(0) },
1140     [RST_BUS_LCD1]      = { 0x5a8, BIT(1) },
1141     [RST_BUS_EDP]       = { 0x5a8, BIT(2) },
1142     [RST_BUS_LVDS]      = { 0x5a8, BIT(3) },
1143     [RST_BUS_CSI]       = { 0x5a8, BIT(4) },
1144     [RST_BUS_HDMI0]     = { 0x5a8, BIT(5) },
1145     [RST_BUS_HDMI1]     = { 0x5a8, BIT(6) },
1146     [RST_BUS_DE]        = { 0x5a8, BIT(7) },
1147     [RST_BUS_MP]        = { 0x5a8, BIT(8) },
1148     [RST_BUS_GPU]       = { 0x5a8, BIT(9) },
1149     [RST_BUS_MIPI_DSI]  = { 0x5a8, BIT(11) },
1150 
1151     /* APB0 reset controls */
1152     [RST_BUS_SPDIF]     = { 0x5b0, BIT(1) },
1153     [RST_BUS_AC97]      = { 0x5b0, BIT(11) },
1154     [RST_BUS_I2S0]      = { 0x5b0, BIT(12) },
1155     [RST_BUS_I2S1]      = { 0x5b0, BIT(13) },
1156     [RST_BUS_LRADC]     = { 0x5b0, BIT(15) },
1157     [RST_BUS_GPADC]     = { 0x5b0, BIT(17) },
1158     [RST_BUS_CIR_TX]    = { 0x5b0, BIT(19) },
1159 
1160     /* APB1 reset controls */
1161     [RST_BUS_I2C0]      = { 0x5b4, BIT(0) },
1162     [RST_BUS_I2C1]      = { 0x5b4, BIT(1) },
1163     [RST_BUS_I2C2]      = { 0x5b4, BIT(2) },
1164     [RST_BUS_I2C3]      = { 0x5b4, BIT(3) },
1165     [RST_BUS_I2C4]      = { 0x5b4, BIT(4) },
1166     [RST_BUS_UART0]     = { 0x5b4, BIT(16) },
1167     [RST_BUS_UART1]     = { 0x5b4, BIT(17) },
1168     [RST_BUS_UART2]     = { 0x5b4, BIT(18) },
1169     [RST_BUS_UART3]     = { 0x5b4, BIT(19) },
1170     [RST_BUS_UART4]     = { 0x5b4, BIT(20) },
1171     [RST_BUS_UART5]     = { 0x5b4, BIT(21) },
1172 };
1173 
1174 static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
1175     .ccu_clks   = sun9i_a80_ccu_clks,
1176     .num_ccu_clks   = ARRAY_SIZE(sun9i_a80_ccu_clks),
1177 
1178     .hw_clks    = &sun9i_a80_hw_clks,
1179 
1180     .resets     = sun9i_a80_ccu_resets,
1181     .num_resets = ARRAY_SIZE(sun9i_a80_ccu_resets),
1182 };
1183 
1184 #define SUN9I_A80_PLL_P_SHIFT   16
1185 #define SUN9I_A80_PLL_N_SHIFT   8
1186 #define SUN9I_A80_PLL_N_WIDTH   8
1187 
1188 static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
1189 {
1190     u32 val = readl(reg);
1191 
1192     /* bail out if P divider is not used */
1193     if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
1194         return;
1195 
1196     /*
1197      * If P is used, output should be less than 288 MHz. When we
1198      * set P to 1, we should also decrease the multiplier so the
1199      * output doesn't go out of range, but not too much such that
1200      * the multiplier stays above 12, the minimal operation value.
1201      *
1202      * To keep it simple, set the multiplier to 17, the reset value.
1203      */
1204     val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
1205             SUN9I_A80_PLL_N_SHIFT);
1206     val |= 17 << SUN9I_A80_PLL_N_SHIFT;
1207 
1208     /* And clear P */
1209     val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
1210 
1211     writel(val, reg);
1212 }
1213 
1214 static int sun9i_a80_ccu_probe(struct platform_device *pdev)
1215 {
1216     void __iomem *reg;
1217     u32 val;
1218 
1219     reg = devm_platform_ioremap_resource(pdev, 0);
1220     if (IS_ERR(reg))
1221         return PTR_ERR(reg);
1222 
1223     /* Enforce d1 = 0, d2 = 0 for Audio PLL */
1224     val = readl(reg + SUN9I_A80_PLL_AUDIO_REG);
1225     val &= ~(BIT(16) | BIT(18));
1226     writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
1227 
1228     /* Enforce P = 1 for both CPU cluster PLLs */
1229     sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
1230     sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
1231 
1232     return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc);
1233 }
1234 
1235 static const struct of_device_id sun9i_a80_ccu_ids[] = {
1236     { .compatible = "allwinner,sun9i-a80-ccu" },
1237     { }
1238 };
1239 
1240 static struct platform_driver sun9i_a80_ccu_driver = {
1241     .probe  = sun9i_a80_ccu_probe,
1242     .driver = {
1243         .name   = "sun9i-a80-ccu",
1244         .suppress_bind_attrs = true,
1245         .of_match_table = sun9i_a80_ccu_ids,
1246     },
1247 };
1248 module_platform_driver(sun9i_a80_ccu_driver);
1249 
1250 MODULE_IMPORT_NS(SUNXI_CCU);
1251 MODULE_LICENSE("GPL");