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

Merge tag 'sunxi-clk-for-4.10' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into clk-next

Pull Allwinner clock changes from Maxime Ripard:

The usual patches from us, but most notably the introduction of the A64
clocks unit.

* tag 'sunxi-clk-for-4.10' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux:
clk: sunxi-ng: sun8i-h3: Set CLK_SET_RATE_PARENT for audio module clocks
clk: sunxi-ng: sun8i-a23: Set CLK_SET_RATE_PARENT for audio module clocks
clk: sunxi-ng: Add A64 clocks
clk: sunxi-ng: Implement minimum for multipliers
clk: sunxi-ng: Add minimums for all the relevant structures and clocks
clk: sunxi-ng: Finish to convert to structures for arguments
clk: sunxi-ng: Remove the use of rational computations
clk: sunxi-ng: Rename the internal structures
clk: sunxi: mod0: improve function-level documentation

+1429 -125
+1
Documentation/devicetree/bindings/clock/sunxi-ccu.txt
··· 7 7 - "allwinner,sun8i-a23-ccu" 8 8 - "allwinner,sun8i-a33-ccu" 9 9 - "allwinner,sun8i-h3-ccu" 10 + - "allwinner,sun50i-a64-ccu" 10 11 11 12 - reg: Must contain the registers base address and length 12 13 - clocks: phandle to the oscillators feeding the CCU. Two are needed:
+11 -3
drivers/clk/sunxi-ng/Kconfig
··· 35 35 36 36 config SUNXI_CCU_NKM 37 37 bool 38 - select RATIONAL 39 38 select SUNXI_CCU_GATE 40 39 41 40 config SUNXI_CCU_NKMP 42 41 bool 43 - select RATIONAL 44 42 select SUNXI_CCU_GATE 45 43 46 44 config SUNXI_CCU_NM 47 45 bool 48 - select RATIONAL 49 46 select SUNXI_CCU_FRAC 50 47 select SUNXI_CCU_GATE 51 48 ··· 52 55 select SUNXI_CCU_MUX 53 56 54 57 # SoC Drivers 58 + 59 + config SUN50I_A64_CCU 60 + bool "Support for the Allwinner A64 CCU" 61 + select SUNXI_CCU_DIV 62 + select SUNXI_CCU_NK 63 + select SUNXI_CCU_NKM 64 + select SUNXI_CCU_NKMP 65 + select SUNXI_CCU_NM 66 + select SUNXI_CCU_MP 67 + select SUNXI_CCU_PHASE 68 + default ARM64 && ARCH_SUNXI 55 69 56 70 config SUN6I_A31_CCU 57 71 bool "Support for the Allwinner A31/A31s CCU"
+1
drivers/clk/sunxi-ng/Makefile
··· 18 18 obj-$(CONFIG_SUNXI_CCU_MP) += ccu_mp.o 19 19 20 20 # SoC support 21 + obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o 21 22 obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o 22 23 obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o 23 24 obj-$(CONFIG_SUN8I_A33_CCU) += ccu-sun8i-a33.o
+915
drivers/clk/sunxi-ng/ccu-sun50i-a64.c
··· 1 + /* 2 + * Copyright (c) 2016 Maxime Ripard. 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_mult.h" 25 + #include "ccu_nk.h" 26 + #include "ccu_nkm.h" 27 + #include "ccu_nkmp.h" 28 + #include "ccu_nm.h" 29 + #include "ccu_phase.h" 30 + 31 + #include "ccu-sun50i-a64.h" 32 + 33 + static struct ccu_nkmp pll_cpux_clk = { 34 + .enable = BIT(31), 35 + .lock = BIT(28), 36 + .n = _SUNXI_CCU_MULT(8, 5), 37 + .k = _SUNXI_CCU_MULT(4, 2), 38 + .m = _SUNXI_CCU_DIV(0, 2), 39 + .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), 40 + .common = { 41 + .reg = 0x000, 42 + .hw.init = CLK_HW_INIT("pll-cpux", 43 + "osc24M", 44 + &ccu_nkmp_ops, 45 + CLK_SET_RATE_UNGATE), 46 + }, 47 + }; 48 + 49 + /* 50 + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from 51 + * the base (2x, 4x and 8x), and one variable divider (the one true 52 + * pll audio). 53 + * 54 + * We don't have any need for the variable divider for now, so we just 55 + * hardcode it to match with the clock names 56 + */ 57 + #define SUN50I_A64_PLL_AUDIO_REG 0x008 58 + 59 + static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", 60 + "osc24M", 0x008, 61 + 8, 7, /* N */ 62 + 0, 5, /* M */ 63 + BIT(31), /* gate */ 64 + BIT(28), /* lock */ 65 + CLK_SET_RATE_UNGATE); 66 + 67 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", 68 + "osc24M", 0x010, 69 + 8, 7, /* N */ 70 + 0, 4, /* M */ 71 + BIT(24), /* frac enable */ 72 + BIT(25), /* frac select */ 73 + 270000000, /* frac rate 0 */ 74 + 297000000, /* frac rate 1 */ 75 + BIT(31), /* gate */ 76 + BIT(28), /* lock */ 77 + CLK_SET_RATE_UNGATE); 78 + 79 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", 80 + "osc24M", 0x018, 81 + 8, 7, /* N */ 82 + 0, 4, /* M */ 83 + BIT(24), /* frac enable */ 84 + BIT(25), /* frac select */ 85 + 270000000, /* frac rate 0 */ 86 + 297000000, /* frac rate 1 */ 87 + BIT(31), /* gate */ 88 + BIT(28), /* lock */ 89 + CLK_SET_RATE_UNGATE); 90 + 91 + static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", 92 + "osc24M", 0x020, 93 + 8, 5, /* N */ 94 + 4, 2, /* K */ 95 + 0, 2, /* M */ 96 + BIT(31), /* gate */ 97 + BIT(28), /* lock */ 98 + CLK_SET_RATE_UNGATE); 99 + 100 + static struct ccu_nk pll_periph0_clk = { 101 + .enable = BIT(31), 102 + .lock = BIT(28), 103 + .n = _SUNXI_CCU_MULT(8, 5), 104 + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), 105 + .fixed_post_div = 2, 106 + .common = { 107 + .reg = 0x028, 108 + .features = CCU_FEATURE_FIXED_POSTDIV, 109 + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", 110 + &ccu_nk_ops, CLK_SET_RATE_UNGATE), 111 + }, 112 + }; 113 + 114 + static struct ccu_nk pll_periph1_clk = { 115 + .enable = BIT(31), 116 + .lock = BIT(28), 117 + .n = _SUNXI_CCU_MULT(8, 5), 118 + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), 119 + .fixed_post_div = 2, 120 + .common = { 121 + .reg = 0x02c, 122 + .features = CCU_FEATURE_FIXED_POSTDIV, 123 + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", 124 + &ccu_nk_ops, CLK_SET_RATE_UNGATE), 125 + }, 126 + }; 127 + 128 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", 129 + "osc24M", 0x030, 130 + 8, 7, /* N */ 131 + 0, 4, /* M */ 132 + BIT(24), /* frac enable */ 133 + BIT(25), /* frac select */ 134 + 270000000, /* frac rate 0 */ 135 + 297000000, /* frac rate 1 */ 136 + BIT(31), /* gate */ 137 + BIT(28), /* lock */ 138 + CLK_SET_RATE_UNGATE); 139 + 140 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", 141 + "osc24M", 0x038, 142 + 8, 7, /* N */ 143 + 0, 4, /* M */ 144 + BIT(24), /* frac enable */ 145 + BIT(25), /* frac select */ 146 + 270000000, /* frac rate 0 */ 147 + 297000000, /* frac rate 1 */ 148 + BIT(31), /* gate */ 149 + BIT(28), /* lock */ 150 + CLK_SET_RATE_UNGATE); 151 + 152 + /* 153 + * The output function can be changed to something more complex that 154 + * we do not handle yet. 155 + * 156 + * Hardcode the mode so that we don't fall in that case. 157 + */ 158 + #define SUN50I_A64_PLL_MIPI_REG 0x040 159 + 160 + struct ccu_nkm pll_mipi_clk = { 161 + .enable = BIT(31), 162 + .lock = BIT(28), 163 + .n = _SUNXI_CCU_MULT(8, 4), 164 + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), 165 + .m = _SUNXI_CCU_DIV(0, 4), 166 + .common = { 167 + .reg = 0x040, 168 + .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", 169 + &ccu_nkm_ops, CLK_SET_RATE_UNGATE), 170 + }, 171 + }; 172 + 173 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic", 174 + "osc24M", 0x044, 175 + 8, 7, /* N */ 176 + 0, 4, /* M */ 177 + BIT(24), /* frac enable */ 178 + BIT(25), /* frac select */ 179 + 270000000, /* frac rate 0 */ 180 + 297000000, /* frac rate 1 */ 181 + BIT(31), /* gate */ 182 + BIT(28), /* lock */ 183 + CLK_SET_RATE_UNGATE); 184 + 185 + static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", 186 + "osc24M", 0x048, 187 + 8, 7, /* N */ 188 + 0, 4, /* M */ 189 + BIT(24), /* frac enable */ 190 + BIT(25), /* frac select */ 191 + 270000000, /* frac rate 0 */ 192 + 297000000, /* frac rate 1 */ 193 + BIT(31), /* gate */ 194 + BIT(28), /* lock */ 195 + CLK_SET_RATE_UNGATE); 196 + 197 + static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", 198 + "osc24M", 0x04c, 199 + 8, 7, /* N */ 200 + 0, 2, /* M */ 201 + BIT(31), /* gate */ 202 + BIT(28), /* lock */ 203 + CLK_SET_RATE_UNGATE); 204 + 205 + static const char * const cpux_parents[] = { "osc32k", "osc24M", 206 + "pll-cpux" , "pll-cpux" }; 207 + static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, 208 + 0x050, 16, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); 209 + 210 + static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); 211 + 212 + static const char * const ahb1_parents[] = { "osc32k", "osc24M", 213 + "axi" , "pll-periph0" }; 214 + static struct ccu_div ahb1_clk = { 215 + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), 216 + 217 + .mux = { 218 + .shift = 12, 219 + .width = 2, 220 + 221 + .variable_prediv = { 222 + .index = 3, 223 + .shift = 6, 224 + .width = 2, 225 + }, 226 + }, 227 + 228 + .common = { 229 + .reg = 0x054, 230 + .features = CCU_FEATURE_VARIABLE_PREDIV, 231 + .hw.init = CLK_HW_INIT_PARENTS("ahb1", 232 + ahb1_parents, 233 + &ccu_div_ops, 234 + 0), 235 + }, 236 + }; 237 + 238 + static struct clk_div_table apb1_div_table[] = { 239 + { .val = 0, .div = 2 }, 240 + { .val = 1, .div = 2 }, 241 + { .val = 2, .div = 4 }, 242 + { .val = 3, .div = 8 }, 243 + { /* Sentinel */ }, 244 + }; 245 + static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", 246 + 0x054, 8, 2, apb1_div_table, 0); 247 + 248 + static const char * const apb2_parents[] = { "osc32k", "osc24M", 249 + "pll-periph0-2x" , 250 + "pll-periph0-2x" }; 251 + static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, 252 + 0, 5, /* M */ 253 + 16, 2, /* P */ 254 + 24, 2, /* mux */ 255 + 0); 256 + 257 + static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" }; 258 + static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = { 259 + { .index = 1, .div = 2 }, 260 + }; 261 + static struct ccu_mux ahb2_clk = { 262 + .mux = { 263 + .shift = 0, 264 + .width = 1, 265 + .fixed_predivs = ahb2_fixed_predivs, 266 + .n_predivs = ARRAY_SIZE(ahb2_fixed_predivs), 267 + }, 268 + 269 + .common = { 270 + .reg = 0x05c, 271 + .features = CCU_FEATURE_FIXED_PREDIV, 272 + .hw.init = CLK_HW_INIT_PARENTS("ahb2", 273 + ahb2_parents, 274 + &ccu_mux_ops, 275 + 0), 276 + }, 277 + }; 278 + 279 + static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", 280 + 0x060, BIT(1), 0); 281 + static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", 282 + 0x060, BIT(5), 0); 283 + static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", 284 + 0x060, BIT(6), 0); 285 + static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", 286 + 0x060, BIT(8), 0); 287 + static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", 288 + 0x060, BIT(9), 0); 289 + static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", 290 + 0x060, BIT(10), 0); 291 + static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", 292 + 0x060, BIT(13), 0); 293 + static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", 294 + 0x060, BIT(14), 0); 295 + static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb2", 296 + 0x060, BIT(17), 0); 297 + static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", 298 + 0x060, BIT(18), 0); 299 + static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", 300 + 0x060, BIT(19), 0); 301 + static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", 302 + 0x060, BIT(20), 0); 303 + static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", 304 + 0x060, BIT(21), 0); 305 + static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", 306 + 0x060, BIT(23), 0); 307 + static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", 308 + 0x060, BIT(24), 0); 309 + static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb2", 310 + 0x060, BIT(25), 0); 311 + static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", 312 + 0x060, BIT(28), 0); 313 + static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb2", 314 + 0x060, BIT(29), 0); 315 + 316 + static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", 317 + 0x064, BIT(0), 0); 318 + static SUNXI_CCU_GATE(bus_tcon0_clk, "bus-tcon0", "ahb1", 319 + 0x064, BIT(3), 0); 320 + static SUNXI_CCU_GATE(bus_tcon1_clk, "bus-tcon1", "ahb1", 321 + 0x064, BIT(4), 0); 322 + static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", 323 + 0x064, BIT(5), 0); 324 + static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb1", 325 + 0x064, BIT(8), 0); 326 + static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb1", 327 + 0x064, BIT(11), 0); 328 + static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", 329 + 0x064, BIT(12), 0); 330 + static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", 331 + 0x064, BIT(20), 0); 332 + static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "ahb1", 333 + 0x064, BIT(21), 0); 334 + static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "ahb1", 335 + 0x064, BIT(22), 0); 336 + 337 + static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", 338 + 0x068, BIT(0), 0); 339 + static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 340 + 0x068, BIT(1), 0); 341 + static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", 342 + 0x068, BIT(5), 0); 343 + static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 344 + 0x068, BIT(8), 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 + 352 + static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 353 + 0x06c, BIT(0), 0); 354 + static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 355 + 0x06c, BIT(1), 0); 356 + static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 357 + 0x06c, BIT(2), 0); 358 + static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", 359 + 0x06c, BIT(5), 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 SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", 372 + 0x070, BIT(7), 0); 373 + 374 + static struct clk_div_table ths_div_table[] = { 375 + { .val = 0, .div = 1 }, 376 + { .val = 1, .div = 2 }, 377 + { .val = 2, .div = 4 }, 378 + { .val = 3, .div = 6 }, 379 + }; 380 + static const char * const ths_parents[] = { "osc24M" }; 381 + static struct ccu_div ths_clk = { 382 + .enable = BIT(31), 383 + .div = _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table), 384 + .mux = _SUNXI_CCU_MUX(24, 2), 385 + .common = { 386 + .reg = 0x074, 387 + .hw.init = CLK_HW_INIT_PARENTS("ths", 388 + ths_parents, 389 + &ccu_div_ops, 390 + 0), 391 + }, 392 + }; 393 + 394 + static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", 395 + "pll-periph1" }; 396 + static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, 397 + 0, 4, /* M */ 398 + 16, 2, /* P */ 399 + 24, 2, /* mux */ 400 + BIT(31), /* gate */ 401 + 0); 402 + 403 + static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x", 404 + "pll-periph1-2x" }; 405 + static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088, 406 + 0, 4, /* M */ 407 + 16, 2, /* P */ 408 + 24, 2, /* mux */ 409 + BIT(31), /* gate */ 410 + 0); 411 + 412 + static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c, 413 + 0, 4, /* M */ 414 + 16, 2, /* P */ 415 + 24, 2, /* mux */ 416 + BIT(31), /* gate */ 417 + 0); 418 + 419 + static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090, 420 + 0, 4, /* M */ 421 + 16, 2, /* P */ 422 + 24, 2, /* mux */ 423 + BIT(31), /* gate */ 424 + 0); 425 + 426 + static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; 427 + static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, 428 + 0, 4, /* M */ 429 + 16, 2, /* P */ 430 + 24, 4, /* mux */ 431 + BIT(31), /* gate */ 432 + 0); 433 + 434 + static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_default_parents, 0x09c, 435 + 0, 4, /* M */ 436 + 16, 2, /* P */ 437 + 24, 2, /* mux */ 438 + BIT(31), /* gate */ 439 + 0); 440 + 441 + static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, 442 + 0, 4, /* M */ 443 + 16, 2, /* P */ 444 + 24, 2, /* mux */ 445 + BIT(31), /* gate */ 446 + 0); 447 + 448 + static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, 449 + 0, 4, /* M */ 450 + 16, 2, /* P */ 451 + 24, 2, /* mux */ 452 + BIT(31), /* gate */ 453 + 0); 454 + 455 + static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", 456 + "pll-audio-2x", "pll-audio" }; 457 + static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, 458 + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 459 + 460 + static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, 461 + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 462 + 463 + static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, 464 + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 465 + 466 + static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio", 467 + 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT); 468 + 469 + static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 470 + 0x0cc, BIT(8), 0); 471 + static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 472 + 0x0cc, BIT(9), 0); 473 + static SUNXI_CCU_GATE(usb_hsic_clk, "usb-hsic", "pll-hsic", 474 + 0x0cc, BIT(10), 0); 475 + static SUNXI_CCU_GATE(usb_hsic_12m_clk, "usb-hsic-12M", "osc12M", 476 + 0x0cc, BIT(11), 0); 477 + static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 478 + 0x0cc, BIT(16), 0); 479 + static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "usb-ohci0", 480 + 0x0cc, BIT(17), 0); 481 + 482 + static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; 483 + static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, 484 + 0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL); 485 + 486 + static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", 487 + 0x100, BIT(0), 0); 488 + static SUNXI_CCU_GATE(dram_csi_clk, "dram-csi", "dram", 489 + 0x100, BIT(1), 0); 490 + static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", 491 + 0x100, BIT(2), 0); 492 + static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", 493 + 0x100, BIT(3), 0); 494 + 495 + static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; 496 + static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 497 + 0x104, 0, 4, 24, 3, BIT(31), 0); 498 + 499 + static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; 500 + static const u8 tcon0_table[] = { 0, 2, }; 501 + static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents, 502 + tcon0_table, 0x118, 24, 3, BIT(31), 503 + CLK_SET_RATE_PARENT); 504 + 505 + static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" }; 506 + static const u8 tcon1_table[] = { 0, 2, }; 507 + struct ccu_div tcon1_clk = { 508 + .enable = BIT(31), 509 + .div = _SUNXI_CCU_DIV(0, 4), 510 + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table), 511 + .common = { 512 + .reg = 0x11c, 513 + .hw.init = CLK_HW_INIT_PARENTS("tcon1", 514 + tcon1_parents, 515 + &ccu_div_ops, 516 + CLK_SET_RATE_PARENT), 517 + }, 518 + }; 519 + 520 + static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; 521 + static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, 522 + 0x124, 0, 4, 24, 3, BIT(31), 0); 523 + 524 + static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 525 + 0x130, BIT(31), 0); 526 + 527 + static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; 528 + static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, 529 + 0x134, 16, 4, 24, 3, BIT(31), 0); 530 + 531 + static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", "pll-periph1" }; 532 + static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents, 533 + 0x134, 0, 5, 8, 3, BIT(15), 0); 534 + 535 + static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 536 + 0x13c, 16, 3, BIT(31), 0); 537 + 538 + static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", 539 + 0x140, BIT(31), CLK_SET_RATE_PARENT); 540 + 541 + static SUNXI_CCU_GATE(ac_dig_4x_clk, "ac-dig-4x", "pll-audio-4x", 542 + 0x140, BIT(30), CLK_SET_RATE_PARENT); 543 + 544 + static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 545 + 0x144, BIT(31), 0); 546 + 547 + static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; 548 + static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 549 + 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); 550 + 551 + static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", 552 + 0x154, BIT(31), 0); 553 + 554 + static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", 555 + "pll-ddr0", "pll-ddr1" }; 556 + static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 557 + 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL); 558 + 559 + static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" }; 560 + static const u8 dsi_dphy_table[] = { 0, 2, }; 561 + static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy", 562 + dsi_dphy_parents, dsi_dphy_table, 563 + 0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT); 564 + 565 + static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", 566 + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); 567 + 568 + /* Fixed Factor clocks */ 569 + static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0); 570 + 571 + /* We hardcode the divider to 4 for now */ 572 + static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", 573 + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); 574 + static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", 575 + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); 576 + static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", 577 + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); 578 + static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", 579 + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); 580 + static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", 581 + "pll-periph0", 1, 2, 0); 582 + static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", 583 + "pll-periph1", 1, 2, 0); 584 + static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", 585 + "pll-video0", 1, 2, CLK_SET_RATE_PARENT); 586 + 587 + static struct ccu_common *sun50i_a64_ccu_clks[] = { 588 + &pll_cpux_clk.common, 589 + &pll_audio_base_clk.common, 590 + &pll_video0_clk.common, 591 + &pll_ve_clk.common, 592 + &pll_ddr0_clk.common, 593 + &pll_periph0_clk.common, 594 + &pll_periph1_clk.common, 595 + &pll_video1_clk.common, 596 + &pll_gpu_clk.common, 597 + &pll_mipi_clk.common, 598 + &pll_hsic_clk.common, 599 + &pll_de_clk.common, 600 + &pll_ddr1_clk.common, 601 + &cpux_clk.common, 602 + &axi_clk.common, 603 + &ahb1_clk.common, 604 + &apb1_clk.common, 605 + &apb2_clk.common, 606 + &ahb2_clk.common, 607 + &bus_mipi_dsi_clk.common, 608 + &bus_ce_clk.common, 609 + &bus_dma_clk.common, 610 + &bus_mmc0_clk.common, 611 + &bus_mmc1_clk.common, 612 + &bus_mmc2_clk.common, 613 + &bus_nand_clk.common, 614 + &bus_dram_clk.common, 615 + &bus_emac_clk.common, 616 + &bus_ts_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_ohci1_clk.common, 625 + &bus_ve_clk.common, 626 + &bus_tcon0_clk.common, 627 + &bus_tcon1_clk.common, 628 + &bus_deinterlace_clk.common, 629 + &bus_csi_clk.common, 630 + &bus_hdmi_clk.common, 631 + &bus_de_clk.common, 632 + &bus_gpu_clk.common, 633 + &bus_msgbox_clk.common, 634 + &bus_spinlock_clk.common, 635 + &bus_codec_clk.common, 636 + &bus_spdif_clk.common, 637 + &bus_pio_clk.common, 638 + &bus_ths_clk.common, 639 + &bus_i2s0_clk.common, 640 + &bus_i2s1_clk.common, 641 + &bus_i2s2_clk.common, 642 + &bus_i2c0_clk.common, 643 + &bus_i2c1_clk.common, 644 + &bus_i2c2_clk.common, 645 + &bus_scr_clk.common, 646 + &bus_uart0_clk.common, 647 + &bus_uart1_clk.common, 648 + &bus_uart2_clk.common, 649 + &bus_uart3_clk.common, 650 + &bus_uart4_clk.common, 651 + &bus_dbg_clk.common, 652 + &ths_clk.common, 653 + &nand_clk.common, 654 + &mmc0_clk.common, 655 + &mmc1_clk.common, 656 + &mmc2_clk.common, 657 + &ts_clk.common, 658 + &ce_clk.common, 659 + &spi0_clk.common, 660 + &spi1_clk.common, 661 + &i2s0_clk.common, 662 + &i2s1_clk.common, 663 + &i2s2_clk.common, 664 + &spdif_clk.common, 665 + &usb_phy0_clk.common, 666 + &usb_phy1_clk.common, 667 + &usb_hsic_clk.common, 668 + &usb_hsic_12m_clk.common, 669 + &usb_ohci0_clk.common, 670 + &usb_ohci1_clk.common, 671 + &dram_clk.common, 672 + &dram_ve_clk.common, 673 + &dram_csi_clk.common, 674 + &dram_deinterlace_clk.common, 675 + &dram_ts_clk.common, 676 + &de_clk.common, 677 + &tcon0_clk.common, 678 + &tcon1_clk.common, 679 + &deinterlace_clk.common, 680 + &csi_misc_clk.common, 681 + &csi_sclk_clk.common, 682 + &csi_mclk_clk.common, 683 + &ve_clk.common, 684 + &ac_dig_clk.common, 685 + &ac_dig_4x_clk.common, 686 + &avs_clk.common, 687 + &hdmi_clk.common, 688 + &hdmi_ddc_clk.common, 689 + &mbus_clk.common, 690 + &dsi_dphy_clk.common, 691 + &gpu_clk.common, 692 + }; 693 + 694 + static struct clk_hw_onecell_data sun50i_a64_hw_clks = { 695 + .hws = { 696 + [CLK_OSC_12M] = &osc12M_clk.hw, 697 + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, 698 + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, 699 + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, 700 + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, 701 + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, 702 + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, 703 + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, 704 + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, 705 + [CLK_PLL_VE] = &pll_ve_clk.common.hw, 706 + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, 707 + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, 708 + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, 709 + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, 710 + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, 711 + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, 712 + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, 713 + [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, 714 + [CLK_PLL_HSIC] = &pll_hsic_clk.common.hw, 715 + [CLK_PLL_DE] = &pll_de_clk.common.hw, 716 + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, 717 + [CLK_CPUX] = &cpux_clk.common.hw, 718 + [CLK_AXI] = &axi_clk.common.hw, 719 + [CLK_AHB1] = &ahb1_clk.common.hw, 720 + [CLK_APB1] = &apb1_clk.common.hw, 721 + [CLK_APB2] = &apb2_clk.common.hw, 722 + [CLK_AHB2] = &ahb2_clk.common.hw, 723 + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, 724 + [CLK_BUS_CE] = &bus_ce_clk.common.hw, 725 + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, 726 + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, 727 + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, 728 + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, 729 + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, 730 + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, 731 + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, 732 + [CLK_BUS_TS] = &bus_ts_clk.common.hw, 733 + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, 734 + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, 735 + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, 736 + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, 737 + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, 738 + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, 739 + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, 740 + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, 741 + [CLK_BUS_VE] = &bus_ve_clk.common.hw, 742 + [CLK_BUS_TCON0] = &bus_tcon0_clk.common.hw, 743 + [CLK_BUS_TCON1] = &bus_tcon1_clk.common.hw, 744 + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, 745 + [CLK_BUS_CSI] = &bus_csi_clk.common.hw, 746 + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, 747 + [CLK_BUS_DE] = &bus_de_clk.common.hw, 748 + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, 749 + [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, 750 + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, 751 + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, 752 + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, 753 + [CLK_BUS_PIO] = &bus_pio_clk.common.hw, 754 + [CLK_BUS_THS] = &bus_ths_clk.common.hw, 755 + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, 756 + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, 757 + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, 758 + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, 759 + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, 760 + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, 761 + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, 762 + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, 763 + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, 764 + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, 765 + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, 766 + [CLK_BUS_SCR] = &bus_scr_clk.common.hw, 767 + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, 768 + [CLK_THS] = &ths_clk.common.hw, 769 + [CLK_NAND] = &nand_clk.common.hw, 770 + [CLK_MMC0] = &mmc0_clk.common.hw, 771 + [CLK_MMC1] = &mmc1_clk.common.hw, 772 + [CLK_MMC2] = &mmc2_clk.common.hw, 773 + [CLK_TS] = &ts_clk.common.hw, 774 + [CLK_CE] = &ce_clk.common.hw, 775 + [CLK_SPI0] = &spi0_clk.common.hw, 776 + [CLK_SPI1] = &spi1_clk.common.hw, 777 + [CLK_I2S0] = &i2s0_clk.common.hw, 778 + [CLK_I2S1] = &i2s1_clk.common.hw, 779 + [CLK_I2S2] = &i2s2_clk.common.hw, 780 + [CLK_SPDIF] = &spdif_clk.common.hw, 781 + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, 782 + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, 783 + [CLK_USB_HSIC] = &usb_hsic_clk.common.hw, 784 + [CLK_USB_HSIC_12M] = &usb_hsic_12m_clk.common.hw, 785 + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, 786 + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, 787 + [CLK_DRAM] = &dram_clk.common.hw, 788 + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, 789 + [CLK_DRAM_CSI] = &dram_csi_clk.common.hw, 790 + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, 791 + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, 792 + [CLK_DE] = &de_clk.common.hw, 793 + [CLK_TCON0] = &tcon0_clk.common.hw, 794 + [CLK_TCON1] = &tcon1_clk.common.hw, 795 + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, 796 + [CLK_CSI_MISC] = &csi_misc_clk.common.hw, 797 + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, 798 + [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, 799 + [CLK_VE] = &ve_clk.common.hw, 800 + [CLK_AC_DIG] = &ac_dig_clk.common.hw, 801 + [CLK_AC_DIG_4X] = &ac_dig_4x_clk.common.hw, 802 + [CLK_AVS] = &avs_clk.common.hw, 803 + [CLK_HDMI] = &hdmi_clk.common.hw, 804 + [CLK_HDMI_DDC] = &hdmi_ddc_clk.common.hw, 805 + [CLK_MBUS] = &mbus_clk.common.hw, 806 + [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, 807 + [CLK_GPU] = &gpu_clk.common.hw, 808 + }, 809 + .num = CLK_NUMBER, 810 + }; 811 + 812 + static struct ccu_reset_map sun50i_a64_ccu_resets[] = { 813 + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, 814 + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, 815 + [RST_USB_HSIC] = { 0x0cc, BIT(2) }, 816 + 817 + [RST_DRAM] = { 0x0f4, BIT(31) }, 818 + [RST_MBUS] = { 0x0fc, BIT(31) }, 819 + 820 + [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, 821 + [RST_BUS_CE] = { 0x2c0, BIT(5) }, 822 + [RST_BUS_DMA] = { 0x2c0, BIT(6) }, 823 + [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, 824 + [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, 825 + [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, 826 + [RST_BUS_NAND] = { 0x2c0, BIT(13) }, 827 + [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, 828 + [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, 829 + [RST_BUS_TS] = { 0x2c0, BIT(18) }, 830 + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, 831 + [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, 832 + [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, 833 + [RST_BUS_OTG] = { 0x2c0, BIT(23) }, 834 + [RST_BUS_EHCI0] = { 0x2c0, BIT(24) }, 835 + [RST_BUS_EHCI1] = { 0x2c0, BIT(25) }, 836 + [RST_BUS_OHCI0] = { 0x2c0, BIT(28) }, 837 + [RST_BUS_OHCI1] = { 0x2c0, BIT(29) }, 838 + 839 + [RST_BUS_VE] = { 0x2c4, BIT(0) }, 840 + [RST_BUS_TCON0] = { 0x2c4, BIT(3) }, 841 + [RST_BUS_TCON1] = { 0x2c4, BIT(4) }, 842 + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, 843 + [RST_BUS_CSI] = { 0x2c4, BIT(8) }, 844 + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, 845 + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, 846 + [RST_BUS_DE] = { 0x2c4, BIT(12) }, 847 + [RST_BUS_GPU] = { 0x2c4, BIT(20) }, 848 + [RST_BUS_MSGBOX] = { 0x2c4, BIT(21) }, 849 + [RST_BUS_SPINLOCK] = { 0x2c4, BIT(22) }, 850 + [RST_BUS_DBG] = { 0x2c4, BIT(31) }, 851 + 852 + [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, 853 + 854 + [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, 855 + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, 856 + [RST_BUS_THS] = { 0x2d0, BIT(8) }, 857 + [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, 858 + [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, 859 + [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, 860 + 861 + [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, 862 + [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, 863 + [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, 864 + [RST_BUS_SCR] = { 0x2d8, BIT(5) }, 865 + [RST_BUS_UART0] = { 0x2d8, BIT(16) }, 866 + [RST_BUS_UART1] = { 0x2d8, BIT(17) }, 867 + [RST_BUS_UART2] = { 0x2d8, BIT(18) }, 868 + [RST_BUS_UART3] = { 0x2d8, BIT(19) }, 869 + [RST_BUS_UART4] = { 0x2d8, BIT(20) }, 870 + }; 871 + 872 + static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = { 873 + .ccu_clks = sun50i_a64_ccu_clks, 874 + .num_ccu_clks = ARRAY_SIZE(sun50i_a64_ccu_clks), 875 + 876 + .hw_clks = &sun50i_a64_hw_clks, 877 + 878 + .resets = sun50i_a64_ccu_resets, 879 + .num_resets = ARRAY_SIZE(sun50i_a64_ccu_resets), 880 + }; 881 + 882 + static int sun50i_a64_ccu_probe(struct platform_device *pdev) 883 + { 884 + struct resource *res; 885 + void __iomem *reg; 886 + u32 val; 887 + 888 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 889 + reg = devm_ioremap_resource(&pdev->dev, res); 890 + if (IS_ERR(reg)) 891 + return PTR_ERR(reg); 892 + 893 + /* Force the PLL-Audio-1x divider to 4 */ 894 + val = readl(reg + SUN50I_A64_PLL_AUDIO_REG); 895 + val &= ~GENMASK(19, 16); 896 + writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG); 897 + 898 + writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG); 899 + 900 + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc); 901 + } 902 + 903 + static const struct of_device_id sun50i_a64_ccu_ids[] = { 904 + { .compatible = "allwinner,sun50i-a64-ccu" }, 905 + { } 906 + }; 907 + 908 + static struct platform_driver sun50i_a64_ccu_driver = { 909 + .probe = sun50i_a64_ccu_probe, 910 + .driver = { 911 + .name = "sun50i-a64-ccu", 912 + .of_match_table = sun50i_a64_ccu_ids, 913 + }, 914 + }; 915 + builtin_platform_driver(sun50i_a64_ccu_driver);
+72
drivers/clk/sunxi-ng/ccu-sun50i-a64.h
··· 1 + /* 2 + * Copyright 2016 Maxime Ripard 3 + * 4 + * Maxime Ripard <maxime.ripard@free-electrons.com> 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_SUN50I_A64_H_ 18 + #define _CCU_SUN50I_A64_H_ 19 + 20 + #include <dt-bindings/clock/sun50i-a64-ccu.h> 21 + #include <dt-bindings/reset/sun50i-a64-ccu.h> 22 + 23 + #define CLK_OSC_12M 0 24 + #define CLK_PLL_CPUX 1 25 + #define CLK_PLL_AUDIO_BASE 2 26 + #define CLK_PLL_AUDIO 3 27 + #define CLK_PLL_AUDIO_2X 4 28 + #define CLK_PLL_AUDIO_4X 5 29 + #define CLK_PLL_AUDIO_8X 6 30 + #define CLK_PLL_VIDEO0 7 31 + #define CLK_PLL_VIDEO0_2X 8 32 + #define CLK_PLL_VE 9 33 + #define CLK_PLL_DDR0 10 34 + #define CLK_PLL_PERIPH0 11 35 + #define CLK_PLL_PERIPH0_2X 12 36 + #define CLK_PLL_PERIPH1 13 37 + #define CLK_PLL_PERIPH1_2X 14 38 + #define CLK_PLL_VIDEO1 15 39 + #define CLK_PLL_GPU 16 40 + #define CLK_PLL_MIPI 17 41 + #define CLK_PLL_HSIC 18 42 + #define CLK_PLL_DE 19 43 + #define CLK_PLL_DDR1 20 44 + #define CLK_CPUX 21 45 + #define CLK_AXI 22 46 + #define CLK_APB 23 47 + #define CLK_AHB1 24 48 + #define CLK_APB1 25 49 + #define CLK_APB2 26 50 + #define CLK_AHB2 27 51 + 52 + /* All the bus gates are exported */ 53 + 54 + /* The first bunch of module clocks are exported */ 55 + 56 + #define CLK_USB_OHCI0_12M 90 57 + 58 + #define CLK_USB_OHCI1_12M 92 59 + 60 + #define CLK_DRAM 94 61 + 62 + /* All the DRAM gates are exported */ 63 + 64 + /* Some more module clocks are exported */ 65 + 66 + #define CLK_MBUS 112 67 + 68 + /* And the DSI and GPU module clock is exported */ 69 + 70 + #define CLK_NUMBER (CLK_GPU + 1) 71 + 72 + #endif /* _CCU_SUN50I_A64_H_ */
+3 -3
drivers/clk/sunxi-ng/ccu-sun8i-a23.c
··· 344 344 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", 345 345 "pll-audio-2x", "pll-audio" }; 346 346 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, 347 - 0x0b0, 16, 2, BIT(31), 0); 347 + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 348 348 349 349 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, 350 - 0x0b4, 16, 2, BIT(31), 0); 350 + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 351 351 352 352 /* TODO: the parent for most of the USB clocks is not known */ 353 353 static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", ··· 415 415 0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT); 416 416 417 417 static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", 418 - 0x140, BIT(31), 0); 418 + 0x140, BIT(31), CLK_SET_RATE_PARENT); 419 419 static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 420 420 0x144, BIT(31), 0); 421 421
+5 -5
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
··· 394 394 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", 395 395 "pll-audio-2x", "pll-audio" }; 396 396 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, 397 - 0x0b0, 16, 2, BIT(31), 0); 397 + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 398 398 399 399 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, 400 - 0x0b4, 16, 2, BIT(31), 0); 400 + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 401 401 402 402 static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, 403 - 0x0b8, 16, 2, BIT(31), 0); 403 + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); 404 404 405 405 static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio", 406 - 0x0c0, 0, 4, BIT(31), 0); 406 + 0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT); 407 407 408 408 static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 409 409 0x0cc, BIT(8), 0); ··· 466 466 0x13c, 16, 3, BIT(31), 0); 467 467 468 468 static SUNXI_CCU_GATE(ac_dig_clk, "ac-dig", "pll-audio", 469 - 0x140, BIT(31), 0); 469 + 0x140, BIT(31), CLK_SET_RATE_PARENT); 470 470 static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 471 471 0x144, BIT(31), 0); 472 472
+3 -3
drivers/clk/sunxi-ng/ccu_div.h
··· 20 20 #include "ccu_mux.h" 21 21 22 22 /** 23 - * struct _ccu_div - Internal divider description 23 + * struct ccu_div_internal - Internal divider description 24 24 * @shift: Bit offset of the divider in its register 25 25 * @width: Width of the divider field in its register 26 26 * @max: Maximum value allowed for that divider. This is the ··· 36 36 * It is basically a wrapper around the clk_divider functions 37 37 * arguments. 38 38 */ 39 - struct _ccu_div { 39 + struct ccu_div_internal { 40 40 u8 shift; 41 41 u8 width; 42 42 ··· 78 78 struct ccu_div { 79 79 u32 enable; 80 80 81 - struct _ccu_div div; 81 + struct ccu_div_internal div; 82 82 struct ccu_mux_internal mux; 83 83 struct ccu_common common; 84 84 };
+6 -6
drivers/clk/sunxi-ng/ccu_frac.c
··· 14 14 #include "ccu_frac.h" 15 15 16 16 bool ccu_frac_helper_is_enabled(struct ccu_common *common, 17 - struct _ccu_frac *cf) 17 + struct ccu_frac_internal *cf) 18 18 { 19 19 if (!(common->features & CCU_FEATURE_FRACTIONAL)) 20 20 return false; ··· 23 23 } 24 24 25 25 void ccu_frac_helper_enable(struct ccu_common *common, 26 - struct _ccu_frac *cf) 26 + struct ccu_frac_internal *cf) 27 27 { 28 28 unsigned long flags; 29 29 u32 reg; ··· 38 38 } 39 39 40 40 void ccu_frac_helper_disable(struct ccu_common *common, 41 - struct _ccu_frac *cf) 41 + struct ccu_frac_internal *cf) 42 42 { 43 43 unsigned long flags; 44 44 u32 reg; ··· 53 53 } 54 54 55 55 bool ccu_frac_helper_has_rate(struct ccu_common *common, 56 - struct _ccu_frac *cf, 56 + struct ccu_frac_internal *cf, 57 57 unsigned long rate) 58 58 { 59 59 if (!(common->features & CCU_FEATURE_FRACTIONAL)) ··· 63 63 } 64 64 65 65 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, 66 - struct _ccu_frac *cf) 66 + struct ccu_frac_internal *cf) 67 67 { 68 68 u32 reg; 69 69 ··· 84 84 } 85 85 86 86 int ccu_frac_helper_set_rate(struct ccu_common *common, 87 - struct _ccu_frac *cf, 87 + struct ccu_frac_internal *cf, 88 88 unsigned long rate) 89 89 { 90 90 unsigned long flags;
+7 -7
drivers/clk/sunxi-ng/ccu_frac.h
··· 18 18 19 19 #include "ccu_common.h" 20 20 21 - struct _ccu_frac { 21 + struct ccu_frac_internal { 22 22 u32 enable; 23 23 u32 select; 24 24 ··· 33 33 } 34 34 35 35 bool ccu_frac_helper_is_enabled(struct ccu_common *common, 36 - struct _ccu_frac *cf); 36 + struct ccu_frac_internal *cf); 37 37 void ccu_frac_helper_enable(struct ccu_common *common, 38 - struct _ccu_frac *cf); 38 + struct ccu_frac_internal *cf); 39 39 void ccu_frac_helper_disable(struct ccu_common *common, 40 - struct _ccu_frac *cf); 40 + struct ccu_frac_internal *cf); 41 41 42 42 bool ccu_frac_helper_has_rate(struct ccu_common *common, 43 - struct _ccu_frac *cf, 43 + struct ccu_frac_internal *cf, 44 44 unsigned long rate); 45 45 46 46 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, 47 - struct _ccu_frac *cf); 47 + struct ccu_frac_internal *cf); 48 48 49 49 int ccu_frac_helper_set_rate(struct ccu_common *common, 50 - struct _ccu_frac *cf, 50 + struct ccu_frac_internal *cf, 51 51 unsigned long rate); 52 52 53 53 #endif /* _CCU_FRAC_H_ */
+2 -2
drivers/clk/sunxi-ng/ccu_mp.h
··· 29 29 struct ccu_mp { 30 30 u32 enable; 31 31 32 - struct _ccu_div m; 33 - struct _ccu_div p; 32 + struct ccu_div_internal m; 33 + struct ccu_div_internal p; 34 34 struct ccu_mux_internal mux; 35 35 struct ccu_common common; 36 36 };
+25 -8
drivers/clk/sunxi-ng/ccu_mult.c
··· 13 13 #include "ccu_gate.h" 14 14 #include "ccu_mult.h" 15 15 16 + struct _ccu_mult { 17 + unsigned long mult, min, max; 18 + }; 19 + 16 20 static void ccu_mult_find_best(unsigned long parent, unsigned long rate, 17 - unsigned int max_n, unsigned int *n) 21 + struct _ccu_mult *mult) 18 22 { 19 - *n = rate / parent; 23 + int _mult; 24 + 25 + _mult = rate / parent; 26 + if (_mult < mult->min) 27 + _mult = mult->min; 28 + 29 + if (_mult > mult->max) 30 + _mult = mult->max; 31 + 32 + mult->mult = _mult; 20 33 } 21 34 22 35 static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux, ··· 38 25 void *data) 39 26 { 40 27 struct ccu_mult *cm = data; 41 - unsigned int n; 28 + struct _ccu_mult _cm; 42 29 43 - ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); 30 + _cm.min = 1; 31 + _cm.max = 1 << cm->mult.width; 32 + ccu_mult_find_best(parent_rate, rate, &_cm); 44 33 45 - return parent_rate * n; 34 + return parent_rate * _cm.mult; 46 35 } 47 36 48 37 static void ccu_mult_disable(struct clk_hw *hw) ··· 98 83 unsigned long parent_rate) 99 84 { 100 85 struct ccu_mult *cm = hw_to_ccu_mult(hw); 86 + struct _ccu_mult _cm; 101 87 unsigned long flags; 102 - unsigned int n; 103 88 u32 reg; 104 89 105 90 ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1, 106 91 &parent_rate); 107 92 108 - ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n); 93 + _cm.min = cm->mult.min; 94 + _cm.max = 1 << cm->mult.width; 95 + ccu_mult_find_best(parent_rate, rate, &_cm); 109 96 110 97 spin_lock_irqsave(cm->common.lock, flags); 111 98 112 99 reg = readl(cm->common.base + cm->common.reg); 113 100 reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift); 114 101 115 - writel(reg | ((n - 1) << cm->mult.shift), 102 + writel(reg | ((_cm.mult - 1) << cm->mult.shift), 116 103 cm->common.base + cm->common.reg); 117 104 118 105 spin_unlock_irqrestore(cm->common.lock, flags);
+11 -6
drivers/clk/sunxi-ng/ccu_mult.h
··· 4 4 #include "ccu_common.h" 5 5 #include "ccu_mux.h" 6 6 7 - struct _ccu_mult { 7 + struct ccu_mult_internal { 8 8 u8 shift; 9 9 u8 width; 10 + u8 min; 10 11 }; 11 12 12 - #define _SUNXI_CCU_MULT(_shift, _width) \ 13 - { \ 14 - .shift = _shift, \ 15 - .width = _width, \ 13 + #define _SUNXI_CCU_MULT_MIN(_shift, _width, _min) \ 14 + { \ 15 + .shift = _shift, \ 16 + .width = _width, \ 17 + .min = _min, \ 16 18 } 19 + 20 + #define _SUNXI_CCU_MULT(_shift, _width) \ 21 + _SUNXI_CCU_MULT_MIN(_shift, _width, 1) 17 22 18 23 struct ccu_mult { 19 24 u32 enable; 20 25 21 - struct _ccu_mult mult; 26 + struct ccu_mult_internal mult; 22 27 struct ccu_mux_internal mux; 23 28 struct ccu_common common; 24 29 };
+26 -17
drivers/clk/sunxi-ng/ccu_nk.c
··· 9 9 */ 10 10 11 11 #include <linux/clk-provider.h> 12 - #include <linux/rational.h> 13 12 14 13 #include "ccu_gate.h" 15 14 #include "ccu_nk.h" 16 15 16 + struct _ccu_nk { 17 + unsigned long n, min_n, max_n; 18 + unsigned long k, min_k, max_k; 19 + }; 20 + 17 21 static void ccu_nk_find_best(unsigned long parent, unsigned long rate, 18 - unsigned int max_n, unsigned int max_k, 19 - unsigned int *n, unsigned int *k) 22 + struct _ccu_nk *nk) 20 23 { 21 24 unsigned long best_rate = 0; 22 25 unsigned int best_k = 0, best_n = 0; 23 26 unsigned int _k, _n; 24 27 25 - for (_k = 1; _k <= max_k; _k++) { 26 - for (_n = 1; _n <= max_n; _n++) { 28 + for (_k = nk->min_k; _k <= nk->max_k; _k++) { 29 + for (_n = nk->min_n; _n <= nk->max_n; _n++) { 27 30 unsigned long tmp_rate = parent * _n * _k; 28 31 29 32 if (tmp_rate > rate) ··· 40 37 } 41 38 } 42 39 43 - *k = best_k; 44 - *n = best_n; 40 + nk->k = best_k; 41 + nk->n = best_n; 45 42 } 46 43 47 44 static void ccu_nk_disable(struct clk_hw *hw) ··· 92 89 unsigned long *parent_rate) 93 90 { 94 91 struct ccu_nk *nk = hw_to_ccu_nk(hw); 95 - unsigned int n, k; 92 + struct _ccu_nk _nk; 96 93 97 94 if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) 98 95 rate *= nk->fixed_post_div; 99 96 100 - ccu_nk_find_best(*parent_rate, rate, 101 - 1 << nk->n.width, 1 << nk->k.width, 102 - &n, &k); 97 + _nk.min_n = nk->n.min; 98 + _nk.max_n = 1 << nk->n.width; 99 + _nk.min_k = nk->k.min; 100 + _nk.max_k = 1 << nk->k.width; 103 101 104 - rate = *parent_rate * n * k; 102 + ccu_nk_find_best(*parent_rate, rate, &_nk); 103 + rate = *parent_rate * _nk.n * _nk.k; 104 + 105 105 if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) 106 106 rate = rate / nk->fixed_post_div; 107 107 ··· 116 110 { 117 111 struct ccu_nk *nk = hw_to_ccu_nk(hw); 118 112 unsigned long flags; 119 - unsigned int n, k; 113 + struct _ccu_nk _nk; 120 114 u32 reg; 121 115 122 116 if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV) 123 117 rate = rate * nk->fixed_post_div; 124 118 125 - ccu_nk_find_best(parent_rate, rate, 126 - 1 << nk->n.width, 1 << nk->k.width, 127 - &n, &k); 119 + _nk.min_n = nk->n.min; 120 + _nk.max_n = 1 << nk->n.width; 121 + _nk.min_k = nk->k.min; 122 + _nk.max_k = 1 << nk->k.width; 123 + 124 + ccu_nk_find_best(parent_rate, rate, &_nk); 128 125 129 126 spin_lock_irqsave(nk->common.lock, flags); 130 127 ··· 135 126 reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift); 136 127 reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift); 137 128 138 - writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift), 129 + writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift), 139 130 nk->common.base + nk->common.reg); 140 131 141 132 spin_unlock_irqrestore(nk->common.lock, flags);
+2 -2
drivers/clk/sunxi-ng/ccu_nk.h
··· 30 30 u32 enable; 31 31 u32 lock; 32 32 33 - struct _ccu_mult n; 34 - struct _ccu_mult k; 33 + struct ccu_mult_internal n; 34 + struct ccu_mult_internal k; 35 35 36 36 unsigned int fixed_post_div; 37 37
+23 -18
drivers/clk/sunxi-ng/ccu_nkm.c
··· 9 9 */ 10 10 11 11 #include <linux/clk-provider.h> 12 - #include <linux/rational.h> 13 12 14 13 #include "ccu_gate.h" 15 14 #include "ccu_nkm.h" 16 15 17 16 struct _ccu_nkm { 18 - unsigned long n, max_n; 19 - unsigned long k, max_k; 20 - unsigned long m, max_m; 17 + unsigned long n, min_n, max_n; 18 + unsigned long k, min_k, max_k; 19 + unsigned long m, min_m, max_m; 21 20 }; 22 21 23 22 static void ccu_nkm_find_best(unsigned long parent, unsigned long rate, ··· 26 27 unsigned long best_n = 0, best_k = 0, best_m = 0; 27 28 unsigned long _n, _k, _m; 28 29 29 - for (_k = 1; _k <= nkm->max_k; _k++) { 30 - unsigned long tmp_rate; 30 + for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { 31 + for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { 32 + for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { 33 + unsigned long tmp_rate; 31 34 32 - rational_best_approximation(rate / _k, parent, 33 - nkm->max_n, nkm->max_m, &_n, &_m); 35 + tmp_rate = parent * _n * _k / _m; 34 36 35 - tmp_rate = parent * _n * _k / _m; 36 - 37 - if (tmp_rate > rate) 38 - continue; 39 - 40 - if ((rate - tmp_rate) < (rate - best_rate)) { 41 - best_rate = tmp_rate; 42 - best_n = _n; 43 - best_k = _k; 44 - best_m = _m; 37 + if (tmp_rate > rate) 38 + continue; 39 + if ((rate - tmp_rate) < (rate - best_rate)) { 40 + best_rate = tmp_rate; 41 + best_n = _n; 42 + best_k = _k; 43 + best_m = _m; 44 + } 45 + } 45 46 } 46 47 } 47 48 ··· 100 101 struct ccu_nkm *nkm = data; 101 102 struct _ccu_nkm _nkm; 102 103 104 + _nkm.min_n = nkm->n.min; 103 105 _nkm.max_n = 1 << nkm->n.width; 106 + _nkm.min_k = nkm->k.min; 104 107 _nkm.max_k = 1 << nkm->k.width; 108 + _nkm.min_m = 1; 105 109 _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; 106 110 107 111 ccu_nkm_find_best(parent_rate, rate, &_nkm); ··· 129 127 unsigned long flags; 130 128 u32 reg; 131 129 130 + _nkm.min_n = nkm->n.min; 132 131 _nkm.max_n = 1 << nkm->n.width; 132 + _nkm.min_k = nkm->k.min; 133 133 _nkm.max_k = 1 << nkm->k.width; 134 + _nkm.min_m = 1; 134 135 _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; 135 136 136 137 ccu_nkm_find_best(parent_rate, rate, &_nkm);
+3 -3
drivers/clk/sunxi-ng/ccu_nkm.h
··· 29 29 u32 enable; 30 30 u32 lock; 31 31 32 - struct _ccu_mult n; 33 - struct _ccu_mult k; 34 - struct _ccu_div m; 32 + struct ccu_mult_internal n; 33 + struct ccu_mult_internal k; 34 + struct ccu_div_internal m; 35 35 struct ccu_mux_internal mux; 36 36 37 37 struct ccu_common common;
+28 -21
drivers/clk/sunxi-ng/ccu_nkmp.c
··· 9 9 */ 10 10 11 11 #include <linux/clk-provider.h> 12 - #include <linux/rational.h> 13 12 14 13 #include "ccu_gate.h" 15 14 #include "ccu_nkmp.h" 16 15 17 16 struct _ccu_nkmp { 18 - unsigned long n, max_n; 19 - unsigned long k, max_k; 20 - unsigned long m, max_m; 21 - unsigned long p, max_p; 17 + unsigned long n, min_n, max_n; 18 + unsigned long k, min_k, max_k; 19 + unsigned long m, min_m, max_m; 20 + unsigned long p, min_p, max_p; 22 21 }; 23 22 24 23 static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate, ··· 27 28 unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0; 28 29 unsigned long _n, _k, _m, _p; 29 30 30 - for (_k = 1; _k <= nkmp->max_k; _k++) { 31 - for (_p = 1; _p <= nkmp->max_p; _p <<= 1) { 32 - unsigned long tmp_rate; 31 + for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) { 32 + for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) { 33 + for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) { 34 + for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) { 35 + unsigned long tmp_rate; 33 36 34 - rational_best_approximation(rate / _k, parent / _p, 35 - nkmp->max_n, nkmp->max_m, 36 - &_n, &_m); 37 + tmp_rate = parent * _n * _k / (_m * _p); 37 38 38 - tmp_rate = parent * _n * _k / (_m * _p); 39 + if (tmp_rate > rate) 40 + continue; 39 41 40 - if (tmp_rate > rate) 41 - continue; 42 - 43 - if ((rate - tmp_rate) < (rate - best_rate)) { 44 - best_rate = tmp_rate; 45 - best_n = _n; 46 - best_k = _k; 47 - best_m = _m; 48 - best_p = _p; 42 + if ((rate - tmp_rate) < (rate - best_rate)) { 43 + best_rate = tmp_rate; 44 + best_n = _n; 45 + best_k = _k; 46 + best_m = _m; 47 + best_p = _p; 48 + } 49 + } 49 50 } 50 51 } 51 52 } ··· 107 108 struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw); 108 109 struct _ccu_nkmp _nkmp; 109 110 111 + _nkmp.min_n = nkmp->n.min; 110 112 _nkmp.max_n = 1 << nkmp->n.width; 113 + _nkmp.min_k = nkmp->k.min; 111 114 _nkmp.max_k = 1 << nkmp->k.width; 115 + _nkmp.min_m = 1; 112 116 _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; 117 + _nkmp.min_p = 1; 113 118 _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); 114 119 115 120 ccu_nkmp_find_best(*parent_rate, rate, &_nkmp); ··· 129 126 unsigned long flags; 130 127 u32 reg; 131 128 129 + _nkmp.min_n = 1; 132 130 _nkmp.max_n = 1 << nkmp->n.width; 131 + _nkmp.min_k = 1; 133 132 _nkmp.max_k = 1 << nkmp->k.width; 133 + _nkmp.min_m = 1; 134 134 _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width; 135 + _nkmp.min_p = 1; 135 136 _nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1); 136 137 137 138 ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
+4 -4
drivers/clk/sunxi-ng/ccu_nkmp.h
··· 29 29 u32 enable; 30 30 u32 lock; 31 31 32 - struct _ccu_mult n; 33 - struct _ccu_mult k; 34 - struct _ccu_div m; 35 - struct _ccu_div p; 32 + struct ccu_mult_internal n; 33 + struct ccu_mult_internal k; 34 + struct ccu_div_internal m; 35 + struct ccu_div_internal p; 36 36 37 37 struct ccu_common common; 38 38 };
+45 -13
drivers/clk/sunxi-ng/ccu_nm.c
··· 9 9 */ 10 10 11 11 #include <linux/clk-provider.h> 12 - #include <linux/rational.h> 13 12 14 13 #include "ccu_frac.h" 15 14 #include "ccu_gate.h" 16 15 #include "ccu_nm.h" 16 + 17 + struct _ccu_nm { 18 + unsigned long n, min_n, max_n; 19 + unsigned long m, min_m, max_m; 20 + }; 21 + 22 + static void ccu_nm_find_best(unsigned long parent, unsigned long rate, 23 + struct _ccu_nm *nm) 24 + { 25 + unsigned long best_rate = 0; 26 + unsigned long best_n = 0, best_m = 0; 27 + unsigned long _n, _m; 28 + 29 + for (_n = nm->min_n; _n <= nm->max_n; _n++) { 30 + for (_m = nm->min_m; _m <= nm->max_m; _m++) { 31 + unsigned long tmp_rate = parent * _n / _m; 32 + 33 + if (tmp_rate > rate) 34 + continue; 35 + 36 + if ((rate - tmp_rate) < (rate - best_rate)) { 37 + best_rate = tmp_rate; 38 + best_n = _n; 39 + best_m = _m; 40 + } 41 + } 42 + } 43 + 44 + nm->n = best_n; 45 + nm->m = best_m; 46 + } 17 47 18 48 static void ccu_nm_disable(struct clk_hw *hw) 19 49 { ··· 91 61 unsigned long *parent_rate) 92 62 { 93 63 struct ccu_nm *nm = hw_to_ccu_nm(hw); 94 - unsigned long max_n, max_m; 95 - unsigned long n, m; 64 + struct _ccu_nm _nm; 96 65 97 - max_n = 1 << nm->n.width; 98 - max_m = nm->m.max ?: 1 << nm->m.width; 66 + _nm.min_n = nm->n.min; 67 + _nm.max_n = 1 << nm->n.width; 68 + _nm.min_m = 1; 69 + _nm.max_m = nm->m.max ?: 1 << nm->m.width; 99 70 100 - rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m); 71 + ccu_nm_find_best(*parent_rate, rate, &_nm); 101 72 102 - return *parent_rate * n / m; 73 + return *parent_rate * _nm.n / _nm.m; 103 74 } 104 75 105 76 static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, 106 77 unsigned long parent_rate) 107 78 { 108 79 struct ccu_nm *nm = hw_to_ccu_nm(hw); 80 + struct _ccu_nm _nm; 109 81 unsigned long flags; 110 - unsigned long max_n, max_m; 111 - unsigned long n, m; 112 82 u32 reg; 113 83 114 84 if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) ··· 116 86 else 117 87 ccu_frac_helper_disable(&nm->common, &nm->frac); 118 88 119 - max_n = 1 << nm->n.width; 120 - max_m = nm->m.max ?: 1 << nm->m.width; 89 + _nm.min_n = 1; 90 + _nm.max_n = 1 << nm->n.width; 91 + _nm.min_m = 1; 92 + _nm.max_m = nm->m.max ?: 1 << nm->m.width; 121 93 122 - rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m); 94 + ccu_nm_find_best(parent_rate, rate, &_nm); 123 95 124 96 spin_lock_irqsave(nm->common.lock, flags); 125 97 ··· 129 97 reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift); 130 98 reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); 131 99 132 - writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift), 100 + writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift), 133 101 nm->common.base + nm->common.reg); 134 102 135 103 spin_unlock_irqrestore(nm->common.lock, flags);
+3 -3
drivers/clk/sunxi-ng/ccu_nm.h
··· 30 30 u32 enable; 31 31 u32 lock; 32 32 33 - struct _ccu_mult n; 34 - struct _ccu_div m; 35 - struct _ccu_frac frac; 33 + struct ccu_mult_internal n; 34 + struct ccu_div_internal m; 35 + struct ccu_frac_internal frac; 36 36 37 37 struct ccu_common common; 38 38 };
+1 -1
drivers/clk/sunxi/clk-mod0.c
··· 24 24 #include "clk-factors.h" 25 25 26 26 /** 27 - * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks 27 + * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks 28 28 * MOD0 rate is calculated as follows 29 29 * rate = (parent_rate >> p) / (m + 1); 30 30 */
+134
include/dt-bindings/clock/sun50i-a64-ccu.h
··· 1 + /* 2 + * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com> 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_CLK_SUN50I_A64_H_ 44 + #define _DT_BINDINGS_CLK_SUN50I_A64_H_ 45 + 46 + #define CLK_BUS_MIPI_DSI 28 47 + #define CLK_BUS_CE 29 48 + #define CLK_BUS_DMA 30 49 + #define CLK_BUS_MMC0 31 50 + #define CLK_BUS_MMC1 32 51 + #define CLK_BUS_MMC2 33 52 + #define CLK_BUS_NAND 34 53 + #define CLK_BUS_DRAM 35 54 + #define CLK_BUS_EMAC 36 55 + #define CLK_BUS_TS 37 56 + #define CLK_BUS_HSTIMER 38 57 + #define CLK_BUS_SPI0 39 58 + #define CLK_BUS_SPI1 40 59 + #define CLK_BUS_OTG 41 60 + #define CLK_BUS_EHCI0 42 61 + #define CLK_BUS_EHCI1 43 62 + #define CLK_BUS_OHCI0 44 63 + #define CLK_BUS_OHCI1 45 64 + #define CLK_BUS_VE 46 65 + #define CLK_BUS_TCON0 47 66 + #define CLK_BUS_TCON1 48 67 + #define CLK_BUS_DEINTERLACE 49 68 + #define CLK_BUS_CSI 50 69 + #define CLK_BUS_HDMI 51 70 + #define CLK_BUS_DE 52 71 + #define CLK_BUS_GPU 53 72 + #define CLK_BUS_MSGBOX 54 73 + #define CLK_BUS_SPINLOCK 55 74 + #define CLK_BUS_CODEC 56 75 + #define CLK_BUS_SPDIF 57 76 + #define CLK_BUS_PIO 58 77 + #define CLK_BUS_THS 59 78 + #define CLK_BUS_I2S0 60 79 + #define CLK_BUS_I2S1 61 80 + #define CLK_BUS_I2S2 62 81 + #define CLK_BUS_I2C0 63 82 + #define CLK_BUS_I2C1 64 83 + #define CLK_BUS_I2C2 65 84 + #define CLK_BUS_SCR 66 85 + #define CLK_BUS_UART0 67 86 + #define CLK_BUS_UART1 68 87 + #define CLK_BUS_UART2 69 88 + #define CLK_BUS_UART3 70 89 + #define CLK_BUS_UART4 71 90 + #define CLK_BUS_DBG 72 91 + #define CLK_THS 73 92 + #define CLK_NAND 74 93 + #define CLK_MMC0 75 94 + #define CLK_MMC1 76 95 + #define CLK_MMC2 77 96 + #define CLK_TS 78 97 + #define CLK_CE 79 98 + #define CLK_SPI0 80 99 + #define CLK_SPI1 81 100 + #define CLK_I2S0 82 101 + #define CLK_I2S1 83 102 + #define CLK_I2S2 84 103 + #define CLK_SPDIF 85 104 + #define CLK_USB_PHY0 86 105 + #define CLK_USB_PHY1 87 106 + #define CLK_USB_HSIC 88 107 + #define CLK_USB_HSIC_12M 89 108 + 109 + #define CLK_USB_OHCI0 91 110 + 111 + #define CLK_USB_OHCI1 93 112 + 113 + #define CLK_DRAM_VE 95 114 + #define CLK_DRAM_CSI 96 115 + #define CLK_DRAM_DEINTERLACE 97 116 + #define CLK_DRAM_TS 98 117 + #define CLK_DE 99 118 + #define CLK_TCON0 100 119 + #define CLK_TCON1 101 120 + #define CLK_DEINTERLACE 102 121 + #define CLK_CSI_MISC 103 122 + #define CLK_CSI_SCLK 104 123 + #define CLK_CSI_MCLK 105 124 + #define CLK_VE 106 125 + #define CLK_AC_DIG 107 126 + #define CLK_AC_DIG_4X 108 127 + #define CLK_AVS 109 128 + #define CLK_HDMI 110 129 + #define CLK_HDMI_DDC 111 130 + 131 + #define CLK_DSI_DPHY 113 132 + #define CLK_GPU 114 133 + 134 + #endif /* _DT_BINDINGS_CLK_SUN50I_H_ */
+98
include/dt-bindings/reset/sun50i-a64-ccu.h
··· 1 + /* 2 + * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com> 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_RST_SUN50I_A64_H_ 44 + #define _DT_BINDINGS_RST_SUN50I_A64_H_ 45 + 46 + #define RST_USB_PHY0 0 47 + #define RST_USB_PHY1 1 48 + #define RST_USB_HSIC 2 49 + #define RST_DRAM 3 50 + #define RST_MBUS 4 51 + #define RST_BUS_MIPI_DSI 5 52 + #define RST_BUS_CE 6 53 + #define RST_BUS_DMA 7 54 + #define RST_BUS_MMC0 8 55 + #define RST_BUS_MMC1 9 56 + #define RST_BUS_MMC2 10 57 + #define RST_BUS_NAND 11 58 + #define RST_BUS_DRAM 12 59 + #define RST_BUS_EMAC 13 60 + #define RST_BUS_TS 14 61 + #define RST_BUS_HSTIMER 15 62 + #define RST_BUS_SPI0 16 63 + #define RST_BUS_SPI1 17 64 + #define RST_BUS_OTG 18 65 + #define RST_BUS_EHCI0 19 66 + #define RST_BUS_EHCI1 20 67 + #define RST_BUS_OHCI0 21 68 + #define RST_BUS_OHCI1 22 69 + #define RST_BUS_VE 23 70 + #define RST_BUS_TCON0 24 71 + #define RST_BUS_TCON1 25 72 + #define RST_BUS_DEINTERLACE 26 73 + #define RST_BUS_CSI 27 74 + #define RST_BUS_HDMI0 28 75 + #define RST_BUS_HDMI1 29 76 + #define RST_BUS_DE 30 77 + #define RST_BUS_GPU 31 78 + #define RST_BUS_MSGBOX 32 79 + #define RST_BUS_SPINLOCK 33 80 + #define RST_BUS_DBG 34 81 + #define RST_BUS_LVDS 35 82 + #define RST_BUS_CODEC 36 83 + #define RST_BUS_SPDIF 37 84 + #define RST_BUS_THS 38 85 + #define RST_BUS_I2S0 39 86 + #define RST_BUS_I2S1 40 87 + #define RST_BUS_I2S2 41 88 + #define RST_BUS_I2C0 42 89 + #define RST_BUS_I2C1 43 90 + #define RST_BUS_I2C2 44 91 + #define RST_BUS_SCR 45 92 + #define RST_BUS_UART0 46 93 + #define RST_BUS_UART1 47 94 + #define RST_BUS_UART2 48 95 + #define RST_BUS_UART3 49 96 + #define RST_BUS_UART4 50 97 + 98 + #endif /* _DT_BINDINGS_RST_SUN50I_A64_H_ */