Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: sunxi-ng: Add driver for A83T CCU

The A83T clock control unit is a hybrid of some new style clock designs
from the A80, and old style layout from the other Allwinner SoCs.

Like the A80, the SoC does not have a low speed 32.768 kHz oscillator.
Unlike the A80, there is no clock input either. The only low speed clock
available is the internal oscillator which runs at around 16 MHz,
divided by 512, yielding a low speed clock around 31.250 kHz.

Also, the MMC2 module clock supports switching to a "new timing" mode.
This mode divides the clock output by half, and disables the CCU based
clock delays. The MMC controller must be configure to the same mode,
and then use its internal clock delays.

This driver does not support runtime switching of the timing modes.
Instead, the new timing mode is enforced at probe time. Consumers can
check which mode is active by trying to get the current phase delay
of the MMC2 phase clocks, which will return -ENOTSUPP if the new
timing mode is active.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

authored by

Chen-Yu Tsai and committed by
Maxime Ripard
05359be1 13e0dde8

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