cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ccu-sun8i-a83t.c (29222B)


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