File Index
Files and directories
Sign in
FILE

ccu-sun55i-a523.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sunxi-ng/ccu-sun55i-a523.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2023-2024 Arm Ltd.
   4 * Based on the D1 CCU driver:
   5 *   Copyright (c) 2020 huangzhenwei@allwinnertech.com
   6 *   Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
   7 */
   8
   9#include <linux/clk-provider.h>
  10#include <linux/io.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13
  14#include <dt-bindings/clock/sun55i-a523-ccu.h>
  15#include <dt-bindings/reset/sun55i-a523-ccu.h>
  16
  17#include "../clk.h"
  18
  19#include "ccu_common.h"
  20#include "ccu_reset.h"
  21
  22#include "ccu_div.h"
  23#include "ccu_gate.h"
  24#include "ccu_mp.h"
  25#include "ccu_mult.h"
  26#include "ccu_nk.h"
  27#include "ccu_nkm.h"
  28#include "ccu_nkmp.h"
  29#include "ccu_nm.h"
  30
  31/*
  32 * The 24 MHz oscillator, the root of most of the clock tree.
  33 * .fw_name is the string used in the DT "clock-names" property, used to
  34 * identify the corresponding clock in the "clocks" property.
  35 */
  36static const struct clk_parent_data osc24M[] = {
  37	{ .fw_name = "hosc" }
  38};
  39
  40/**************************************************************************
  41 *                              PLLs                                      *
  42 **************************************************************************/
  43
  44/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
  45#define SUN55I_A523_PLL_DDR0_REG		0x010
  46static struct ccu_nkmp pll_ddr_clk = {
  47	.enable		= BIT(27),
  48	.lock		= BIT(28),
  49	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
  50	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
  51	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
  52	.common		= {
  53		.reg		= 0x010,
  54		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ddr0", osc24M,
  55							   &ccu_nkmp_ops,
  56							   CLK_SET_RATE_GATE |
  57							   CLK_IS_CRITICAL),
  58	},
  59};
  60
  61/*
  62 * There is no actual clock output with that frequency (2.4 GHz), instead it
  63 * has multiple outputs with adjustable dividers from that base frequency.
  64 * Model them separately as divider clocks based on that parent here.
  65 */
  66#define SUN55I_A523_PLL_PERIPH0_REG	0x020
  67static struct ccu_nm pll_periph0_4x_clk = {
  68	.enable		= BIT(27),
  69	.lock		= BIT(28),
  70	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
  71	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
  72	.common		= {
  73		.reg		= 0x020,
  74		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph0-4x",
  75							   osc24M, &ccu_nm_ops,
  76							   CLK_SET_RATE_GATE),
  77	},
  78};
  79/*
  80 * Most clock-defining macros expect an *array* of parent clocks, even if
  81 * they do not contain a muxer to select between different parents.
  82 * The macros ending in just _HW take a simple clock pointer, but then create
  83 * a single-entry array out of that. The macros using _HWS take such an
  84 * array (even when it is a single entry one), this avoids having those
  85 * helper arrays created inside *every* clock definition.
  86 * This means for every clock that is referenced more than once it is
  87 * useful to create such a dummy array and use _HWS.
  88 */
  89static const struct clk_hw *pll_periph0_4x_hws[] = {
  90	&pll_periph0_4x_clk.common.hw
  91};
  92
  93static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
  94		       pll_periph0_4x_hws, 0x020, 16, 3, 0);
  95static const struct clk_hw *pll_periph0_2x_hws[] = {
  96	&pll_periph0_2x_clk.common.hw
  97};
  98static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M",
  99		       pll_periph0_4x_hws, 0x020, 20, 3, 0);
 100static SUNXI_CCU_M_HWS(pll_periph0_480M_clk, "pll-periph0-480M",
 101		       pll_periph0_4x_hws, 0x020, 2, 3, 0);
 102static const struct clk_hw *pll_periph0_480M_hws[] = {
 103	&pll_periph0_480M_clk.common.hw
 104};
 105static CLK_FIXED_FACTOR_HWS(pll_periph0_600M_clk, "pll-periph0-600M",
 106			    pll_periph0_2x_hws, 2, 1, 0);
 107static CLK_FIXED_FACTOR_HWS(pll_periph0_400M_clk, "pll-periph0-400M",
 108			    pll_periph0_2x_hws, 3, 1, 0);
 109static CLK_FIXED_FACTOR_HWS(pll_periph0_300M_clk, "pll-periph0-300M",
 110			    pll_periph0_2x_hws, 4, 1, 0);
 111static CLK_FIXED_FACTOR_HWS(pll_periph0_200M_clk, "pll-periph0-200M",
 112			    pll_periph0_2x_hws, 6, 1, 0);
 113static CLK_FIXED_FACTOR_HWS(pll_periph0_150M_clk, "pll-periph0-150M",
 114			    pll_periph0_2x_hws, 8, 1, 0);
 115static CLK_FIXED_FACTOR_HWS(pll_periph0_160M_clk, "pll-periph0-160M",
 116			    pll_periph0_480M_hws, 3, 1, 0);
 117static const struct clk_hw *pll_periph0_150M_hws[] = {
 118	&pll_periph0_150M_clk.hw
 119};
 120
 121#define SUN55I_A523_PLL_PERIPH1_REG	0x028
 122static struct ccu_nm pll_periph1_4x_clk = {
 123	.enable		= BIT(27),
 124	.lock		= BIT(28),
 125	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 126	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 127	.common		= {
 128		.reg		= 0x028,
 129		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-periph1-4x",
 130							   osc24M, &ccu_nm_ops,
 131							   CLK_SET_RATE_GATE),
 132	},
 133};
 134
 135static const struct clk_hw *pll_periph1_4x_hws[] = {
 136	&pll_periph1_4x_clk.common.hw
 137};
 138static SUNXI_CCU_M_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
 139		       pll_periph1_4x_hws, 0x028, 16, 3, 0);
 140static SUNXI_CCU_M_HWS(pll_periph1_800M_clk, "pll-periph1-800M",
 141		       pll_periph1_4x_hws, 0x028, 20, 3, 0);
 142static SUNXI_CCU_M_HWS(pll_periph1_480M_clk, "pll-periph1-480M",
 143		       pll_periph1_4x_hws, 0x028, 2, 3, 0);
 144
 145static const struct clk_hw *pll_periph1_2x_hws[] = {
 146	&pll_periph1_2x_clk.common.hw
 147};
 148static CLK_FIXED_FACTOR_HWS(pll_periph1_600M_clk, "pll-periph1-600M",
 149			    pll_periph1_2x_hws, 2, 1, 0);
 150static CLK_FIXED_FACTOR_HWS(pll_periph1_400M_clk, "pll-periph1-400M",
 151			    pll_periph1_2x_hws, 3, 1, 0);
 152static CLK_FIXED_FACTOR_HWS(pll_periph1_300M_clk, "pll-periph1-300M",
 153			    pll_periph1_2x_hws, 4, 1, 0);
 154static CLK_FIXED_FACTOR_HWS(pll_periph1_200M_clk, "pll-periph1-200M",
 155			    pll_periph1_2x_hws, 6, 1, 0);
 156static CLK_FIXED_FACTOR_HWS(pll_periph1_150M_clk, "pll-periph1-150M",
 157			    pll_periph1_2x_hws, 8, 1, 0);
 158static const struct clk_hw *pll_periph1_480M_hws[] = {
 159	&pll_periph1_480M_clk.common.hw
 160};
 161static CLK_FIXED_FACTOR_HWS(pll_periph1_160M_clk, "pll-periph1-160M",
 162			    pll_periph1_480M_hws, 3, 1, 0);
 163
 164#define SUN55I_A523_PLL_GPU_REG		0x030
 165static struct ccu_nkmp pll_gpu_clk = {
 166	.enable		= BIT(27),
 167	.lock		= BIT(28),
 168	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 169	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 170	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
 171	.common		= {
 172		.reg		= 0x030,
 173		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-gpu", osc24M,
 174							   &ccu_nkmp_ops,
 175							   CLK_SET_RATE_GATE),
 176	},
 177};
 178
 179#define SUN55I_A523_PLL_VIDEO0_REG	0x040
 180static struct ccu_nm pll_video0_8x_clk = {
 181	.enable		= BIT(27),
 182	.lock		= BIT(28),
 183	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 184	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 185	.common		= {
 186		.reg		= 0x040,
 187		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video0-8x",
 188							   osc24M, &ccu_nm_ops,
 189							   CLK_SET_RATE_GATE),
 190	},
 191};
 192
 193static const struct clk_hw *pll_video0_8x_hws[] = {
 194	&pll_video0_8x_clk.common.hw
 195};
 196static SUNXI_CCU_M_HWS(pll_video0_4x_clk, "pll-video0-4x",
 197		       pll_video0_8x_hws, 0x040, 0, 1, 0);
 198static CLK_FIXED_FACTOR_HWS(pll_video0_3x_clk, "pll-video0-3x",
 199			    pll_video0_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
 200
 201#define SUN55I_A523_PLL_VIDEO1_REG	0x048
 202static struct ccu_nm pll_video1_8x_clk = {
 203	.enable		= BIT(27),
 204	.lock		= BIT(28),
 205	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 206	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 207	.common		= {
 208		.reg		= 0x048,
 209		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video1-8x",
 210							   osc24M, &ccu_nm_ops,
 211							   CLK_SET_RATE_GATE),
 212	},
 213};
 214
 215static const struct clk_hw *pll_video1_8x_hws[] = {
 216	&pll_video1_8x_clk.common.hw
 217};
 218static SUNXI_CCU_M_HWS(pll_video1_4x_clk, "pll-video1-4x",
 219		       pll_video1_8x_hws, 0x048, 0, 1, 0);
 220static CLK_FIXED_FACTOR_HWS(pll_video1_3x_clk, "pll-video1-3x",
 221			    pll_video1_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
 222
 223#define SUN55I_A523_PLL_VIDEO2_REG	0x050
 224static struct ccu_nm pll_video2_8x_clk = {
 225	.enable		= BIT(27),
 226	.lock		= BIT(28),
 227	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 228	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 229	.common		= {
 230		.reg		= 0x050,
 231		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video2-8x",
 232							   osc24M, &ccu_nm_ops,
 233							   CLK_SET_RATE_GATE),
 234	},
 235};
 236
 237static const struct clk_hw *pll_video2_8x_hws[] = {
 238	&pll_video2_8x_clk.common.hw
 239};
 240static SUNXI_CCU_M_HWS(pll_video2_4x_clk, "pll-video2-4x",
 241		       pll_video2_8x_hws, 0x050, 0, 1, 0);
 242static CLK_FIXED_FACTOR_HWS(pll_video2_3x_clk, "pll-video2-3x",
 243			    pll_video2_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
 244
 245#define SUN55I_A523_PLL_VE_REG		0x058
 246static struct ccu_nkmp pll_ve_clk = {
 247	.enable		= BIT(27),
 248	.lock		= BIT(28),
 249	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 250	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 251	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
 252	.common		= {
 253		.reg		= 0x058,
 254		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-ve", osc24M,
 255							   &ccu_nkmp_ops,
 256							   CLK_SET_RATE_GATE),
 257	},
 258};
 259
 260#define SUN55I_A523_PLL_VIDEO3_REG	0x068
 261static struct ccu_nm pll_video3_8x_clk = {
 262	.enable		= BIT(27),
 263	.lock		= BIT(28),
 264	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 265	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
 266	.common		= {
 267		.reg		= 0x068,
 268		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-video3-8x",
 269							   osc24M, &ccu_nm_ops,
 270							   CLK_SET_RATE_GATE),
 271	},
 272};
 273
 274static const struct clk_hw *pll_video3_8x_hws[] = {
 275	&pll_video3_8x_clk.common.hw
 276};
 277static SUNXI_CCU_M_HWS(pll_video3_4x_clk, "pll-video3-4x",
 278		       pll_video3_8x_hws, 0x068, 0, 1, 0);
 279static CLK_FIXED_FACTOR_HWS(pll_video3_3x_clk, "pll-video3-3x",
 280			    pll_video3_8x_hws, 3, 1, CLK_SET_RATE_PARENT);
 281
 282/*
 283 * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors.
 284 * Since we only need some fixed frequency from this PLL (22.5792MHz x 4 and
 285 * 24.576MHz x 4), ignore those dividers and force both of them to 1 (encoded
 286 * as 0), in the probe function below.
 287 * The M factor must be an even number to produce a 50% duty cycle output.
 288 */
 289#define SUN55I_A523_PLL_AUDIO0_REG		0x078
 290static struct ccu_sdm_setting pll_audio0_sdm_table[] = {
 291	{ .rate = 90316800, .pattern = 0xc000872b, .m = 20, .n = 75 },
 292	{ .rate = 98304000, .pattern = 0xc0004dd3, .m = 12, .n = 49 },
 293
 294};
 295
 296static struct ccu_nm pll_audio0_4x_clk = {
 297	.enable		= BIT(27),
 298	.lock		= BIT(28),
 299	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 300	.m		= _SUNXI_CCU_DIV(16, 6),
 301	.sdm		= _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24),
 302					 0x178, BIT(31)),
 303	.min_rate	= 90000000U,
 304	.max_rate	= 3000000000U,
 305	.common		= {
 306		.reg		= 0x078,
 307		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
 308		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-audio0-4x",
 309							   osc24M, &ccu_nm_ops,
 310							   CLK_SET_RATE_GATE),
 311	},
 312};
 313
 314static CLK_FIXED_FACTOR_HW(pll_audio0_2x_clk, "pll-audio0-2x",
 315			   &pll_audio0_4x_clk.common.hw, 2, 1, 0);
 316static CLK_FIXED_FACTOR_HW(pll_audio0_clk, "pll-audio0",
 317			   &pll_audio0_4x_clk.common.hw, 4, 1, 0);
 318
 319#define SUN55I_A523_PLL_NPU_REG			0x080
 320static struct ccu_nm pll_npu_4x_clk = {
 321	.enable		= BIT(27),
 322	.lock		= BIT(28),
 323	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
 324	.m		= _SUNXI_CCU_DIV(1, 1),	/* input divider */
 325	.common		= {
 326		.reg		= 0x0080,
 327		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-npu-4x",
 328							   osc24M, &ccu_nm_ops,
 329							   CLK_SET_RATE_GATE),
 330	},
 331};
 332static CLK_FIXED_FACTOR_HW(pll_npu_2x_clk, "pll-npu-2x",
 333			   &pll_npu_4x_clk.common.hw, 2, 1, CLK_SET_RATE_PARENT);
 334
 335static CLK_FIXED_FACTOR_HW(pll_npu_1x_clk, "pll-npu-1x",
 336			   &pll_npu_4x_clk.common.hw, 4, 1, 0);
 337
 338
 339/**************************************************************************
 340 *                           bus clocks                                   *
 341 **************************************************************************/
 342
 343static const struct clk_parent_data ahb_apb0_parents[] = {
 344	{ .fw_name = "hosc" },
 345	{ .fw_name = "losc" },
 346	{ .fw_name = "iosc" },
 347	{ .hw = &pll_periph0_600M_clk.hw },
 348};
 349
 350static SUNXI_CCU_M_DATA_WITH_MUX(ahb_clk, "ahb", ahb_apb0_parents, 0x510,
 351				 0, 5,		/* M */
 352				 24, 2,		/* mux */
 353				 0);
 354static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
 355
 356static SUNXI_CCU_M_DATA_WITH_MUX(apb0_clk, "apb0", ahb_apb0_parents, 0x520,
 357				 0, 5,		/* M */
 358				 24, 2,	/* mux */
 359				 0);
 360static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
 361
 362static const struct clk_parent_data apb1_parents[] = {
 363	{ .fw_name = "hosc" },
 364	{ .fw_name = "losc" },
 365	{ .fw_name = "iosc" },
 366	{ .hw = &pll_periph0_600M_clk.hw },
 367	{ .hw = &pll_periph0_480M_clk.common.hw },
 368};
 369static SUNXI_CCU_M_DATA_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x524,
 370				 0, 5,		/* M */
 371				 24, 3,		/* mux */
 372				 0);
 373static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
 374
 375static const struct clk_parent_data mbus_parents[] = {
 376	{ .hw = &pll_ddr_clk.common.hw },
 377	{ .hw = &pll_periph1_600M_clk.hw },
 378	{ .hw = &pll_periph1_480M_clk.common.hw },
 379	{ .hw = &pll_periph1_400M_clk.hw },
 380	{ .hw = &pll_periph1_150M_clk.hw },
 381	{ .fw_name = "hosc" },
 382};
 383static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
 384					    0x540,
 385					    0, 5,		/* M */
 386					    0, 0,		/* no P */
 387					    24, 3,	/* mux */
 388					    BIT(31),	/* gate */
 389					    CLK_IS_CRITICAL,
 390					    CCU_FEATURE_UPDATE_BIT);
 391
 392static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw };
 393
 394/**************************************************************************
 395 *                          mod clocks with gates                         *
 396 **************************************************************************/
 397
 398static const struct clk_hw *de_parents[] = {
 399	&pll_periph0_300M_clk.hw,
 400	&pll_periph0_400M_clk.hw,
 401	&pll_video3_4x_clk.common.hw,
 402	&pll_video3_3x_clk.hw,
 403};
 404
 405static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
 406				    0, 5,	/* M */
 407				    24, 3,	/* mux */
 408				    BIT(31),	/* gate */
 409				    CLK_SET_RATE_PARENT);
 410
 411static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws, 0x60c, BIT(0), 0);
 412
 413static const struct clk_hw *di_parents[] = {
 414	&pll_periph0_300M_clk.hw,
 415	&pll_periph0_400M_clk.hw,
 416	&pll_video0_4x_clk.common.hw,
 417	&pll_video1_4x_clk.common.hw,
 418};
 419
 420static SUNXI_CCU_M_HW_WITH_MUX_GATE(di_clk, "di", di_parents, 0x620,
 421				    0, 5,	/* M */
 422				    24, 3,	/* mux */
 423				    BIT(31),	/* gate */
 424				    CLK_SET_RATE_PARENT);
 425
 426static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", ahb_hws, 0x62c, BIT(0), 0);
 427
 428static const struct clk_hw *g2d_parents[] = {
 429	&pll_periph0_400M_clk.hw,
 430	&pll_periph0_300M_clk.hw,
 431	&pll_video0_4x_clk.common.hw,
 432	&pll_video1_4x_clk.common.hw,
 433};
 434
 435static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", g2d_parents, 0x630,
 436				    0, 5,	/* M */
 437				    24, 3,	/* mux */
 438				    BIT(31),	/* gate */
 439				    0);
 440
 441static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws, 0x63c, BIT(0), 0);
 442
 443static const struct clk_hw *gpu_parents[] = {
 444	&pll_gpu_clk.common.hw,
 445	&pll_periph0_800M_clk.common.hw,
 446	&pll_periph0_600M_clk.hw,
 447	&pll_periph0_400M_clk.hw,
 448	&pll_periph0_300M_clk.hw,
 449	&pll_periph0_200M_clk.hw,
 450};
 451
 452static SUNXI_CCU_M_HW_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670,
 453				    0, 4,	/* M */
 454				    24, 3,	/* mux */
 455				    BIT(31),	/* gate */
 456				    CLK_SET_RATE_PARENT);
 457
 458static SUNXI_CCU_GATE_HWS(bus_gpu_clk, "bus-gpu", ahb_hws, 0x67c, BIT(0), 0);
 459
 460static const struct clk_parent_data ce_parents[] = {
 461	{ .fw_name = "hosc" },
 462	{ .hw = &pll_periph0_480M_clk.common.hw },
 463	{ .hw = &pll_periph0_400M_clk.hw },
 464	{ .hw = &pll_periph0_300M_clk.hw },
 465};
 466static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
 467				       0, 5,	/* M */
 468				       24, 3,	/* mux */
 469				       BIT(31),	/* gate */
 470				       0);
 471
 472static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws, 0x68c, BIT(0), 0);
 473static SUNXI_CCU_GATE_HWS(bus_ce_sys_clk, "bus-ce-sys", ahb_hws, 0x68c,
 474			  BIT(1), 0);
 475
 476static const struct clk_hw *ve_parents[] = {
 477	&pll_ve_clk.common.hw,
 478	&pll_periph0_480M_clk.common.hw,
 479	&pll_periph0_400M_clk.hw,
 480	&pll_periph0_300M_clk.hw,
 481};
 482static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
 483				    0, 5,	/* M */
 484				    24, 3,	/* mux */
 485				    BIT(31),	/* gate */
 486				    CLK_SET_RATE_PARENT);
 487
 488static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws, 0x69c, BIT(0), 0);
 489
 490static const struct clk_hw *npu_parents[] = {
 491	&pll_periph0_480M_clk.common.hw,
 492	&pll_periph0_600M_clk.hw,
 493	&pll_periph0_800M_clk.common.hw,
 494	&pll_npu_2x_clk.hw,
 495};
 496static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
 497				    0, 5,	/* M */
 498				    24, 3,	/* mux */
 499				    BIT(31),	/* gate */
 500				    CLK_SET_RATE_PARENT);
 501
 502static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws, 0x70c, BIT(0), 0);
 503
 504static SUNXI_CCU_GATE_HWS(bus_msgbox_clk, "bus-msgbox", ahb_hws, 0x71c,
 505			  BIT(0), 0);
 506
 507static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws, 0x72c,
 508			  BIT(0), 0);
 509
 510static const struct clk_parent_data hstimer_parents[] = {
 511	{ .fw_name = "hosc" },
 512	{ .fw_name = "iosc" },
 513	{ .fw_name = "losc" },
 514	{ .hw = &pll_periph0_200M_clk.hw },
 515};
 516static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
 517				       hstimer_parents, 0x730,
 518				       0, 0,	/* M */
 519				       0, 3,	/* P */
 520				       24, 3,	/* mux */
 521				       BIT(31),	/* gate */
 522				       0);
 523
 524static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
 525				       hstimer_parents,
 526				       0x734,
 527				       0, 0,	/* M */
 528				       0, 3,	/* P */
 529				       24, 3,	/* mux */
 530				       BIT(31),	/* gate */
 531				       0);
 532
 533static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
 534				       hstimer_parents,
 535				       0x738,
 536				       0, 0,	/* M */
 537				       0, 3,	/* P */
 538				       24, 3,	/* mux */
 539				       BIT(31),	/* gate */
 540				       0);
 541
 542static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
 543				       hstimer_parents,
 544				       0x73c,
 545				       0, 0,	/* M */
 546				       0, 3,	/* P */
 547				       24, 3,	/* mux */
 548				       BIT(31),	/* gate */
 549				       0);
 550
 551static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
 552				       hstimer_parents,
 553				       0x740,
 554				       0, 0,	/* M */
 555				       0, 3,	/* P */
 556				       24, 3,	/* mux */
 557				       BIT(31),	/* gate */
 558				       0);
 559
 560static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
 561				       hstimer_parents,
 562				       0x744,
 563				       0, 0,	/* M */
 564				       0, 3,	/* P */
 565				       24, 3,	/* mux */
 566				       BIT(31),	/* gate */
 567				       0);
 568
 569static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
 570			  BIT(0), 0);
 571
 572static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws, 0x78c,
 573			  BIT(0), 0);
 574
 575static SUNXI_CCU_GATE_HWS(bus_pwm0_clk, "bus-pwm0", apb1_hws, 0x7ac, BIT(0), 0);
 576static SUNXI_CCU_GATE_HWS(bus_pwm1_clk, "bus-pwm1", apb1_hws, 0x7ac, BIT(1), 0);
 577
 578static const struct clk_parent_data iommu_parents[] = {
 579	{ .hw = &pll_periph0_600M_clk.hw },
 580	{ .hw = &pll_ddr_clk.common.hw },
 581	{ .hw = &pll_periph0_480M_clk.common.hw },
 582	{ .hw = &pll_periph0_400M_clk.hw },
 583	{ .hw = &pll_periph0_150M_clk.hw },
 584	{ .fw_name = "hosc" },
 585};
 586
 587static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
 588					    0x7b0,
 589					    0, 5,	/* M */
 590					    0, 0,	/* no P */
 591					    24, 3,	/* mux */
 592					    BIT(31),	/* gate */
 593					    CLK_SET_RATE_PARENT,
 594					    CCU_FEATURE_UPDATE_BIT);
 595
 596static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
 597			  BIT(0), 0);
 598
 599static const struct clk_parent_data dram_parents[] = {
 600	{ .hw = &pll_ddr_clk.common.hw },
 601	{ .hw = &pll_periph0_600M_clk.hw },
 602	{ .hw = &pll_periph0_480M_clk.common.hw },
 603	{ .hw = &pll_periph0_400M_clk.hw },
 604	{ .hw = &pll_periph0_150M_clk.hw },
 605};
 606static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
 607					    0x800,
 608					    0, 5,	/* M */
 609					    0, 0,	/* no P */
 610					    24, 3,	/* mux */
 611					    BIT(31),	/* gate */
 612					    CLK_IS_CRITICAL,
 613					    CCU_FEATURE_UPDATE_BIT);
 614
 615static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
 616			  0x804, BIT(0), 0);
 617static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
 618			  0x804, BIT(1), 0);
 619static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
 620			  0x804, BIT(2), 0);
 621static SUNXI_CCU_GATE_HWS(mbus_nand_clk, "mbus-nand", mbus_hws,
 622			  0x804, BIT(5), 0);
 623static SUNXI_CCU_GATE_HWS(mbus_usb3_clk, "mbus-usb3", mbus_hws,
 624			  0x804, BIT(6), 0);
 625static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
 626			  0x804, BIT(8), 0);
 627static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
 628			  0x804, BIT(9), 0);
 629static SUNXI_CCU_GATE_HWS(mbus_gmac1_clk, "mbus-gmac1", mbus_hws,
 630			  0x804, BIT(12), 0);
 631
 632static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws, 0x80c,
 633			  BIT(0), CLK_IS_CRITICAL);
 634
 635static const struct clk_parent_data nand_mmc_parents[] = {
 636	{ .fw_name = "hosc" },
 637	{ .hw = &pll_periph0_400M_clk.hw },
 638	{ .hw = &pll_periph0_300M_clk.hw },
 639	{ .hw = &pll_periph1_400M_clk.hw },
 640	{ .hw = &pll_periph1_300M_clk.hw },
 641};
 642
 643static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand0_clk, "nand0", nand_mmc_parents,
 644				    0x810,
 645				    0, 5,	/* M */
 646				    24, 3,	/* mux */
 647				    BIT(31),	/* gate */
 648				    0);
 649
 650static SUNXI_CCU_M_DATA_WITH_MUX_GATE(nand1_clk, "nand1", nand_mmc_parents,
 651				    0x814,
 652				    0, 5,	/* M */
 653				    24, 3,	/* mux */
 654				    BIT(31),	/* gate */
 655				    0);
 656
 657static SUNXI_CCU_GATE_HWS(bus_nand_clk, "bus-nand", ahb_hws, 0x82c,
 658			  BIT(0), 0);
 659
 660static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc0_clk, "mmc0", nand_mmc_parents,
 661					     0x830,
 662					     0, 5,	/* M */
 663					     8, 5,	/* P */
 664					     24, 3,	/* mux */
 665					     BIT(31),	/* gate */
 666					     2,		/* post div */
 667					     0);
 668
 669static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc1_clk, "mmc1", nand_mmc_parents,
 670					     0x834,
 671					     0, 5,	/* M */
 672					     8, 5,	/* P */
 673					     24, 3,	/* mux */
 674					     BIT(31),	/* gate */
 675					     2,		/* post div */
 676					     0);
 677
 678static const struct clk_parent_data mmc2_parents[] = {
 679	{ .fw_name = "hosc" },
 680	{ .hw = &pll_periph0_800M_clk.common.hw },
 681	{ .hw = &pll_periph0_600M_clk.hw },
 682	{ .hw = &pll_periph1_800M_clk.common.hw },
 683	{ .hw = &pll_periph1_600M_clk.hw },
 684};
 685
 686static SUNXI_CCU_MP_MUX_GATE_POSTDIV_DUALDIV(mmc2_clk, "mmc2", mmc2_parents,
 687					     0x838,
 688					     0, 5,	/* M */
 689					     8, 5,	/* P */
 690					     24, 3,	/* mux */
 691					     BIT(31),	/* gate */
 692					     2,		/* post div */
 693					     0);
 694
 695static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws, 0x84c, BIT(0), 0);
 696static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws, 0x84c, BIT(1), 0);
 697static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws, 0x84c, BIT(2), 0);
 698
 699static SUNXI_CCU_GATE_HWS(bus_sysdap_clk, "bus-sysdap", apb1_hws, 0x88c,
 700			  BIT(0), 0);
 701
 702static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, 0x90c,
 703			  BIT(0), 0);
 704static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, 0x90c,
 705			  BIT(1), 0);
 706static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, 0x90c,
 707			  BIT(2), 0);
 708static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, 0x90c,
 709			  BIT(3), 0);
 710static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, 0x90c,
 711			  BIT(4), 0);
 712static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, 0x90c,
 713			  BIT(5), 0);
 714static SUNXI_CCU_GATE_HWS(bus_uart6_clk, "bus-uart6", apb1_hws, 0x90c,
 715			  BIT(6), 0);
 716static SUNXI_CCU_GATE_HWS(bus_uart7_clk, "bus-uart7", apb1_hws, 0x90c,
 717			  BIT(7), 0);
 718
 719static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, 0x91c, BIT(0), 0);
 720static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, 0x91c, BIT(1), 0);
 721static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, 0x91c, BIT(2), 0);
 722static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, 0x91c, BIT(3), 0);
 723static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws, 0x91c, BIT(4), 0);
 724static SUNXI_CCU_GATE_HWS(bus_i2c5_clk, "bus-i2c5", apb1_hws, 0x91c, BIT(5), 0);
 725
 726static SUNXI_CCU_GATE_HWS(bus_can_clk, "bus-can", apb1_hws, 0x92c, BIT(0), 0);
 727
 728static const struct clk_parent_data spi_parents[] = {
 729	{ .fw_name = "hosc" },
 730	{ .hw = &pll_periph0_300M_clk.hw },
 731	{ .hw = &pll_periph0_200M_clk.hw },
 732	{ .hw = &pll_periph1_300M_clk.hw },
 733	{ .hw = &pll_periph1_200M_clk.hw },
 734};
 735static SUNXI_CCU_DUALDIV_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
 736				  0, 5,		/* M */
 737				  8, 5,		/* P */
 738				  24, 3,	/* mux */
 739				  BIT(31),	/* gate */
 740				  0);
 741static SUNXI_CCU_DUALDIV_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
 742				  0, 5,		/* M */
 743				  8, 5,		/* P */
 744				  24, 3,	/* mux */
 745				  BIT(31),	/* gate */
 746				  0);
 747static SUNXI_CCU_DUALDIV_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
 748				  0, 5,		/* M */
 749				  8, 5,		/* P */
 750				  24, 3,	/* mux */
 751				  BIT(31),	/* gate */
 752				  0);
 753static SUNXI_CCU_DUALDIV_MUX_GATE(spifc_clk, "spifc", nand_mmc_parents, 0x950,
 754				  0, 5,		/* M */
 755				  8, 5,		/* P */
 756				  24, 3,	/* mux */
 757				  BIT(31),	/* gate */
 758				  0);
 759static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws, 0x96c, BIT(0), 0);
 760static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws, 0x96c, BIT(1), 0);
 761static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws, 0x96c, BIT(2), 0);
 762static SUNXI_CCU_GATE_HWS(bus_spifc_clk, "bus-spifc", ahb_hws, 0x96c,
 763			  BIT(3), 0);
 764
 765static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac0_25M_clk, "emac0-25M",
 766				      pll_periph0_150M_hws,
 767				      0x970, BIT(31) | BIT(30), 6, 0);
 768static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac1_25M_clk, "emac1-25M",
 769				      pll_periph0_150M_hws,
 770				      0x974, BIT(31) | BIT(30), 6, 0);
 771static SUNXI_CCU_GATE_HWS(bus_emac0_clk, "bus-emac0", ahb_hws, 0x97c,
 772			  BIT(0), 0);
 773static SUNXI_CCU_GATE_HWS(bus_emac1_clk, "bus-emac1", ahb_hws, 0x98c,
 774			  BIT(0), 0);
 775
 776static const struct clk_parent_data ir_rx_parents[] = {
 777	{ .fw_name = "losc" },
 778	{ .fw_name = "hosc" },
 779};
 780
 781static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_rx_parents, 0x990,
 782				      0, 5,	/* M */
 783				      24, 1,	/* mux */
 784				      BIT(31),	/* gate */
 785				      0);
 786static SUNXI_CCU_GATE_HWS(bus_ir_rx_clk, "bus-ir-rx", apb0_hws, 0x99c,
 787			  BIT(0), 0);
 788
 789static const struct clk_parent_data ir_tx_ledc_parents[] = {
 790	{ .fw_name = "hosc" },
 791	{ .hw = &pll_periph1_600M_clk.hw },
 792};
 793static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_ledc_parents,
 794				      0x9c0,
 795				      0, 5,	/* M */
 796				      24, 1,	/* mux */
 797				      BIT(31),	/* gate */
 798				      0);
 799static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, 0x9cc,
 800			  BIT(0), 0);
 801
 802static SUNXI_CCU_M_WITH_GATE(gpadc0_clk, "gpadc0", "hosc", 0x9e0,
 803				 0, 5,		/* M */
 804				 BIT(31),	/* gate */
 805				 0);
 806static SUNXI_CCU_M_WITH_GATE(gpadc1_clk, "gpadc1", "hosc", 0x9e4,
 807				 0, 5,		/* M */
 808				 BIT(31),	/* gate */
 809				 0);
 810static SUNXI_CCU_GATE_HWS(bus_gpadc0_clk, "bus-gpadc0", ahb_hws, 0x9ec,
 811			  BIT(0), 0);
 812static SUNXI_CCU_GATE_HWS(bus_gpadc1_clk, "bus-gpadc1", ahb_hws, 0x9ec,
 813			  BIT(1), 0);
 814
 815static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, 0x9fc, BIT(0), 0);
 816
 817/*
 818 * The first parent is a 48 MHz input clock divided by 4. That 48 MHz clock is
 819 * a 2x multiplier from osc24M synchronized by pll-periph0, and is also used by
 820 * the OHCI module.
 821 */
 822static const struct clk_parent_data usb_ohci_parents[] = {
 823	{ .hw = &pll_periph0_4x_clk.common.hw },
 824	{ .fw_name = "hosc" },
 825	{ .fw_name = "losc" },
 826	{ .fw_name = "iosc" },
 827};
 828static const struct ccu_mux_fixed_prediv usb_ohci_predivs[] = {
 829	{ .index = 0, .div = 50 },
 830	{ .index = 1, .div = 2 },
 831};
 832
 833static struct ccu_mux usb_ohci0_clk = {
 834	.enable		= BIT(31),
 835	.mux		= {
 836		.shift		= 24,
 837		.width		= 2,
 838		.fixed_predivs	= usb_ohci_predivs,
 839		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
 840	},
 841	.common		= {
 842		.reg		= 0xa70,
 843		.features	= CCU_FEATURE_FIXED_PREDIV,
 844		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci0",
 845							   usb_ohci_parents,
 846							   &ccu_mux_ops,
 847							   0),
 848	},
 849};
 850
 851static struct ccu_mux usb_ohci1_clk = {
 852	.enable		= BIT(31),
 853	.mux		= {
 854		.shift		= 24,
 855		.width		= 2,
 856		.fixed_predivs	= usb_ohci_predivs,
 857		.n_predivs	= ARRAY_SIZE(usb_ohci_predivs),
 858	},
 859	.common		= {
 860		.reg		= 0xa74,
 861		.features	= CCU_FEATURE_FIXED_PREDIV,
 862		.hw.init	= CLK_HW_INIT_PARENTS_DATA("usb-ohci1",
 863							   usb_ohci_parents,
 864							   &ccu_mux_ops,
 865							   0),
 866	},
 867};
 868
 869static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", ahb_hws, 0xa8c,
 870			  BIT(0), 0);
 871static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", ahb_hws, 0xa8c,
 872			  BIT(1), 0);
 873static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", ahb_hws, 0xa8c,
 874			  BIT(4), 0);
 875static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", ahb_hws, 0xa8c,
 876			  BIT(5), 0);
 877static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
 878
 879static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, 0xa9c,
 880			  BIT(0), 0);
 881
 882static const struct clk_parent_data losc_hosc_parents[] = {
 883	{ .fw_name = "hosc" },
 884	{ .fw_name = "losc" },
 885};
 886
 887static SUNXI_CCU_M_DATA_WITH_MUX_GATE(pcie_aux_clk, "pcie-aux",
 888				      losc_hosc_parents, 0xaa0,
 889				      0, 5,	/* M */
 890				      24, 1,	/* mux */
 891				      BIT(31),	/* gate */
 892				      0);
 893
 894static SUNXI_CCU_GATE_HWS(bus_display0_top_clk, "bus-display0-top", ahb_hws,
 895			  0xabc, BIT(0), 0);
 896static SUNXI_CCU_GATE_HWS(bus_display1_top_clk, "bus-display1-top", ahb_hws,
 897			  0xacc, BIT(0), 0);
 898
 899static SUNXI_CCU_GATE_DATA(hdmi_24M_clk, "hdmi-24M", osc24M, 0xb04, BIT(31), 0);
 900
 901static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k",
 902				      pll_periph0_2x_hws,
 903				      0xb10, BIT(30), 36621, 0);
 904
 905static const struct clk_parent_data hdmi_cec_parents[] = {
 906	{ .fw_name = "losc" },
 907	{ .hw = &hdmi_cec_32k_clk.common.hw },
 908};
 909static SUNXI_CCU_MUX_DATA_WITH_GATE(hdmi_cec_clk, "hdmi-cec", hdmi_cec_parents,
 910				    0xb10,
 911				    24, 1,	/* mux */
 912				    BIT(31),	/* gate */
 913				    0);
 914
 915static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", ahb_hws, 0xb1c, BIT(0), 0);
 916
 917static const struct clk_parent_data mipi_dsi_parents[] = {
 918	{ .fw_name = "hosc" },
 919	{ .hw = &pll_periph0_200M_clk.hw },
 920	{ .hw = &pll_periph0_150M_clk.hw },
 921};
 922static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi0_clk, "mipi-dsi0",
 923				      mipi_dsi_parents, 0xb24,
 924				      0, 5,	/* M */
 925				      24, 3,	/* mux */
 926				      BIT(31),	/* gate */
 927				      0);
 928
 929static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi1_clk, "mipi-dsi1",
 930				      mipi_dsi_parents, 0xb28,
 931				      0, 5,	/* M */
 932				      24, 3,	/* mux */
 933				      BIT(31),	/* gate */
 934				      0);
 935
 936static SUNXI_CCU_GATE_HWS(bus_mipi_dsi0_clk, "bus-mipi-dsi0", ahb_hws, 0xb4c,
 937			  BIT(0), 0);
 938
 939static SUNXI_CCU_GATE_HWS(bus_mipi_dsi1_clk, "bus-mipi-dsi1", ahb_hws, 0xb4c,
 940			  BIT(1), 0);
 941
 942static const struct clk_hw *tcon_parents[] = {
 943	&pll_video0_4x_clk.common.hw,
 944	&pll_video1_4x_clk.common.hw,
 945	&pll_video2_4x_clk.common.hw,
 946	&pll_video3_4x_clk.common.hw,
 947	&pll_periph0_2x_clk.common.hw,
 948	&pll_video0_3x_clk.hw,
 949	&pll_video1_3x_clk.hw,
 950};
 951static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents,
 952				    0xb60,
 953				    0,  5,	/* M */
 954				    24, 3,	/* mux */
 955				    BIT(31),	/* gate */
 956				    CLK_SET_RATE_PARENT);
 957
 958static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents,
 959				    0xb64,
 960				    0,  5,	/* M */
 961				    24, 3,	/* mux */
 962				    BIT(31),	/* gate */
 963				    CLK_SET_RATE_PARENT);
 964
 965static const struct clk_hw *tcon_tv_parents[] = {
 966	&pll_video0_4x_clk.common.hw,
 967	&pll_video1_4x_clk.common.hw,
 968	&pll_video2_4x_clk.common.hw,
 969	&pll_video3_4x_clk.common.hw,
 970	&pll_periph0_2x_clk.common.hw,
 971};
 972static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_lcd2_clk, "tcon-lcd2",
 973				    tcon_tv_parents, 0xb68,
 974				    0,  5,	/* M */
 975				    24, 3,	/* mux */
 976				    BIT(31),	/* gate */
 977				    CLK_SET_RATE_PARENT);
 978
 979static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi0_clk, "combophy-dsi0",
 980				    tcon_parents, 0xb6c,
 981				    0,  5,	/* M */
 982				    24, 3,	/* mux */
 983				    BIT(31),	/* gate */
 984				    CLK_SET_RATE_PARENT);
 985
 986static SUNXI_CCU_M_HW_WITH_MUX_GATE(combophy_dsi1_clk, "combophy-dsi1",
 987				    tcon_parents, 0xb70,
 988				    0,  5,	/* M */
 989				    24, 3,	/* mux */
 990				    BIT(31),	/* gate */
 991				    CLK_SET_RATE_PARENT);
 992
 993static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", ahb_hws, 0xb7c,
 994			  BIT(0), 0);
 995static SUNXI_CCU_GATE_HWS(bus_tcon_lcd1_clk, "bus-tcon-lcd1", ahb_hws, 0xb7c,
 996			  BIT(1), 0);
 997static SUNXI_CCU_GATE_HWS(bus_tcon_lcd2_clk, "bus-tcon-lcd2", ahb_hws, 0xb7c,
 998			  BIT(2), 0);
 999
