Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
0004  *
0005  * Based on ccu-sun8i-h3.c, which is:
0006  * Copyright (c) 2016 Maxime Ripard. All rights reserved.
0007  */
0008 
0009 #include <linux/clk-provider.h>
0010 #include <linux/io.h>
0011 #include <linux/module.h>
0012 #include <linux/of_device.h>
0013 #include <linux/platform_device.h>
0014 
0015 #include "ccu_common.h"
0016 #include "ccu_reset.h"
0017 
0018 #include "ccu_div.h"
0019 #include "ccu_gate.h"
0020 #include "ccu_mp.h"
0021 #include "ccu_mult.h"
0022 #include "ccu_nk.h"
0023 #include "ccu_nkm.h"
0024 #include "ccu_nkmp.h"
0025 #include "ccu_nm.h"
0026 #include "ccu_phase.h"
0027 
0028 #include "ccu-sun8i-v3s.h"
0029 
0030 static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpu_clk, "pll-cpu",
0031                      "osc24M", 0x000,
0032                      8, 5,  /* N */
0033                      4, 2,  /* K */
0034                      0, 2,  /* M */
0035                      16, 2, /* P */
0036                      BIT(31),   /* gate */
0037                      BIT(28),   /* lock */
0038                      0);
0039 
0040 /*
0041  * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
0042  * the base (2x, 4x and 8x), and one variable divider (the one true
0043  * pll audio).
0044  *
0045  * With sigma-delta modulation for fractional-N on the audio PLL,
0046  * we have to use specific dividers. This means the variable divider
0047  * can no longer be used, as the audio codec requests the exact clock
0048  * rates we support through this mechanism. So we now hard code the
0049  * variable divider to 1. This means the clock rates will no longer
0050  * match the clock names.
0051  */
0052 #define SUN8I_V3S_PLL_AUDIO_REG 0x008
0053 
0054 static struct ccu_sdm_setting pll_audio_sdm_table[] = {
0055     { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 },
0056     { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 },
0057 };
0058 
0059 static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
0060                        "osc24M", 0x008,
0061                        8, 7,    /* N */
0062                        0, 5,    /* M */
0063                        pll_audio_sdm_table, BIT(24),
0064                        0x284, BIT(31),
0065                        BIT(31), /* gate */
0066                        BIT(28), /* lock */
0067                        CLK_SET_RATE_UNGATE);
0068 
0069 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
0070                     "osc24M", 0x0010,
0071                     8, 7,       /* N */
0072                     0, 4,       /* M */
0073                     BIT(24),    /* frac enable */
0074                     BIT(25),    /* frac select */
0075                     270000000,  /* frac rate 0 */
0076                     297000000,  /* frac rate 1 */
0077                     BIT(31),    /* gate */
0078                     BIT(28),    /* lock */
0079                     0);
0080 
0081 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
0082                     "osc24M", 0x0018,
0083                     8, 7,       /* N */
0084                     0, 4,       /* M */
0085                     BIT(24),    /* frac enable */
0086                     BIT(25),    /* frac select */
0087                     270000000,  /* frac rate 0 */
0088                     297000000,  /* frac rate 1 */
0089                     BIT(31),    /* gate */
0090                     BIT(28),    /* lock */
0091                     0);
0092 
0093 static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0",
0094                     "osc24M", 0x020,
0095                     8, 5,   /* N */
0096                     4, 2,   /* K */
0097                     0, 2,   /* M */
0098                     BIT(31),    /* gate */
0099                     BIT(28),    /* lock */
0100                     0);
0101 
0102 static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph0_clk, "pll-periph0",
0103                        "osc24M", 0x028,
0104                        8, 5,    /* N */
0105                        4, 2,    /* K */
0106                        BIT(31), /* gate */
0107                        BIT(28), /* lock */
0108                        2,       /* post-div */
0109                        0);
0110 
0111 static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_isp_clk, "pll-isp",
0112                     "osc24M", 0x002c,
0113                     8, 7,       /* N */
0114                     0, 4,       /* M */
0115                     BIT(24),    /* frac enable */
0116                     BIT(25),    /* frac select */
0117                     270000000,  /* frac rate 0 */
0118                     297000000,  /* frac rate 1 */
0119                     BIT(31),    /* gate */
0120                     BIT(28),    /* lock */
0121                     0);
0122 
0123 static SUNXI_CCU_NK_WITH_GATE_LOCK_POSTDIV(pll_periph1_clk, "pll-periph1",
0124                        "osc24M", 0x044,
0125                        8, 5,    /* N */
0126                        4, 2,    /* K */
0127                        BIT(31), /* gate */
0128                        BIT(28), /* lock */
0129                        2,       /* post-div */
0130                        0);
0131 
0132 static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
0133                    "osc24M", 0x04c,
0134                    8, 7,    /* N */
0135                    0, 2,    /* M */
0136                    BIT(31), /* gate */
0137                    BIT(28), /* lock */
0138                    0);
0139 
0140 static const char * const cpu_parents[] = { "osc32k", "osc24M",
0141                          "pll-cpu", "pll-cpu" };
0142 static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents,
0143              0x050, 16, 2, CLK_IS_CRITICAL);
0144 
0145 static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x050, 0, 2, 0);
0146 
0147 static const char * const ahb1_parents[] = { "osc32k", "osc24M",
0148                          "axi", "pll-periph0" };
0149 static const struct ccu_mux_var_prediv ahb1_predivs[] = {
0150     { .index = 3, .shift = 6, .width = 2 },
0151 };
0152 static struct ccu_div ahb1_clk = {
0153     .div        = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
0154 
0155     .mux        = {
0156         .shift  = 12,
0157         .width  = 2,
0158 
0159         .var_predivs    = ahb1_predivs,
0160         .n_var_predivs  = ARRAY_SIZE(ahb1_predivs),
0161     },
0162 
0163     .common     = {
0164         .reg        = 0x054,
0165         .features   = CCU_FEATURE_VARIABLE_PREDIV,
0166         .hw.init    = CLK_HW_INIT_PARENTS("ahb1",
0167                               ahb1_parents,
0168                               &ccu_div_ops,
0169                               0),
0170     },
0171 };
0172 
0173 static struct clk_div_table apb1_div_table[] = {
0174     { .val = 0, .div = 2 },
0175     { .val = 1, .div = 2 },
0176     { .val = 2, .div = 4 },
0177     { .val = 3, .div = 8 },
0178     { /* Sentinel */ },
0179 };
0180 static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
0181                0x054, 8, 2, apb1_div_table, 0);
0182 
0183 static const char * const apb2_parents[] = { "osc32k", "osc24M",
0184                          "pll-periph0", "pll-periph0" };
0185 static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
0186                  0, 5,  /* M */
0187                  16, 2, /* P */
0188                  24, 2, /* mux */
0189                  0);
0190 
0191 static const char * const ahb2_parents[] = { "ahb1", "pll-periph0" };
0192 static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = {
0193     { .index = 1, .div = 2 },
0194 };
0195 static struct ccu_mux ahb2_clk = {
0196     .mux        = {
0197         .shift  = 0,
0198         .width  = 1,
0199         .fixed_predivs  = ahb2_fixed_predivs,
0200         .n_predivs  = ARRAY_SIZE(ahb2_fixed_predivs),
0201     },
0202 
0203     .common     = {
0204         .reg        = 0x05c,
0205         .features   = CCU_FEATURE_FIXED_PREDIV,
0206         .hw.init    = CLK_HW_INIT_PARENTS("ahb2",
0207                               ahb2_parents,
0208                               &ccu_mux_ops,
0209                               0),
0210     },
0211 };
0212 
0213 static SUNXI_CCU_GATE(bus_ce_clk,   "bus-ce",   "ahb1",
0214               0x060, BIT(5), 0);
0215 static SUNXI_CCU_GATE(bus_dma_clk,  "bus-dma",  "ahb1",
0216               0x060, BIT(6), 0);
0217 static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1",
0218               0x060, BIT(8), 0);
0219 static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1",
0220               0x060, BIT(9), 0);
0221 static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1",
0222               0x060, BIT(10), 0);
0223 static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1",
0224               0x060, BIT(14), 0);
0225 static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2",
0226               0x060, BIT(17), 0);
0227 static SUNXI_CCU_GATE(bus_hstimer_clk,  "bus-hstimer",  "ahb1",
0228               0x060, BIT(19), 0);
0229 static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1",
0230               0x060, BIT(20), 0);
0231 static SUNXI_CCU_GATE(bus_otg_clk,  "bus-otg",  "ahb1",
0232               0x060, BIT(24), 0);
0233 static SUNXI_CCU_GATE(bus_ehci0_clk,    "bus-ehci0",    "ahb1",
0234               0x060, BIT(26), 0);
0235 static SUNXI_CCU_GATE(bus_ohci0_clk,    "bus-ohci0",    "ahb1",
0236               0x060, BIT(29), 0);
0237 
0238 static SUNXI_CCU_GATE(bus_ve_clk,   "bus-ve",   "ahb1",
0239               0x064, BIT(0), 0);
0240 static SUNXI_CCU_GATE(bus_tcon0_clk,    "bus-tcon0",    "ahb1",
0241               0x064, BIT(4), 0);
0242 static SUNXI_CCU_GATE(bus_csi_clk,  "bus-csi",  "ahb1",
0243               0x064, BIT(8), 0);
0244 static SUNXI_CCU_GATE(bus_de_clk,   "bus-de",   "ahb1",
0245               0x064, BIT(12), 0);
0246 
0247 static SUNXI_CCU_GATE(bus_codec_clk,    "bus-codec",    "apb1",
0248               0x068, BIT(0), 0);
0249 static SUNXI_CCU_GATE(bus_pio_clk,  "bus-pio",  "apb1",
0250               0x068, BIT(5), 0);
0251 static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1",
0252               0x068, BIT(12), 0);
0253 
0254 static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2",
0255               0x06c, BIT(0), 0);
0256 static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2",
0257               0x06c, BIT(1), 0);
0258 static SUNXI_CCU_GATE(bus_uart0_clk,    "bus-uart0",    "apb2",
0259               0x06c, BIT(16), 0);
0260 static SUNXI_CCU_GATE(bus_uart1_clk,    "bus-uart1",    "apb2",
0261               0x06c, BIT(17), 0);
0262 static SUNXI_CCU_GATE(bus_uart2_clk,    "bus-uart2",    "apb2",
0263               0x06c, BIT(18), 0);
0264 
0265 static SUNXI_CCU_GATE(bus_ephy_clk, "bus-ephy", "ahb1",
0266               0x070, BIT(0), 0);
0267 static SUNXI_CCU_GATE(bus_dbg_clk,  "bus-dbg",  "ahb1",
0268               0x070, BIT(7), 0);
0269 
0270 static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0",
0271                              "pll-periph1" };
0272 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
0273                   0, 4,     /* M */
0274                   16, 2,    /* P */
0275                   24, 2,    /* mux */
0276                   BIT(31),  /* gate */
0277                   0);
0278 
0279 static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
0280                0x088, 20, 3, 0);
0281 static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
0282                0x088, 8, 3, 0);
0283 
0284 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
0285                   0, 4,     /* M */
0286                   16, 2,    /* P */
0287                   24, 2,    /* mux */
0288                   BIT(31),  /* gate */
0289                   0);
0290 
0291 static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
0292                0x08c, 20, 3, 0);
0293 static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
0294                0x08c, 8, 3, 0);
0295 
0296 static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090,
0297                   0, 4,     /* M */
0298                   16, 2,    /* P */
0299                   24, 2,    /* mux */
0300                   BIT(31),  /* gate */
0301                   0);
0302 
0303 static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
0304                0x090, 20, 3, 0);
0305 static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
0306                0x090, 8, 3, 0);
0307 
0308 static const char * const ce_parents[] = { "osc24M", "pll-periph0", };
0309 
0310 static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c,
0311                   0, 4,     /* M */
0312                   16, 2,    /* P */
0313                   24, 2,    /* mux */
0314                   BIT(31),  /* gate */
0315                   0);
0316 
0317 static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
0318                   0, 4,     /* M */
0319                   16, 2,    /* P */
0320                   24, 2,    /* mux */
0321                   BIT(31),  /* gate */
0322                   0);
0323 
0324 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
0325                         "pll-audio-2x", "pll-audio" };
0326 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
0327                    0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
0328 
0329 static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
0330               0x0cc, BIT(8), 0);
0331 static SUNXI_CCU_GATE(usb_ohci0_clk,    "usb-ohci0",    "osc24M",
0332               0x0cc, BIT(16), 0);
0333 
0334 static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1",
0335                          "pll-periph0-2x" };
0336 static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
0337                 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL);
0338 
0339 static SUNXI_CCU_GATE(dram_ve_clk,  "dram-ve",  "dram",
0340               0x100, BIT(0), 0);
0341 static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram",
0342               0x100, BIT(1), 0);
0343 static SUNXI_CCU_GATE(dram_ehci_clk,    "dram-ehci",    "dram",
0344               0x100, BIT(17), 0);
0345 static SUNXI_CCU_GATE(dram_ohci_clk,    "dram-ohci",    "dram",
0346               0x100, BIT(18), 0);
0347 
0348 static const char * const de_parents[] = { "pll-video", "pll-periph0" };
0349 static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
0350                  0x104, 0, 4, 24, 2, BIT(31),
0351                  CLK_SET_RATE_PARENT);
0352 
0353 static const char * const tcon_parents[] = { "pll-video" };
0354 static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents,
0355                  0x118, 0, 4, 24, 3, BIT(31), 0);
0356 
0357 static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M",
0358               0x130, BIT(31), 0);
0359 
0360 static const char * const csi_mclk_parents[] = { "osc24M", "pll-video",
0361                          "pll-periph0", "pll-periph1" };
0362 static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", csi_mclk_parents,
0363                  0x130, 0, 5, 8, 3, BIT(15), 0);
0364 
0365 static const char * const csi1_sclk_parents[] = { "pll-video", "pll-isp" };
0366 static SUNXI_CCU_M_WITH_MUX_GATE(csi1_sclk_clk, "csi-sclk", csi1_sclk_parents,
0367                  0x134, 16, 4, 24, 3, BIT(31), 0);
0368 
0369 static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi-mclk", csi_mclk_parents,
0370                  0x134, 0, 5, 8, 3, BIT(15), 0);
0371 
0372 static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
0373                  0x13c, 16, 3, BIT(31), 0);
0374 
0375 static SUNXI_CCU_GATE(ac_dig_clk,   "ac-dig",   "pll-audio",
0376               0x140, BIT(31), CLK_SET_RATE_PARENT);
0377 static SUNXI_CCU_GATE(avs_clk,      "avs",      "osc24M",
0378               0x144, BIT(31), 0);
0379 
0380 static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
0381                          "pll-ddr" };
0382 static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
0383                  0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
0384 
0385 static const char * const mipi_csi_parents[] = { "pll-video", "pll-periph0",
0386                          "pll-isp" };
0387 static SUNXI_CCU_M_WITH_MUX_GATE(mipi_csi_clk, "mipi-csi", mipi_csi_parents,
0388                  0x16c, 0, 3, 24, 2, BIT(31), 0);
0389 
0390 static struct ccu_common *sun8i_v3s_ccu_clks[] = {
0391     &pll_cpu_clk.common,
0392     &pll_audio_base_clk.common,
0393     &pll_video_clk.common,
0394     &pll_ve_clk.common,
0395     &pll_ddr0_clk.common,
0396     &pll_periph0_clk.common,
0397     &pll_isp_clk.common,
0398     &pll_periph1_clk.common,
0399     &pll_ddr1_clk.common,
0400     &cpu_clk.common,
0401     &axi_clk.common,
0402     &ahb1_clk.common,
0403     &apb1_clk.common,
0404     &apb2_clk.common,
0405     &ahb2_clk.common,
0406     &bus_ce_clk.common,
0407     &bus_dma_clk.common,
0408     &bus_mmc0_clk.common,
0409     &bus_mmc1_clk.common,
0410     &bus_mmc2_clk.common,
0411     &bus_dram_clk.common,
0412     &bus_emac_clk.common,
0413     &bus_hstimer_clk.common,
0414     &bus_spi0_clk.common,
0415     &bus_otg_clk.common,
0416     &bus_ehci0_clk.common,
0417     &bus_ohci0_clk.common,
0418     &bus_ve_clk.common,
0419     &bus_tcon0_clk.common,
0420     &bus_csi_clk.common,
0421     &bus_de_clk.common,
0422     &bus_codec_clk.common,
0423     &bus_pio_clk.common,
0424     &bus_i2s0_clk.common,
0425     &bus_i2c0_clk.common,
0426     &bus_i2c1_clk.common,
0427     &bus_uart0_clk.common,
0428     &bus_uart1_clk.common,
0429     &bus_uart2_clk.common,
0430     &bus_ephy_clk.common,
0431     &bus_dbg_clk.common,
0432     &mmc0_clk.common,
0433     &mmc0_sample_clk.common,
0434     &mmc0_output_clk.common,
0435     &mmc1_clk.common,
0436     &mmc1_sample_clk.common,
0437     &mmc1_output_clk.common,
0438     &mmc2_clk.common,
0439     &mmc2_sample_clk.common,
0440     &mmc2_output_clk.common,
0441     &ce_clk.common,
0442     &spi0_clk.common,
0443     &i2s0_clk.common,
0444     &usb_phy0_clk.common,
0445     &usb_ohci0_clk.common,
0446     &dram_clk.common,
0447     &dram_ve_clk.common,
0448     &dram_csi_clk.common,
0449     &dram_ohci_clk.common,
0450     &dram_ehci_clk.common,
0451     &de_clk.common,
0452     &tcon_clk.common,
0453     &csi_misc_clk.common,
0454     &csi0_mclk_clk.common,
0455     &csi1_sclk_clk.common,
0456     &csi1_mclk_clk.common,
0457     &ve_clk.common,
0458     &ac_dig_clk.common,
0459     &avs_clk.common,
0460     &mbus_clk.common,
0461     &mipi_csi_clk.common,
0462 };
0463 
0464 static const struct clk_hw *clk_parent_pll_audio[] = {
0465     &pll_audio_base_clk.common.hw
0466 };
0467 
0468 /* We hardcode the divider to 1 for SDM support */
0469 static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio",
0470                 clk_parent_pll_audio,
0471                 1, 1, CLK_SET_RATE_PARENT);
0472 static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
0473                 clk_parent_pll_audio,
0474                 2, 1, CLK_SET_RATE_PARENT);
0475 static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
0476                 clk_parent_pll_audio,
0477                 1, 1, CLK_SET_RATE_PARENT);
0478 static CLK_FIXED_FACTOR_HWS(pll_audio_8x_clk, "pll-audio-8x",
0479                 clk_parent_pll_audio,
0480                 1, 2, CLK_SET_RATE_PARENT);
0481 static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x",
0482                &pll_periph0_clk.common.hw,
0483                1, 2, 0);
0484 
0485 static struct clk_hw_onecell_data sun8i_v3s_hw_clks = {
0486     .hws    = {
0487         [CLK_PLL_CPU]       = &pll_cpu_clk.common.hw,
0488         [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
0489         [CLK_PLL_AUDIO]     = &pll_audio_clk.hw,
0490         [CLK_PLL_AUDIO_2X]  = &pll_audio_2x_clk.hw,
0491         [CLK_PLL_AUDIO_4X]  = &pll_audio_4x_clk.hw,
0492         [CLK_PLL_AUDIO_8X]  = &pll_audio_8x_clk.hw,
0493         [CLK_PLL_VIDEO]     = &pll_video_clk.common.hw,
0494         [CLK_PLL_VE]        = &pll_ve_clk.common.hw,
0495         [CLK_PLL_DDR0]      = &pll_ddr0_clk.common.hw,
0496         [CLK_PLL_PERIPH0]   = &pll_periph0_clk.common.hw,
0497         [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
0498         [CLK_PLL_ISP]       = &pll_isp_clk.common.hw,
0499         [CLK_PLL_PERIPH1]   = &pll_periph1_clk.common.hw,
0500         [CLK_PLL_DDR1]      = &pll_ddr1_clk.common.hw,
0501         [CLK_CPU]       = &cpu_clk.common.hw,
0502         [CLK_AXI]       = &axi_clk.common.hw,
0503         [CLK_AHB1]      = &ahb1_clk.common.hw,
0504         [CLK_APB1]      = &apb1_clk.common.hw,
0505         [CLK_APB2]      = &apb2_clk.common.hw,
0506         [CLK_AHB2]      = &ahb2_clk.common.hw,
0507         [CLK_BUS_CE]        = &bus_ce_clk.common.hw,
0508         [CLK_BUS_DMA]       = &bus_dma_clk.common.hw,
0509         [CLK_BUS_MMC0]      = &bus_mmc0_clk.common.hw,
0510         [CLK_BUS_MMC1]      = &bus_mmc1_clk.common.hw,
0511         [CLK_BUS_MMC2]      = &bus_mmc2_clk.common.hw,
0512         [CLK_BUS_DRAM]      = &bus_dram_clk.common.hw,
0513         [CLK_BUS_EMAC]      = &bus_emac_clk.common.hw,
0514         [CLK_BUS_HSTIMER]   = &bus_hstimer_clk.common.hw,
0515         [CLK_BUS_SPI0]      = &bus_spi0_clk.common.hw,
0516         [CLK_BUS_OTG]       = &bus_otg_clk.common.hw,
0517         [CLK_BUS_EHCI0]     = &bus_ehci0_clk.common.hw,
0518         [CLK_BUS_OHCI0]     = &bus_ohci0_clk.common.hw,
0519         [CLK_BUS_VE]        = &bus_ve_clk.common.hw,
0520         [CLK_BUS_TCON0]     = &bus_tcon0_clk.common.hw,
0521         [CLK_BUS_CSI]       = &bus_csi_clk.common.hw,
0522         [CLK_BUS_DE]        = &bus_de_clk.common.hw,
0523         [CLK_BUS_CODEC]     = &bus_codec_clk.common.hw,
0524         [CLK_BUS_PIO]       = &bus_pio_clk.common.hw,
0525         [CLK_BUS_I2C0]      = &bus_i2c0_clk.common.hw,
0526         [CLK_BUS_I2C1]      = &bus_i2c1_clk.common.hw,
0527         [CLK_BUS_UART0]     = &bus_uart0_clk.common.hw,
0528         [CLK_BUS_UART1]     = &bus_uart1_clk.common.hw,
0529         [CLK_BUS_UART2]     = &bus_uart2_clk.common.hw,
0530         [CLK_BUS_EPHY]      = &bus_ephy_clk.common.hw,
0531         [CLK_BUS_DBG]       = &bus_dbg_clk.common.hw,
0532         [CLK_MMC0]      = &mmc0_clk.common.hw,
0533         [CLK_MMC0_SAMPLE]   = &mmc0_sample_clk.common.hw,
0534         [CLK_MMC0_OUTPUT]   = &mmc0_output_clk.common.hw,
0535         [CLK_MMC1]      = &mmc1_clk.common.hw,
0536         [CLK_MMC1_SAMPLE]   = &mmc1_sample_clk.common.hw,
0537         [CLK_MMC1_OUTPUT]   = &mmc1_output_clk.common.hw,
0538         [CLK_MMC2]      = &mmc2_clk.common.hw,
0539         [CLK_MMC2_SAMPLE]   = &mmc2_sample_clk.common.hw,
0540         [CLK_MMC2_OUTPUT]   = &mmc2_output_clk.common.hw,
0541         [CLK_CE]        = &ce_clk.common.hw,
0542         [CLK_SPI0]      = &spi0_clk.common.hw,
0543         [CLK_USB_PHY0]      = &usb_phy0_clk.common.hw,
0544         [CLK_USB_OHCI0]     = &usb_ohci0_clk.common.hw,
0545         [CLK_DRAM]      = &dram_clk.common.hw,
0546         [CLK_DRAM_VE]       = &dram_ve_clk.common.hw,
0547         [CLK_DRAM_CSI]      = &dram_csi_clk.common.hw,
0548         [CLK_DRAM_EHCI]     = &dram_ehci_clk.common.hw,
0549         [CLK_DRAM_OHCI]     = &dram_ohci_clk.common.hw,
0550         [CLK_DE]        = &de_clk.common.hw,
0551         [CLK_TCON0]     = &tcon_clk.common.hw,
0552         [CLK_CSI_MISC]      = &csi_misc_clk.common.hw,
0553         [CLK_CSI0_MCLK]     = &csi0_mclk_clk.common.hw,
0554         [CLK_CSI1_SCLK]     = &csi1_sclk_clk.common.hw,
0555         [CLK_CSI1_MCLK]     = &csi1_mclk_clk.common.hw,
0556         [CLK_VE]        = &ve_clk.common.hw,
0557         [CLK_AC_DIG]        = &ac_dig_clk.common.hw,
0558         [CLK_AVS]       = &avs_clk.common.hw,
0559         [CLK_MBUS]      = &mbus_clk.common.hw,
0560         [CLK_MIPI_CSI]      = &mipi_csi_clk.common.hw,
0561     },
0562     .num    = CLK_PLL_DDR1 + 1,
0563 };
0564 
0565 static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
0566     .hws    = {
0567         [CLK_PLL_CPU]       = &pll_cpu_clk.common.hw,
0568         [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
0569         [CLK_PLL_AUDIO]     = &pll_audio_clk.hw,
0570         [CLK_PLL_AUDIO_2X]  = &pll_audio_2x_clk.hw,
0571         [CLK_PLL_AUDIO_4X]  = &pll_audio_4x_clk.hw,
0572         [CLK_PLL_AUDIO_8X]  = &pll_audio_8x_clk.hw,
0573         [CLK_PLL_VIDEO]     = &pll_video_clk.common.hw,
0574         [CLK_PLL_VE]        = &pll_ve_clk.common.hw,
0575         [CLK_PLL_DDR0]      = &pll_ddr0_clk.common.hw,
0576         [CLK_PLL_PERIPH0]   = &pll_periph0_clk.common.hw,
0577         [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
0578         [CLK_PLL_ISP]       = &pll_isp_clk.common.hw,
0579         [CLK_PLL_PERIPH1]   = &pll_periph1_clk.common.hw,
0580         [CLK_PLL_DDR1]      = &pll_ddr1_clk.common.hw,
0581         [CLK_CPU]       = &cpu_clk.common.hw,
0582         [CLK_AXI]       = &axi_clk.common.hw,
0583         [CLK_AHB1]      = &ahb1_clk.common.hw,
0584         [CLK_APB1]      = &apb1_clk.common.hw,
0585         [CLK_APB2]      = &apb2_clk.common.hw,
0586         [CLK_AHB2]      = &ahb2_clk.common.hw,
0587         [CLK_BUS_CE]        = &bus_ce_clk.common.hw,
0588         [CLK_BUS_DMA]       = &bus_dma_clk.common.hw,
0589         [CLK_BUS_MMC0]      = &bus_mmc0_clk.common.hw,
0590         [CLK_BUS_MMC1]      = &bus_mmc1_clk.common.hw,
0591         [CLK_BUS_MMC2]      = &bus_mmc2_clk.common.hw,
0592         [CLK_BUS_DRAM]      = &bus_dram_clk.common.hw,
0593         [CLK_BUS_EMAC]      = &bus_emac_clk.common.hw,
0594         [CLK_BUS_HSTIMER]   = &bus_hstimer_clk.common.hw,
0595         [CLK_BUS_SPI0]      = &bus_spi0_clk.common.hw,
0596         [CLK_BUS_OTG]       = &bus_otg_clk.common.hw,
0597         [CLK_BUS_EHCI0]     = &bus_ehci0_clk.common.hw,
0598         [CLK_BUS_OHCI0]     = &bus_ohci0_clk.common.hw,
0599         [CLK_BUS_VE]        = &bus_ve_clk.common.hw,
0600         [CLK_BUS_TCON0]     = &bus_tcon0_clk.common.hw,
0601         [CLK_BUS_CSI]       = &bus_csi_clk.common.hw,
0602         [CLK_BUS_DE]        = &bus_de_clk.common.hw,
0603         [CLK_BUS_CODEC]     = &bus_codec_clk.common.hw,
0604         [CLK_BUS_PIO]       = &bus_pio_clk.common.hw,
0605         [CLK_BUS_I2S0]      = &bus_i2s0_clk.common.hw,
0606         [CLK_BUS_I2C0]      = &bus_i2c0_clk.common.hw,
0607         [CLK_BUS_I2C1]      = &bus_i2c1_clk.common.hw,
0608         [CLK_BUS_UART0]     = &bus_uart0_clk.common.hw,
0609         [CLK_BUS_UART1]     = &bus_uart1_clk.common.hw,
0610         [CLK_BUS_UART2]     = &bus_uart2_clk.common.hw,
0611         [CLK_BUS_EPHY]      = &bus_ephy_clk.common.hw,
0612         [CLK_BUS_DBG]       = &bus_dbg_clk.common.hw,
0613         [CLK_MMC0]      = &mmc0_clk.common.hw,
0614         [CLK_MMC0_SAMPLE]   = &mmc0_sample_clk.common.hw,
0615         [CLK_MMC0_OUTPUT]   = &mmc0_output_clk.common.hw,
0616         [CLK_MMC1]      = &mmc1_clk.common.hw,
0617         [CLK_MMC1_SAMPLE]   = &mmc1_sample_clk.common.hw,
0618         [CLK_MMC1_OUTPUT]   = &mmc1_output_clk.common.hw,
0619         [CLK_MMC2]      = &mmc2_clk.common.hw,
0620         [CLK_MMC2_SAMPLE]   = &mmc2_sample_clk.common.hw,
0621         [CLK_MMC2_OUTPUT]   = &mmc2_output_clk.common.hw,
0622         [CLK_CE]        = &ce_clk.common.hw,
0623         [CLK_SPI0]      = &spi0_clk.common.hw,
0624         [CLK_I2S0]      = &i2s0_clk.common.hw,
0625         [CLK_USB_PHY0]      = &usb_phy0_clk.common.hw,
0626         [CLK_USB_OHCI0]     = &usb_ohci0_clk.common.hw,
0627         [CLK_DRAM]      = &dram_clk.common.hw,
0628         [CLK_DRAM_VE]       = &dram_ve_clk.common.hw,
0629         [CLK_DRAM_CSI]      = &dram_csi_clk.common.hw,
0630         [CLK_DRAM_EHCI]     = &dram_ehci_clk.common.hw,
0631         [CLK_DRAM_OHCI]     = &dram_ohci_clk.common.hw,
0632         [CLK_DE]        = &de_clk.common.hw,
0633         [CLK_TCON0]     = &tcon_clk.common.hw,
0634         [CLK_CSI_MISC]      = &csi_misc_clk.common.hw,
0635         [CLK_CSI0_MCLK]     = &csi0_mclk_clk.common.hw,
0636         [CLK_CSI1_SCLK]     = &csi1_sclk_clk.common.hw,
0637         [CLK_CSI1_MCLK]     = &csi1_mclk_clk.common.hw,
0638         [CLK_VE]        = &ve_clk.common.hw,
0639         [CLK_AC_DIG]        = &ac_dig_clk.common.hw,
0640         [CLK_AVS]       = &avs_clk.common.hw,
0641         [CLK_MBUS]      = &mbus_clk.common.hw,
0642         [CLK_MIPI_CSI]      = &mipi_csi_clk.common.hw,
0643     },
0644     .num    = CLK_I2S0 + 1,
0645 };
0646 
0647 static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
0648     [RST_USB_PHY0]      =  { 0x0cc, BIT(0) },
0649 
0650     [RST_MBUS]      =  { 0x0fc, BIT(31) },
0651 
0652     [RST_BUS_CE]        =  { 0x2c0, BIT(5) },
0653     [RST_BUS_DMA]       =  { 0x2c0, BIT(6) },
0654     [RST_BUS_MMC0]      =  { 0x2c0, BIT(8) },
0655     [RST_BUS_MMC1]      =  { 0x2c0, BIT(9) },
0656     [RST_BUS_MMC2]      =  { 0x2c0, BIT(10) },
0657     [RST_BUS_DRAM]      =  { 0x2c0, BIT(14) },
0658     [RST_BUS_EMAC]      =  { 0x2c0, BIT(17) },
0659     [RST_BUS_HSTIMER]   =  { 0x2c0, BIT(19) },
0660     [RST_BUS_SPI0]      =  { 0x2c0, BIT(20) },
0661     [RST_BUS_OTG]       =  { 0x2c0, BIT(24) },
0662     [RST_BUS_EHCI0]     =  { 0x2c0, BIT(26) },
0663     [RST_BUS_OHCI0]     =  { 0x2c0, BIT(29) },
0664 
0665     [RST_BUS_VE]        =  { 0x2c4, BIT(0) },
0666     [RST_BUS_TCON0]     =  { 0x2c4, BIT(4) },
0667     [RST_BUS_CSI]       =  { 0x2c4, BIT(8) },
0668     [RST_BUS_DE]        =  { 0x2c4, BIT(12) },
0669     [RST_BUS_DBG]       =  { 0x2c4, BIT(31) },
0670 
0671     [RST_BUS_EPHY]      =  { 0x2c8, BIT(2) },
0672 
0673     [RST_BUS_CODEC]     =  { 0x2d0, BIT(0) },
0674 
0675     [RST_BUS_I2C0]      =  { 0x2d8, BIT(0) },
0676     [RST_BUS_I2C1]      =  { 0x2d8, BIT(1) },
0677     [RST_BUS_UART0]     =  { 0x2d8, BIT(16) },
0678     [RST_BUS_UART1]     =  { 0x2d8, BIT(17) },
0679     [RST_BUS_UART2]     =  { 0x2d8, BIT(18) },
0680 };
0681 
0682 static struct ccu_reset_map sun8i_v3_ccu_resets[] = {
0683     [RST_USB_PHY0]      =  { 0x0cc, BIT(0) },
0684 
0685     [RST_MBUS]      =  { 0x0fc, BIT(31) },
0686 
0687     [RST_BUS_CE]        =  { 0x2c0, BIT(5) },
0688     [RST_BUS_DMA]       =  { 0x2c0, BIT(6) },
0689     [RST_BUS_MMC0]      =  { 0x2c0, BIT(8) },
0690     [RST_BUS_MMC1]      =  { 0x2c0, BIT(9) },
0691     [RST_BUS_MMC2]      =  { 0x2c0, BIT(10) },
0692     [RST_BUS_DRAM]      =  { 0x2c0, BIT(14) },
0693     [RST_BUS_EMAC]      =  { 0x2c0, BIT(17) },
0694     [RST_BUS_HSTIMER]   =  { 0x2c0, BIT(19) },
0695     [RST_BUS_SPI0]      =  { 0x2c0, BIT(20) },
0696     [RST_BUS_OTG]       =  { 0x2c0, BIT(24) },
0697     [RST_BUS_EHCI0]     =  { 0x2c0, BIT(26) },
0698     [RST_BUS_OHCI0]     =  { 0x2c0, BIT(29) },
0699 
0700     [RST_BUS_VE]        =  { 0x2c4, BIT(0) },
0701     [RST_BUS_TCON0]     =  { 0x2c4, BIT(4) },
0702     [RST_BUS_CSI]       =  { 0x2c4, BIT(8) },
0703     [RST_BUS_DE]        =  { 0x2c4, BIT(12) },
0704     [RST_BUS_DBG]       =  { 0x2c4, BIT(31) },
0705 
0706     [RST_BUS_EPHY]      =  { 0x2c8, BIT(2) },
0707 
0708     [RST_BUS_CODEC]     =  { 0x2d0, BIT(0) },
0709     [RST_BUS_I2S0]      =  { 0x2d0, BIT(12) },
0710 
0711     [RST_BUS_I2C0]      =  { 0x2d8, BIT(0) },
0712     [RST_BUS_I2C1]      =  { 0x2d8, BIT(1) },
0713     [RST_BUS_UART0]     =  { 0x2d8, BIT(16) },
0714     [RST_BUS_UART1]     =  { 0x2d8, BIT(17) },
0715     [RST_BUS_UART2]     =  { 0x2d8, BIT(18) },
0716 };
0717 
0718 static const struct sunxi_ccu_desc sun8i_v3s_ccu_desc = {
0719     .ccu_clks   = sun8i_v3s_ccu_clks,
0720     .num_ccu_clks   = ARRAY_SIZE(sun8i_v3s_ccu_clks),
0721 
0722     .hw_clks    = &sun8i_v3s_hw_clks,
0723 
0724     .resets     = sun8i_v3s_ccu_resets,
0725     .num_resets = ARRAY_SIZE(sun8i_v3s_ccu_resets),
0726 };
0727 
0728 static const struct sunxi_ccu_desc sun8i_v3_ccu_desc = {
0729     .ccu_clks   = sun8i_v3s_ccu_clks,
0730     .num_ccu_clks   = ARRAY_SIZE(sun8i_v3s_ccu_clks),
0731 
0732     .hw_clks    = &sun8i_v3_hw_clks,
0733 
0734     .resets     = sun8i_v3_ccu_resets,
0735     .num_resets = ARRAY_SIZE(sun8i_v3_ccu_resets),
0736 };
0737 
0738 static int sun8i_v3s_ccu_probe(struct platform_device *pdev)
0739 {
0740     const struct sunxi_ccu_desc *desc;
0741     void __iomem *reg;
0742     u32 val;
0743 
0744     desc = of_device_get_match_data(&pdev->dev);
0745     if (!desc)
0746         return -EINVAL;
0747 
0748     reg = devm_platform_ioremap_resource(pdev, 0);
0749     if (IS_ERR(reg))
0750         return PTR_ERR(reg);
0751 
0752     /* Force the PLL-Audio-1x divider to 1 */
0753     val = readl(reg + SUN8I_V3S_PLL_AUDIO_REG);
0754     val &= ~GENMASK(19, 16);
0755     writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG);
0756 
0757     return devm_sunxi_ccu_probe(&pdev->dev, reg, desc);
0758 }
0759 
0760 static const struct of_device_id sun8i_v3s_ccu_ids[] = {
0761     {
0762         .compatible = "allwinner,sun8i-v3-ccu",
0763         .data = &sun8i_v3_ccu_desc,
0764     },
0765     {
0766         .compatible = "allwinner,sun8i-v3s-ccu",
0767         .data = &sun8i_v3s_ccu_desc,
0768     },
0769     { }
0770 };
0771 
0772 static struct platform_driver sun8i_v3s_ccu_driver = {
0773     .probe  = sun8i_v3s_ccu_probe,
0774     .driver = {
0775         .name           = "sun8i-v3s-ccu",
0776         .suppress_bind_attrs    = true,
0777         .of_match_table     = sun8i_v3s_ccu_ids,
0778     },
0779 };
0780 module_platform_driver(sun8i_v3s_ccu_driver);
0781 
0782 MODULE_IMPORT_NS(SUNXI_CCU);
0783 MODULE_LICENSE("GPL");