Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
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_mult.h"
0018 #include "ccu_nk.h"
0019 #include "ccu_nkm.h"
0020 #include "ccu_nkmp.h"
0021 #include "ccu_nm.h"
0022 
0023 #include "ccu-sun50i-h6.h"
0024 
0025 /*
0026  * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
0027  * P should only be used for output frequencies lower than 288 MHz.
0028  *
0029  * For now we can just model it as a multiplier clock, and force P to /1.
0030  *
0031  * The M factor is present in the register's description, but not in the
0032  * frequency formula, and it's documented as "M is only used for backdoor
0033  * testing", so it's not modelled and then force to 0.
0034  */
0035 #define SUN50I_H6_PLL_CPUX_REG      0x000
0036 static struct ccu_mult pll_cpux_clk = {
0037     .enable     = BIT(31),
0038     .lock       = BIT(28),
0039     .mult       = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0040     .common     = {
0041         .reg        = 0x000,
0042         .hw.init    = CLK_HW_INIT("pll-cpux", "osc24M",
0043                           &ccu_mult_ops,
0044                           CLK_SET_RATE_UNGATE),
0045     },
0046 };
0047 
0048 /* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
0049 #define SUN50I_H6_PLL_DDR0_REG      0x010
0050 static struct ccu_nkmp pll_ddr0_clk = {
0051     .enable     = BIT(31),
0052     .lock       = BIT(28),
0053     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0054     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0055     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0056     .common     = {
0057         .reg        = 0x010,
0058         .hw.init    = CLK_HW_INIT("pll-ddr0", "osc24M",
0059                           &ccu_nkmp_ops,
0060                           CLK_SET_RATE_UNGATE),
0061     },
0062 };
0063 
0064 #define SUN50I_H6_PLL_PERIPH0_REG   0x020
0065 static struct ccu_nkmp pll_periph0_clk = {
0066     .enable     = BIT(31),
0067     .lock       = BIT(28),
0068     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0069     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0070     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0071     .fixed_post_div = 4,
0072     .common     = {
0073         .reg        = 0x020,
0074         .features   = CCU_FEATURE_FIXED_POSTDIV,
0075         .hw.init    = CLK_HW_INIT("pll-periph0", "osc24M",
0076                           &ccu_nkmp_ops,
0077                           CLK_SET_RATE_UNGATE),
0078     },
0079 };
0080 
0081 #define SUN50I_H6_PLL_PERIPH1_REG   0x028
0082 static struct ccu_nkmp pll_periph1_clk = {
0083     .enable     = BIT(31),
0084     .lock       = BIT(28),
0085     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0086     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0087     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0088     .fixed_post_div = 4,
0089     .common     = {
0090         .reg        = 0x028,
0091         .features   = CCU_FEATURE_FIXED_POSTDIV,
0092         .hw.init    = CLK_HW_INIT("pll-periph1", "osc24M",
0093                           &ccu_nkmp_ops,
0094                           CLK_SET_RATE_UNGATE),
0095     },
0096 };
0097 
0098 /* For GPU PLL, using an output divider for DFS causes system to fail */
0099 #define SUN50I_H6_PLL_GPU_REG       0x030
0100 static struct ccu_nkmp pll_gpu_clk = {
0101     .enable     = BIT(31),
0102     .lock       = BIT(28),
0103     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0104     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0105     .common     = {
0106         .reg        = 0x030,
0107         .hw.init    = CLK_HW_INIT("pll-gpu", "osc24M",
0108                           &ccu_nkmp_ops,
0109                           CLK_SET_RATE_UNGATE),
0110     },
0111 };
0112 
0113 /*
0114  * For Video PLLs, the output divider is described as "used for testing"
0115  * in the user manual. So it's not modelled and forced to 0.
0116  */
0117 #define SUN50I_H6_PLL_VIDEO0_REG    0x040
0118 static struct ccu_nm pll_video0_clk = {
0119     .enable     = BIT(31),
0120     .lock       = BIT(28),
0121     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0122     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0123     .fixed_post_div = 4,
0124     .min_rate   = 288000000,
0125     .max_rate   = 2400000000UL,
0126     .common     = {
0127         .reg        = 0x040,
0128         .features   = CCU_FEATURE_FIXED_POSTDIV,
0129         .hw.init    = CLK_HW_INIT("pll-video0", "osc24M",
0130                           &ccu_nm_ops,
0131                           CLK_SET_RATE_UNGATE),
0132     },
0133 };
0134 
0135 #define SUN50I_H6_PLL_VIDEO1_REG    0x048
0136 static struct ccu_nm pll_video1_clk = {
0137     .enable     = BIT(31),
0138     .lock       = BIT(28),
0139     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0140     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0141     .fixed_post_div = 4,
0142     .min_rate   = 288000000,
0143     .max_rate   = 2400000000UL,
0144     .common     = {
0145         .reg        = 0x048,
0146         .features   = CCU_FEATURE_FIXED_POSTDIV,
0147         .hw.init    = CLK_HW_INIT("pll-video1", "osc24M",
0148                           &ccu_nm_ops,
0149                           CLK_SET_RATE_UNGATE),
0150     },
0151 };
0152 
0153 #define SUN50I_H6_PLL_VE_REG        0x058
0154 static struct ccu_nkmp pll_ve_clk = {
0155     .enable     = BIT(31),
0156     .lock       = BIT(28),
0157     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0158     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0159     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0160     .common     = {
0161         .reg        = 0x058,
0162         .hw.init    = CLK_HW_INIT("pll-ve", "osc24M",
0163                           &ccu_nkmp_ops,
0164                           CLK_SET_RATE_UNGATE),
0165     },
0166 };
0167 
0168 #define SUN50I_H6_PLL_DE_REG        0x060
0169 static struct ccu_nkmp pll_de_clk = {
0170     .enable     = BIT(31),
0171     .lock       = BIT(28),
0172     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0173     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0174     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0175     .common     = {
0176         .reg        = 0x060,
0177         .hw.init    = CLK_HW_INIT("pll-de", "osc24M",
0178                           &ccu_nkmp_ops,
0179                           CLK_SET_RATE_UNGATE),
0180     },
0181 };
0182 
0183 #define SUN50I_H6_PLL_HSIC_REG      0x070
0184 static struct ccu_nkmp pll_hsic_clk = {
0185     .enable     = BIT(31),
0186     .lock       = BIT(28),
0187     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0188     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0189     .p      = _SUNXI_CCU_DIV(0, 1), /* output divider */
0190     .common     = {
0191         .reg        = 0x070,
0192         .hw.init    = CLK_HW_INIT("pll-hsic", "osc24M",
0193                           &ccu_nkmp_ops,
0194                           CLK_SET_RATE_UNGATE),
0195     },
0196 };
0197 
0198 /*
0199  * The Audio PLL is supposed to have 3 outputs: 2 fixed factors from
0200  * the base (2x and 4x), and one variable divider (the one true pll audio).
0201  *
0202  * We don't have any need for the variable divider for now, so we just
0203  * hardcode it to match with the clock names.
0204  */
0205 #define SUN50I_H6_PLL_AUDIO_REG     0x078
0206 
0207 static struct ccu_sdm_setting pll_audio_sdm_table[] = {
0208     { .rate = 541900800, .pattern = 0xc001288d, .m = 1, .n = 22 },
0209     { .rate = 589824000, .pattern = 0xc00126e9, .m = 1, .n = 24 },
0210 };
0211 
0212 static struct ccu_nm pll_audio_base_clk = {
0213     .enable     = BIT(31),
0214     .lock       = BIT(28),
0215     .n      = _SUNXI_CCU_MULT_MIN(8, 8, 12),
0216     .m      = _SUNXI_CCU_DIV(1, 1), /* input divider */
0217     .sdm        = _SUNXI_CCU_SDM(pll_audio_sdm_table,
0218                      BIT(24), 0x178, BIT(31)),
0219     .common     = {
0220         .features   = CCU_FEATURE_SIGMA_DELTA_MOD,
0221         .reg        = 0x078,
0222         .hw.init    = CLK_HW_INIT("pll-audio-base", "osc24M",
0223                           &ccu_nm_ops,
0224                           CLK_SET_RATE_UNGATE),
0225     },
0226 };
0227 
0228 static const char * const cpux_parents[] = { "osc24M", "osc32k",
0229                          "iosc", "pll-cpux" };
0230 static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
0231              0x500, 24, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
0232 static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
0233 static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
0234 
0235 static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
0236                               "iosc", "pll-periph0" };
0237 static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
0238                  psi_ahb1_ahb2_parents,
0239                  0x510,
0240                  0, 2,  /* M */
0241                  8, 2,  /* P */
0242                  24, 2, /* mux */
0243                  0);
0244 
0245 static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
0246                                "psi-ahb1-ahb2",
0247                                "pll-periph0" };
0248 static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
0249                  0, 2,  /* M */
0250                  8, 2,  /* P */
0251                  24, 2, /* mux */
0252                  0);
0253 
0254 static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
0255                  0, 2,  /* M */
0256                  8, 2,  /* P */
0257                  24, 2, /* mux */
0258                  0);
0259 
0260 static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
0261                  0, 2,  /* M */
0262                  8, 2,  /* P */
0263                  24, 2, /* mux */
0264                  0);
0265 
0266 static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
0267                          "pll-ddr0", "pll-periph0-4x" };
0268 static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
0269                        0, 3,    /* M */
0270                        24, 2,   /* mux */
0271                        BIT(31), /* gate */
0272                        CLK_IS_CRITICAL);
0273 
0274 static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
0275 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
0276                        0, 4,    /* M */
0277                        24, 1,   /* mux */
0278                        BIT(31), /* gate */
0279                        CLK_SET_RATE_PARENT);
0280 
0281 static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
0282               0x60c, BIT(0), 0);
0283 
0284 static const char * const deinterlace_parents[] = { "pll-periph0",
0285                             "pll-periph1" };
0286 static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
0287                        deinterlace_parents,
0288                        0x620,
0289                        0, 4,    /* M */
0290                        24, 1,   /* mux */
0291                        BIT(31), /* gate */
0292                        0);
0293 
0294 static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
0295               0x62c, BIT(0), 0);
0296 
0297 /* Keep GPU_CLK divider const to avoid DFS instability. */
0298 static const char * const gpu_parents[] = { "pll-gpu" };
0299 static SUNXI_CCU_MUX_WITH_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
0300                        24, 1,   /* mux */
0301                        BIT(31), /* gate */
0302                        CLK_SET_RATE_PARENT);
0303 
0304 static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
0305               0x67c, BIT(0), 0);
0306 
0307 /* Also applies to EMCE */
0308 static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
0309 static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
0310                     0, 4,   /* M */
0311                     8, 2,   /* N */
0312                     24, 1,  /* mux */
0313                     BIT(31),/* gate */
0314                     0);
0315 
0316 static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
0317               0x68c, BIT(0), 0);
0318 
0319 static const char * const ve_parents[] = { "pll-ve" };
0320 static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
0321                        0, 3,    /* M */
0322                        24, 1,   /* mux */
0323                        BIT(31), /* gate */
0324                        CLK_SET_RATE_PARENT);
0325 
0326 static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
0327               0x69c, BIT(0), 0);
0328 
0329 static SUNXI_CCU_MP_WITH_MUX_GATE(emce_clk, "emce", ce_parents, 0x6b0,
0330                     0, 4,   /* M */
0331                     8, 2,   /* N */
0332                     24, 1,  /* mux */
0333                     BIT(31),/* gate */
0334                     0);
0335 
0336 static SUNXI_CCU_GATE(bus_emce_clk, "bus-emce", "psi-ahb1-ahb2",
0337               0x6bc, BIT(0), 0);
0338 
0339 static const char * const vp9_parents[] = { "pll-ve", "pll-periph0-2x" };
0340 static SUNXI_CCU_M_WITH_MUX_GATE(vp9_clk, "vp9", vp9_parents, 0x6c0,
0341                        0, 3,    /* M */
0342                        24, 1,   /* mux */
0343                        BIT(31), /* gate */
0344                        0);
0345 
0346 static SUNXI_CCU_GATE(bus_vp9_clk, "bus-vp9", "psi-ahb1-ahb2",
0347               0x6cc, BIT(0), 0);
0348 
0349 static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
0350               0x70c, BIT(0), 0);
0351 
0352 static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "psi-ahb1-ahb2",
0353               0x71c, BIT(0), 0);
0354 
0355 static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "psi-ahb1-ahb2",
0356               0x72c, BIT(0), 0);
0357 
0358 static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
0359               0x73c, BIT(0), 0);
0360 
0361 static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
0362 
0363 static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
0364               0x78c, BIT(0), 0);
0365 
0366 static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
0367               0x79c, BIT(0), 0);
0368 
0369 static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
0370 
0371 static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
0372 
0373 static const char * const dram_parents[] = { "pll-ddr0" };
0374 static struct ccu_div dram_clk = {
0375     .div        = _SUNXI_CCU_DIV(0, 2),
0376     .mux        = _SUNXI_CCU_MUX(24, 2),
0377     .common = {
0378         .reg        = 0x800,
0379         .hw.init    = CLK_HW_INIT_PARENTS("dram",
0380                               dram_parents,
0381                               &ccu_div_ops,
0382                               CLK_IS_CRITICAL),
0383     },
0384 };
0385 
0386 static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
0387               0x804, BIT(0), 0);
0388 static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
0389               0x804, BIT(1), 0);
0390 static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
0391               0x804, BIT(2), 0);
0392 static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
0393               0x804, BIT(3), 0);
0394 static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
0395               0x804, BIT(5), 0);
0396 static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi", "mbus",
0397               0x804, BIT(8), 0);
0398 static SUNXI_CCU_GATE(mbus_deinterlace_clk, "mbus-deinterlace", "mbus",
0399               0x804, BIT(11), 0);
0400 
0401 static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
0402               0x80c, BIT(0), CLK_IS_CRITICAL);
0403 
0404 static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
0405                          "pll-periph1", "pll-periph0-2x",
0406                          "pll-periph1-2x" };
0407 static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
0408                     0, 4,   /* M */
0409                     8, 2,   /* N */
0410                     24, 3,  /* mux */
0411                     BIT(31),/* gate */
0412                     0);
0413 
0414 static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
0415                     0, 4,   /* M */
0416                     8, 2,   /* N */
0417                     24, 3,  /* mux */
0418                     BIT(31),/* gate */
0419                     0);
0420 
0421 static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
0422 
0423 static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
0424                         "pll-periph1-2x" };
0425 static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
0426                       0, 4,     /* M */
0427                       8, 2,     /* N */
0428                       24, 2,    /* mux */
0429                       BIT(31),  /* gate */
0430                       2,        /* post-div */
0431                       0);
0432 
0433 static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
0434                       0, 4,     /* M */
0435                       8, 2,     /* N */
0436                       24, 2,    /* mux */
0437                       BIT(31),  /* gate */
0438                       2,        /* post-div */
0439                       0);
0440 
0441 static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
0442                       0, 4,     /* M */
0443                       8, 2,     /* N */
0444                       24, 2,    /* mux */
0445                       BIT(31),  /* gate */
0446                       2,        /* post-div */
0447                       0);
0448 
0449 static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
0450 static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
0451 static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
0452 
0453 static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
0454 static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
0455 static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
0456 static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
0457 
0458 static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
0459 static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
0460 static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
0461 static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
0462 
0463 static SUNXI_CCU_GATE(bus_scr0_clk, "bus-scr0", "apb2", 0x93c, BIT(0), 0);
0464 static SUNXI_CCU_GATE(bus_scr1_clk, "bus-scr1", "apb2", 0x93c, BIT(1), 0);
0465 
0466 static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
0467                     0, 4,   /* M */
0468                     8, 2,   /* N */
0469                     24, 3,  /* mux */
0470                     BIT(31),/* gate */
0471                     0);
0472 
0473 static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
0474                     0, 4,   /* M */
0475                     8, 2,   /* N */
0476                     24, 3,  /* mux */
0477                     BIT(31),/* gate */
0478                     0);
0479 
0480 static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
0481 static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
0482 
0483 static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb3", 0x97c, BIT(0), 0);
0484 
0485 static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
0486 static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
0487                     0, 4,   /* M */
0488                     8, 2,   /* N */
0489                     24, 1,  /* mux */
0490                     BIT(31),/* gate */
0491                     0);
0492 
0493 static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
0494 
0495 static const char * const ir_tx_parents[] = { "osc32k", "osc24M" };
0496 static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_parents, 0x9c0,
0497                     0, 4,   /* M */
0498                     8, 2,   /* N */
0499                     24, 1,  /* mux */
0500                     BIT(31),/* gate */
0501                     0);
0502 
0503 static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0);
0504 
0505 static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
0506 
0507 static const char * const audio_parents[] = { "pll-audio", "pll-audio-2x", "pll-audio-4x" };
0508 static struct ccu_div i2s3_clk = {
0509     .enable     = BIT(31),
0510     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0511     .mux        = _SUNXI_CCU_MUX(24, 2),
0512     .common     = {
0513         .reg        = 0xa0c,
0514         .hw.init    = CLK_HW_INIT_PARENTS("i2s3",
0515                               audio_parents,
0516                               &ccu_div_ops,
0517                               CLK_SET_RATE_PARENT),
0518     },
0519 };
0520 
0521 static struct ccu_div i2s0_clk = {
0522     .enable     = BIT(31),
0523     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0524     .mux        = _SUNXI_CCU_MUX(24, 2),
0525     .common     = {
0526         .reg        = 0xa10,
0527         .hw.init    = CLK_HW_INIT_PARENTS("i2s0",
0528                               audio_parents,
0529                               &ccu_div_ops,
0530                               CLK_SET_RATE_PARENT),
0531     },
0532 };
0533 
0534 static struct ccu_div i2s1_clk = {
0535     .enable     = BIT(31),
0536     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0537     .mux        = _SUNXI_CCU_MUX(24, 2),
0538     .common     = {
0539         .reg        = 0xa14,
0540         .hw.init    = CLK_HW_INIT_PARENTS("i2s1",
0541                               audio_parents,
0542                               &ccu_div_ops,
0543                               CLK_SET_RATE_PARENT),
0544     },
0545 };
0546 
0547 static struct ccu_div i2s2_clk = {
0548     .enable     = BIT(31),
0549     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0550     .mux        = _SUNXI_CCU_MUX(24, 2),
0551     .common     = {
0552         .reg        = 0xa18,
0553         .hw.init    = CLK_HW_INIT_PARENTS("i2s2",
0554                               audio_parents,
0555                               &ccu_div_ops,
0556                               CLK_SET_RATE_PARENT),
0557     },
0558 };
0559 
0560 static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa1c, BIT(0), 0);
0561 static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa1c, BIT(1), 0);
0562 static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", 0xa1c, BIT(2), 0);
0563 static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3", "apb1", 0xa1c, BIT(3), 0);
0564 
0565 static struct ccu_div spdif_clk = {
0566     .enable     = BIT(31),
0567     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0568     .mux        = _SUNXI_CCU_MUX(24, 2),
0569     .common     = {
0570         .reg        = 0xa20,
0571         .hw.init    = CLK_HW_INIT_PARENTS("spdif",
0572                               audio_parents,
0573                               &ccu_div_ops,
0574                               0),
0575     },
0576 };
0577 
0578 static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
0579 
0580 static struct ccu_div dmic_clk = {
0581     .enable     = BIT(31),
0582     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0583     .mux        = _SUNXI_CCU_MUX(24, 2),
0584     .common     = {
0585         .reg        = 0xa40,
0586         .hw.init    = CLK_HW_INIT_PARENTS("dmic",
0587                               audio_parents,
0588                               &ccu_div_ops,
0589                               0),
0590     },
0591 };
0592 
0593 static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
0594 
0595 static struct ccu_div audio_hub_clk = {
0596     .enable     = BIT(31),
0597     .div        = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
0598     .mux        = _SUNXI_CCU_MUX(24, 2),
0599     .common     = {
0600         .reg        = 0xa60,
0601         .hw.init    = CLK_HW_INIT_PARENTS("audio-hub",
0602                               audio_parents,
0603                               &ccu_div_ops,
0604                               0),
0605     },
0606 };
0607 
0608 static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
0609 
0610 /*
0611  * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports.
0612  * We will force them to 0 (12M divided from 48M).
0613  */
0614 #define SUN50I_H6_USB0_CLK_REG      0xa70
0615 #define SUN50I_H6_USB3_CLK_REG      0xa7c
0616 
0617 static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
0618 static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
0619 
0620 static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
0621 
0622 static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
0623 static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc12M", 0xa7c, BIT(29), 0);
0624 static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M", 0xa7c, BIT(27), 0);
0625 static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic", 0xa7c, BIT(26), 0);
0626 
0627 static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
0628 static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
0629 static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
0630 static SUNXI_CCU_GATE(bus_xhci_clk, "bus-xhci", "ahb3", 0xa8c, BIT(5), 0);
0631 static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
0632 static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
0633 
0634 static struct clk_fixed_factor pll_periph0_4x_clk;
0635 static CLK_FIXED_FACTOR_HW(pcie_ref_100m_clk, "pcie-ref-100M",
0636                &pll_periph0_4x_clk.hw, 24, 1, 0);
0637 static SUNXI_CCU_GATE(pcie_ref_clk, "pcie-ref", "pcie-ref-100M",
0638               0xab0, BIT(31), 0);
0639 static SUNXI_CCU_GATE(pcie_ref_out_clk, "pcie-ref-out", "pcie-ref",
0640               0xab0, BIT(30), 0);
0641 
0642 static SUNXI_CCU_M_WITH_GATE(pcie_maxi_clk, "pcie-maxi",
0643                  "pll-periph0", 0xab4,
0644                  0, 4,  /* M */
0645                  BIT(31),   /* gate */
0646                  0);
0647 
0648 static SUNXI_CCU_M_WITH_GATE(pcie_aux_clk, "pcie-aux", "osc24M", 0xab8,
0649                  0, 5,  /* M */
0650                  BIT(31),   /* gate */
0651                  0);
0652 
0653 static SUNXI_CCU_GATE(bus_pcie_clk, "bus-pcie", "psi-ahb1-ahb2",
0654               0xabc, BIT(0), 0);
0655 
0656 static const char * const hdmi_parents[] = { "pll-video0", "pll-video1",
0657                           "pll-video1-4x" };
0658 static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
0659                  0, 4,      /* M */
0660                  24, 2,     /* mux */
0661                  BIT(31),   /* gate */
0662                  0);
0663 
0664 static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
0665 
0666 static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
0667 static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
0668     { .index = 1, .div = 36621 },
0669 };
0670 
0671 #define SUN50I_H6_HDMI_CEC_CLK_REG      0xb10
0672 static struct ccu_mux hdmi_cec_clk = {
0673     .enable     = BIT(31),
0674 
0675     .mux        = {
0676         .shift  = 24,
0677         .width  = 2,
0678 
0679         .fixed_predivs  = hdmi_cec_predivs,
0680         .n_predivs  = ARRAY_SIZE(hdmi_cec_predivs),
0681     },
0682 
0683     .common     = {
0684         .reg        = 0xb10,
0685         .features   = CCU_FEATURE_FIXED_PREDIV,
0686         .hw.init    = CLK_HW_INIT_PARENTS("hdmi-cec",
0687                               hdmi_cec_parents,
0688                               &ccu_mux_ops,
0689                               0),
0690     },
0691 };
0692 
0693 static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
0694 
0695 static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
0696               0xb5c, BIT(0), 0);
0697 
0698 static const char * const tcon_lcd0_parents[] = { "pll-video0",
0699                           "pll-video0-4x",
0700                           "pll-video1" };
0701 static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0",
0702                    tcon_lcd0_parents, 0xb60,
0703                    24, 3,   /* mux */
0704                    BIT(31), /* gate */
0705                    CLK_SET_RATE_PARENT);
0706 
0707 static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb3",
0708               0xb7c, BIT(0), 0);
0709 
0710 static const char * const tcon_tv0_parents[] = { "pll-video0",
0711                          "pll-video0-4x",
0712                          "pll-video1",
0713                          "pll-video1-4x" };
0714 static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
0715                   tcon_tv0_parents, 0xb80,
0716                   0, 4,     /* M */
0717                   8, 2,     /* P */
0718                   24, 3,    /* mux */
0719                   BIT(31),  /* gate */
0720                   CLK_SET_RATE_PARENT);
0721 
0722 static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
0723               0xb9c, BIT(0), 0);
0724 
0725 static SUNXI_CCU_GATE(csi_cci_clk, "csi-cci", "osc24M", 0xc00, BIT(0), 0);
0726 
0727 static const char * const csi_top_parents[] = { "pll-video0", "pll-ve",
0728                           "pll-periph0" };
0729 static const u8 csi_top_table[] = { 0, 2, 3 };
0730 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_top_clk, "csi-top",
0731                        csi_top_parents, csi_top_table, 0xc04,
0732                        0, 4,    /* M */
0733                        24, 3,   /* mux */
0734                        BIT(31), /* gate */
0735                        0);
0736 
0737 static const char * const csi_mclk_parents[] = { "osc24M", "pll-video0",
0738                            "pll-periph0", "pll-periph1" };
0739 static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk",
0740                  csi_mclk_parents, 0xc08,
0741                  0, 5,      /* M */
0742                  24, 3,     /* mux */
0743                  BIT(31),   /* gate */
0744                  0);
0745 
0746 static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb3", 0xc2c, BIT(0), 0);
0747 
0748 static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
0749 static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
0750                  0, 4,      /* M */
0751                  24, 2,     /* mux */
0752                  BIT(31),   /* gate */
0753                  0);
0754 
0755 static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
0756 
0757 /* Fixed factor clocks */
0758 static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
0759 
0760 static const struct clk_hw *clk_parent_pll_audio[] = {
0761     &pll_audio_base_clk.common.hw
0762 };
0763 
0764 /*
0765  * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
0766  * rates can be set exactly in conjunction with sigma-delta modulation.
0767  */
0768 static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
0769                 clk_parent_pll_audio,
0770                 24, 1, CLK_SET_RATE_PARENT);
0771 static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
0772                 clk_parent_pll_audio,
0773                 4, 1, CLK_SET_RATE_PARENT);
0774 static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
0775                 clk_parent_pll_audio,
0776                 2, 1, CLK_SET_RATE_PARENT);
0777 
0778 static const struct clk_hw *pll_periph0_parents[] = {
0779     &pll_periph0_clk.common.hw
0780 };
0781 static CLK_FIXED_FACTOR_HWS(pll_periph0_4x_clk, "pll-periph0-4x",
0782                 pll_periph0_parents,
0783                 1, 4, 0);
0784 static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
0785                 pll_periph0_parents,
0786                 1, 2, 0);
0787 
0788 static const struct clk_hw *pll_periph1_parents[] = {
0789     &pll_periph1_clk.common.hw
0790 };
0791 static CLK_FIXED_FACTOR_HWS(pll_periph1_4x_clk, "pll-periph1-4x",
0792                 pll_periph1_parents,
0793                 1, 4, 0);
0794 static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
0795                 pll_periph1_parents,
0796                 1, 2, 0);
0797 
0798 static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
0799                &pll_video0_clk.common.hw,
0800                1, 4, CLK_SET_RATE_PARENT);
0801 static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
0802                &pll_video1_clk.common.hw,
0803                1, 4, CLK_SET_RATE_PARENT);
0804 
0805 static struct ccu_common *sun50i_h6_ccu_clks[] = {
0806     &pll_cpux_clk.common,
0807     &pll_ddr0_clk.common,
0808     &pll_periph0_clk.common,
0809     &pll_periph1_clk.common,
0810     &pll_gpu_clk.common,
0811     &pll_video0_clk.common,
0812     &pll_video1_clk.common,
0813     &pll_ve_clk.common,
0814     &pll_de_clk.common,
0815     &pll_hsic_clk.common,
0816     &pll_audio_base_clk.common,
0817     &cpux_clk.common,
0818     &axi_clk.common,
0819     &cpux_apb_clk.common,
0820     &psi_ahb1_ahb2_clk.common,
0821     &ahb3_clk.common,
0822     &apb1_clk.common,
0823     &apb2_clk.common,
0824     &mbus_clk.common,
0825     &de_clk.common,
0826     &bus_de_clk.common,
0827     &deinterlace_clk.common,
0828     &bus_deinterlace_clk.common,
0829     &gpu_clk.common,
0830     &bus_gpu_clk.common,
0831     &ce_clk.common,
0832     &bus_ce_clk.common,
0833     &ve_clk.common,
0834     &bus_ve_clk.common,
0835     &emce_clk.common,
0836     &bus_emce_clk.common,
0837     &vp9_clk.common,
0838     &bus_vp9_clk.common,
0839     &bus_dma_clk.common,
0840     &bus_msgbox_clk.common,
0841     &bus_spinlock_clk.common,
0842     &bus_hstimer_clk.common,
0843     &avs_clk.common,
0844     &bus_dbg_clk.common,
0845     &bus_psi_clk.common,
0846     &bus_pwm_clk.common,
0847     &bus_iommu_clk.common,
0848     &dram_clk.common,
0849     &mbus_dma_clk.common,
0850     &mbus_ve_clk.common,
0851     &mbus_ce_clk.common,
0852     &mbus_ts_clk.common,
0853     &mbus_nand_clk.common,
0854     &mbus_csi_clk.common,
0855     &mbus_deinterlace_clk.common,
0856     &bus_dram_clk.common,
0857     &nand0_clk.common,
0858     &nand1_clk.common,
0859     &bus_nand_clk.common,
0860     &mmc0_clk.common,
0861     &mmc1_clk.common,
0862     &mmc2_clk.common,
0863     &bus_mmc0_clk.common,
0864     &bus_mmc1_clk.common,
0865     &bus_mmc2_clk.common,
0866     &bus_uart0_clk.common,
0867     &bus_uart1_clk.common,
0868     &bus_uart2_clk.common,
0869     &bus_uart3_clk.common,
0870     &bus_i2c0_clk.common,
0871     &bus_i2c1_clk.common,
0872     &bus_i2c2_clk.common,
0873     &bus_i2c3_clk.common,
0874     &bus_scr0_clk.common,
0875     &bus_scr1_clk.common,
0876     &spi0_clk.common,
0877     &spi1_clk.common,
0878     &bus_spi0_clk.common,
0879     &bus_spi1_clk.common,
0880     &bus_emac_clk.common,
0881     &ts_clk.common,
0882     &bus_ts_clk.common,
0883     &ir_tx_clk.common,
0884     &bus_ir_tx_clk.common,
0885     &bus_ths_clk.common,
0886     &i2s3_clk.common,
0887     &i2s0_clk.common,
0888     &i2s1_clk.common,
0889     &i2s2_clk.common,
0890     &bus_i2s0_clk.common,
0891     &bus_i2s1_clk.common,
0892     &bus_i2s2_clk.common,
0893     &bus_i2s3_clk.common,
0894     &spdif_clk.common,
0895     &bus_spdif_clk.common,
0896     &dmic_clk.common,
0897     &bus_dmic_clk.common,
0898     &audio_hub_clk.common,
0899     &bus_audio_hub_clk.common,
0900     &usb_ohci0_clk.common,
0901     &usb_phy0_clk.common,
0902     &usb_phy1_clk.common,
0903     &usb_ohci3_clk.common,
0904     &usb_phy3_clk.common,
0905     &usb_hsic_12m_clk.common,
0906     &usb_hsic_clk.common,
0907     &bus_ohci0_clk.common,
0908     &bus_ohci3_clk.common,
0909     &bus_ehci0_clk.common,
0910     &bus_xhci_clk.common,
0911     &bus_ehci3_clk.common,
0912     &bus_otg_clk.common,
0913     &pcie_ref_clk.common,
0914     &pcie_ref_out_clk.common,
0915     &pcie_maxi_clk.common,
0916     &pcie_aux_clk.common,
0917     &bus_pcie_clk.common,
0918     &hdmi_clk.common,
0919     &hdmi_slow_clk.common,
0920     &hdmi_cec_clk.common,
0921     &bus_hdmi_clk.common,
0922     &bus_tcon_top_clk.common,
0923     &tcon_lcd0_clk.common,
0924     &bus_tcon_lcd0_clk.common,
0925     &tcon_tv0_clk.common,
0926     &bus_tcon_tv0_clk.common,
0927     &csi_cci_clk.common,
0928     &csi_top_clk.common,
0929     &csi_mclk_clk.common,
0930     &bus_csi_clk.common,
0931     &hdcp_clk.common,
0932     &bus_hdcp_clk.common,
0933 };
0934 
0935 static struct clk_hw_onecell_data sun50i_h6_hw_clks = {
0936     .hws    = {
0937         [CLK_OSC12M]        = &osc12M_clk.hw,
0938         [CLK_PLL_CPUX]      = &pll_cpux_clk.common.hw,
0939         [CLK_PLL_DDR0]      = &pll_ddr0_clk.common.hw,
0940         [CLK_PLL_PERIPH0]   = &pll_periph0_clk.common.hw,
0941         [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
0942         [CLK_PLL_PERIPH0_4X]    = &pll_periph0_4x_clk.hw,
0943         [CLK_PLL_PERIPH1]   = &pll_periph1_clk.common.hw,
0944         [CLK_PLL_PERIPH1_2X]    = &pll_periph1_2x_clk.hw,
0945         [CLK_PLL_PERIPH1_4X]    = &pll_periph1_4x_clk.hw,
0946         [CLK_PLL_GPU]       = &pll_gpu_clk.common.hw,
0947         [CLK_PLL_VIDEO0]    = &pll_video0_clk.common.hw,
0948         [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
0949         [CLK_PLL_VIDEO1]    = &pll_video1_clk.common.hw,
0950         [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
0951         [CLK_PLL_VE]        = &pll_ve_clk.common.hw,
0952         [CLK_PLL_DE]        = &pll_de_clk.common.hw,
0953         [CLK_PLL_HSIC]      = &pll_hsic_clk.common.hw,
0954         [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
0955         [CLK_PLL_AUDIO]     = &pll_audio_clk.hw,
0956         [CLK_PLL_AUDIO_2X]  = &pll_audio_2x_clk.hw,
0957         [CLK_PLL_AUDIO_4X]  = &pll_audio_4x_clk.hw,
0958         [CLK_CPUX]      = &cpux_clk.common.hw,
0959         [CLK_AXI]       = &axi_clk.common.hw,
0960         [CLK_CPUX_APB]      = &cpux_apb_clk.common.hw,
0961         [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
0962         [CLK_AHB3]      = &ahb3_clk.common.hw,
0963         [CLK_APB1]      = &apb1_clk.common.hw,
0964         [CLK_APB2]      = &apb2_clk.common.hw,
0965         [CLK_MBUS]      = &mbus_clk.common.hw,
0966         [CLK_DE]        = &de_clk.common.hw,
0967         [CLK_BUS_DE]        = &bus_de_clk.common.hw,
0968         [CLK_DEINTERLACE]   = &deinterlace_clk.common.hw,
0969         [CLK_BUS_DEINTERLACE]   = &bus_deinterlace_clk.common.hw,
0970         [CLK_GPU]       = &gpu_clk.common.hw,
0971         [CLK_BUS_GPU]       = &bus_gpu_clk.common.hw,
0972         [CLK_CE]        = &ce_clk.common.hw,
0973         [CLK_BUS_CE]        = &bus_ce_clk.common.hw,
0974         [CLK_VE]        = &ve_clk.common.hw,
0975         [CLK_BUS_VE]        = &bus_ve_clk.common.hw,
0976         [CLK_EMCE]      = &emce_clk.common.hw,
0977         [CLK_BUS_EMCE]      = &bus_emce_clk.common.hw,
0978         [CLK_VP9]       = &vp9_clk.common.hw,
0979         [CLK_BUS_VP9]       = &bus_vp9_clk.common.hw,
0980         [CLK_BUS_DMA]       = &bus_dma_clk.common.hw,
0981         [CLK_BUS_MSGBOX]    = &bus_msgbox_clk.common.hw,
0982         [CLK_BUS_SPINLOCK]  = &bus_spinlock_clk.common.hw,
0983         [CLK_BUS_HSTIMER]   = &bus_hstimer_clk.common.hw,
0984         [CLK_AVS]       = &avs_clk.common.hw,
0985         [CLK_BUS_DBG]       = &bus_dbg_clk.common.hw,
0986         [CLK_BUS_PSI]       = &bus_psi_clk.common.hw,
0987         [CLK_BUS_PWM]       = &bus_pwm_clk.common.hw,
0988         [CLK_BUS_IOMMU]     = &bus_iommu_clk.common.hw,
0989         [CLK_DRAM]      = &dram_clk.common.hw,
0990         [CLK_MBUS_DMA]      = &mbus_dma_clk.common.hw,
0991         [CLK_MBUS_VE]       = &mbus_ve_clk.common.hw,
0992         [CLK_MBUS_CE]       = &mbus_ce_clk.common.hw,
0993         [CLK_MBUS_TS]       = &mbus_ts_clk.common.hw,
0994         [CLK_MBUS_NAND]     = &mbus_nand_clk.common.hw,
0995         [CLK_MBUS_CSI]      = &mbus_csi_clk.common.hw,
0996         [CLK_MBUS_DEINTERLACE]  = &mbus_deinterlace_clk.common.hw,
0997         [CLK_BUS_DRAM]      = &bus_dram_clk.common.hw,
0998         [CLK_NAND0]     = &nand0_clk.common.hw,
0999         [CLK_NAND1]     = &nand1_clk.common.hw,
1000         [CLK_BUS_NAND]      = &bus_nand_clk.common.hw,
1001         [CLK_MMC0]      = &mmc0_clk.common.hw,
1002         [CLK_MMC1]      = &mmc1_clk.common.hw,
1003         [CLK_MMC2]      = &mmc2_clk.common.hw,
1004         [CLK_BUS_MMC0]      = &bus_mmc0_clk.common.hw,
1005         [CLK_BUS_MMC1]      = &bus_mmc1_clk.common.hw,
1006         [CLK_BUS_MMC2]      = &bus_mmc2_clk.common.hw,
1007         [CLK_BUS_UART0]     = &bus_uart0_clk.common.hw,
1008         [CLK_BUS_UART1]     = &bus_uart1_clk.common.hw,
1009         [CLK_BUS_UART2]     = &bus_uart2_clk.common.hw,
1010         [CLK_BUS_UART3]     = &bus_uart3_clk.common.hw,
1011         [CLK_BUS_I2C0]      = &bus_i2c0_clk.common.hw,
1012         [CLK_BUS_I2C1]      = &bus_i2c1_clk.common.hw,
1013         [CLK_BUS_I2C2]      = &bus_i2c2_clk.common.hw,
1014         [CLK_BUS_I2C3]      = &bus_i2c3_clk.common.hw,
1015         [CLK_BUS_SCR0]      = &bus_scr0_clk.common.hw,
1016         [CLK_BUS_SCR1]      = &bus_scr1_clk.common.hw,
1017         [CLK_SPI0]      = &spi0_clk.common.hw,
1018         [CLK_SPI1]      = &spi1_clk.common.hw,
1019         [CLK_BUS_SPI0]      = &bus_spi0_clk.common.hw,
1020         [CLK_BUS_SPI1]      = &bus_spi1_clk.common.hw,
1021         [CLK_BUS_EMAC]      = &bus_emac_clk.common.hw,
1022         [CLK_TS]        = &ts_clk.common.hw,
1023         [CLK_BUS_TS]        = &bus_ts_clk.common.hw,
1024         [CLK_IR_TX]     = &ir_tx_clk.common.hw,
1025         [CLK_BUS_IR_TX]     = &bus_ir_tx_clk.common.hw,
1026         [CLK_BUS_THS]       = &bus_ths_clk.common.hw,
1027         [CLK_I2S3]      = &i2s3_clk.common.hw,
1028         [CLK_I2S0]      = &i2s0_clk.common.hw,
1029         [CLK_I2S1]      = &i2s1_clk.common.hw,
1030         [CLK_I2S2]      = &i2s2_clk.common.hw,
1031         [CLK_BUS_I2S0]      = &bus_i2s0_clk.common.hw,
1032         [CLK_BUS_I2S1]      = &bus_i2s1_clk.common.hw,
1033         [CLK_BUS_I2S2]      = &bus_i2s2_clk.common.hw,
1034         [CLK_BUS_I2S3]      = &bus_i2s3_clk.common.hw,
1035         [CLK_SPDIF]     = &spdif_clk.common.hw,
1036         [CLK_BUS_SPDIF]     = &bus_spdif_clk.common.hw,
1037         [CLK_DMIC]      = &dmic_clk.common.hw,
1038         [CLK_BUS_DMIC]      = &bus_dmic_clk.common.hw,
1039         [CLK_AUDIO_HUB]     = &audio_hub_clk.common.hw,
1040         [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw,
1041         [CLK_USB_OHCI0]     = &usb_ohci0_clk.common.hw,
1042         [CLK_USB_PHY0]      = &usb_phy0_clk.common.hw,
1043         [CLK_USB_PHY1]      = &usb_phy1_clk.common.hw,
1044         [CLK_USB_OHCI3]     = &usb_ohci3_clk.common.hw,
1045         [CLK_USB_PHY3]      = &usb_phy3_clk.common.hw,
1046         [CLK_USB_HSIC_12M]  = &usb_hsic_12m_clk.common.hw,
1047         [CLK_USB_HSIC]      = &usb_hsic_clk.common.hw,
1048         [CLK_BUS_OHCI0]     = &bus_ohci0_clk.common.hw,
1049         [CLK_BUS_OHCI3]     = &bus_ohci3_clk.common.hw,
1050         [CLK_BUS_EHCI0]     = &bus_ehci0_clk.common.hw,
1051         [CLK_BUS_XHCI]      = &bus_xhci_clk.common.hw,
1052         [CLK_BUS_EHCI3]     = &bus_ehci3_clk.common.hw,
1053         [CLK_BUS_OTG]       = &bus_otg_clk.common.hw,
1054         [CLK_PCIE_REF_100M] = &pcie_ref_100m_clk.hw,
1055         [CLK_PCIE_REF]      = &pcie_ref_clk.common.hw,
1056         [CLK_PCIE_REF_OUT]  = &pcie_ref_out_clk.common.hw,
1057         [CLK_PCIE_MAXI]     = &pcie_maxi_clk.common.hw,
1058         [CLK_PCIE_AUX]      = &pcie_aux_clk.common.hw,
1059         [CLK_BUS_PCIE]      = &bus_pcie_clk.common.hw,
1060         [CLK_HDMI]      = &hdmi_clk.common.hw,
1061         [CLK_HDMI_SLOW]     = &hdmi_slow_clk.common.hw,
1062         [CLK_HDMI_CEC]      = &hdmi_cec_clk.common.hw,
1063         [CLK_BUS_HDMI]      = &bus_hdmi_clk.common.hw,
1064         [CLK_BUS_TCON_TOP]  = &bus_tcon_top_clk.common.hw,
1065         [CLK_TCON_LCD0]     = &tcon_lcd0_clk.common.hw,
1066         [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw,
1067         [CLK_TCON_TV0]      = &tcon_tv0_clk.common.hw,
1068         [CLK_BUS_TCON_TV0]  = &bus_tcon_tv0_clk.common.hw,
1069         [CLK_CSI_CCI]       = &csi_cci_clk.common.hw,
1070         [CLK_CSI_TOP]       = &csi_top_clk.common.hw,
1071         [CLK_CSI_MCLK]      = &csi_mclk_clk.common.hw,
1072         [CLK_BUS_CSI]       = &bus_csi_clk.common.hw,
1073         [CLK_HDCP]      = &hdcp_clk.common.hw,
1074         [CLK_BUS_HDCP]      = &bus_hdcp_clk.common.hw,
1075     },
1076     .num = CLK_NUMBER,
1077 };
1078 
1079 static struct ccu_reset_map sun50i_h6_ccu_resets[] = {
1080     [RST_MBUS]      = { 0x540, BIT(30) },
1081 
1082     [RST_BUS_DE]        = { 0x60c, BIT(16) },
1083     [RST_BUS_DEINTERLACE]   = { 0x62c, BIT(16) },
1084     [RST_BUS_GPU]       = { 0x67c, BIT(16) },
1085     [RST_BUS_CE]        = { 0x68c, BIT(16) },
1086     [RST_BUS_VE]        = { 0x69c, BIT(16) },
1087     [RST_BUS_EMCE]      = { 0x6bc, BIT(16) },
1088     [RST_BUS_VP9]       = { 0x6cc, BIT(16) },
1089     [RST_BUS_DMA]       = { 0x70c, BIT(16) },
1090     [RST_BUS_MSGBOX]    = { 0x71c, BIT(16) },
1091     [RST_BUS_SPINLOCK]  = { 0x72c, BIT(16) },
1092     [RST_BUS_HSTIMER]   = { 0x73c, BIT(16) },
1093     [RST_BUS_DBG]       = { 0x78c, BIT(16) },
1094     [RST_BUS_PSI]       = { 0x79c, BIT(16) },
1095     [RST_BUS_PWM]       = { 0x7ac, BIT(16) },
1096     [RST_BUS_IOMMU]     = { 0x7bc, BIT(16) },
1097     [RST_BUS_DRAM]      = { 0x80c, BIT(16) },
1098     [RST_BUS_NAND]      = { 0x82c, BIT(16) },
1099     [RST_BUS_MMC0]      = { 0x84c, BIT(16) },
1100     [RST_BUS_MMC1]      = { 0x84c, BIT(17) },
1101     [RST_BUS_MMC2]      = { 0x84c, BIT(18) },
1102     [RST_BUS_UART0]     = { 0x90c, BIT(16) },
1103     [RST_BUS_UART1]     = { 0x90c, BIT(17) },
1104     [RST_BUS_UART2]     = { 0x90c, BIT(18) },
1105     [RST_BUS_UART3]     = { 0x90c, BIT(19) },
1106     [RST_BUS_I2C0]      = { 0x91c, BIT(16) },
1107     [RST_BUS_I2C1]      = { 0x91c, BIT(17) },
1108     [RST_BUS_I2C2]      = { 0x91c, BIT(18) },
1109     [RST_BUS_I2C3]      = { 0x91c, BIT(19) },
1110     [RST_BUS_SCR0]      = { 0x93c, BIT(16) },
1111     [RST_BUS_SCR1]      = { 0x93c, BIT(17) },
1112     [RST_BUS_SPI0]      = { 0x96c, BIT(16) },
1113     [RST_BUS_SPI1]      = { 0x96c, BIT(17) },
1114     [RST_BUS_EMAC]      = { 0x97c, BIT(16) },
1115     [RST_BUS_TS]        = { 0x9bc, BIT(16) },
1116     [RST_BUS_IR_TX]     = { 0x9cc, BIT(16) },
1117     [RST_BUS_THS]       = { 0x9fc, BIT(16) },
1118     [RST_BUS_I2S0]      = { 0xa1c, BIT(16) },
1119     [RST_BUS_I2S1]      = { 0xa1c, BIT(17) },
1120     [RST_BUS_I2S2]      = { 0xa1c, BIT(18) },
1121     [RST_BUS_I2S3]      = { 0xa1c, BIT(19) },
1122     [RST_BUS_SPDIF]     = { 0xa2c, BIT(16) },
1123     [RST_BUS_DMIC]      = { 0xa4c, BIT(16) },
1124     [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) },
1125 
1126     [RST_USB_PHY0]      = { 0xa70, BIT(30) },
1127     [RST_USB_PHY1]      = { 0xa74, BIT(30) },
1128     [RST_USB_PHY3]      = { 0xa7c, BIT(30) },
1129     [RST_USB_HSIC]      = { 0xa7c, BIT(28) },
1130 
1131     [RST_BUS_OHCI0]     = { 0xa8c, BIT(16) },
1132     [RST_BUS_OHCI3]     = { 0xa8c, BIT(19) },
1133     [RST_BUS_EHCI0]     = { 0xa8c, BIT(20) },
1134     [RST_BUS_XHCI]      = { 0xa8c, BIT(21) },
1135     [RST_BUS_EHCI3]     = { 0xa8c, BIT(23) },
1136     [RST_BUS_OTG]       = { 0xa8c, BIT(24) },
1137     [RST_BUS_PCIE]      = { 0xabc, BIT(16) },
1138 
1139     [RST_PCIE_POWERUP]  = { 0xabc, BIT(17) },
1140 
1141     [RST_BUS_HDMI]      = { 0xb1c, BIT(16) },
1142     [RST_BUS_HDMI_SUB]  = { 0xb1c, BIT(17) },
1143     [RST_BUS_TCON_TOP]  = { 0xb5c, BIT(16) },
1144     [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) },
1145     [RST_BUS_TCON_TV0]  = { 0xb9c, BIT(16) },
1146     [RST_BUS_CSI]       = { 0xc2c, BIT(16) },
1147     [RST_BUS_HDCP]      = { 0xc4c, BIT(16) },
1148 };
1149 
1150 static const struct sunxi_ccu_desc sun50i_h6_ccu_desc = {
1151     .ccu_clks   = sun50i_h6_ccu_clks,
1152     .num_ccu_clks   = ARRAY_SIZE(sun50i_h6_ccu_clks),
1153 
1154     .hw_clks    = &sun50i_h6_hw_clks,
1155 
1156     .resets     = sun50i_h6_ccu_resets,
1157     .num_resets = ARRAY_SIZE(sun50i_h6_ccu_resets),
1158 };
1159 
1160 static const u32 pll_regs[] = {
1161     SUN50I_H6_PLL_CPUX_REG,
1162     SUN50I_H6_PLL_DDR0_REG,
1163     SUN50I_H6_PLL_PERIPH0_REG,
1164     SUN50I_H6_PLL_PERIPH1_REG,
1165     SUN50I_H6_PLL_GPU_REG,
1166     SUN50I_H6_PLL_VIDEO0_REG,
1167     SUN50I_H6_PLL_VIDEO1_REG,
1168     SUN50I_H6_PLL_VE_REG,
1169     SUN50I_H6_PLL_DE_REG,
1170     SUN50I_H6_PLL_HSIC_REG,
1171     SUN50I_H6_PLL_AUDIO_REG,
1172 };
1173 
1174 static const u32 pll_video_regs[] = {
1175     SUN50I_H6_PLL_VIDEO0_REG,
1176     SUN50I_H6_PLL_VIDEO1_REG,
1177 };
1178 
1179 static const u32 usb2_clk_regs[] = {
1180     SUN50I_H6_USB0_CLK_REG,
1181     SUN50I_H6_USB3_CLK_REG,
1182 };
1183 
1184 static int sun50i_h6_ccu_probe(struct platform_device *pdev)
1185 {
1186     void __iomem *reg;
1187     u32 val;
1188     int i;
1189 
1190     reg = devm_platform_ioremap_resource(pdev, 0);
1191     if (IS_ERR(reg))
1192         return PTR_ERR(reg);
1193 
1194     /*
1195      * Force PLL_GPU output divider bits to 0 and adjust
1196      * multiplier to sensible default value of 432 MHz.
1197      */
1198     val = readl(reg + SUN50I_H6_PLL_GPU_REG);
1199     val &= ~(GENMASK(15, 8) | BIT(0));
1200     val |= 17 << 8;
1201     writel(val, reg + SUN50I_H6_PLL_GPU_REG);
1202 
1203     /* Force GPU_CLK divider bits to 0 */
1204     val = readl(reg + gpu_clk.common.reg);
1205     val &= ~GENMASK(3, 0);
1206     writel(val, reg + gpu_clk.common.reg);
1207 
1208     /* Enable the lock bits on all PLLs */
1209     for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
1210         val = readl(reg + pll_regs[i]);
1211         val |= BIT(29);
1212         writel(val, reg + pll_regs[i]);
1213     }
1214 
1215     /*
1216      * Force the output divider of video PLLs to 0.
1217      *
1218      * See the comment before pll-video0 definition for the reason.
1219      */
1220     for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
1221         val = readl(reg + pll_video_regs[i]);
1222         val &= ~BIT(0);
1223         writel(val, reg + pll_video_regs[i]);
1224     }
1225 
1226     /*
1227      * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
1228      *
1229      * This clock mux is still mysterious, and the code just enforces
1230      * it to have a valid clock parent.
1231      */
1232     for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
1233         val = readl(reg + usb2_clk_regs[i]);
1234         val &= ~GENMASK(25, 24);
1235         writel (val, reg + usb2_clk_regs[i]);
1236     }
1237 
1238     /*
1239      * Force the post-divider of pll-audio to 12 and the output divider
1240      * of it to 2, so 24576000 and 22579200 rates can be set exactly.
1241      */
1242     val = readl(reg + SUN50I_H6_PLL_AUDIO_REG);
1243     val &= ~(GENMASK(21, 16) | BIT(0));
1244     writel(val | (11 << 16) | BIT(0), reg + SUN50I_H6_PLL_AUDIO_REG);
1245 
1246     /*
1247      * First clock parent (osc32K) is unusable for CEC. But since there
1248      * is no good way to force parent switch (both run with same frequency),
1249      * just set second clock parent here.
1250      */
1251     val = readl(reg + SUN50I_H6_HDMI_CEC_CLK_REG);
1252     val |= BIT(24);
1253     writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
1254 
1255     return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
1256 }
1257 
1258 static const struct of_device_id sun50i_h6_ccu_ids[] = {
1259     { .compatible = "allwinner,sun50i-h6-ccu" },
1260     { }
1261 };
1262 
1263 static struct platform_driver sun50i_h6_ccu_driver = {
1264     .probe  = sun50i_h6_ccu_probe,
1265     .driver = {
1266         .name   = "sun50i-h6-ccu",
1267         .suppress_bind_attrs = true,
1268         .of_match_table = sun50i_h6_ccu_ids,
1269     },
1270 };
1271 module_platform_driver(sun50i_h6_ccu_driver);
1272 
1273 MODULE_IMPORT_NS(SUNXI_CCU);
1274 MODULE_LICENSE("GPL");