1000static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_tv_parents,
1001				    0xb80,
1002				    0, 4,	/* M */
1003				    24, 3,	/* mux */
1004				    BIT(31),	/* gate */
1005				    CLK_SET_RATE_PARENT);
1006
1007static SUNXI_CCU_M_HW_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_tv_parents,
1008				    0xb84,
1009				    0, 4,	/* M */
1010				    24, 3,	/* mux */
1011				    BIT(31),	/* gate */
1012				    CLK_SET_RATE_PARENT);
1013
1014static SUNXI_CCU_GATE_HWS(bus_tcon_tv0_clk, "bus-tcon-tv0", ahb_hws, 0xb9c,
1015			  BIT(0), 0);
1016static SUNXI_CCU_GATE_HWS(bus_tcon_tv1_clk, "bus-tcon-tv1", ahb_hws, 0xb9c,
1017			  BIT(1), 0);
1018
1019static const struct clk_hw *edp_parents[] = {
1020	&pll_video0_4x_clk.common.hw,
1021	&pll_video1_4x_clk.common.hw,
1022	&pll_video2_4x_clk.common.hw,
1023	&pll_video3_4x_clk.common.hw,
1024	&pll_periph0_2x_clk.common.hw,
1025};
1026static SUNXI_CCU_M_HW_WITH_MUX_GATE(edp_clk, "edp", edp_parents, 0xbb0,
1027				    0, 4,	/* M */
1028				    24, 3,	/* mux */
1029				    BIT(31),	/* gate */
1030				    CLK_SET_RATE_PARENT);
1031
1032static SUNXI_CCU_GATE_HWS(bus_edp_clk, "bus-edp", ahb_hws, 0xbbc, BIT(0), 0);
1033
1034static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ledc_clk, "ledc", ir_tx_ledc_parents,
1035				      0xbf0,
1036				      0, 4,	/* M */
1037				      24, 1,	/* mux */
1038				      BIT(31),	/* gate */
1039				      0);
1040
1041static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", apb0_hws, 0xbfc, BIT(0), 0);
1042
1043static const struct clk_hw *csi_top_parents[] = {
1044	&pll_periph0_300M_clk.hw,
1045	&pll_periph0_400M_clk.hw,
1046	&pll_periph0_480M_clk.common.hw,
1047	&pll_video3_4x_clk.common.hw,
1048	&pll_video3_3x_clk.hw,
1049};
1050static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents,
1051				    0xc04,
1052				    0, 5,	/* M */
1053				    24, 3,	/* mux */
1054				    BIT(31),	/* gate */
1055				    0);
1056
1057static const struct clk_parent_data csi_mclk_parents[] = {
1058	{ .fw_name = "hosc" },
1059	{ .hw = &pll_video3_4x_clk.common.hw },
1060	{ .hw = &pll_video0_4x_clk.common.hw },
1061	{ .hw = &pll_video1_4x_clk.common.hw },
1062	{ .hw = &pll_video2_4x_clk.common.hw },
1063};
1064static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents,
1065				  0xc08,
1066				  0, 5,		/* M */
1067				  8, 5,		/* P */
1068				  24, 3,	/* mux */
1069				  BIT(31),	/* gate */
1070				  0);
1071
1072static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents,
1073				  0xc0c,
1074				  0, 5,		/* M */
1075				  8, 5,		/* P */
1076				  24, 3,	/* mux */
1077				  BIT(31),	/* gate */
1078				  0);
1079
1080static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents,
1081				  0xc10,
1082				  0, 5,		/* M */
1083				  8, 5,		/* P */
1084				  24, 3,	/* mux */
1085				  BIT(31),	/* gate */
1086				  0);
1087
1088static SUNXI_CCU_DUALDIV_MUX_GATE(csi_mclk3_clk, "csi-mclk3", csi_mclk_parents,
1089				  0xc14,
1090				  0, 5,		/* M */
1091				  8, 5,		/* P */
1092				  24, 3,	/* mux */
1093				  BIT(31),	/* gate */
1094				  0);
1095
1096static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws, 0xc1c, BIT(0), 0);
1097
1098static const struct clk_hw *isp_parents[] = {
1099	&pll_periph0_300M_clk.hw,
1100	&pll_periph0_400M_clk.hw,
1101	&pll_video2_4x_clk.common.hw,
1102	&pll_video3_4x_clk.common.hw,
1103};
1104static SUNXI_CCU_M_HW_WITH_MUX_GATE(isp_clk, "isp", isp_parents, 0xc20,
1105				    0, 5,	/* M */
1106				    24, 3,	/* mux */
1107				    BIT(31),	/* gate */
1108				    0);
1109
1110static const struct clk_parent_data dsp_parents[] = {
1111	{ .fw_name = "hosc" },
1112	{ .fw_name = "losc" },
1113	{ .fw_name = "iosc" },
1114	{ .hw = &pll_periph0_2x_clk.common.hw },
1115	{ .hw = &pll_periph0_480M_clk.common.hw, },
1116};
1117static SUNXI_CCU_M_DATA_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70,
1118				      0, 5,	/* M */
1119				      24, 3,	/* mux */
1120				      BIT(31),	/* gate */
1121				      0);
1122
1123static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
1124			   0xf30, BIT(0), 0);
1125static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
1126				       0xf30, BIT(1), 2, 0);
1127static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M",
1128				      pll_periph0_480M_hws,
1129				      0xf30, BIT(2), 30, 0);
1130static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M",
1131				      pll_periph0_2x_hws,
1132				      0xf30, BIT(3), 48, 0);
1133static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_50M_clk, "fanout-50M",
1134				      pll_periph0_2x_hws,
1135				      0xf30, BIT(4), 24, 0);
1136
1137static const struct clk_parent_data fanout_27M_parents[] = {
1138	{ .hw = &pll_video0_4x_clk.common.hw },
1139	{ .hw = &pll_video1_4x_clk.common.hw },
1140	{ .hw = &pll_video2_4x_clk.common.hw },
1141	{ .hw = &pll_video3_4x_clk.common.hw },
1142};
1143static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_27M_clk, "fanout-27M",
1144				  fanout_27M_parents, 0xf34,
1145				  0, 5,		/* div0 */
1146				  8, 5,		/* div1 */
1147				  24, 2,	/* mux */
1148				  BIT(31),	/* gate */
1149				  0);
1150
1151static const struct clk_parent_data fanout_pclk_parents[] = {
1152	{ .hw = &apb0_clk.common.hw }
1153};
1154static SUNXI_CCU_DUALDIV_MUX_GATE(fanout_pclk_clk, "fanout-pclk",
1155				  fanout_pclk_parents,
1156				  0xf38,
1157				  0, 5,		/* div0 */
1158				  5, 5,		/* div1 */
1159				  0, 0,		/* mux */
1160				  BIT(31),	/* gate */
1161				  0);
1162
1163static const struct clk_parent_data fanout_parents[] = {
1164	{ .fw_name = "losc-fanout" },
1165	{ .hw = &fanout_12M_clk.common.hw, },
1166	{ .hw = &fanout_16M_clk.common.hw, },
1167	{ .hw = &fanout_24M_clk.common.hw, },
1168	{ .hw = &fanout_25M_clk.common.hw, },
1169	{ .hw = &fanout_27M_clk.common.hw, },
1170	{ .hw = &fanout_pclk_clk.common.hw, },
1171	{ .hw = &fanout_50M_clk.common.hw, },
1172};
1173static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents,
1174				    0xf3c,
1175				    0, 3,	/* mux */
1176				    BIT(21),	/* gate */
1177				    0);
1178static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents,
1179				    0xf3c,
1180				    3, 3,	/* mux */
1181				    BIT(22),	/* gate */
1182				    0);
1183static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents,
1184				    0xf3c,
1185				    6, 3,	/* mux */
1186				    BIT(23),	/* gate */
1187				    0);
1188
1189/*
1190 * Contains all clocks that are controlled by a hardware register. They
1191 * have a (sunxi) .common member, which needs to be initialised by the common
1192 * sunxi CCU code, to be filled with the MMIO base address and the shared lock.
1193 */
1194static struct ccu_common *sun55i_a523_ccu_clks[] = {
1195	&pll_ddr_clk.common,
1196	&pll_periph0_4x_clk.common,
1197	&pll_periph0_2x_clk.common,
1198	&pll_periph0_800M_clk.common,
1199	&pll_periph0_480M_clk.common,
1200	&pll_periph1_4x_clk.common,
1201	&pll_periph1_2x_clk.common,
1202	&pll_periph1_800M_clk.common,
1203	&pll_periph1_480M_clk.common,
1204	&pll_gpu_clk.common,
1205	&pll_video0_8x_clk.common,
1206	&pll_video0_4x_clk.common,
1207	&pll_video1_8x_clk.common,
1208	&pll_video1_4x_clk.common,
1209	&pll_video2_8x_clk.common,
1210	&pll_video2_4x_clk.common,
1211	&pll_video3_8x_clk.common,
1212	&pll_video3_4x_clk.common,
1213	&pll_ve_clk.common,
1214	&pll_audio0_4x_clk.common,
1215	&pll_npu_4x_clk.common,
1216	&ahb_clk.common,
1217	&apb0_clk.common,
1218	&apb1_clk.common,
1219	&mbus_clk.common,
1220	&de_clk.common,
1221	&bus_de_clk.common,
1222	&di_clk.common,
1223	&bus_di_clk.common,
1224	&g2d_clk.common,
1225	&bus_g2d_clk.common,
1226	&gpu_clk.common,
1227	&bus_gpu_clk.common,
1228	&ce_clk.common,
1229	&bus_ce_clk.common,
1230	&bus_ce_sys_clk.common,
1231	&ve_clk.common,
1232	&bus_ve_clk.common,
1233	&npu_clk.common,
1234	&bus_dma_clk.common,
1235	&bus_msgbox_clk.common,
1236	&bus_spinlock_clk.common,
1237	&hstimer0_clk.common,
1238	&hstimer1_clk.common,
1239	&hstimer2_clk.common,
1240	&hstimer3_clk.common,
1241	&hstimer4_clk.common,
1242	&hstimer5_clk.common,
1243	&bus_hstimer_clk.common,
1244	&bus_dbg_clk.common,
1245	&bus_pwm0_clk.common,
1246	&bus_pwm1_clk.common,
1247	&iommu_clk.common,
1248	&bus_iommu_clk.common,
1249	&dram_clk.common,
1250	&mbus_dma_clk.common,
1251	&mbus_ve_clk.common,
1252	&mbus_ce_clk.common,
1253	&mbus_nand_clk.common,
1254	&mbus_usb3_clk.common,
1255	&mbus_csi_clk.common,
1256	&mbus_isp_clk.common,
1257	&mbus_gmac1_clk.common,
1258	&bus_dram_clk.common,
1259	&nand0_clk.common,
1260	&nand1_clk.common,
1261	&bus_nand_clk.common,
1262	&mmc0_clk.common,
1263	&mmc1_clk.common,
1264	&mmc2_clk.common,
1265	&bus_sysdap_clk.common,
1266	&bus_mmc0_clk.common,
1267	&bus_mmc1_clk.common,
1268	&bus_mmc2_clk.common,
1269	&bus_uart0_clk.common,
1270	&bus_uart1_clk.common,
1271	&bus_uart2_clk.common,
1272	&bus_uart3_clk.common,
1273	&bus_uart4_clk.common,
1274	&bus_uart5_clk.common,
1275	&bus_uart6_clk.common,
1276	&bus_uart7_clk.common,
1277	&bus_i2c0_clk.common,
1278	&bus_i2c1_clk.common,
1279	&bus_i2c2_clk.common,
1280	&bus_i2c3_clk.common,
1281	&bus_i2c4_clk.common,
1282	&bus_i2c5_clk.common,
1283	&bus_can_clk.common,
1284	&spi0_clk.common,
1285	&spi1_clk.common,
1286	&spi2_clk.common,
1287	&spifc_clk.common,
1288	&bus_spi0_clk.common,
1289	&bus_spi1_clk.common,
1290	&bus_spi2_clk.common,
1291	&bus_spifc_clk.common,
1292	&emac0_25M_clk.common,
1293	&emac1_25M_clk.common,
1294	&bus_emac0_clk.common,
1295	&bus_emac1_clk.common,
1296	&ir_rx_clk.common,
1297	&bus_ir_rx_clk.common,
1298	&ir_tx_clk.common,
1299	&bus_ir_tx_clk.common,
1300	&gpadc0_clk.common,
1301	&gpadc1_clk.common,
1302	&bus_gpadc0_clk.common,
1303	&bus_gpadc1_clk.common,
1304	&bus_ths_clk.common,
1305	&usb_ohci0_clk.common,
1306	&usb_ohci1_clk.common,
1307	&bus_ohci0_clk.common,
1308	&bus_ohci1_clk.common,
1309	&bus_ehci0_clk.common,
1310	&bus_ehci1_clk.common,
1311	&bus_otg_clk.common,
1312	&bus_lradc_clk.common,
1313	&pcie_aux_clk.common,
1314	&bus_display0_top_clk.common,
1315	&bus_display1_top_clk.common,
1316	&hdmi_24M_clk.common,
1317	&hdmi_cec_32k_clk.common,
1318	&hdmi_cec_clk.common,
1319	&bus_hdmi_clk.common,
1320	&mipi_dsi0_clk.common,
1321	&mipi_dsi1_clk.common,
1322	&bus_mipi_dsi0_clk.common,
1323	&bus_mipi_dsi1_clk.common,
1324	&tcon_lcd0_clk.common,
1325	&tcon_lcd1_clk.common,
1326	&tcon_lcd2_clk.common,
1327	&combophy_dsi0_clk.common,
1328	&combophy_dsi1_clk.common,
1329	&bus_tcon_lcd0_clk.common,
1330	&bus_tcon_lcd1_clk.common,
1331	&bus_tcon_lcd2_clk.common,
1332	&tcon_tv0_clk.common,
1333	&tcon_tv1_clk.common,
1334	&bus_tcon_tv0_clk.common,
1335	&bus_tcon_tv1_clk.common,
1336	&edp_clk.common,
1337	&bus_edp_clk.common,
1338	&ledc_clk.common,
1339	&bus_ledc_clk.common,
1340	&csi_top_clk.common,
1341	&csi_mclk0_clk.common,
1342	&csi_mclk1_clk.common,
1343	&csi_mclk2_clk.common,
1344	&csi_mclk3_clk.common,
1345	&bus_csi_clk.common,
1346	&isp_clk.common,
1347	&dsp_clk.common,
1348	&fanout_24M_clk.common,
1349	&fanout_12M_clk.common,
1350	&fanout_16M_clk.common,
1351	&fanout_25M_clk.common,
1352	&fanout_27M_clk.common,
1353	&fanout_pclk_clk.common,
1354	&fanout0_clk.common,
1355	&fanout1_clk.common,
1356	&fanout2_clk.common,
1357};
1358
1359static struct clk_hw_onecell_data sun55i_a523_hw_clks = {
1360	.hws	= {
1361		[CLK_PLL_DDR0]		= &pll_ddr_clk.common.hw,
1362		[CLK_PLL_PERIPH0_4X]	= &pll_periph0_4x_clk.common.hw,
1363		[CLK_PLL_PERIPH0_2X]	= &pll_periph0_2x_clk.common.hw,
1364		[CLK_PLL_PERIPH0_800M]	= &pll_periph0_800M_clk.common.hw,
1365		[CLK_PLL_PERIPH0_480M]	= &pll_periph0_480M_clk.common.hw,
1366		[CLK_PLL_PERIPH0_600M]	= &pll_periph0_600M_clk.hw,
1367		[CLK_PLL_PERIPH0_400M]	= &pll_periph0_400M_clk.hw,
1368		[CLK_PLL_PERIPH0_300M]	= &pll_periph0_300M_clk.hw,
1369		[CLK_PLL_PERIPH0_200M]	= &pll_periph0_200M_clk.hw,
1370		[CLK_PLL_PERIPH0_160M]	= &pll_periph0_160M_clk.hw,
1371		[CLK_PLL_PERIPH0_150M]	= &pll_periph0_150M_clk.hw,
1372		[CLK_PLL_PERIPH1_4X]	= &pll_periph1_4x_clk.common.hw,
1373		[CLK_PLL_PERIPH1_2X]	= &pll_periph1_2x_clk.common.hw,
1374		[CLK_PLL_PERIPH1_800M]	= &pll_periph1_800M_clk.common.hw,
1375		[CLK_PLL_PERIPH1_480M]	= &pll_periph1_480M_clk.common.hw,
1376		[CLK_PLL_PERIPH1_600M]	= &pll_periph1_600M_clk.hw,
1377		[CLK_PLL_PERIPH1_400M]	= &pll_periph1_400M_clk.hw,
1378		[CLK_PLL_PERIPH1_300M]	= &pll_periph1_300M_clk.hw,
1379		[CLK_PLL_PERIPH1_200M]	= &pll_periph1_200M_clk.hw,
1380		[CLK_PLL_PERIPH1_160M]	= &pll_periph1_160M_clk.hw,
1381		[CLK_PLL_PERIPH1_150M]	= &pll_periph1_150M_clk.hw,
1382		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
1383		[CLK_PLL_VIDEO0_8X]	= &pll_video0_8x_clk.common.hw,
1384		[CLK_PLL_VIDEO0_4X]	= &pll_video0_4x_clk.common.hw,
1385		[CLK_PLL_VIDEO0_3X]	= &pll_video0_3x_clk.hw,
1386		[CLK_PLL_VIDEO1_8X]	= &pll_video1_8x_clk.common.hw,
1387		[CLK_PLL_VIDEO1_4X]	= &pll_video1_4x_clk.common.hw,
1388		[CLK_PLL_VIDEO1_3X]	= &pll_video1_3x_clk.hw,
1389		[CLK_PLL_VIDEO2_8X]	= &pll_video2_8x_clk.common.hw,
1390		[CLK_PLL_VIDEO2_4X]	= &pll_video2_4x_clk.common.hw,
1391		[CLK_PLL_VIDEO2_3X]	= &pll_video2_3x_clk.hw,
1392		[CLK_PLL_VIDEO3_8X]	= &pll_video3_8x_clk.common.hw,
1393		[CLK_PLL_VIDEO3_4X]	= &pll_video3_4x_clk.common.hw,
1394		[CLK_PLL_VIDEO3_3X]	= &pll_video3_3x_clk.hw,
1395		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
1396		[CLK_PLL_AUDIO0_4X]	= &pll_audio0_4x_clk.common.hw,
1397		[CLK_PLL_AUDIO0_2X]	= &pll_audio0_2x_clk.hw,
1398		[CLK_PLL_AUDIO0]	= &pll_audio0_clk.hw,
1399		[CLK_PLL_NPU_4X]	= &pll_npu_4x_clk.common.hw,
1400		[CLK_PLL_NPU_2X]	= &pll_npu_2x_clk.hw,
1401		[CLK_PLL_NPU]		= &pll_npu_1x_clk.hw,
1402		[CLK_AHB]		= &ahb_clk.common.hw,
1403		[CLK_APB0]		= &apb0_clk.common.hw,
1404		[CLK_APB1]		= &apb1_clk.common.hw,
1405		[CLK_MBUS]		= &mbus_clk.common.hw,
1406		[CLK_DE]		= &de_clk.common.hw,
1407		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
1408		[CLK_DI]		= &di_clk.common.hw,
1409		[CLK_BUS_DI]		= &bus_di_clk.common.hw,
1410		[CLK_G2D]		= &g2d_clk.common.hw,
1411		[CLK_BUS_G2D]		= &bus_g2d_clk.common.hw,
1412		[CLK_GPU]		= &gpu_clk.common.hw,
1413		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
1414		[CLK_CE]		= &ce_clk.common.hw,
1415		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
1416		[CLK_BUS_CE_SYS]	= &bus_ce_sys_clk.common.hw,
1417		[CLK_VE]		= &ve_clk.common.hw,
1418		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
1419		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
1420		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
1421		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
1422		[CLK_HSTIMER0]		= &hstimer0_clk.common.hw,
1423		[CLK_HSTIMER1]		= &hstimer1_clk.common.hw,
1424		[CLK_HSTIMER2]		= &hstimer2_clk.common.hw,
1425		[CLK_HSTIMER3]		= &hstimer3_clk.common.hw,
1426		[CLK_HSTIMER4]		= &hstimer4_clk.common.hw,
1427		[CLK_HSTIMER5]		= &hstimer5_clk.common.hw,
1428		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
1429		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
1430		[CLK_BUS_PWM0]		= &bus_pwm0_clk.common.hw,
1431		[CLK_BUS_PWM1]		= &bus_pwm1_clk.common.hw,
1432		[CLK_IOMMU]		= &iommu_clk.common.hw,
1433		[CLK_BUS_IOMMU]		= &bus_iommu_clk.common.hw,
1434		[CLK_DRAM]		= &dram_clk.common.hw,
1435		[CLK_MBUS_DMA]		= &mbus_dma_clk.common.hw,
1436		[CLK_MBUS_VE]		= &mbus_ve_clk.common.hw,
1437		[CLK_MBUS_CE]		= &mbus_ce_clk.common.hw,
1438		[CLK_MBUS_CSI]		= &mbus_csi_clk.common.hw,
1439		[CLK_MBUS_ISP]		= &mbus_isp_clk.common.hw,
1440		[CLK_MBUS_EMAC1]	= &mbus_gmac1_clk.common.hw,
1441		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
1442		[CLK_NAND0]		= &nand0_clk.common.hw,
1443		[CLK_NAND1]		= &nand1_clk.common.hw,
1444		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
1445		[CLK_MMC0]		= &mmc0_clk.common.hw,
1446		[CLK_MMC1]		= &mmc1_clk.common.hw,
1447		[CLK_MMC2]		= &mmc2_clk.common.hw,
1448		[CLK_BUS_SYSDAP]	= &bus_sysdap_clk.common.hw,
1449		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
1450		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
1451		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
1452		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
1453		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
1454		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
1455		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
1456		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
1457		[CLK_BUS_UART5]		= &bus_uart5_clk.common.hw,
1458		[CLK_BUS_UART6]		= &bus_uart6_clk.common.hw,
1459		[CLK_BUS_UART7]		= &bus_uart7_clk.common.hw,
1460		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
1461		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
1462		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
1463		[CLK_BUS_I2C3]		= &bus_i2c3_clk.common.hw,
1464		[CLK_BUS_I2C4]		= &bus_i2c4_clk.common.hw,
1465		[CLK_BUS_I2C5]		= &bus_i2c5_clk.common.hw,
1466		[CLK_BUS_CAN]		= &bus_can_clk.common.hw,
1467		[CLK_SPI0]		= &spi0_clk.common.hw,
1468		[CLK_SPI1]		= &spi1_clk.common.hw,
1469		[CLK_SPI2]		= &spi2_clk.common.hw,
1470		[CLK_SPIFC]		= &spifc_clk.common.hw,
1471		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
1472		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
1473		[CLK_BUS_SPI2]		= &bus_spi2_clk.common.hw,
1474		[CLK_BUS_SPIFC]		= &bus_spifc_clk.common.hw,
1475		[CLK_EMAC0_25M]		= &emac0_25M_clk.common.hw,
1476		[CLK_EMAC1_25M]		= &emac1_25M_clk.common.hw,
1477		[CLK_BUS_EMAC0]		= &bus_emac0_clk.common.hw,
1478		[CLK_BUS_EMAC1]		= &bus_emac1_clk.common.hw,
1479		[CLK_IR_RX]		= &ir_rx_clk.common.hw,
1480		[CLK_BUS_IR_RX]		= &bus_ir_rx_clk.common.hw,
1481		[CLK_IR_TX]		= &ir_tx_clk.common.hw,
1482		[CLK_BUS_IR_TX]		= &bus_ir_tx_clk.common.hw,
1483		[CLK_GPADC0]		= &gpadc0_clk.common.hw,
1484		[CLK_GPADC1]		= &gpadc1_clk.common.hw,
1485		[CLK_BUS_GPADC0]	= &bus_gpadc0_clk.common.hw,
1486		[CLK_BUS_GPADC1]	= &bus_gpadc1_clk.common.hw,
1487		[CLK_BUS_THS]		= &bus_ths_clk.common.hw,
1488		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
1489		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
1490		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
1491		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
1492		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
1493		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
1494		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
1495		[CLK_BUS_LRADC]		= &bus_lradc_clk.common.hw,
1496		[CLK_PCIE_AUX]		= &pcie_aux_clk.common.hw,
1497		[CLK_BUS_DISPLAY0_TOP]	= &bus_display0_top_clk.common.hw,
1498		[CLK_BUS_DISPLAY1_TOP]	= &bus_display1_top_clk.common.hw,
1499		[CLK_HDMI_24M]		= &hdmi_24M_clk.common.hw,
1500		[CLK_HDMI_CEC_32K]	= &hdmi_cec_32k_clk.common.hw,
1501		[CLK_HDMI_CEC]		= &hdmi_cec_clk.common.hw,
1502		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
1503		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
1504		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
1505		[CLK_BUS_MIPI_DSI0]	= &bus_mipi_dsi0_clk.common.hw,
1506		[CLK_BUS_MIPI_DSI1]	= &bus_mipi_dsi1_clk.common.hw,
1507		[CLK_TCON_LCD0]		= &tcon_lcd0_clk.common.hw,
1508		[CLK_TCON_LCD1]		= &tcon_lcd1_clk.common.hw,
1509		[CLK_TCON_LCD2]		= &tcon_lcd2_clk.common.hw,
1510		[CLK_COMBOPHY_DSI0]	= &combophy_dsi0_clk.common.hw,
1511		[CLK_COMBOPHY_DSI1]	= &combophy_dsi1_clk.common.hw,
1512		[CLK_BUS_TCON_LCD0]	= &bus_tcon_lcd0_clk.common.hw,
1513		[CLK_BUS_TCON_LCD1]	= &bus_tcon_lcd1_clk.common.hw,
1514		[CLK_BUS_TCON_LCD2]	= &bus_tcon_lcd2_clk.common.hw,
1515		[CLK_TCON_TV0]		= &tcon_tv0_clk.common.hw,
1516		[CLK_TCON_TV1]		= &tcon_tv1_clk.common.hw,
1517		[CLK_BUS_TCON_TV0]	= &bus_tcon_tv0_clk.common.hw,
1518		[CLK_BUS_TCON_TV1]	= &bus_tcon_tv1_clk.common.hw,
1519		[CLK_EDP]		= &edp_clk.common.hw,
1520		[CLK_BUS_EDP]		= &bus_edp_clk.common.hw,
1521		[CLK_LEDC]		= &ledc_clk.common.hw,
1522		[CLK_BUS_LEDC]		= &bus_ledc_clk.common.hw,
1523		[CLK_CSI_TOP]		= &csi_top_clk.common.hw,
1524		[CLK_CSI_MCLK0]		= &csi_mclk0_clk.common.hw,
1525		[CLK_CSI_MCLK1]		= &csi_mclk1_clk.common.hw,
1526		[CLK_CSI_MCLK2]		= &csi_mclk2_clk.common.hw,
1527		[CLK_CSI_MCLK3]		= &csi_mclk3_clk.common.hw,
1528		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
1529		[CLK_ISP]		= &isp_clk.common.hw,
1530		[CLK_DSP]		= &dsp_clk.common.hw,
1531		[CLK_FANOUT_24M]	= &fanout_24M_clk.common.hw,
1532		[CLK_FANOUT_12M]	= &fanout_12M_clk.common.hw,
1533		[CLK_FANOUT_16M]	= &fanout_16M_clk.common.hw,
1534		[CLK_FANOUT_25M]	= &fanout_25M_clk.common.hw,
1535		[CLK_FANOUT_27M]	= &fanout_27M_clk.common.hw,
1536		[CLK_FANOUT_PCLK]	= &fanout_pclk_clk.common.hw,
1537		[CLK_FANOUT0]		= &fanout0_clk.common.hw,
1538		[CLK_FANOUT1]		= &fanout1_clk.common.hw,
1539		[CLK_FANOUT2]		= &fanout2_clk.common.hw,
1540		[CLK_NPU]		= &npu_clk.common.hw,
1541	},
1542	.num	= CLK_NPU + 1,
1543};
1544
1545static struct ccu_reset_map sun55i_a523_ccu_resets[] = {
1546	[RST_MBUS]		= { 0x540, BIT(30) },
1547	[RST_BUS_NSI]		= { 0x54c, BIT(16) },
1548	[RST_BUS_DE]		= { 0x60c, BIT(16) },
1549	[RST_BUS_DI]		= { 0x62c, BIT(16) },
1550	[RST_BUS_G2D]		= { 0x63c, BIT(16) },
1551	[RST_BUS_SYS]		= { 0x64c, BIT(16) },
1552	[RST_BUS_GPU]		= { 0x67c, BIT(16) },
1553	[RST_BUS_CE]		= { 0x68c, BIT(16) },
1554	[RST_BUS_SYS_CE]	= { 0x68c, BIT(17) },
1555	[RST_BUS_VE]		= { 0x69c, BIT(16) },
1556	[RST_BUS_DMA]		= { 0x70c, BIT(16) },
1557	[RST_BUS_MSGBOX]	= { 0x71c, BIT(16) },
1558	[RST_BUS_SPINLOCK]	= { 0x72c, BIT(16) },
1559	[RST_BUS_CPUXTIMER]	= { 0x74c, BIT(16) },
1560	[RST_BUS_DBG]		= { 0x78c, BIT(16) },
1561	[RST_BUS_PWM0]		= { 0x7ac, BIT(16) },
1562	[RST_BUS_PWM1]		= { 0x7ac, BIT(17) },
1563	[RST_BUS_DRAM]		= { 0x80c, BIT(16) },
1564	[RST_BUS_NAND]		= { 0x82c, BIT(16) },
1565	[RST_BUS_MMC0]		= { 0x84c, BIT(16) },
1566	[RST_BUS_MMC1]		= { 0x84c, BIT(17) },
1567	[RST_BUS_MMC2]		= { 0x84c, BIT(18) },
1568	[RST_BUS_SYSDAP]	= { 0x88c, BIT(16) },
1569	[RST_BUS_UART0]		= { 0x90c, BIT(16) },
1570	[RST_BUS_UART1]		= { 0x90c, BIT(17) },
1571	[RST_BUS_UART2]		= { 0x90c, BIT(18) },
1572	[RST_BUS_UART3]		= { 0x90c, BIT(19) },
1573	[RST_BUS_UART4]		= { 0x90c, BIT(20) },
1574	[RST_BUS_UART5]		= { 0x90c, BIT(21) },
1575	[RST_BUS_UART6]		= { 0x90c, BIT(22) },
1576	[RST_BUS_UART7]		= { 0x90c, BIT(23) },
1577	[RST_BUS_I2C0]		= { 0x91c, BIT(16) },
1578	[RST_BUS_I2C1]		= { 0x91c, BIT(17) },
1579	[RST_BUS_I2C2]		= { 0x91c, BIT(18) },
1580	[RST_BUS_I2C3]		= { 0x91c, BIT(19) },
1581	[RST_BUS_I2C4]		= { 0x91c, BIT(20) },
1582	[RST_BUS_I2C5]		= { 0x91c, BIT(21) },
1583	[RST_BUS_CAN]		= { 0x92c, BIT(16) },
1584	[RST_BUS_SPI0]		= { 0x96c, BIT(16) },
1585	[RST_BUS_SPI1]		= { 0x96c, BIT(17) },
1586	[RST_BUS_SPI2]		= { 0x96c, BIT(18) },
1587	[RST_BUS_SPIFC]		= { 0x96c, BIT(19) },
1588	[RST_BUS_EMAC0]		= { 0x97c, BIT(16) },
1589	[RST_BUS_EMAC1]		= { 0x98c, BIT(16) | BIT(17) },	/* GMAC1-AXI */
1590	[RST_BUS_IR_RX]		= { 0x99c, BIT(16) },
1591	[RST_BUS_IR_TX]		= { 0x9cc, BIT(16) },
1592	[RST_BUS_GPADC0]	= { 0x9ec, BIT(16) },
1593	[RST_BUS_GPADC1]	= { 0x9ec, BIT(17) },
1594	[RST_BUS_THS]		= { 0x9fc, BIT(16) },
1595	[RST_USB_PHY0]		= { 0xa70, BIT(30) },
1596	[RST_USB_PHY1]		= { 0xa74, BIT(30) },
1597	[RST_BUS_OHCI0]		= { 0xa8c, BIT(16) },
1598	[RST_BUS_OHCI1]		= { 0xa8c, BIT(17) },
1599	[RST_BUS_EHCI0]		= { 0xa8c, BIT(20) },
1600	[RST_BUS_EHCI1]		= { 0xa8c, BIT(21) },
1601	[RST_BUS_OTG]		= { 0xa8c, BIT(24) },
1602	[RST_BUS_3]		= { 0xa8c, BIT(25) },	/* BSP + register */
1603	[RST_BUS_LRADC]		= { 0xa9c, BIT(16) },
1604	[RST_BUS_PCIE_USB3]	= { 0xaac, BIT(16) },
1605	[RST_BUS_DISPLAY0_TOP]	= { 0xabc, BIT(16) },
1606	[RST_BUS_DISPLAY1_TOP]	= { 0xacc, BIT(16) },
1607	[RST_BUS_HDMI_MAIN]	= { 0xb1c, BIT(16) },
1608	[RST_BUS_HDMI_SUB]	= { 0xb1c, BIT(17) },
1609	[RST_BUS_MIPI_DSI0]	= { 0xb4c, BIT(16) },
1610	[RST_BUS_MIPI_DSI1]	= { 0xb4c, BIT(17) },
1611	[RST_BUS_TCON_LCD0]	= { 0xb7c, BIT(16) },
1612	[RST_BUS_TCON_LCD1]	= { 0xb7c, BIT(17) },
1613	[RST_BUS_TCON_LCD2]	= { 0xb7c, BIT(18) },
1614	[RST_BUS_TCON_TV0]	= { 0xb9c, BIT(16) },
1615	[RST_BUS_TCON_TV1]	= { 0xb9c, BIT(17) },
1616	[RST_BUS_LVDS0]		= { 0xbac, BIT(16) },
1617	[RST_BUS_LVDS1]		= { 0xbac, BIT(17) },
1618	[RST_BUS_EDP]		= { 0xbbc, BIT(16) },
1619	[RST_BUS_VIDEO_OUT0]	= { 0xbcc, BIT(16) },
1620	[RST_BUS_VIDEO_OUT1]	= { 0xbcc, BIT(17) },
1621	[RST_BUS_LEDC]		= { 0xbfc, BIT(16) },
1622	[RST_BUS_CSI]		= { 0xc1c, BIT(16) },
1623	[RST_BUS_ISP]		= { 0xc2c, BIT(16) },	/* BSP + register */
1624};
1625
1626static const struct sunxi_ccu_desc sun55i_a523_ccu_desc = {
1627	.ccu_clks	= sun55i_a523_ccu_clks,
1628	.num_ccu_clks	= ARRAY_SIZE(sun55i_a523_ccu_clks),
1629
1630	.hw_clks	= &sun55i_a523_hw_clks,
1631
1632	.resets		= sun55i_a523_ccu_resets,
1633	.num_resets	= ARRAY_SIZE(sun55i_a523_ccu_resets),
1634};
1635
1636static const u32 pll_regs[] = {
1637	SUN55I_A523_PLL_DDR0_REG,
1638	SUN55I_A523_PLL_PERIPH0_REG,
1639	SUN55I_A523_PLL_PERIPH1_REG,
1640	SUN55I_A523_PLL_GPU_REG,
1641	SUN55I_A523_PLL_VIDEO0_REG,
1642	SUN55I_A523_PLL_VIDEO1_REG,
1643	SUN55I_A523_PLL_VIDEO2_REG,
1644	SUN55I_A523_PLL_VE_REG,
1645	SUN55I_A523_PLL_VIDEO3_REG,
1646	SUN55I_A523_PLL_AUDIO0_REG,
1647	SUN55I_A523_PLL_NPU_REG,
1648};
1649
1650static int sun55i_a523_ccu_probe(struct platform_device *pdev)
1651{
1652	void __iomem *reg;
1653	u32 val;
1654	int i, ret;
1655
1656	reg = devm_platform_ioremap_resource(pdev, 0);
1657	if (IS_ERR(reg))
1658		return PTR_ERR(reg);
1659
1660	/*
1661	 * The PLL clock code does not model all bits, for instance it does
1662	 * not support a separate enable and gate bit. We present the
1663	 * gate bit(27) as the enable bit, but then have to set the
1664	 * PLL Enable, LDO Enable, and Lock Enable bits on all PLLs here.
1665	 */
1666	for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
1667		val = readl(reg + pll_regs[i]);
1668		val |= BIT(31) | BIT(30) | BIT(29);
1669		writel(val, reg + pll_regs[i]);
1670	}
1671
1672	/* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */
1673	val = readl(reg + SUN55I_A523_PLL_AUDIO0_REG);
1674	val &= ~(BIT(1) | BIT(0));
1675	writel(val, reg + SUN55I_A523_PLL_AUDIO0_REG);
1676
1677	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun55i_a523_ccu_desc);
1678	if (ret)
1679		return ret;
1680
1681	return 0;
1682}
1683
1684static const struct of_device_id sun55i_a523_ccu_ids[] = {
1685	{ .compatible = "allwinner,sun55i-a523-ccu" },
1686	{ }
1687};
1688
1689static struct platform_driver sun55i_a523_ccu_driver = {
1690	.probe	= sun55i_a523_ccu_probe,
1691	.driver	= {
1692		.name			= "sun55i-a523-ccu",
1693		.suppress_bind_attrs	= true,
1694		.of_match_table		= sun55i_a523_ccu_ids,
1695	},
1696};
1697module_platform_driver(sun55i_a523_ccu_driver);
1698
1699MODULE_IMPORT_NS("SUNXI_CCU");
1700MODULE_DESCRIPTION("Support for the Allwinner A523 CCU");
1701MODULE_LICENSE("GPL");
~/ Read-only file preview.