929 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved.4 */5 6#include <linux/clk-provider.h>7#include <linux/io.h>8#include <linux/module.h>9#include <linux/platform_device.h>10 11#include "ccu_common.h"12#include "ccu_reset.h"13 14#include "ccu_div.h"15#include "ccu_gate.h"16#include "ccu_mp.h"17#include "ccu_mux.h"18#include "ccu_nkmp.h"19#include "ccu_nm.h"20#include "ccu_phase.h"21 22#include "ccu-sun8i-a83t.h"23 24#define CCU_SUN8I_A83T_LOCK_REG 0x20c25 26/*27 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However28 * P should only be used for output frequencies lower than 228 MHz.29 * Neither mainline Linux, U-boot, nor the vendor BSPs use these.30 *31 * For now we can just model it as a multiplier clock, and force P to /1.32 */33#define SUN8I_A83T_PLL_C0CPUX_REG 0x00034#define SUN8I_A83T_PLL_C1CPUX_REG 0x00435 36static struct ccu_mult pll_c0cpux_clk = {37 .enable = BIT(31),38 .lock = BIT(0),39 .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),40 .common = {41 .reg = SUN8I_A83T_PLL_C0CPUX_REG,42 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,43 .features = CCU_FEATURE_LOCK_REG,44 .hw.init = CLK_HW_INIT("pll-c0cpux", "osc24M",45 &ccu_mult_ops,46 CLK_SET_RATE_UNGATE),47 },48};49 50static struct ccu_mult pll_c1cpux_clk = {51 .enable = BIT(31),52 .lock = BIT(1),53 .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),54 .common = {55 .reg = SUN8I_A83T_PLL_C1CPUX_REG,56 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,57 .features = CCU_FEATURE_LOCK_REG,58 .hw.init = CLK_HW_INIT("pll-c1cpux", "osc24M",59 &ccu_mult_ops,60 CLK_SET_RATE_UNGATE),61 },62};63 64/*65 * The Audio PLL has d1, d2 dividers in addition to the usual N, M66 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz67 * and 24.576 MHz, ignore them for now. Enforce the default for them,68 * which is d1 = 0, d2 = 1.69 */70#define SUN8I_A83T_PLL_AUDIO_REG 0x00871 72/* clock rates doubled for post divider */73static struct ccu_sdm_setting pll_audio_sdm_table[] = {74 { .rate = 45158400, .pattern = 0xc00121ff, .m = 29, .n = 54 },75 { .rate = 49152000, .pattern = 0xc000e147, .m = 30, .n = 61 },76};77 78static struct ccu_nm pll_audio_clk = {79 .enable = BIT(31),80 .lock = BIT(2),81 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),82 .m = _SUNXI_CCU_DIV(0, 6),83 .fixed_post_div = 2,84 .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24),85 0x284, BIT(31)),86 .common = {87 .reg = SUN8I_A83T_PLL_AUDIO_REG,88 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,89 .features = CCU_FEATURE_LOCK_REG |90 CCU_FEATURE_FIXED_POSTDIV |91 CCU_FEATURE_SIGMA_DELTA_MOD,92 .hw.init = CLK_HW_INIT("pll-audio", "osc24M",93 &ccu_nm_ops, CLK_SET_RATE_UNGATE),94 },95};96 97/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */98static struct ccu_nkmp pll_video0_clk = {99 .enable = BIT(31),100 .lock = BIT(3),101 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),102 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */103 .p = _SUNXI_CCU_DIV(0, 2), /* output divider */104 .max_rate = 3000000000UL,105 .common = {106 .reg = 0x010,107 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,108 .features = CCU_FEATURE_LOCK_REG,109 .hw.init = CLK_HW_INIT("pll-video0", "osc24M",110 &ccu_nkmp_ops,111 CLK_SET_RATE_UNGATE),112 },113};114 115static struct ccu_nkmp pll_ve_clk = {116 .enable = BIT(31),117 .lock = BIT(4),118 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),119 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */120 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */121 .common = {122 .reg = 0x018,123 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,124 .features = CCU_FEATURE_LOCK_REG,125 .hw.init = CLK_HW_INIT("pll-ve", "osc24M",126 &ccu_nkmp_ops,127 CLK_SET_RATE_UNGATE),128 },129};130 131static struct ccu_nkmp pll_ddr_clk = {132 .enable = BIT(31),133 .lock = BIT(5),134 .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),135 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */136 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */137 .common = {138 .reg = 0x020,139 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,140 .features = CCU_FEATURE_LOCK_REG,141 .hw.init = CLK_HW_INIT("pll-ddr", "osc24M",142 &ccu_nkmp_ops,143 CLK_SET_RATE_UNGATE),144 },145};146 147static struct ccu_nkmp pll_periph_clk = {148 .enable = BIT(31),149 .lock = BIT(6),150 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),151 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */152 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */153 .common = {154 .reg = 0x028,155 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,156 .features = CCU_FEATURE_LOCK_REG,157 .hw.init = CLK_HW_INIT("pll-periph", "osc24M",158 &ccu_nkmp_ops,159 CLK_SET_RATE_UNGATE),160 },161};162 163static struct ccu_nkmp pll_gpu_clk = {164 .enable = BIT(31),165 .lock = BIT(7),166 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),167 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */168 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */169 .common = {170 .reg = 0x038,171 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,172 .features = CCU_FEATURE_LOCK_REG,173 .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",174 &ccu_nkmp_ops,175 CLK_SET_RATE_UNGATE),176 },177};178 179static struct ccu_nkmp pll_hsic_clk = {180 .enable = BIT(31),181 .lock = BIT(8),182 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),183 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */184 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */185 .common = {186 .reg = 0x044,187 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,188 .features = CCU_FEATURE_LOCK_REG,189 .hw.init = CLK_HW_INIT("pll-hsic", "osc24M",190 &ccu_nkmp_ops,191 CLK_SET_RATE_UNGATE),192 },193};194 195static struct ccu_nkmp pll_de_clk = {196 .enable = BIT(31),197 .lock = BIT(9),198 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),199 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */200 .p = _SUNXI_CCU_DIV(18, 1), /* output divider */201 .common = {202 .reg = 0x048,203 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,204 .features = CCU_FEATURE_LOCK_REG,205 .hw.init = CLK_HW_INIT("pll-de", "osc24M",206 &ccu_nkmp_ops,207 CLK_SET_RATE_UNGATE),208 },209};210 211static struct ccu_nkmp pll_video1_clk = {212 .enable = BIT(31),213 .lock = BIT(10),214 .n = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),215 .m = _SUNXI_CCU_DIV(16, 1), /* input divider */216 .p = _SUNXI_CCU_DIV(0, 2), /* external divider p */217 .max_rate = 3000000000UL,218 .common = {219 .reg = 0x04c,220 .lock_reg = CCU_SUN8I_A83T_LOCK_REG,221 .features = CCU_FEATURE_LOCK_REG,222 .hw.init = CLK_HW_INIT("pll-video1", "osc24M",223 &ccu_nkmp_ops,224 CLK_SET_RATE_UNGATE),225 },226};227 228static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };229static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,230 0x50, 12, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);231 232static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };233static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,234 0x50, 28, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);235 236static SUNXI_CCU_M(axi0_clk, "axi0", "c0cpux", 0x050, 0, 2, 0);237static SUNXI_CCU_M(axi1_clk, "axi1", "c1cpux", 0x050, 16, 2, 0);238 239static const char * const ahb1_parents[] = { "osc16M-d512", "osc24M",240 "pll-periph",241 "pll-periph" };242static const struct ccu_mux_var_prediv ahb1_predivs[] = {243 { .index = 2, .shift = 6, .width = 2 },244 { .index = 3, .shift = 6, .width = 2 },245};246static struct ccu_div ahb1_clk = {247 .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),248 .mux = {249 .shift = 12,250 .width = 2,251 252 .var_predivs = ahb1_predivs,253 .n_var_predivs = ARRAY_SIZE(ahb1_predivs),254 },255 .common = {256 .reg = 0x054,257 .hw.init = CLK_HW_INIT_PARENTS("ahb1",258 ahb1_parents,259 &ccu_div_ops,260 0),261 },262};263 264static SUNXI_CCU_M(apb1_clk, "apb1", "ahb1", 0x054, 8, 2, 0);265 266static const char * const apb2_parents[] = { "osc16M-d512", "osc24M",267 "pll-periph", "pll-periph" };268 269static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,270 0, 5, /* M */271 16, 2, /* P */272 24, 2, /* mux */273 0);274 275static const char * const ahb2_parents[] = { "ahb1", "pll-periph" };276static const struct ccu_mux_fixed_prediv ahb2_prediv = {277 .index = 1, .div = 2278};279static struct ccu_mux ahb2_clk = {280 .mux = {281 .shift = 0,282 .width = 2,283 .fixed_predivs = &ahb2_prediv,284 .n_predivs = 1,285 },286 .common = {287 .reg = 0x05c,288 .hw.init = CLK_HW_INIT_PARENTS("ahb2",289 ahb2_parents,290 &ccu_mux_ops,291 0),292 },293};294 295static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1",296 0x060, BIT(1), 0);297static SUNXI_CCU_GATE(bus_ss_clk, "bus-ss", "ahb1",298 0x060, BIT(5), 0);299static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1",300 0x060, BIT(6), 0);301static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1",302 0x060, BIT(8), 0);303static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1",304 0x060, BIT(9), 0);305static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1",306 0x060, BIT(10), 0);307static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1",308 0x060, BIT(13), 0);309static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1",310 0x060, BIT(14), 0);311static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2",312 0x060, BIT(17), 0);313static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1",314 0x060, BIT(19), 0);315static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1",316 0x060, BIT(20), 0);317static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1",318 0x060, BIT(21), 0);319static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1",320 0x060, BIT(24), 0);321static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb2",322 0x060, BIT(26), 0);323static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2",324 0x060, BIT(27), 0);325static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb2",326 0x060, BIT(29), 0);327 328static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1",329 0x064, BIT(0), 0);330static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1",331 0x064, BIT(4), 0);332static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1",333 0x064, BIT(5), 0);334static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1",335 0x064, BIT(8), 0);336static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1",337 0x064, BIT(11), 0);338static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1",339 0x064, BIT(12), 0);340static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1",341 0x064, BIT(20), 0);342static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1",343 0x064, BIT(21), 0);344static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1",345 0x064, BIT(22), 0);346 347static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1",348 0x068, BIT(1), 0);349static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1",350 0x068, BIT(5), 0);351static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1",352 0x068, BIT(12), 0);353static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1",354 0x068, BIT(13), 0);355static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1",356 0x068, BIT(14), 0);357static SUNXI_CCU_GATE(bus_tdm_clk, "bus-tdm", "apb1",358 0x068, BIT(15), 0);359 360static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2",361 0x06c, BIT(0), 0);362static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2",363 0x06c, BIT(1), 0);364static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2",365 0x06c, BIT(2), 0);366static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2",367 0x06c, BIT(16), 0);368static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2",369 0x06c, BIT(17), 0);370static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2",371 0x06c, BIT(18), 0);372static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2",373 0x06c, BIT(19), 0);374static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2",375 0x06c, BIT(20), 0);376 377static const char * const cci400_parents[] = { "osc24M", "pll-periph",378 "pll-hsic" };379static struct ccu_div cci400_clk = {380 .div = _SUNXI_CCU_DIV_FLAGS(0, 2, 0),381 .mux = _SUNXI_CCU_MUX(24, 2),382 .common = {383 .reg = 0x078,384 .hw.init = CLK_HW_INIT_PARENTS("cci400",385 cci400_parents,386 &ccu_div_ops,387 CLK_IS_CRITICAL),388 },389};390 391static const char * const mod0_default_parents[] = { "osc24M", "pll-periph" };392 393static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents,394 0x080,395 0, 4, /* M */396 16, 2, /* P */397 24, 2, /* mux */398 BIT(31), /* gate */399 0);400 401static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,402 0x088,403 0, 4, /* M */404 16, 2, /* P */405 24, 2, /* mux */406 BIT(31), /* gate */407 0);408 409static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",410 0x088, 20, 3, 0);411static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",412 0x088, 8, 3, 0);413 414static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,415 0x08c,416 0, 4, /* M */417 16, 2, /* P */418 24, 2, /* mux */419 BIT(31), /* gate */420 0);421 422static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",423 0x08c, 20, 3, 0);424static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",425 0x08c, 8, 3, 0);426 427static SUNXI_CCU_MP_MMC_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,428 0x090, 0);429 430static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",431 0x090, 20, 3, 0);432static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",433 0x090, 8, 3, 0);434 435static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents,436 0x09c,437 0, 4, /* M */438 16, 2, /* P */439 24, 2, /* mux */440 BIT(31), /* gate */441 0);442 443static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,444 0x0a0,445 0, 4, /* M */446 16, 2, /* P */447 24, 4, /* mux */448 BIT(31), /* gate */449 0);450 451static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,452 0x0a4,453 0, 4, /* M */454 16, 2, /* P */455 24, 4, /* mux */456 BIT(31), /* gate */457 0);458 459static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",460 0x0b0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);461static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",462 0x0b4, 0, 4, BIT(31), CLK_SET_RATE_PARENT);463static SUNXI_CCU_M_WITH_GATE(i2s2_clk, "i2s2", "pll-audio",464 0x0b8, 0, 4, BIT(31), CLK_SET_RATE_PARENT);465static SUNXI_CCU_M_WITH_GATE(tdm_clk, "tdm", "pll-audio",466 0x0bc, 0, 4, BIT(31), CLK_SET_RATE_PARENT);467static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",468 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);469 470static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",471 0x0cc, BIT(8), 0);472static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M",473 0x0cc, BIT(9), 0);474static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic",475 0x0cc, BIT(10), 0);476static struct ccu_gate usb_hsic_12m_clk = {477 .enable = BIT(11),478 .common = {479 .reg = 0x0cc,480 .prediv = 2,481 .features = CCU_FEATURE_ALL_PREDIV,482 .hw.init = CLK_HW_INIT("usb-hsic-12m", "osc24M",483 &ccu_gate_ops, 0),484 }485};486static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc24M",487 0x0cc, BIT(16), 0);488 489/* TODO divider has minimum of 2 */490static SUNXI_CCU_M(dram_clk, "dram", "pll-ddr", 0x0f4, 0, 4, CLK_IS_CRITICAL);491 492static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram",493 0x100, BIT(0), 0);494static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram",495 0x100, BIT(1), 0);496 497static const char * const tcon0_parents[] = { "pll-video0" };498static SUNXI_CCU_MUX_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,499 0x118, 24, 3, BIT(31), CLK_SET_RATE_PARENT);500 501static const char * const tcon1_parents[] = { "pll-video1" };502static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_clk, "tcon1", tcon1_parents,503 0x11c, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);504 505static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x130, BIT(16), 0);506 507static SUNXI_CCU_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x130, BIT(31), 0);508 509static const char * const csi_mclk_parents[] = { "pll-video0", "pll-de",510 "osc24M" };511static const u8 csi_mclk_table[] = { 0, 3, 5 };512static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_mclk_clk, "csi-mclk",513 csi_mclk_parents, csi_mclk_table,514 0x134,515 0, 5, /* M */516 8, 3, /* mux */517 BIT(15), /* gate */518 0);519 520static const char * const csi_sclk_parents[] = { "pll-periph", "pll-ve" };521static const u8 csi_sclk_table[] = { 0, 5 };522static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_sclk_clk, "csi-sclk",523 csi_sclk_parents, csi_sclk_table,524 0x134,525 16, 4, /* M */526 24, 3, /* mux */527 BIT(31), /* gate */528 0);529 530static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c,531 16, 3, BIT(31), CLK_SET_RATE_PARENT);532 533static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x144, BIT(31), 0);534 535static const char * const hdmi_parents[] = { "pll-video1" };536static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,537 0x150,538 0, 4, /* M */539 24, 2, /* mux */540 BIT(31), /* gate */541 CLK_SET_RATE_PARENT);542 543static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x154, BIT(31), 0);544 545static const char * const mbus_parents[] = { "osc24M", "pll-periph",546 "pll-ddr" };547static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,548 0x15c,549 0, 3, /* M */550 24, 2, /* mux */551 BIT(31), /* gate */552 CLK_IS_CRITICAL);553 554static const char * const mipi_dsi0_parents[] = { "pll-video0" };555static const u8 mipi_dsi0_table[] = { 8 };556static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",557 mipi_dsi0_parents, mipi_dsi0_table,558 0x168,559 0, 4, /* M */560 24, 4, /* mux */561 BIT(31), /* gate */562 CLK_SET_RATE_PARENT);563 564static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video0" };565static const u8 mipi_dsi1_table[] = { 0, 9 };566static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",567 mipi_dsi1_parents, mipi_dsi1_table,568 0x16c,569 0, 4, /* M */570 24, 4, /* mux */571 BIT(31), /* gate */572 CLK_SET_RATE_PARENT);573 574static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x1a0,575 0, 3, BIT(31), CLK_SET_RATE_PARENT);576 577static const char * const gpu_memory_parents[] = { "pll-gpu", "pll-ddr" };578static SUNXI_CCU_M_WITH_MUX_GATE(gpu_memory_clk, "gpu-memory",579 gpu_memory_parents,580 0x1a4,581 0, 3, /* M */582 24, 1, /* mux */583 BIT(31), /* gate */584 CLK_SET_RATE_PARENT);585 586static SUNXI_CCU_M_WITH_GATE(gpu_hyd_clk, "gpu-hyd", "pll-gpu", 0x1a8,587 0, 3, BIT(31), CLK_SET_RATE_PARENT);588 589static struct ccu_common *sun8i_a83t_ccu_clks[] = {590 &pll_c0cpux_clk.common,591 &pll_c1cpux_clk.common,592 &pll_audio_clk.common,593 &pll_video0_clk.common,594 &pll_ve_clk.common,595 &pll_ddr_clk.common,596 &pll_periph_clk.common,597 &pll_gpu_clk.common,598 &pll_hsic_clk.common,599 &pll_de_clk.common,600 &pll_video1_clk.common,601 &c0cpux_clk.common,602 &c1cpux_clk.common,603 &axi0_clk.common,604 &axi1_clk.common,605 &ahb1_clk.common,606 &ahb2_clk.common,607 &apb1_clk.common,608 &apb2_clk.common,609 &bus_mipi_dsi_clk.common,610 &bus_ss_clk.common,611 &bus_dma_clk.common,612 &bus_mmc0_clk.common,613 &bus_mmc1_clk.common,614 &bus_mmc2_clk.common,615 &bus_nand_clk.common,616 &bus_dram_clk.common,617 &bus_emac_clk.common,618 &bus_hstimer_clk.common,619 &bus_spi0_clk.common,620 &bus_spi1_clk.common,621 &bus_otg_clk.common,622 &bus_ehci0_clk.common,623 &bus_ehci1_clk.common,624 &bus_ohci0_clk.common,625 &bus_ve_clk.common,626 &bus_tcon0_clk.common,627 &bus_tcon1_clk.common,628 &bus_csi_clk.common,629 &bus_hdmi_clk.common,630 &bus_de_clk.common,631 &bus_gpu_clk.common,632 &bus_msgbox_clk.common,633 &bus_spinlock_clk.common,634 &bus_spdif_clk.common,635 &bus_pio_clk.common,636 &bus_i2s0_clk.common,637 &bus_i2s1_clk.common,638 &bus_i2s2_clk.common,639 &bus_tdm_clk.common,640 &bus_i2c0_clk.common,641 &bus_i2c1_clk.common,642 &bus_i2c2_clk.common,643 &bus_uart0_clk.common,644 &bus_uart1_clk.common,645 &bus_uart2_clk.common,646 &bus_uart3_clk.common,647 &bus_uart4_clk.common,648 &cci400_clk.common,649 &nand_clk.common,650 &mmc0_clk.common,651 &mmc0_sample_clk.common,652 &mmc0_output_clk.common,653 &mmc1_clk.common,654 &mmc1_sample_clk.common,655 &mmc1_output_clk.common,656 &mmc2_clk.common,657 &mmc2_sample_clk.common,658 &mmc2_output_clk.common,659 &ss_clk.common,660 &spi0_clk.common,661 &spi1_clk.common,662 &i2s0_clk.common,663 &i2s1_clk.common,664 &i2s2_clk.common,665 &tdm_clk.common,666 &spdif_clk.common,667 &usb_phy0_clk.common,668 &usb_phy1_clk.common,669 &usb_hsic_clk.common,670 &usb_hsic_12m_clk.common,671 &usb_ohci0_clk.common,672 &dram_clk.common,673 &dram_ve_clk.common,674 &dram_csi_clk.common,675 &tcon0_clk.common,676 &tcon1_clk.common,677 &csi_misc_clk.common,678 &mipi_csi_clk.common,679 &csi_mclk_clk.common,680 &csi_sclk_clk.common,681 &ve_clk.common,682 &avs_clk.common,683 &hdmi_clk.common,684 &hdmi_slow_clk.common,685 &mbus_clk.common,686 &mipi_dsi0_clk.common,687 &mipi_dsi1_clk.common,688 &gpu_core_clk.common,689 &gpu_memory_clk.common,690 &gpu_hyd_clk.common,691};692 693static struct clk_hw_onecell_data sun8i_a83t_hw_clks = {694 .hws = {695 [CLK_PLL_C0CPUX] = &pll_c0cpux_clk.common.hw,696 [CLK_PLL_C1CPUX] = &pll_c1cpux_clk.common.hw,697 [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw,698 [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,699 [CLK_PLL_VE] = &pll_ve_clk.common.hw,700 [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,701 [CLK_PLL_PERIPH] = &pll_periph_clk.common.hw,702 [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,703 [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw,704 [CLK_PLL_DE] = &pll_de_clk.common.hw,705 [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,706 [CLK_C0CPUX] = &c0cpux_clk.common.hw,707 [CLK_C1CPUX] = &c1cpux_clk.common.hw,708 [CLK_AXI0] = &axi0_clk.common.hw,709 [CLK_AXI1] = &axi1_clk.common.hw,710 [CLK_AHB1] = &ahb1_clk.common.hw,711 [CLK_AHB2] = &ahb2_clk.common.hw,712 [CLK_APB1] = &apb1_clk.common.hw,713 [CLK_APB2] = &apb2_clk.common.hw,714 [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,715 [CLK_BUS_SS] = &bus_ss_clk.common.hw,716 [CLK_BUS_DMA] = &bus_dma_clk.common.hw,717 [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,718 [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,719 [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,720 [CLK_BUS_NAND] = &bus_nand_clk.common.hw,721 [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,722 [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,723 [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,724 [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,725 [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,726 [CLK_BUS_OTG] = &bus_otg_clk.common.hw,727 [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,728 [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,729 [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,730 [CLK_BUS_VE] = &bus_ve_clk.common.hw,731 [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw,732 [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw,733 [CLK_BUS_CSI] = &bus_csi_clk.common.hw,734 [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,735 [CLK_BUS_DE] = &bus_de_clk.common.hw,736 [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,737 [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw,738 [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw,739 [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,740 [CLK_BUS_PIO] = &bus_pio_clk.common.hw,741 [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,742 [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,743 [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw,744 [CLK_BUS_TDM] = &bus_tdm_clk.common.hw,745 [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,746 [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,747 [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,748 [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,749 [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,750 [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,751 [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,752 [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,753 [CLK_CCI400] = &cci400_clk.common.hw,754 [CLK_NAND] = &nand_clk.common.hw,755 [CLK_MMC0] = &mmc0_clk.common.hw,756 [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw,757 [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw,758 [CLK_MMC1] = &mmc1_clk.common.hw,759 [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw,760 [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,761 [CLK_MMC2] = &mmc2_clk.common.hw,762 [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw,763 [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw,764 [CLK_SS] = &ss_clk.common.hw,765 [CLK_SPI0] = &spi0_clk.common.hw,766 [CLK_SPI1] = &spi1_clk.common.hw,767 [CLK_I2S0] = &i2s0_clk.common.hw,768 [CLK_I2S1] = &i2s1_clk.common.hw,769 [CLK_I2S2] = &i2s2_clk.common.hw,770 [CLK_TDM] = &tdm_clk.common.hw,771 [CLK_SPDIF] = &spdif_clk.common.hw,772 [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,773 [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,774 [CLK_USB_HSIC] = &usb_hsic_clk.common.hw,775 [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw,776 [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,777 [CLK_DRAM] = &dram_clk.common.hw,778 [CLK_DRAM_VE] = &dram_ve_clk.common.hw,779 [CLK_DRAM_CSI] = &dram_csi_clk.common.hw,780 [CLK_TCON0] = &tcon0_clk.common.hw,781 [CLK_TCON1] = &tcon1_clk.common.hw,782 [CLK_CSI_MISC] = &csi_misc_clk.common.hw,783 [CLK_MIPI_CSI] = &mipi_csi_clk.common.hw,784 [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw,785 [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw,786 [CLK_VE] = &ve_clk.common.hw,787 [CLK_AVS] = &avs_clk.common.hw,788 [CLK_HDMI] = &hdmi_clk.common.hw,789 [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,790 [CLK_MBUS] = &mbus_clk.common.hw,791 [CLK_MIPI_DSI0] = &mipi_dsi0_clk.common.hw,792 [CLK_MIPI_DSI1] = &mipi_dsi1_clk.common.hw,793 [CLK_GPU_CORE] = &gpu_core_clk.common.hw,794 [CLK_GPU_MEMORY] = &gpu_memory_clk.common.hw,795 [CLK_GPU_HYD] = &gpu_hyd_clk.common.hw,796 },797 .num = CLK_NUMBER,798};799 800static struct ccu_reset_map sun8i_a83t_ccu_resets[] = {801 [RST_USB_PHY0] = { 0x0cc, BIT(0) },802 [RST_USB_PHY1] = { 0x0cc, BIT(1) },803 [RST_USB_HSIC] = { 0x0cc, BIT(2) },804 [RST_DRAM] = { 0x0f4, BIT(31) },805 [RST_MBUS] = { 0x0fc, BIT(31) },806 [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) },807 [RST_BUS_SS] = { 0x2c0, BIT(5) },808 [RST_BUS_DMA] = { 0x2c0, BIT(6) },809 [RST_BUS_MMC0] = { 0x2c0, BIT(8) },810 [RST_BUS_MMC1] = { 0x2c0, BIT(9) },811 [RST_BUS_MMC2] = { 0x2c0, BIT(10) },812 [RST_BUS_NAND] = { 0x2c0, BIT(13) },813 [RST_BUS_DRAM] = { 0x2c0, BIT(14) },814 [RST_BUS_EMAC] = { 0x2c0, BIT(17) },815 [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) },816 [RST_BUS_SPI0] = { 0x2c0, BIT(20) },817 [RST_BUS_SPI1] = { 0x2c0, BIT(21) },818 [RST_BUS_OTG] = { 0x2c0, BIT(24) },819 [RST_BUS_EHCI0] = { 0x2c0, BIT(26) },820 [RST_BUS_EHCI1] = { 0x2c0, BIT(27) },821 [RST_BUS_OHCI0] = { 0x2c0, BIT(29) },822 [RST_BUS_VE] = { 0x2c4, BIT(0) },823 [RST_BUS_TCON0] = { 0x2c4, BIT(4) },824 [RST_BUS_TCON1] = { 0x2c4, BIT(5) },825 [RST_BUS_CSI] = { 0x2c4, BIT(8) },826 [RST_BUS_HDMI0] = { 0x2c4, BIT(10) },827 [RST_BUS_HDMI1] = { 0x2c4, BIT(11) },828 [RST_BUS_DE] = { 0x2c4, BIT(12) },829 [RST_BUS_GPU] = { 0x2c4, BIT(20) },830 [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) },831 [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) },832 [RST_BUS_LVDS] = { 0x2c8, BIT(0) },833 [RST_BUS_SPDIF] = { 0x2d0, BIT(1) },834 [RST_BUS_I2S0] = { 0x2d0, BIT(12) },835 [RST_BUS_I2S1] = { 0x2d0, BIT(13) },836 [RST_BUS_I2S2] = { 0x2d0, BIT(14) },837 [RST_BUS_TDM] = { 0x2d0, BIT(15) },838 [RST_BUS_I2C0] = { 0x2d8, BIT(0) },839 [RST_BUS_I2C1] = { 0x2d8, BIT(1) },840 [RST_BUS_I2C2] = { 0x2d8, BIT(2) },841 [RST_BUS_UART0] = { 0x2d8, BIT(16) },842 [RST_BUS_UART1] = { 0x2d8, BIT(17) },843 [RST_BUS_UART2] = { 0x2d8, BIT(18) },844 [RST_BUS_UART3] = { 0x2d8, BIT(19) },845 [RST_BUS_UART4] = { 0x2d8, BIT(20) },846};847 848static const struct sunxi_ccu_desc sun8i_a83t_ccu_desc = {849 .ccu_clks = sun8i_a83t_ccu_clks,850 .num_ccu_clks = ARRAY_SIZE(sun8i_a83t_ccu_clks),851 852 .hw_clks = &sun8i_a83t_hw_clks,853 854 .resets = sun8i_a83t_ccu_resets,855 .num_resets = ARRAY_SIZE(sun8i_a83t_ccu_resets),856};857 858#define SUN8I_A83T_PLL_P_SHIFT 16859#define SUN8I_A83T_PLL_N_SHIFT 8860#define SUN8I_A83T_PLL_N_WIDTH 8861 862static void sun8i_a83t_cpu_pll_fixup(void __iomem *reg)863{864 u32 val = readl(reg);865 866 /* bail out if P divider is not used */867 if (!(val & BIT(SUN8I_A83T_PLL_P_SHIFT)))868 return;869 870 /*871 * If P is used, output should be less than 288 MHz. When we872 * set P to 1, we should also decrease the multiplier so the873 * output doesn't go out of range, but not too much such that874 * the multiplier stays above 12, the minimal operation value.875 *876 * To keep it simple, set the multiplier to 17, the reset value.877 */878 val &= ~GENMASK(SUN8I_A83T_PLL_N_SHIFT + SUN8I_A83T_PLL_N_WIDTH - 1,879 SUN8I_A83T_PLL_N_SHIFT);880 val |= 17 << SUN8I_A83T_PLL_N_SHIFT;881 882 /* And clear P */883 val &= ~BIT(SUN8I_A83T_PLL_P_SHIFT);884 885 writel(val, reg);886}887 888static int sun8i_a83t_ccu_probe(struct platform_device *pdev)889{890 void __iomem *reg;891 u32 val;892 893 reg = devm_platform_ioremap_resource(pdev, 0);894 if (IS_ERR(reg))895 return PTR_ERR(reg);896 897 /* Enforce d1 = 0, d2 = 1 for Audio PLL */898 val = readl(reg + SUN8I_A83T_PLL_AUDIO_REG);899 val &= ~BIT(16);900 val |= BIT(18);901 writel(val, reg + SUN8I_A83T_PLL_AUDIO_REG);902 903 /* Enforce P = 1 for both CPU cluster PLLs */904 sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C0CPUX_REG);905 sun8i_a83t_cpu_pll_fixup(reg + SUN8I_A83T_PLL_C1CPUX_REG);906 907 return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_a83t_ccu_desc);908}909 910static const struct of_device_id sun8i_a83t_ccu_ids[] = {911 { .compatible = "allwinner,sun8i-a83t-ccu" },912 { }913};914MODULE_DEVICE_TABLE(of, sun8i_a83t_ccu_ids);915 916static struct platform_driver sun8i_a83t_ccu_driver = {917 .probe = sun8i_a83t_ccu_probe,918 .driver = {919 .name = "sun8i-a83t-ccu",920 .suppress_bind_attrs = true,921 .of_match_table = sun8i_a83t_ccu_ids,922 },923};924module_platform_driver(sun8i_a83t_ccu_driver);925 926MODULE_IMPORT_NS(SUNXI_CCU);927MODULE_DESCRIPTION("Support for the Allwinner A83T CCU");928MODULE_LICENSE("GPL");929