File Index
Files and directories
Sign in
FILE

ccu-sun9i-a80.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sunxi-ng/ccu-sun9i-a80.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/io.h>
   8#include <linux/module.h>
   9#include <linux/platform_device.h>
  10
  11#include "ccu_common.h"
  12#include "ccu_reset.h"
  13
  14#include "ccu_div.h"
  15#include "ccu_gate.h"
  16#include "ccu_mp.h"
  17#include "ccu_nkmp.h"
  18#include "ccu_nm.h"
  19#include "ccu_phase.h"
  20
  21#include "ccu-sun9i-a80.h"
  22
  23#define CCU_SUN9I_LOCK_REG	0x09c
  24
  25/*
  26 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
  27 * P should only be used for output frequencies lower than 228 MHz.
  28 * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
  29 *
  30 * For now we can just model it as a multiplier clock, and force P to /1.
  31 */
  32#define SUN9I_A80_PLL_C0CPUX_REG	0x000
  33#define SUN9I_A80_PLL_C1CPUX_REG	0x004
  34
  35static struct ccu_mult pll_c0cpux_clk = {
  36	.enable		= BIT(31),
  37	.lock		= BIT(0),
  38	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  39	.common		= {
  40		.reg		= SUN9I_A80_PLL_C0CPUX_REG,
  41		.lock_reg	= CCU_SUN9I_LOCK_REG,
  42		.features	= CCU_FEATURE_LOCK_REG,
  43		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
  44					      &ccu_mult_ops,
  45					      CLK_SET_RATE_UNGATE),
  46	},
  47};
  48
  49static struct ccu_mult pll_c1cpux_clk = {
  50	.enable		= BIT(31),
  51	.lock		= BIT(1),
  52	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  53	.common		= {
  54		.reg		= SUN9I_A80_PLL_C1CPUX_REG,
  55		.lock_reg	= CCU_SUN9I_LOCK_REG,
  56		.features	= CCU_FEATURE_LOCK_REG,
  57		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
  58					      &ccu_mult_ops,
  59					      CLK_SET_RATE_UNGATE),
  60	},
  61};
  62
  63/*
  64 * The Audio PLL has d1, d2 dividers in addition to the usual N, M
  65 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
  66 * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
  67 */
  68#define SUN9I_A80_PLL_AUDIO_REG	0x008
  69
  70static struct ccu_nm pll_audio_clk = {
  71	.enable		= BIT(31),
  72	.lock		= BIT(2),
  73	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  74	.m		= _SUNXI_CCU_DIV_OFFSET(0, 6, 0),
  75	.common		= {
  76		.reg		= 0x008,
  77		.lock_reg	= CCU_SUN9I_LOCK_REG,
  78		.features	= CCU_FEATURE_LOCK_REG,
  79		.hw.init	= CLK_HW_INIT("pll-audio", "osc24M",
  80					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
  81	},
  82};
  83
  84/* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */
  85static struct ccu_nkmp pll_periph0_clk = {
  86	.enable		= BIT(31),
  87	.lock		= BIT(3),
  88	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
  89	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
  90	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
  91	.common		= {
  92		.reg		= 0x00c,
  93		.lock_reg	= CCU_SUN9I_LOCK_REG,
  94		.features	= CCU_FEATURE_LOCK_REG,
  95		.hw.init	= CLK_HW_INIT("pll-periph0", "osc24M",
  96					      &ccu_nkmp_ops,
  97					      CLK_SET_RATE_UNGATE),
  98	},
  99};
 100
 101static struct ccu_nkmp pll_ve_clk = {
 102	.enable		= BIT(31),
 103	.lock		= BIT(4),
 104	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 105	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 106	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 107	.common		= {
 108		.reg		= 0x010,
 109		.lock_reg	= CCU_SUN9I_LOCK_REG,
 110		.features	= CCU_FEATURE_LOCK_REG,
 111		.hw.init	= CLK_HW_INIT("pll-ve", "osc24M",
 112					      &ccu_nkmp_ops,
 113					      CLK_SET_RATE_UNGATE),
 114	},
 115};
 116
 117static struct ccu_nkmp pll_ddr_clk = {
 118	.enable		= BIT(31),
 119	.lock		= BIT(5),
 120	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 121	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 122	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 123	.common		= {
 124		.reg		= 0x014,
 125		.lock_reg	= CCU_SUN9I_LOCK_REG,
 126		.features	= CCU_FEATURE_LOCK_REG,
 127		.hw.init	= CLK_HW_INIT("pll-ddr", "osc24M",
 128					      &ccu_nkmp_ops,
 129					      CLK_SET_RATE_UNGATE),
 130	},
 131};
 132
 133static struct ccu_nm pll_video0_clk = {
 134	.enable		= BIT(31),
 135	.lock		= BIT(6),
 136	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 137	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 138	.common		= {
 139		.reg		= 0x018,
 140		.lock_reg	= CCU_SUN9I_LOCK_REG,
 141		.features	= CCU_FEATURE_LOCK_REG,
 142		.hw.init	= CLK_HW_INIT("pll-video0", "osc24M",
 143					      &ccu_nm_ops,
 144					      CLK_SET_RATE_UNGATE),
 145	},
 146};
 147
 148static struct ccu_nkmp pll_video1_clk = {
 149	.enable		= BIT(31),
 150	.lock		= BIT(7),
 151	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 152	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 153	.p		= _SUNXI_CCU_DIV(0, 2), /* external divider p */
 154	.common		= {
 155		.reg		= 0x01c,
 156		.lock_reg	= CCU_SUN9I_LOCK_REG,
 157		.features	= CCU_FEATURE_LOCK_REG,
 158		.hw.init	= CLK_HW_INIT("pll-video1", "osc24M",
 159					      &ccu_nkmp_ops,
 160					      CLK_SET_RATE_UNGATE),
 161	},
 162};
 163
 164static struct ccu_nkmp pll_gpu_clk = {
 165	.enable		= BIT(31),
 166	.lock		= BIT(8),
 167	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 168	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 169	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 170	.common		= {
 171		.reg		= 0x020,
 172		.lock_reg	= CCU_SUN9I_LOCK_REG,
 173		.features	= CCU_FEATURE_LOCK_REG,
 174		.hw.init	= CLK_HW_INIT("pll-gpu", "osc24M",
 175					      &ccu_nkmp_ops,
 176					      CLK_SET_RATE_UNGATE),
 177	},
 178};
 179
 180static struct ccu_nkmp pll_de_clk = {
 181	.enable		= BIT(31),
 182	.lock		= BIT(9),
 183	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 184	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 185	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 186	.common		= {
 187		.reg		= 0x024,
 188		.lock_reg	= CCU_SUN9I_LOCK_REG,
 189		.features	= CCU_FEATURE_LOCK_REG,
 190		.hw.init	= CLK_HW_INIT("pll-de", "osc24M",
 191					      &ccu_nkmp_ops,
 192					      CLK_SET_RATE_UNGATE),
 193	},
 194};
 195
 196static struct ccu_nkmp pll_isp_clk = {
 197	.enable		= BIT(31),
 198	.lock		= BIT(10),
 199	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 200	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 201	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 202	.common		= {
 203		.reg		= 0x028,
 204		.lock_reg	= CCU_SUN9I_LOCK_REG,
 205		.features	= CCU_FEATURE_LOCK_REG,
 206		.hw.init	= CLK_HW_INIT("pll-isp", "osc24M",
 207					      &ccu_nkmp_ops,
 208					      CLK_SET_RATE_UNGATE),
 209	},
 210};
 211
 212static struct ccu_nkmp pll_periph1_clk = {
 213	.enable		= BIT(31),
 214	.lock		= BIT(11),
 215	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 216	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
 217	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */
 218	.common		= {
 219		.reg		= 0x028,
 220		.lock_reg	= CCU_SUN9I_LOCK_REG,
 221		.features	= CCU_FEATURE_LOCK_REG,
 222		.hw.init	= CLK_HW_INIT("pll-periph1", "osc24M",
 223					      &ccu_nkmp_ops,
 224					      CLK_SET_RATE_UNGATE),
 225	},
 226};
 227
 228static const char * const c0cpux_parents[] = { "osc24M", "pll-c0cpux" };
 229static SUNXI_CCU_MUX(c0cpux_clk, "c0cpux", c0cpux_parents,
 230		     0x50, 0, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
 231
 232static const char * const c1cpux_parents[] = { "osc24M", "pll-c1cpux" };
 233static SUNXI_CCU_MUX(c1cpux_clk, "c1cpux", c1cpux_parents,
 234		     0x50, 8, 1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
 235
 236static struct clk_div_table axi_div_table[] = {
 237	{ .val = 0, .div = 1 },
 238	{ .val = 1, .div = 2 },
 239	{ .val = 2, .div = 3 },
 240	{ .val = 3, .div = 4 },
 241	{ .val = 4, .div = 4 },
 242	{ .val = 5, .div = 4 },
 243	{ .val = 6, .div = 4 },
 244	{ .val = 7, .div = 4 },
 245	{ /* Sentinel */ },
 246};
 247
 248static SUNXI_CCU_M(atb0_clk, "atb0", "c0cpux", 0x054, 8, 2, 0);
 249
 250static SUNXI_CCU_DIV_TABLE(axi0_clk, "axi0", "c0cpux",
 251			   0x054, 0, 3, axi_div_table, 0);
 252
 253static SUNXI_CCU_M(atb1_clk, "atb1", "c1cpux", 0x058, 8, 2, 0);
 254
 255static SUNXI_CCU_DIV_TABLE(axi1_clk, "axi1", "c1cpux",
 256			   0x058, 0, 3, axi_div_table, 0);
 257
 258static const char * const gtbus_parents[] = { "osc24M", "pll-periph0",
 259					      "pll-periph1", "pll-periph1" };
 260static SUNXI_CCU_M_WITH_MUX(gtbus_clk, "gtbus", gtbus_parents,
 261			    0x05c, 0, 2, 24, 2, CLK_IS_CRITICAL);
 262
 263static const char * const ahb_parents[] = { "gtbus", "pll-periph0",
 264					    "pll-periph1", "pll-periph1" };
 265static struct ccu_div ahb0_clk = {
 266	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 267	.mux		= _SUNXI_CCU_MUX(24, 2),
 268	.common		= {
 269		.reg		= 0x060,
 270		.hw.init	= CLK_HW_INIT_PARENTS("ahb0",
 271						      ahb_parents,
 272						      &ccu_div_ops,
 273						      0),
 274	},
 275};
 276
 277static struct ccu_div ahb1_clk = {
 278	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 279	.mux		= _SUNXI_CCU_MUX(24, 2),
 280	.common		= {
 281		.reg		= 0x064,
 282		.hw.init	= CLK_HW_INIT_PARENTS("ahb1",
 283						      ahb_parents,
 284						      &ccu_div_ops,
 285						      0),
 286	},
 287};
 288
 289static struct ccu_div ahb2_clk = {
 290	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 291	.mux		= _SUNXI_CCU_MUX(24, 2),
 292	.common		= {
 293		.reg		= 0x068,
 294		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
 295						      ahb_parents,
 296						      &ccu_div_ops,
 297						      0),
 298	},
 299};
 300
 301static const char * const apb_parents[] = { "osc24M", "pll-periph0" };
 302
 303static struct ccu_div apb0_clk = {
 304	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 305	.mux		= _SUNXI_CCU_MUX(24, 1),
 306	.common		= {
 307		.reg		= 0x070,
 308		.hw.init	= CLK_HW_INIT_PARENTS("apb0",
 309						      apb_parents,
 310						      &ccu_div_ops,
 311						      0),
 312	},
 313};
 314
 315static struct ccu_div apb1_clk = {
 316	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 317	.mux		= _SUNXI_CCU_MUX(24, 1),
 318	.common		= {
 319		.reg		= 0x074,
 320		.hw.init	= CLK_HW_INIT_PARENTS("apb1",
 321						      apb_parents,
 322						      &ccu_div_ops,
 323						      0),
 324	},
 325};
 326
 327static struct ccu_div cci400_clk = {
 328	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
 329	.mux		= _SUNXI_CCU_MUX(24, 2),
 330	.common		= {
 331		.reg		= 0x078,
 332		.hw.init	= CLK_HW_INIT_PARENTS("cci400",
 333						      ahb_parents,
 334						      &ccu_div_ops,
 335						      CLK_IS_CRITICAL),
 336	},
 337};
 338
 339static SUNXI_CCU_M_WITH_MUX_GATE(ats_clk, "ats", apb_parents,
 340				 0x080, 0, 3, 24, 2, BIT(31), 0);
 341
 342static SUNXI_CCU_M_WITH_MUX_GATE(trace_clk, "trace", apb_parents,
 343				 0x084, 0, 3, 24, 2, BIT(31), 0);
 344
 345static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" };
 346static const struct ccu_mux_fixed_prediv out_prediv = {
 347	.index = 0, .div = 750
 348};
 349
 350static struct ccu_mp out_a_clk = {
 351	.enable		= BIT(31),
 352	.m		= _SUNXI_CCU_DIV(8, 5),
 353	.p		= _SUNXI_CCU_DIV(20, 2),
 354	.mux		= {
 355		.shift		= 24,
 356		.width		= 4,
 357		.fixed_predivs	= &out_prediv,
 358		.n_predivs	= 1,
 359	},
 360	.common		= {
 361		.reg		= 0x180,
 362		.features	= CCU_FEATURE_FIXED_PREDIV,
 363		.hw.init	= CLK_HW_INIT_PARENTS("out-a",
 364						      out_parents,
 365						      &ccu_mp_ops,
 366						      0),
 367	},
 368};
 369
 370static struct ccu_mp out_b_clk = {
 371	.enable		= BIT(31),
 372	.m		= _SUNXI_CCU_DIV(8, 5),
 373	.p		= _SUNXI_CCU_DIV(20, 2),
 374	.mux		= {
 375		.shift		= 24,
 376		.width		= 4,
 377		.fixed_predivs	= &out_prediv,
 378		.n_predivs	= 1,
 379	},
 380	.common		= {
 381		.reg		= 0x184,
 382		.features	= CCU_FEATURE_FIXED_PREDIV,
 383		.hw.init	= CLK_HW_INIT_PARENTS("out-b",
 384						      out_parents,
 385						      &ccu_mp_ops,
 386						      0),
 387	},
 388};
 389
 390static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0" };
 391
 392static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_0_clk, "nand0-0", mod0_default_parents,
 393				  0x400,
 394				  0, 4,		/* M */
 395				  16, 2,	/* P */
 396				  24, 4,	/* mux */
 397				  BIT(31),	/* gate */
 398				  0);
 399
 400static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_1_clk, "nand0-1", mod0_default_parents,
 401				  0x404,
 402				  0, 4,		/* M */
 403				  16, 2,	/* P */
 404				  24, 4,	/* mux */
 405				  BIT(31),	/* gate */
 406				  0);
 407
 408static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_0_clk, "nand1-0", mod0_default_parents,
 409				  0x408,
 410				  0, 4,		/* M */
 411				  16, 2,	/* P */
 412				  24, 4,	/* mux */
 413				  BIT(31),	/* gate */
 414				  0);
 415
 416static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_1_clk, "nand1-1", mod0_default_parents,
 417				  0x40c,
 418				  0, 4,		/* M */
 419				  16, 2,	/* P */
 420				  24, 4,	/* mux */
 421				  BIT(31),	/* gate */
 422				  0);
 423
 424static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents,
 425				  0x410,
 426				  0, 4,		/* M */
 427				  16, 2,	/* P */
 428				  24, 4,	/* mux */
 429				  BIT(31),	/* gate */
 430				  0);
 431
 432static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0-sample", "mmc0",
 433		       0x410, 20, 3, 0);
 434static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0-output", "mmc0",
 435		       0x410, 8, 3, 0);
 436
 437static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents,
 438				  0x414,
 439				  0, 4,		/* M */
 440				  16, 2,	/* P */
 441				  24, 4,	/* mux */
 442				  BIT(31),	/* gate */
 443				  0);
 444
 445static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1-sample", "mmc1",
 446		       0x414, 20, 3, 0);
 447static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1-output", "mmc1",
 448		       0x414, 8, 3, 0);
 449
 450static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents,
 451				  0x418,
 452				  0, 4,		/* M */
 453				  16, 2,	/* P */
 454				  24, 4,	/* mux */
 455				  BIT(31),	/* gate */
 456				  0);
 457
 458static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2-sample", "mmc2",
 459		       0x418, 20, 3, 0);
 460static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2-output", "mmc2",
 461		       0x418, 8, 3, 0);
 462
 463static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents,
 464				  0x41c,
 465				  0, 4,		/* M */
 466				  16, 2,	/* P */
 467				  24, 4,	/* mux */
 468				  BIT(31),	/* gate */
 469				  0);
 470
 471static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3-sample", "mmc3",
 472		       0x41c, 20, 3, 0);
 473static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3-output", "mmc3",
 474		       0x41c, 8, 3, 0);
 475
 476static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents,
 477				  0x428,
 478				  0, 4,		/* M */
 479				  16, 2,	/* P */
 480				  24, 4,	/* mux */
 481				  BIT(31),	/* gate */
 482				  0);
 483
 484static const char * const ss_parents[] = { "osc24M", "pll-periph",
 485					   "pll-periph1" };
 486static const u8 ss_table[] = { 0, 1, 13 };
 487static struct ccu_mp ss_clk = {
 488	.enable		= BIT(31),
 489	.m		= _SUNXI_CCU_DIV(0, 4),
 490	.p		= _SUNXI_CCU_DIV(16, 2),
 491	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, ss_table),
 492	.common		= {
 493		.reg		= 0x42c,
 494		.hw.init	= CLK_HW_INIT_PARENTS("ss",
 495						      ss_parents,
 496						      &ccu_mp_ops,
 497						      0),
 498	},
 499};
 500
 501static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents,
 502				  0x430,
 503				  0, 4,		/* M */
 504				  16, 2,	/* P */
 505				  24, 4,	/* mux */
 506				  BIT(31),	/* gate */
 507				  0);
 508
 509static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents,
 510				  0x434,
 511				  0, 4,		/* M */
 512				  16, 2,	/* P */
 513				  24, 4,	/* mux */
 514				  BIT(31),	/* gate */
 515				  0);
 516
 517static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents,
 518				  0x438,
 519				  0, 4,		/* M */
 520				  16, 2,	/* P */
 521				  24, 4,	/* mux */
 522				  BIT(31),	/* gate */
 523				  0);
 524
 525static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents,
 526				  0x43c,
 527				  0, 4,		/* M */
 528				  16, 2,	/* P */
 529				  24, 4,	/* mux */
 530				  BIT(31),	/* gate */
 531				  0);
 532
 533static SUNXI_CCU_M_WITH_GATE(i2s0_clk, "i2s0", "pll-audio",
 534			     0x440, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 535static SUNXI_CCU_M_WITH_GATE(i2s1_clk, "i2s1", "pll-audio",
 536			     0x444, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 537static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
 538			     0x44c, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 539
 540static const char * const sdram_parents[] = { "pll-periph0", "pll-ddr" };
 541static const u8 sdram_table[] = { 0, 3 };
 542
 543static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(sdram_clk, "sdram",
 544				       sdram_parents, sdram_table,
 545				       0x484,
 546				       8, 4,	/* M */
 547				       12, 4,	/* mux */
 548				       0,	/* no gate */
 549				       CLK_IS_CRITICAL);
 550
 551static SUNXI_CCU_M_WITH_GATE(de_clk, "de", "pll-de", 0x490,
 552			     0, 4, BIT(31), CLK_SET_RATE_PARENT);
 553
 554static SUNXI_CCU_GATE(edp_clk, "edp", "osc24M", 0x494, BIT(31), 0);
 555
 556static const char * const mp_parents[] = { "pll-video1", "pll-gpu", "pll-de" };
 557static const u8 mp_table[] = { 9, 10, 11 };
 558static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mp_clk, "mp", mp_parents, mp_table,
 559				       0x498,
 560				       0, 4,	/* M */
 561				       24, 4,	/* mux */
 562				       BIT(31),	/* gate */
 563				       0);
 564
 565static const char * const display_parents[] = { "pll-video0", "pll-video1" };
 566static const u8 display_table[] = { 8, 9 };
 567
 568static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd0_clk, "lcd0",
 569				       display_parents, display_table,
 570				       0x49c,
 571				       0, 4,	/* M */
 572				       24, 4,	/* mux */
 573				       BIT(31),	/* gate */
 574				       CLK_SET_RATE_NO_REPARENT |
 575				       CLK_SET_RATE_PARENT);
 576
 577static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(lcd1_clk, "lcd1",
 578				       display_parents, display_table,
 579				       0x4a0,
 580				       0, 4,	/* M */
 581				       24, 4,	/* mux */
 582				       BIT(31),	/* gate */
 583				       CLK_SET_RATE_NO_REPARENT |
 584				       CLK_SET_RATE_PARENT);
 585
 586static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi0_clk, "mipi-dsi0",
 587				       display_parents, display_table,
 588				       0x4a8,
 589				       0, 4,	/* M */
 590				       24, 4,	/* mux */
 591				       BIT(31),	/* gate */
 592				       CLK_SET_RATE_PARENT);
 593
 594static const char * const mipi_dsi1_parents[] = { "osc24M", "pll-video1" };
 595static const u8 mipi_dsi1_table[] = { 0, 9 };
 596static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(mipi_dsi1_clk, "mipi-dsi1",
 597				       mipi_dsi1_parents, mipi_dsi1_table,
 598				       0x4ac,
 599				       0, 4,	/* M */
 600				       24, 4,	/* mux */
 601				       BIT(31),	/* gate */
 602				       CLK_SET_RATE_PARENT);
 603
 604static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi_clk, "hdmi",
 605				       display_parents, display_table,
 606				       0x4b0,
 607				       0, 4,	/* M */
 608				       24, 4,	/* mux */
 609				       BIT(31),	/* gate */
 610				       CLK_SET_RATE_NO_REPARENT |
 611				       CLK_SET_RATE_PARENT);
 612
 613static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0x4b4, BIT(31), 0);
 614
 615static SUNXI_CCU_M_WITH_GATE(mipi_csi_clk, "mipi-csi", "osc24M", 0x4bc,
 616			     0, 4, BIT(31), 0);
 617
 618static SUNXI_CCU_M_WITH_GATE(csi_isp_clk, "csi-isp", "pll-isp", 0x4c0,
 619			     0, 4, BIT(31), CLK_SET_RATE_PARENT);
 620
 621static SUNXI_CCU_GATE(csi_misc_clk, "csi-misc", "osc24M", 0x4c0, BIT(16), 0);
 622
 623static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_mclk_clk, "csi0-mclk",
 624				       mipi_dsi1_parents, mipi_dsi1_table,
 625				       0x4c4,
 626				       0, 4,	/* M */
 627				       24, 4,	/* mux */
 628				       BIT(31),	/* gate */
 629				       CLK_SET_RATE_PARENT);
 630
 631static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_mclk_clk, "csi1-mclk",
 632				       mipi_dsi1_parents, mipi_dsi1_table,
 633				       0x4c8,
 634				       0, 4,	/* M */
 635				       24, 4,	/* mux */
 636				       BIT(31),	/* gate */
 637				       CLK_SET_RATE_PARENT);
 638
 639static const char * const fd_parents[] = { "pll-periph0", "pll-isp" };
 640static const u8 fd_table[] = { 1, 12 };
 641static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(fd_clk, "fd", fd_parents, fd_table,
 642				       0x4cc,
 643				       0, 4,	/* M */
 644				       24, 4,	/* mux */
 645				       BIT(31),	/* gate */
 646				       0);
 647static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x4d0,
 648			     16, 3, BIT(31), CLK_SET_RATE_PARENT);
 649
 650static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x4d4, BIT(31), 0);
 651
 652static SUNXI_CCU_M_WITH_GATE(gpu_core_clk, "gpu-core", "pll-gpu", 0x4f0,
 653			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
 654static SUNXI_CCU_M_WITH_GATE(gpu_memory_clk, "gpu-memory", "pll-gpu", 0x4f4,
 655			     0, 3, BIT(31), CLK_SET_RATE_PARENT);
 656
 657static const char * const gpu_axi_parents[] = { "pll-periph0", "pll-gpu" };
 658static const u8 gpu_axi_table[] = { 1, 10 };
 659static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_axi_clk, "gpu-axi",
 660				       gpu_axi_parents, gpu_axi_table,
 661				       0x4f8,
 662				       0, 4,	/* M */
 663				       24, 4,	/* mux */
 664				       BIT(31),	/* gate */
 665				       CLK_SET_RATE_PARENT);
 666
 667static SUNXI_CCU_M_WITH_GATE(sata_clk, "sata", "pll-periph0", 0x500,
 668			     0, 4, BIT(31), 0);
 669
 670static SUNXI_CCU_M_WITH_GATE(ac97_clk, "ac97", "pll-audio",
 671			     0x504, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 672
 673static SUNXI_CCU_M_WITH_MUX_GATE(mipi_hsi_clk, "mipi-hsi",
 674				 mod0_default_parents, 0x508,
 675				 0, 4,		/* M */
 676				 24, 4,		/* mux */
 677				 BIT(31),	/* gate */
 678				 0);
 679
 680static const char * const gpadc_parents[] = { "osc24M", "pll-audio", "osc32k" };
 681static const u8 gpadc_table[] = { 0, 4, 7 };
 682static struct ccu_mp gpadc_clk = {
 683	.enable		= BIT(31),
 684	.m		= _SUNXI_CCU_DIV(0, 4),
 685	.p		= _SUNXI_CCU_DIV(16, 2),
 686	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, gpadc_table),
 687	.common		= {
 688		.reg		= 0x50c,
 689		.hw.init	= CLK_HW_INIT_PARENTS("gpadc",
 690						      gpadc_parents,
 691						      &ccu_mp_ops,
 692						      0),
 693	},
 694};
 695
 696static const char * const cir_tx_parents[] = { "osc24M", "osc32k" };
 697static const u8 cir_tx_table[] = { 0, 7 };
 698static struct ccu_mp cir_tx_clk = {
 699	.enable		= BIT(31),
 700	.m		= _SUNXI_CCU_DIV(0, 4),
 701	.p		= _SUNXI_CCU_DIV(16, 2),
 702	.mux		= _SUNXI_CCU_MUX_TABLE(24, 4, cir_tx_table),
 703	.common		= {
 704		.reg		= 0x510,
 705		.hw.init	= CLK_HW_INIT_PARENTS("cir-tx",
 706						      cir_tx_parents,
 707						      &ccu_mp_ops,
 708						      0),
 709	},
 710};
 711
 712/* AHB0 bus gates */
 713static SUNXI_CCU_GATE(bus_fd_clk,	"bus-fd",	"ahb0",
 714		      0x580, BIT(0), 0);
 715static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb0",
 716		      0x580, BIT(1), 0);
 717static SUNXI_CCU_GATE(bus_gpu_ctrl_clk,	"bus-gpu-ctrl",	"ahb0",
 718		      0x580, BIT(3), 0);
 719static SUNXI_CCU_GATE(bus_ss_clk,	"bus-ss",	"ahb0",
 720		      0x580, BIT(5), 0);
 721static SUNXI_CCU_GATE(bus_mmc_clk,	"bus-mmc",	"ahb0",
 722		      0x580, BIT(8), 0);
 723static SUNXI_CCU_GATE(bus_nand0_clk,	"bus-nand0",	"ahb0",
 724		      0x580, BIT(12), 0);
 725static SUNXI_CCU_GATE(bus_nand1_clk,	"bus-nand1",	"ahb0",
 726		      0x580, BIT(13), 0);
 727static SUNXI_CCU_GATE(bus_sdram_clk,	"bus-sdram",	"ahb0",
 728		      0x580, BIT(14), 0);
 729static SUNXI_CCU_GATE(bus_mipi_hsi_clk,	"bus-mipi-hsi",	"ahb0",
 730		      0x580, BIT(15), 0);
 731static SUNXI_CCU_GATE(bus_sata_clk,	"bus-sata",	"ahb0",
 732		      0x580, BIT(16), 0);
 733static SUNXI_CCU_GATE(bus_ts_clk,	"bus-ts",	"ahb0",
 734		      0x580, BIT(18), 0);
 735static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb0",
 736		      0x580, BIT(20), 0);
 737static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb0",
 738		      0x580, BIT(21), 0);
 739static SUNXI_CCU_GATE(bus_spi2_clk,	"bus-spi2",	"ahb0",
 740		      0x580, BIT(22), 0);
 741static SUNXI_CCU_GATE(bus_spi3_clk,	"bus-spi3",	"ahb0",
 742		      0x580, BIT(23), 0);
 743
 744/* AHB1 bus gates */
 745static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
 746		      0x584, BIT(0), 0);
 747static SUNXI_CCU_GATE(bus_usb_clk,	"bus-usb",	"ahb1",
 748		      0x584, BIT(1), 0);
 749static SUNXI_CCU_GATE(bus_gmac_clk,	"bus-gmac",	"ahb1",
 750		      0x584, BIT(17), 0);
 751static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
 752		      0x584, BIT(21), 0);
 753static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
 754		      0x584, BIT(22), 0);
 755static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
 756		      0x584, BIT(23), 0);
 757static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
 758		      0x584, BIT(24), 0);
 759
 760/* AHB2 bus gates */
 761static SUNXI_CCU_GATE(bus_lcd0_clk,	"bus-lcd0",	"ahb2",
 762		      0x588, BIT(0), 0);
 763static SUNXI_CCU_GATE(bus_lcd1_clk,	"bus-lcd1",	"ahb2",
 764		      0x588, BIT(1), 0);
 765static SUNXI_CCU_GATE(bus_edp_clk,	"bus-edp",	"ahb2",
 766		      0x588, BIT(2), 0);
 767static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb2",
 768		      0x588, BIT(4), 0);
 769static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb2",
 770		      0x588, BIT(5), 0);
 771static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb2",
 772		      0x588, BIT(7), 0);
 773static SUNXI_CCU_GATE(bus_mp_clk,	"bus-mp",	"ahb2",
 774		      0x588, BIT(8), 0);
 775static SUNXI_CCU_GATE(bus_mipi_dsi_clk,	"bus-mipi-dsi",	"ahb2",
 776		      0x588, BIT(11), 0);
 777
 778/* APB0 bus gates */
 779static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb0",
 780		      0x590, BIT(1), 0);
 781static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb0",
 782		      0x590, BIT(5), 0);
 783static SUNXI_CCU_GATE(bus_ac97_clk,	"bus-ac97",	"apb0",
 784		      0x590, BIT(11), 0);
 785static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb0",
 786		      0x590, BIT(12), 0);
 787static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb0",
 788		      0x590, BIT(13), 0);
 789static SUNXI_CCU_GATE(bus_lradc_clk,	"bus-lradc",	"apb0",
 790		      0x590, BIT(15), 0);
 791static SUNXI_CCU_GATE(bus_gpadc_clk,	"bus-gpadc",	"apb0",
 792		      0x590, BIT(17), 0);
 793static SUNXI_CCU_GATE(bus_twd_clk,	"bus-twd",	"apb0",
 794		      0x590, BIT(18), 0);
 795static SUNXI_CCU_GATE(bus_cir_tx_clk,	"bus-cir-tx",	"apb0",
 796		      0x590, BIT(19), 0);
 797
 798/* APB1 bus gates */
 799static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb1",
 800		      0x594, BIT(0), 0);
 801static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb1",
 802		      0x594, BIT(1), 0);
 803static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb1",
 804		      0x594, BIT(2), 0);
 805static SUNXI_CCU_GATE(bus_i2c3_clk,	"bus-i2c3",	"apb1",
 806		      0x594, BIT(3), 0);
 807static SUNXI_CCU_GATE(bus_i2c4_clk,	"bus-i2c4",	"apb1",
 808		      0x594, BIT(4), 0);
 809static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb1",
 810		      0x594, BIT(16), 0);
 811static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb1",
 812		      0x594, BIT(17), 0);
 813static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb1",
 814		      0x594, BIT(18), 0);
 815static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb1",
 816		      0x594, BIT(19), 0);
 817static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb1",
 818		      0x594, BIT(20), 0);
 819static SUNXI_CCU_GATE(bus_uart5_clk,	"bus-uart5",	"apb1",
 820		      0x594, BIT(21), 0);
 821
 822static struct ccu_common *sun9i_a80_ccu_clks[] = {
 823	&pll_c0cpux_clk.common,
 824	&pll_c1cpux_clk.common,
 825	&pll_audio_clk.common,
 826	&pll_periph0_clk.common,
 827	&pll_ve_clk.common,
 828	&pll_ddr_clk.common,
 829	&pll_video0_clk.common,
 830	&pll_video1_clk.common,
 831	&pll_gpu_clk.common,
 832	&pll_de_clk.common,
 833	&pll_isp_clk.common,
 834	&pll_periph1_clk.common,
 835	&c0cpux_clk.common,
 836	&c1cpux_clk.common,
 837	&atb0_clk.common,
 838	&axi0_clk.common,
 839	&atb1_clk.common,
 840	&axi1_clk.common,
 841	&gtbus_clk.common,
 842	&ahb0_clk.common,
 843	&ahb1_clk.common,
 844	&ahb2_clk.common,
 845	&apb0_clk.common,
 846	&apb1_clk.common,
 847	&cci400_clk.common,
 848	&ats_clk.common,
 849	&trace_clk.common,
 850
 851	&out_a_clk.common,
 852	&out_b_clk.common,
 853
 854	/* module clocks */
 855	&nand0_0_clk.common,
 856	&nand0_1_clk.common,
 857	&nand1_0_clk.common,
 858	&nand1_1_clk.common,
 859	&mmc0_clk.common,
 860	&mmc0_sample_clk.common,
 861	&mmc0_output_clk.common,
 862	&mmc1_clk.common,
 863	&mmc1_sample_clk.common,
 864	&mmc1_output_clk.common,
 865	&mmc2_clk.common,
 866	&mmc2_sample_clk.common,
 867	&mmc2_output_clk.common,
 868	&mmc3_clk.common,
 869	&mmc3_sample_clk.common,
 870	&mmc3_output_clk.common,
 871	&ts_clk.common,
 872	&ss_clk.common,
 873	&spi0_clk.common,
 874	&spi1_clk.common,
 875	&spi2_clk.common,
 876	&spi3_clk.common,
 877	&i2s0_clk.common,
 878	&i2s1_clk.common,
 879	&spdif_clk.common,
 880	&sdram_clk.common,
 881	&de_clk.common,
 882	&edp_clk.common,
 883	&mp_clk.common,
 884	&lcd0_clk.common,
 885	&lcd1_clk.common,
 886	&mipi_dsi0_clk.common,
 887	&mipi_dsi1_clk.common,
 888	&hdmi_clk.common,
 889	&hdmi_slow_clk.common,
 890	&mipi_csi_clk.common,
 891	&csi_isp_clk.common,
 892	&csi_misc_clk.common,
 893	&csi0_mclk_clk.common,
 894	&csi1_mclk_clk.common,
 895	&fd_clk.common,
 896	&ve_clk.common,
 897	&avs_clk.common,
 898	&gpu_core_clk.common,
 899	&gpu_memory_clk.common,
 900	&gpu_axi_clk.common,
 901	&sata_clk.common,
 902	&ac97_clk.common,
 903	&mipi_hsi_clk.common,
 904	&gpadc_clk.common,
 905	&cir_tx_clk.common,
 906
 907	/* AHB0 bus gates */
 908	&bus_fd_clk.common,
 909	&bus_ve_clk.common,
 910	&bus_gpu_ctrl_clk.common,
 911	&bus_ss_clk.common,
 912	&bus_mmc_clk.common,
 913	&bus_nand0_clk.common,
 914	&bus_nand1_clk.common,
 915	&bus_sdram_clk.common,
 916	&bus_mipi_hsi_clk.common,
 917	&bus_sata_clk.common,
 918	&bus_ts_clk.common,
 919	&bus_spi0_clk.common,
 920	&bus_spi1_clk.common,
 921	&bus_spi2_clk.common,
 922	&bus_spi3_clk.common,
 923
 924	/* AHB1 bus gates */
 925	&bus_otg_clk.common,
 926	&bus_usb_clk.common,
 927	&bus_gmac_clk.common,
 928	&bus_msgbox_clk.common,
 929	&bus_spinlock_clk.common,
 930	&bus_hstimer_clk.common,
 931	&bus_dma_clk.common,
 932
 933	/* AHB2 bus gates */
 934	&bus_lcd0_clk.common,
 935	&bus_lcd1_clk.common,
 936	&bus_edp_clk.common,
 937	&bus_csi_clk.common,
 938	&bus_hdmi_clk.common,
 939	&bus_de_clk.common,
 940	&bus_mp_clk.common,
 941	&bus_mipi_dsi_clk.common,
 942
 943	/* APB0 bus gates */
 944	&bus_spdif_clk.common,
 945	&bus_pio_clk.common,
 946	&bus_ac97_clk.common,
 947	&bus_i2s0_clk.common,
 948	&bus_i2s1_clk.common,
 949	&bus_lradc_clk.common,
 950	&bus_gpadc_clk.common,
 951	&bus_twd_clk.common,
 952	&bus_cir_tx_clk.common,
 953
 954	/* APB1 bus gates */
 955	&bus_i2c0_clk.common,
 956	&bus_i2c1_clk.common,
 957	&bus_i2c2_clk.common,
 958	&bus_i2c3_clk.common,
 959	&bus_i2c4_clk.common,
 960	&bus_uart0_clk.common,
 961	&bus_uart1_clk.common,
 962	&bus_uart2_clk.common,
 963	&bus_uart3_clk.common,
 964	&bus_uart4_clk.common,
 965	&bus_uart5_clk.common,
 966};
 967
 968static struct clk_hw_onecell_data sun9i_a80_hw_clks = {
 969	.hws	= {
 970		[CLK_PLL_C0CPUX]	= &pll_c0cpux_clk.common.hw,
 971		[CLK_PLL_C1CPUX]	= &pll_c1cpux_clk.common.hw,
 972		[CLK_PLL_AUDIO]		= &pll_audio_clk.common.hw,
 973		[CLK_PLL_PERIPH0]	= &pll_periph0_clk.common.hw,
 974		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
 975		[CLK_PLL_DDR]		= &pll_ddr_clk.common.hw,
 976		[CLK_PLL_VIDEO0]	= &pll_video0_clk.common.hw,
 977		[CLK_PLL_VIDEO1]	= &pll_video1_clk.common.hw,
 978		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
 979		[CLK_PLL_DE]		= &pll_de_clk.common.hw,
 980		[CLK_PLL_ISP]		= &pll_isp_clk.common.hw,
 981		[CLK_PLL_PERIPH1]	= &pll_periph1_clk.common.hw,
 982		[CLK_C0CPUX]		= &c0cpux_clk.common.hw,
 983		[CLK_C1CPUX]		= &c1cpux_clk.common.hw,
 984		[CLK_ATB0]		= &atb0_clk.common.hw,
 985		[CLK_AXI0]		= &axi0_clk.common.hw,
 986		[CLK_ATB1]		= &atb1_clk.common.hw,
 987		[CLK_AXI1]		= &axi1_clk.common.hw,
 988		[CLK_GTBUS]		= &gtbus_clk.common.hw,
 989		[CLK_AHB0]		= &ahb0_clk.common.hw,
 990		[CLK_AHB1]		= &ahb1_clk.common.hw,
 991		[CLK_AHB2]		= &ahb2_clk.common.hw,
 992		[CLK_APB0]		= &apb0_clk.common.hw,
 993		[CLK_APB1]		= &apb1_clk.common.hw,
 994		[CLK_CCI400]		= &cci400_clk.common.hw,
 995		[CLK_ATS]		= &ats_clk.common.hw,
 996		[CLK_TRACE]		= &trace_clk.common.hw,
 997
 998		[CLK_OUT_A]		= &out_a_clk.common.hw,
 999		[CLK_OUT_B]		= &out_b_clk.common.hw,
1000
1001		[CLK_NAND0_0]		= &nand0_0_clk.common.hw,
1002		[CLK_NAND0_1]		= &nand0_1_clk.common.hw,
1003		[CLK_NAND1_0]		= &nand1_0_clk.common.hw,
1004		[CLK_NAND1_1]		= &nand1_1_clk.common.hw,
1005		[CLK_MMC0]		= &mmc0_clk.common.hw,
1006		[CLK_MMC0_SAMPLE]	= &mmc0_sample_clk.common.hw,
1007		[CLK_MMC0_OUTPUT]	= &mmc0_output_clk.common.hw,
1008		[CLK_MMC1]		= &mmc1_clk.common.hw,
1009		[CLK_MMC1_SAMPLE]	= &mmc1_sample_clk.common.hw,
1010		[CLK_MMC1_OUTPUT]	= &mmc1_output_clk.common.hw,
1011		[CLK_MMC2]		= &mmc2_clk.common.hw,
1012		[CLK_MMC2_SAMPLE]	= &mmc2_sample_clk.common.hw,
1013		[CLK_MMC2_OUTPUT]	= &mmc2_output_clk.common.hw,
1014		[CLK_MMC3]		= &mmc3_clk.common.hw,
1015		[CLK_MMC3_SAMPLE]	= &mmc3_sample_clk.common.hw,
1016		[CLK_MMC3_OUTPUT]	= &mmc3_output_clk.common.hw,
1017		[CLK_TS]		= &ts_clk.common.hw,
1018		[CLK_SS]		= &ss_clk.common.hw,
1019		[CLK_SPI0]		= &spi0_clk.common.hw,
1020		[CLK_SPI1]		= &spi1_clk.common.hw,
1021		[CLK_SPI2]		= &spi2_clk.common.hw,
1022		[CLK_SPI3]		= &spi3_clk.common.hw,
1023		[CLK_I2S0]		= &i2s0_clk.common.hw,
1024		[CLK_I2S1]		= &i2s1_clk.common.hw,
1025		[CLK_SPDIF]		= &spdif_clk.common.hw,
1026		[CLK_SDRAM]		= &sdram_clk.common.hw,
1027		[CLK_DE]		= &de_clk.common.hw,
1028		[CLK_EDP]		= &edp_clk.common.hw,
1029		[CLK_MP]		= &mp_clk.common.hw,
1030		[CLK_LCD0]		= &lcd0_clk.common.hw,
1031		[CLK_LCD1]		= &lcd1_clk.common.hw,
1032		[CLK_MIPI_DSI0]		= &mipi_dsi0_clk.common.hw,
1033		[CLK_MIPI_DSI1]		= &mipi_dsi1_clk.common.hw,
1034		[CLK_HDMI]		= &hdmi_clk.common.hw,
1035		[CLK_HDMI_SLOW]		= &hdmi_slow_clk.common.hw,
1036		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
1037		[CLK_CSI_ISP]		= &csi_isp_clk.common.hw,
1038		[CLK_CSI_MISC]		= &csi_misc_clk.common.hw,
1039		[CLK_CSI0_MCLK]		= &csi0_mclk_clk.common.hw,
1040		[CLK_CSI1_MCLK]		= &csi1_mclk_clk.common.hw,
1041		[CLK_FD]		= &fd_clk.common.hw,
1042		[CLK_VE]		= &ve_clk.common.hw,
1043		[CLK_AVS]		= &avs_clk.common.hw,
1044		[CLK_GPU_CORE]		= &gpu_core_clk.common.hw,
1045		[CLK_GPU_MEMORY]	= &gpu_memory_clk.common.hw,
1046		[CLK_GPU_AXI]		= &gpu_axi_clk.common.hw,
1047		[CLK_SATA]		= &sata_clk.common.hw,
1048		[CLK_AC97]		= &ac97_clk.common.hw,
1049		[CLK_MIPI_HSI]		= &mipi_hsi_clk.common.hw,
1050		[CLK_GPADC]		= &gpadc_clk.common.hw,
1051		[CLK_CIR_TX]		= &cir_tx_clk.common.hw,
1052
1053		[CLK_BUS_FD]		= &bus_fd_clk.common.hw,
1054		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
1055		[CLK_BUS_GPU_CTRL]	= &bus_gpu_ctrl_clk.common.hw,
1056		[CLK_BUS_SS]		= &bus_ss_clk.common.hw,
1057		[CLK_BUS_MMC]		= &bus_mmc_clk.common.hw,
1058		[CLK_BUS_NAND0]		= &bus_nand0_clk.common.hw,
1059		[CLK_BUS_NAND1]		= &bus_nand1_clk.common.hw,
1060		[CLK_BUS_SDRAM]		= &bus_sdram_clk.common.hw,
1061		[CLK_BUS_MIPI_HSI]	= &bus_mipi_hsi_clk.common.hw,
1062		[CLK_BUS_SATA]		= &bus_sata_clk.common.hw,
1063		[CLK_BUS_TS]		= &bus_ts_clk.common.hw,
1064		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
1065		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
1066		[CLK_BUS_SPI2]		= &bus_spi2_clk.common.hw,
1067		[CLK_BUS_SPI3]		= &bus_spi3_clk.common.hw,
1068
1069		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
1070		[CLK_BUS_USB]		= &bus_usb_clk.common.hw,
1071		[CLK_BUS_GMAC]		= &bus_gmac_clk.common.hw,
1072		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
1073		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
1074		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
1075		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
1076
1077		[CLK_BUS_LCD0]		= &bus_lcd0_clk.common.hw,
1078		[CLK_BUS_LCD1]		= &bus_lcd1_clk.common.hw,
1079		[CLK_BUS_EDP]		= &bus_edp_clk.common.hw,
1080		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
1081		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
1082		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
1083		[CLK_BUS_MP]		= &bus_mp_clk.common.hw,
1084		[CLK_BUS_MIPI_DSI]	= &bus_mipi_dsi_clk.common.hw,
1085
1086		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
1087		[CLK_BUS_PIO]		= &bus_pio_clk.common.hw,
1088		[CLK_BUS_AC97]		= &bus_ac97_clk.common.hw,
1089		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
1090		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
1091		[CLK_BUS_LRADC]		= &bus_lradc_clk.common.hw,
1092		[CLK_BUS_GPADC]		= &bus_gpadc_clk.common.hw,
1093		[CLK_BUS_TWD]		= &bus_twd_clk.common.hw,
1094		[CLK_BUS_CIR_TX]	= &bus_cir_tx_clk.common.hw,
1095
1096		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
1097		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
1098		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
1099		[CLK_BUS_I2C3]		= &bus_i2c3_clk.common.hw,
1100		[CLK_BUS_I2C4]		= &bus_i2c4_clk.common.hw,
1101		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
1102		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
1103		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
1104		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
1105		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
1106		[CLK_BUS_UART5]		= &bus_uart5_clk.common.hw,
1107	},
1108	.num	= CLK_NUMBER,
1109};
1110
1111static const struct ccu_reset_map sun9i_a80_ccu_resets[] = {
1112	/* AHB0 reset controls */
1113	[RST_BUS_FD]		= { 0x5a0, BIT(0) },
1114	[RST_BUS_VE]		= { 0x5a0, BIT(1) },
1115	[RST_BUS_GPU_CTRL]	= { 0x5a0, BIT(3) },
1116	[RST_BUS_SS]		= { 0x5a0, BIT(5) },
1117	[RST_BUS_MMC]		= { 0x5a0, BIT(8) },
1118	[RST_BUS_NAND0]		= { 0x5a0, BIT(12) },
1119	[RST_BUS_NAND1]		= { 0x5a0, BIT(13) },
1120	[RST_BUS_SDRAM]		= { 0x5a0, BIT(14) },
1121	[RST_BUS_SATA]		= { 0x5a0, BIT(16) },
1122	[RST_BUS_TS]		= { 0x5a0, BIT(18) },
1123	[RST_BUS_SPI0]		= { 0x5a0, BIT(20) },
1124	[RST_BUS_SPI1]		= { 0x5a0, BIT(21) },
1125	[RST_BUS_SPI2]		= { 0x5a0, BIT(22) },
1126	[RST_BUS_SPI3]		= { 0x5a0, BIT(23) },
1127
1128	/* AHB1 reset controls */
1129	[RST_BUS_OTG]		= { 0x5a4, BIT(0) },
1130	[RST_BUS_OTG_PHY]	= { 0x5a4, BIT(1) },
1131	[RST_BUS_MIPI_HSI]	= { 0x5a4, BIT(9) },
1132	[RST_BUS_GMAC]		= { 0x5a4, BIT(17) },
1133	[RST_BUS_MSGBOX]	= { 0x5a4, BIT(21) },
1134	[RST_BUS_SPINLOCK]	= { 0x5a4, BIT(22) },
1135	[RST_BUS_HSTIMER]	= { 0x5a4, BIT(23) },
1136	[RST_BUS_DMA]		= { 0x5a4, BIT(24) },
1137
1138	/* AHB2 reset controls */
1139	[RST_BUS_LCD0]		= { 0x5a8, BIT(0) },
1140	[RST_BUS_LCD1]		= { 0x5a8, BIT(1) },
1141	[RST_BUS_EDP]		= { 0x5a8, BIT(2) },
1142	[RST_BUS_LVDS]		= { 0x5a8, BIT(3) },
1143	[RST_BUS_CSI]		= { 0x5a8, BIT(4) },
1144	[RST_BUS_HDMI0]		= { 0x5a8, BIT(5) },
1145	[RST_BUS_HDMI1]		= { 0x5a8, BIT(6) },
1146	[RST_BUS_DE]		= { 0x5a8, BIT(7) },
1147	[RST_BUS_MP]		= { 0x5a8, BIT(8) },
1148	[RST_BUS_GPU]		= { 0x5a8, BIT(9) },
1149	[RST_BUS_MIPI_DSI]	= { 0x5a8, BIT(11) },
1150
1151	/* APB0 reset controls */
1152	[RST_BUS_SPDIF]		= { 0x5b0, BIT(1) },
1153	[RST_BUS_AC97]		= { 0x5b0, BIT(11) },
1154	[RST_BUS_I2S0]		= { 0x5b0, BIT(12) },
1155	[RST_BUS_I2S1]		= { 0x5b0, BIT(13) },
1156	[RST_BUS_LRADC]		= { 0x5b0, BIT(15) },
1157	[RST_BUS_GPADC]		= { 0x5b0, BIT(17) },
1158	[RST_BUS_CIR_TX]	= { 0x5b0, BIT(19) },
1159
1160	/* APB1 reset controls */
1161	[RST_BUS_I2C0]		= { 0x5b4, BIT(0) },
1162	[RST_BUS_I2C1]		= { 0x5b4, BIT(1) },
1163	[RST_BUS_I2C2]		= { 0x5b4, BIT(2) },
1164	[RST_BUS_I2C3]		= { 0x5b4, BIT(3) },
1165	[RST_BUS_I2C4]		= { 0x5b4, BIT(4) },
1166	[RST_BUS_UART0]		= { 0x5b4, BIT(16) },
1167	[RST_BUS_UART1]		= { 0x5b4, BIT(17) },
1168	[RST_BUS_UART2]		= { 0x5b4, BIT(18) },
1169	[RST_BUS_UART3]		= { 0x5b4, BIT(19) },
1170	[RST_BUS_UART4]		= { 0x5b4, BIT(20) },
1171	[RST_BUS_UART5]		= { 0x5b4, BIT(21) },
1172};
1173
1174static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
1175	.ccu_clks	= sun9i_a80_ccu_clks,
1176	.num_ccu_clks	= ARRAY_SIZE(sun9i_a80_ccu_clks),
1177
1178	.hw_clks	= &sun9i_a80_hw_clks,
1179
1180	.resets		= sun9i_a80_ccu_resets,
1181	.num_resets	= ARRAY_SIZE(sun9i_a80_ccu_resets),
1182};
1183
1184#define SUN9I_A80_PLL_P_SHIFT	16
1185#define SUN9I_A80_PLL_N_SHIFT	8
1186#define SUN9I_A80_PLL_N_WIDTH	8
1187
1188static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
1189{
1190	u32 val = readl(reg);
1191
1192	/* bail out if P divider is not used */
1193	if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
1194		return;
1195
1196	/*
1197	 * If P is used, output should be less than 288 MHz. When we
1198	 * set P to 1, we should also decrease the multiplier so the
1199	 * output doesn't go out of range, but not too much such that
1200	 * the multiplier stays above 12, the minimal operation value.
1201	 *
1202	 * To keep it simple, set the multiplier to 17, the reset value.
1203	 */
1204	val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
1205			SUN9I_A80_PLL_N_SHIFT);
1206	val |= 17 << SUN9I_A80_PLL_N_SHIFT;
1207
1208	/* And clear P */
1209	val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
1210
1211	writel(val, reg);
1212}
1213
1214static int sun9i_a80_ccu_probe(struct platform_device *pdev)
1215{
1216	void __iomem *reg;
1217	u32 val;
1218
1219	reg = devm_platform_ioremap_resource(pdev, 0);
1220	if (IS_ERR(reg))
1221		return PTR_ERR(reg);
1222
1223	/* Enforce d1 = 0, d2 = 0 for Audio PLL */
1224	val = readl(reg + SUN9I_A80_PLL_AUDIO_REG);
1225	val &= ~(BIT(16) | BIT(18));
1226	writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
1227
1228	/* Enforce P = 1 for both CPU cluster PLLs */
1229	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
1230	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
1231
1232	return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_ccu_desc);
1233}
1234
1235static const struct of_device_id sun9i_a80_ccu_ids[] = {
1236	{ .compatible = "allwinner,sun9i-a80-ccu" },
1237	{ }
1238};
1239MODULE_DEVICE_TABLE(of, sun9i_a80_ccu_ids);
1240
1241static struct platform_driver sun9i_a80_ccu_driver = {
1242	.probe	= sun9i_a80_ccu_probe,
1243	.driver	= {
1244		.name	= "sun9i-a80-ccu",
1245		.suppress_bind_attrs = true,
1246		.of_match_table	= sun9i_a80_ccu_ids,
1247	},
1248};
1249module_platform_driver(sun9i_a80_ccu_driver);
1250
1251MODULE_IMPORT_NS("SUNXI_CCU");
1252MODULE_DESCRIPTION("Support for the Allwinner A80 CCU");
1253MODULE_LICENSE("GPL");
~/ Read-only file preview.