brintos

brintos / linux-shallow public Read only

0
0
Text · 28.6 KiB · cb4c6b1 Raw
929 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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	0x20c25 26/*27 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However28 * 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	0x00034#define SUN8I_A83T_PLL_C1CPUX_REG	0x00435 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, M66 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz67 * 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	0x00871 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 = 2278};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	16859#define SUN8I_A83T_PLL_N_SHIFT	8860#define SUN8I_A83T_PLL_N_WIDTH	8861 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 we872	 * set P to 1, we should also decrease the multiplier so the873	 * output doesn't go out of range, but not too much such that874	 * 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};914MODULE_DEVICE_TABLE(of, sun8i_a83t_ccu_ids);915 916static struct platform_driver sun8i_a83t_ccu_driver = {917	.probe	= sun8i_a83t_ccu_probe,918	.driver	= {919		.name	= "sun8i-a83t-ccu",920		.suppress_bind_attrs = true,921		.of_match_table	= sun8i_a83t_ccu_ids,922	},923};924module_platform_driver(sun8i_a83t_ccu_driver);925 926MODULE_IMPORT_NS(SUNXI_CCU);927MODULE_DESCRIPTION("Support for the Allwinner A83T CCU");928MODULE_LICENSE("GPL");929