From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8182C433E0 for ; Fri, 22 May 2020 15:14:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9DAD5205CB for ; Fri, 22 May 2020 15:14:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=cerno.tech header.i=@cerno.tech header.b="iXI7/TWz"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="kj4yBiOX" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730151AbgEVPOM (ORCPT ); Fri, 22 May 2020 11:14:12 -0400 Received: from wnew3-smtp.messagingengine.com ([64.147.123.17]:55491 "EHLO wnew3-smtp.messagingengine.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729929AbgEVPOL (ORCPT ); Fri, 22 May 2020 11:14:11 -0400 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.west.internal (Postfix) with ESMTP id 8390FC6E; Fri, 22 May 2020 11:14:08 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Fri, 22 May 2020 11:14:09 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cerno.tech; h= date:from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=fm2; bh=+zAmwRGj4Hx3zU7KnF4LtFM1k3X wqQ3FWC8F7d1g2TU=; b=iXI7/TWzWXtSN6Rv5Y9knaov3gdiieQZghy9j75ny9o OrFDuDaDi3HpGbDMpq7QG/ENSBPQdMdDqng21VKPQdl2mNZeWkkxpKc4ImP+woSF 9KfwW/+re5ArYBJN+i+Pa8cbElPQQVTMOZqBEGQaQ/knEEWAvW8nE6q9SuTWbKL1 KinUMGKTVRIfSK9qo566UBMyPpkoeEqYDjsdVA/3jC7hfXz8iqRDmdi5RLT3D/5l z/89sogj0PpP8sSC1aksfGR1qELtvtAeg0hQOEmUnMYkMTKV67HtrIv6ra6WlEXf QSAsKatFg7UCMvYT5evFvZw6gb/O7xNETy0srlryE4g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=+zAmwR Gj4Hx3zU7KnF4LtFM1k3XwqQ3FWC8F7d1g2TU=; b=kj4yBiOXio8ZSCt+hW8YKl K+2Z1WJO5wgHWdn2wFUFr6NqELmka0AOLxR1crclzQmNpAeoYm5cWpooWXE5iD76 5qklPh46BjaPdLUDum6twHBuJFIhl1KoM7ZCAi+c2V8S113t4aL7b5uprpZDH+5R UcHrWpAlGFrAlgk3WspfrZdt/st+ftBCo2d6tAi/tbZHwfMP8S4/eXF/s3xC0w42 B0Bk7EuNIU+HtiwsbHB2kKwOXZZtVzOvA4v7GtWtkDdvw2S4qyw2L6M8aHeYuWyf z9bcwEZ1ktUiePWC23bJU77NncIg6u/tV4tt2m6hFrsdNzoTp4jjzM4LU0/KRsfQ == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduhedruddufedgkeehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvffukfhfgggtuggjsehgtderredttddvnecuhfhrohhmpeforgigihhm vgcutfhiphgrrhguuceomhgrgihimhgvsegtvghrnhhordhtvggthheqnecuggftrfgrth htvghrnhepfeehfeejudejtefhiefgudeugfektddvgeeuveehfeeifeeuudelhedtheev geeunecuffhomhgrihhnpegtohhmmhhonhdrtghmnecukfhppeeltddrkeelrdeikedrje einecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepmhgr gihimhgvsegtvghrnhhordhtvggthh X-ME-Proxy: Received: from localhost (lfbn-tou-1-1502-76.w90-89.abo.wanadoo.fr [90.89.68.76]) by mail.messagingengine.com (Postfix) with ESMTPA id 246373280063; Fri, 22 May 2020 11:14:05 -0400 (EDT) Date: Fri, 22 May 2020 17:14:03 +0200 From: Maxime Ripard To: Frank Lee Cc: wens@csie.org, robh+dt@kernel.org, mturquette@baylibre.com, sboyd@kernel.org, linus.walleij@linaro.org, p.zabel@pengutronix.de, huangshuosheng@allwinnertech.com, tiny.windzz@gmail.com, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org Subject: Re: [PATCH 1/4] clk: sunxi-ng: add support for the Allwinner A100 CCU Message-ID: <20200522151403.7ovbdza2o3cjrb7a@gilmour.lan> References: <20200522030743.10204-1-frank@allwinnertech.com> <20200522030743.10204-2-frank@allwinnertech.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="3gi2rcwjojrhvt23" Content-Disposition: inline In-Reply-To: <20200522030743.10204-2-frank@allwinnertech.com> Sender: linux-gpio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org --3gi2rcwjojrhvt23 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi, On Fri, May 22, 2020 at 11:07:40AM +0800, Frank Lee wrote: > Add support for a100 in the sunxi-ng CCU framework. >=20 > Signed-off-by: Frank Lee > --- > drivers/clk/sunxi-ng/Kconfig | 10 + > drivers/clk/sunxi-ng/Makefile | 2 + > drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c | 206 +++ > drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h | 14 + > drivers/clk/sunxi-ng/ccu-sun50i-a100.c | 1255 +++++++++++++++++ > drivers/clk/sunxi-ng/ccu-sun50i-a100.h | 14 + > include/dt-bindings/clock/sun50i-a100-ccu.h | 141 ++ > include/dt-bindings/clock/sun50i-a100-r-ccu.h | 25 + > include/dt-bindings/reset/sun50i-a100-ccu.h | 68 + > include/dt-bindings/reset/sun50i-a100-r-ccu.h | 18 + > 10 files changed, 1753 insertions(+) > create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c > create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h > create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a100.c > create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-a100.h > create mode 100644 include/dt-bindings/clock/sun50i-a100-ccu.h > create mode 100644 include/dt-bindings/clock/sun50i-a100-r-ccu.h > create mode 100644 include/dt-bindings/reset/sun50i-a100-ccu.h > create mode 100644 include/dt-bindings/reset/sun50i-a100-r-ccu.h >=20 > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig > index cdf333003c30..ce5f5847d5d3 100644 > --- a/drivers/clk/sunxi-ng/Kconfig > +++ b/drivers/clk/sunxi-ng/Kconfig > @@ -17,6 +17,16 @@ config SUN50I_A64_CCU > default ARM64 && ARCH_SUNXI > depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST > =20 > +config SUN50I_A100_CCU > + bool "Support for the Allwinner A100 CCU" > + default ARM64 && ARCH_SUNXI > + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST > + > +config SUN50I_A100_R_CCU > + bool "Support for the Allwinner A100 PRCM CCU" > + default ARM64 && ARCH_SUNXI > + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST > + > config SUN50I_H6_CCU > bool "Support for the Allwinner H6 CCU" > default ARM64 && ARCH_SUNXI > diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile > index 4c7bee883f2f..3eb5cff40eac 100644 > --- a/drivers/clk/sunxi-ng/Makefile > +++ b/drivers/clk/sunxi-ng/Makefile > @@ -23,6 +23,8 @@ obj-y +=3D ccu_mp.o > # SoC support > obj-$(CONFIG_SUNIV_F1C100S_CCU) +=3D ccu-suniv-f1c100s.o > obj-$(CONFIG_SUN50I_A64_CCU) +=3D ccu-sun50i-a64.o > +obj-$(CONFIG_SUN50I_A100_CCU) +=3D ccu-sun50i-a100.o > +obj-$(CONFIG_SUN50I_A100_R_CCU) +=3D ccu-sun50i-a100-r.o > obj-$(CONFIG_SUN50I_H6_CCU) +=3D ccu-sun50i-h6.o > obj-$(CONFIG_SUN50I_H6_R_CCU) +=3D ccu-sun50i-h6-r.o > obj-$(CONFIG_SUN4I_A10_CCU) +=3D ccu-sun4i-a10.o > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi= -ng/ccu-sun50i-a100-r.c > new file mode 100644 > index 000000000000..31875269ef90 > --- /dev/null > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c > @@ -0,0 +1,206 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Frank Lee The domain doesn't match the one used to send that patch, is that intention= al? > + */ > + > +#include > +#include > +#include > +#include > + > +#include "ccu_common.h" > +#include "ccu_reset.h" > + > +#include "ccu_div.h" > +#include "ccu_gate.h" > +#include "ccu_mp.h" > +#include "ccu_nm.h" > + > +#include "ccu-sun50i-a100-r.h" > + > +static const char * const cpus_r_apb2_parents[] =3D { "dcxo24M", "osc32k= ", > + "iosc", "pll-periph0" }; > +static const struct ccu_mux_var_prediv cpus_r_apb2_predivs[] =3D { > + { .index =3D 3, .shift =3D 0, .width =3D 5 }, > +}; > + > +static struct ccu_div cpus_clk =3D { > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + > + .mux =3D { > + .shift =3D 24, > + .width =3D 2, > + > + .var_predivs =3D cpus_r_apb2_predivs, > + .n_var_predivs =3D ARRAY_SIZE(cpus_r_apb2_predivs), > + }, > + > + .common =3D { > + .reg =3D 0x000, > + .features =3D CCU_FEATURE_VARIABLE_PREDIV, > + .hw.init =3D CLK_HW_INIT_PARENTS("cpus", > + cpus_r_apb2_parents, > + &ccu_div_ops, > + 0), > + }, > +}; > + > +static CLK_FIXED_FACTOR_HW(r_ahb_clk, "r-ahb", &cpus_clk.common.hw, 1, 1= , 0); > + > +static struct ccu_div r_apb1_clk =3D { > + .div =3D _SUNXI_CCU_DIV(0, 2), > + > + .common =3D { > + .reg =3D 0x00c, > + .hw.init =3D CLK_HW_INIT("r-apb1", > + "r-ahb", > + &ccu_div_ops, > + 0), > + }, > +}; > + > +static struct ccu_div r_apb2_clk =3D { > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + > + .mux =3D { > + .shift =3D 24, > + .width =3D 2, > + > + .var_predivs =3D cpus_r_apb2_predivs, > + .n_var_predivs =3D ARRAY_SIZE(cpus_r_apb2_predivs), > + }, > + > + .common =3D { > + .reg =3D 0x010, > + .features =3D CCU_FEATURE_VARIABLE_PREDIV, > + .hw.init =3D CLK_HW_INIT_PARENTS("r-apb2", > + cpus_r_apb2_parents, > + &ccu_div_ops, > + 0), > + }, > +}; > + > +static SUNXI_CCU_GATE(r_apb1_timer_clk, "r-apb1-timer", "r-apb1", > + 0x11c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_apb1_twd_clk, "r-apb1-twd", "r-apb1", > + 0x12c, BIT(0), 0); > + > +static const char * const r_apb1_pwm_clk_parents[] =3D { "dcxo24M", "osc= 32k", > + "iosc" }; > +static SUNXI_CCU_MUX(r_apb1_pwm_clk, "r-apb1-pwm", r_apb1_pwm_clk_parent= s, > + 0x130, 24, 2, 0); > + > +static SUNXI_CCU_GATE(r_apb1_bus_pwm_clk, "r-apb1-bus-pwm", "r-apb1", > + 0x13c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_apb1_ppu_clk, "r-apb1-ppu", "r-apb1", > + 0x17c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_apb2_uart_clk, "r-apb2-uart", "r-apb2", > + 0x18c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_apb2_i2c0_clk, "r-apb2-i2c0", "r-apb2", > + 0x19c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_apb2_i2c1_clk, "r-apb2-i2c1", "r-apb2", > + 0x19c, BIT(1), 0); You should be using SUNXI_CCU_GATE_DATA here > +static const char * const r_apb1_ir_rx_parents[] =3D { "osc32k", "dcxo24= M" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb1_ir_rx_clk, "r-apb1-ir-rx", > + r_apb1_ir_rx_parents, 0x1c0, > + 0, 5, /* M */ > + 8, 2, /* P */ > + 24, 1, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(r_apb1_bus_ir_rx_clk, "r-apb1-bus-ir-rx", "r-apb1", > + 0x1cc, BIT(0), 0); > + > +static SUNXI_CCU_GATE(r_ahb_bus_rtc_clk, "r-ahb-rtc", "r-ahb", > + 0x20c, BIT(0), 0); > + > +static struct ccu_common *sun50i_a100_r_ccu_clks[] =3D { > + &cpus_clk.common, > + &r_apb1_clk.common, > + &r_apb2_clk.common, > + &r_apb1_timer_clk.common, > + &r_apb1_twd_clk.common, > + &r_apb1_pwm_clk.common, > + &r_apb1_bus_pwm_clk.common, > + &r_apb1_ppu_clk.common, > + &r_apb2_uart_clk.common, > + &r_apb2_i2c0_clk.common, > + &r_apb2_i2c1_clk.common, > + &r_apb1_ir_rx_clk.common, > + &r_apb1_bus_ir_rx_clk.common, > + &r_ahb_bus_rtc_clk.common, > +}; > + > +static struct clk_hw_onecell_data sun50i_a100_r_hw_clks =3D { > + .hws =3D { > + [CLK_CPUS] =3D &cpus_clk.common.hw, > + [CLK_R_AHB] =3D &r_ahb_clk.hw, Having some consistency here would be great, CLK_R_CPUS would be best I gue= ss. > + [CLK_R_APB1] =3D &r_apb1_clk.common.hw, > + [CLK_R_APB2] =3D &r_apb2_clk.common.hw, > + [CLK_R_APB1_TIMER] =3D &r_apb1_timer_clk.common.hw, > + [CLK_R_APB1_TWD] =3D &r_apb1_twd_clk.common.hw, > + [CLK_R_APB1_PWM] =3D &r_apb1_pwm_clk.common.hw, > + [CLK_R_APB1_BUS_PWM] =3D &r_apb1_bus_pwm_clk.common.hw, > + [CLK_R_APB1_PPU] =3D &r_apb1_ppu_clk.common.hw, > + [CLK_R_APB2_UART] =3D &r_apb2_uart_clk.common.hw, > + [CLK_R_APB2_I2C0] =3D &r_apb2_i2c0_clk.common.hw, > + [CLK_R_APB2_I2C1] =3D &r_apb2_i2c1_clk.common.hw, > + [CLK_R_APB1_IR] =3D &r_apb1_ir_rx_clk.common.hw, > + [CLK_R_APB1_BUS_IR] =3D &r_apb1_bus_ir_rx_clk.common.hw, > + [CLK_R_AHB_BUS_RTC] =3D &r_ahb_bus_rtc_clk.common.hw, > + }, > + .num =3D CLK_NUMBER, > +}; > + > +static struct ccu_reset_map sun50i_a100_r_ccu_resets[] =3D { > + [RST_R_APB1_TIMER] =3D { 0x11c, BIT(16) }, > + [RST_R_APB1_BUS_PWM] =3D { 0x13c, BIT(16) }, > + [RST_R_APB1_PPU] =3D { 0x17c, BIT(16) }, > + [RST_R_APB2_UART] =3D { 0x18c, BIT(16) }, > + [RST_R_APB2_I2C0] =3D { 0x19c, BIT(16) }, > + [RST_R_APB2_I2C1] =3D { 0x19c, BIT(17) }, > + [RST_R_APB1_BUS_IR] =3D { 0x1cc, BIT(16) }, > + [RST_R_AHB_BUS_RTC] =3D { 0x20c, BIT(16) }, > +}; > + > +static const struct sunxi_ccu_desc sun50i_a100_r_ccu_desc =3D { > + .ccu_clks =3D sun50i_a100_r_ccu_clks, > + .num_ccu_clks =3D ARRAY_SIZE(sun50i_a100_r_ccu_clks), > + > + .hw_clks =3D &sun50i_a100_r_hw_clks, > + > + .resets =3D sun50i_a100_r_ccu_resets, > + .num_resets =3D ARRAY_SIZE(sun50i_a100_r_ccu_resets), > +}; > + > +static int sun50i_a100_r_ccu_probe(struct platform_device *pdev) > +{ > + void __iomem *reg; > + > + reg =3D devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(reg)) > + return PTR_ERR(reg); > + > + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc); > +} > + > +static const struct of_device_id sun50i_a100_r_ccu_ids[] =3D { > + { .compatible =3D "allwinner,sun50i-a100-r-ccu" }, > + { } > +}; You're going to need a DT binding here too. > +static struct platform_driver sun50i_a100_r_ccu_driver =3D { > + .probe =3D sun50i_a100_r_ccu_probe, > + .driver =3D { > + .name =3D "sun50i-a100-r-ccu", > + .of_match_table =3D sun50i_a100_r_ccu_ids, > + }, > +}; > +module_platform_driver(sun50i_a100_r_ccu_driver); > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h b/drivers/clk/sunxi= -ng/ccu-sun50i-a100-r.h > new file mode 100644 > index 000000000000..c26a08b924db > --- /dev/null > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h > @@ -0,0 +1,14 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Frank Lee > + */ > + > +#ifndef _CCU_SUN50IW10_R_H > +#define _CCU_SUN50IW10_R_H > + > +#include > +#include > + > +#define CLK_NUMBER (CLK_R_AHB_BUS_RTC + 1) > + > +#endif /* _CCU_SUN50IW10_R_H */ > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-n= g/ccu-sun50i-a100.c > new file mode 100644 > index 000000000000..f9a0a7754eed > --- /dev/null > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c > @@ -0,0 +1,1255 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2020 Frank Lee > + */ > + > +#include > +#include > +#include > +#include > +#include > + > +#include "ccu_common.h" > +#include "ccu_reset.h" > + > +#include "ccu_div.h" > +#include "ccu_gate.h" > +#include "ccu_mp.h" > +#include "ccu_mult.h" > +#include "ccu_nk.h" > +#include "ccu_nkm.h" > +#include "ccu_nkmp.h" > +#include "ccu_nm.h" > + > +#include "ccu-sun50i-a100.h" > + > +/* > + * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However > + * P should only be used for output frequencies lower than 288 MHz. > + * > + * For now we can just model it as a multiplier clock, and force P to /1. > + * > + * The M factor is present in the register's description, but not in the > + * frequency formula, and it's documented as "M is only used for backdoor > + * testing", so it's not modelled and then force to 0. > + */ > +#define SUN50I_A100_PLL_CPUX_REG 0x000 > +static struct ccu_mult pll_cpux_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .mult =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .common =3D { > + .reg =3D 0x000, > + .hw.init =3D CLK_HW_INIT("pll-cpux", "dcxo24M", > + &ccu_mult_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ > +#define SUN50I_A100_PLL_DDR0_REG 0x010 > +static struct ccu_nkmp pll_ddr0_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .p =3D _SUNXI_CCU_DIV(0, 1), /* output divider */ > + .common =3D { > + .reg =3D 0x010, > + .hw.init =3D CLK_HW_INIT("pll-ddr0", "dcxo24M", > + &ccu_nkmp_ops, > + CLK_SET_RATE_UNGATE | > + CLK_IS_CRITICAL), > + }, > +}; > + > +#define SUN50I_A100_PLL_PERIPH0_REG 0x020 > +static struct ccu_nkmp pll_periph0_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .p =3D _SUNXI_CCU_DIV(0, 1), /* output divider */ > + .fixed_post_div =3D 2, > + .common =3D { > + .reg =3D 0x020, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-periph0", "dcxo24M", > + &ccu_nkmp_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +#define SUN50I_A100_PLL_PERIPH1_REG 0x028 > +static struct ccu_nkmp pll_periph1_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .p =3D _SUNXI_CCU_DIV(0, 1), /* output divider */ > + .fixed_post_div =3D 2, > + .common =3D { > + .reg =3D 0x028, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-periph1", "dcxo24M", > + &ccu_nkmp_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > +#define SUN50I_A100_PLL_PERIPH1_PATTERN0_REG 0x128 > + > +#define SUN50I_A100_PLL_GPU_REG 0x030 > +static struct ccu_nkmp pll_gpu_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .p =3D _SUNXI_CCU_DIV(0, 1), /* output divider */ > + .common =3D { > + .reg =3D 0x030, > + .hw.init =3D CLK_HW_INIT("pll-gpu", "dcxo24M", > + &ccu_nkmp_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +/* > + * For Video PLLs, the output divider is described as "used for testing" > + * in the user manual. So it's not modelled and forced to 0. > + */ > +#define SUN50I_A100_PLL_VIDEO0_REG 0x040 > +static struct ccu_nm pll_video0_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .fixed_post_div =3D 4, > + .common =3D { > + .reg =3D 0x040, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-video0", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +#define SUN50I_A100_PLL_VIDEO1_REG 0x048 > +static struct ccu_nm pll_video1_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .fixed_post_div =3D 4, > + .common =3D { > + .reg =3D 0x048, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-video1", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +#define SUN50I_A100_PLL_VIDEO2_REG 0x050 > +static struct ccu_nm pll_video2_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .fixed_post_div =3D 4, > + .common =3D { > + .reg =3D 0x050, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-video2", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +#define SUN50I_A100_PLL_VE_REG 0x058 > +static struct ccu_nkmp pll_ve_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .p =3D _SUNXI_CCU_DIV(0, 1), /* output divider */ > + .common =3D { > + .reg =3D 0x058, > + .hw.init =3D CLK_HW_INIT("pll-ve", "dcxo24M", > + &ccu_nkmp_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +/* > + * The COM PLL has m0 dividers in addition to the usual N, M > + * factors. Since we only need 1 frequencies from this PLL: 45.1584 MHz, > + * ignore it for now. > + */ > +#define SUN50I_A100_PLL_COM_REG 0x060 > +static struct ccu_sdm_setting pll_com_sdm_table[] =3D { > + { .rate =3D 451584000, .pattern =3D 0xc0014396, .m =3D 2, .n =3D 37 }, > +}; > + > +static struct ccu_nm pll_com_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(0, 1), > + .sdm =3D _SUNXI_CCU_SDM(pll_com_sdm_table, BIT(24), > + 0x160, BIT(31)), > + .common =3D { > + .reg =3D 0x060, > + .features =3D CCU_FEATURE_SIGMA_DELTA_MOD, > + .hw.init =3D CLK_HW_INIT("pll-com", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +#define SUN50I_A100_PLL_VIDEO3_REG 0x068 > +static struct ccu_nm pll_video3_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(1, 1), /* input divider */ > + .fixed_post_div =3D 4, > + .common =3D { > + .reg =3D 0x068, > + .features =3D CCU_FEATURE_FIXED_POSTDIV, > + .hw.init =3D CLK_HW_INIT("pll-video3", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +/* > + * The Audio PLL has m0, m1 dividers in addition to the usual N, M > + * factors. Since we only need 4 frequencies from this PLL: 22.5792 MHz, > + * 24.576 MHz, 90.3168MHz and 98.304MHz ignore them for now. > + * Enforce the default for them, which is m0 =3D 1, m1 =3D 0. > + */ > +#define SUN50I_A100_PLL_AUDIO_REG 0x078 > +static struct ccu_sdm_setting pll_audio_sdm_table[] =3D { > + { .rate =3D 45158400, .pattern =3D 0xc001bcd3, .m =3D 18, .n =3D 33 }, > + { .rate =3D 49152000, .pattern =3D 0xc001eb85, .m =3D 20, .n =3D 40 }, > + { .rate =3D 180633600, .pattern =3D 0xc001288d, .m =3D 3, .n =3D 22 }, > + { .rate =3D 196608000, .pattern =3D 0xc001eb85, .m =3D 5, .n =3D 40 }, > +}; > + > +static struct ccu_nm pll_audio_clk =3D { > + .enable =3D BIT(27), > + .lock =3D BIT(28), > + .n =3D _SUNXI_CCU_MULT_MIN(8, 8, 12), > + .m =3D _SUNXI_CCU_DIV(16, 6), > + .fixed_post_div =3D 2, > + .sdm =3D _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24), > + 0x178, BIT(31)), > + .common =3D { > + .reg =3D 0x078, > + .features =3D CCU_FEATURE_FIXED_POSTDIV | > + CCU_FEATURE_SIGMA_DELTA_MOD, > + .hw.init =3D CLK_HW_INIT("pll-audio", "dcxo24M", > + &ccu_nm_ops, > + CLK_SET_RATE_UNGATE), > + }, > +}; > + > +static const char * const cpux_parents[] =3D { "dcxo24M", "osc32k", > + "iosc", "pll-cpux", > + "pll-periph0" }; > +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, > + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); > +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0); > +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0); > + > +static const char * const psi_ahb1_ahb2_parents[] =3D { "dcxo24M", "osc3= 2k", > + "iosc", "pll-periph0", > + "pll-periph0-2x" }; > +static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", > + psi_ahb1_ahb2_parents, > + 0x510, > + 0, 2, /* M */ > + 8, 2, /* P */ > + 24, 3, /* mux */ > + 0); > + > +static const char * const ahb3_apb1_apb2_parents[] =3D { "dcxo24M", "osc= 32k", > + "psi-ahb1-ahb2", > + "pll-periph0", > + "pll-periph0-2x" }; > +static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0= x51c, > + 0, 2, /* M */ > + 8, 2, /* P */ > + 24, 3, /* mux */ > + 0); > + > +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0= x520, > + 0, 2, /* M */ > + 8, 2, /* P */ > + 24, 3, /* mux */ > + 0); > + > +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0= x524, > + 0, 2, /* M */ > + 8, 2, /* P */ > + 24, 3, /* mux */ > + 0); > + > +static const char * const mbus_parents[] =3D { "dcxo24M", "pll-ddr0", > + "pll-periph0", > + "pll-periph0-2x" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540, > + 0, 3, /* M */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + CLK_IS_CRITICAL); > + > +static const char * const de_parents[] =3D { "pll-com", "pll-periph0-2x"= }; > +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de0", de_parents, 0x600, > + 0, 4, /* M */ > + 24, 1, /* mux */ > + BIT(31), /* gate */ > + CLK_SET_RATE_PARENT); > + > +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2", > + 0x60c, BIT(0), 0); > + > +static const char * const g2d_parents[] =3D { "pll-com", "pll-periph0-2x= ", > + "pll-video0-2x", "pll-video1-2x", > + "pll-video2-2x"}; > +static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", > + g2d_parents, > + 0x630, > + 0, 4, /* M */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2", > + 0x63c, BIT(0), 0); > + > +static const char * const gpu_parents[] =3D { "pll-gpu" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670, > + 0, 2, /* M */ > + 24, 1, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", > + 0x67c, BIT(0), 0); > + > +static const char * const ce_parents[] =3D { "dcxo24M", "pll-periph0-2x"= }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 1, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2", > + 0x68c, BIT(0), 0); > + > +static const char * const ve_parents[] =3D { "pll-ve" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, > + 0, 3, /* M */ > + 24, 1, /* mux */ > + BIT(31), /* gate */ > + CLK_SET_RATE_PARENT); > + > +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2", > + 0x69c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2", > + 0x70c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "psi-ahb1-ahb2", > + 0x71c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "psi-ahb1-ahb2", > + 0x72c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2", > + 0x73c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(avs_clk, "avs", "dcxo24M", 0x740, BIT(31), 0); > + > +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", > + 0x78c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", > + 0x79c, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0),= 0); > + > +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus", > + 0x804, BIT(0), 0); > +static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus", > + 0x804, BIT(1), 0); > +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus", > + 0x804, BIT(2), 0); > +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus", > + 0x804, BIT(5), 0); > +static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi", "mbus", > + 0x804, BIT(8), 0); > +static SUNXI_CCU_GATE(mbus_isp_clk, "mbus-isp", "mbus", > + 0x804, BIT(9), 0); > +static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus", > + 0x804, BIT(10), 0); > + > +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2", > + 0x80c, BIT(0), CLK_IS_CRITICAL); > + > +static const char * const nand_spi_parents[] =3D { "dcxo24M", > + "pll-periph0", > + "pll-periph1", > + "pll-periph0-2x", > + "pll-periph1-2x" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, = 0x810, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, = 0x814, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0= ); > + > +/* don't use postdiv for bsp kernel */ > +static const char * const mmc_parents[] =3D { "dcxo24M", "pll-periph0-2x= ", > + "pll-periph1-2x" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_parents, 0x830, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + CLK_SET_RATE_NO_REPARENT); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_parents, 0x834, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + CLK_SET_RATE_NO_REPARENT); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_parents, 0x838, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + CLK_SET_RATE_NO_REPARENT); > + > +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0= ); > +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0= ); > +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0= ); > + > +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0),= 0); > +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1),= 0); > +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2),= 0); > +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3),= 0); > +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4),= 0); > + > +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0= ); > +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0= ); > +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0= ); > +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0= ); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x= 940, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x= 944, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", nand_spi_parents, 0x= 948, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0= ); > +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0= ); > +static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb3", 0x96c, BIT(2), 0= ); > + > +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970, > + BIT(31) | BIT(30), 0); > + > +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb3", 0x97c, BIT(0), 0= ); > + > +static const char * const ir_parents[] =3D { "osc32k", "iosc", > + "pll-periph0", "pll-periph1" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "ahb3", 0x99c, BIT(0),= 0); > + > +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0),= 0); > + > +static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc", "apb1", 0x9ec, BIT(0),= 0); > + > +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0); > + > +static const char * const audio_parents[] =3D { "pll-audio", "pll-com-au= dio" }; > +static struct ccu_div i2s0_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa10, > + .hw.init =3D CLK_HW_INIT_PARENTS("i2s0", > + audio_parents, > + &ccu_div_ops, > + CLK_SET_RATE_PARENT), > + }, > +}; > + > +static struct ccu_div i2s1_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa14, > + .hw.init =3D CLK_HW_INIT_PARENTS("i2s1", > + audio_parents, > + &ccu_div_ops, > + CLK_SET_RATE_PARENT), > + }, > +}; > + > +static struct ccu_div i2s2_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa18, > + .hw.init =3D CLK_HW_INIT_PARENTS("i2s2", > + audio_parents, > + &ccu_div_ops, > + CLK_SET_RATE_PARENT), > + }, > +}; > + > +static struct ccu_div i2s3_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa1c, > + .hw.init =3D CLK_HW_INIT_PARENTS("i2s3", > + audio_parents, > + &ccu_div_ops, > + CLK_SET_RATE_PARENT), > + }, > +}; > + > +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0= ); > +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0= ); > +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", 0xa20, BIT(2), 0= ); > +static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3", "apb1", 0xa20, BIT(3), 0= ); > + > +static struct ccu_div spdif_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa24, > + .hw.init =3D CLK_HW_INIT_PARENTS("spdif", > + audio_parents, > + &ccu_div_ops, > + 0), > + }, > +}; > + > +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0),= 0); > + > +static struct ccu_div dmic_clk =3D { > + .enable =3D BIT(31), > + .div =3D _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), > + .mux =3D _SUNXI_CCU_MUX(24, 2), > + .common =3D { > + .reg =3D 0xa40, > + .hw.init =3D CLK_HW_INIT_PARENTS("dmic", > + audio_parents, > + &ccu_div_ops, > + 0), > + }, > +}; > + > +static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0= ); > + > +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", > + audio_parents, 0xa50, > + 0, 4, /* M */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", > + audio_parents, 0xa54, > + 0, 4, /* M */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x", > + audio_parents, 0xa58, > + 0, 4, /* M */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0x= a5c, > + BIT(0), 0); > + > +/* > + * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports. > + * We will force them to 0 (12M divided from 48M). > + */ > +#define SUN50I_A100_USB0_CLK_REG 0xa70 > +#define SUN50I_A100_USB1_CLK_REG 0xa74 > + > +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(3= 1), 0); > +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "dcxo24M", 0xa70, BIT(29= ), 0); > + > +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(3= 1), 0); > +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "dcxo24M", 0xa74, BIT(29= ), 0); > + > +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0),= 0); > +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1),= 0); > +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4),= 0); > +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5),= 0); > +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0); > + > +static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc", "ahb3", 0xa9c, BIT(0),= 0); > + > +static SUNXI_CCU_GATE(bus_dpss_top0_clk, "bus-dpss-top0", "ahb3", > + 0xabc, BIT(0), 0); > + > +static SUNXI_CCU_GATE(bus_dpss_top1_clk, "bus-dpss-top1", "ahb3", > + 0xacc, BIT(0), 0); > + > +static const char * const mipi_dsi_parents[] =3D { "dcxo24M", "pll-perip= h0-2x", > + "pll-periph0" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", > + mipi_dsi_parents, > + 0xb24, > + 0, 4, /* M */ > + 24, 2, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb3", > + 0xb4c, BIT(0), 0); > + > +static const char * const tcon_lcd_parents[] =3D { "pll-video0-4x", > + "pll-video1-4x", > + "pll-video2-4x", > + "pll-video3-4x", > + "pll-periph0-2x" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd0", > + tcon_lcd_parents, 0xb60, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_tcon_lcd_clk, "bus-tcon-lcd0", "ahb3", > + 0xb7c, BIT(0), 0); > + > +static const char * const ledc_parents[] =3D { "dcxo24M", > + "pll-periph0" }; > +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", > + ledc_parents, 0xbf0, > + 0, 4, /* M */ > + 8, 2, /* N */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "ahb3", 0xbfc, BIT(0), 0= ); > + > +static const char * const csi_top_parents[] =3D { "pll-periph0-2x", > + "pll-video0-2x", > + "pll-video1-2x", > + "pll-video2-2x", > + "pll-video3-2x" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(csi_top_clk, "csi-top", > + csi_top_parents, 0xc04, > + 0, 4, /* M */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static const char * const csi0_mclk_parents[] =3D { "dcxo24M", "pll-vide= o2", > + "pll-video3", "pll-video0", > + "pll-video1" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", > + csi0_mclk_parents, 0xc08, > + 0, 5, /* M */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static const char * const csi1_mclk_parents[] =3D { "dcxo24M", "pll-vide= o3", > + "pll-video0", "pll-video1", > + "pll-video2" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", > + csi1_mclk_parents, 0xc0c, > + 0, 5, /* M */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb3", 0xc1c, BIT(0), 0); > + > +static const char * const csi_isp_parents[] =3D { "pll-periph0-2x", > + "pll-video0-2x", > + "pll-video1-2x", > + "pll-video2-2x", > + "pll-video3-2x" }; > +static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp", > + csi_isp_parents, 0xc20, > + 0, 5, /* M */ > + 24, 3, /* mux */ > + BIT(31), /* gate */ > + 0); > + > +/* Fixed factor clocks */ > +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0); > + > +static CLK_FIXED_FACTOR_HW(pll_com_audio_clk, "pll-com-audio", > + &pll_com_clk.common.hw, > + 5, 1, CLK_SET_RATE_PARENT); > + > +static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x", > + &pll_periph0_clk.common.hw, > + 1, 2, 0); > + > +static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x", > + &pll_periph1_clk.common.hw, > + 1, 2, 0); > + > +static const struct clk_hw *pll_video0_parents[] =3D { > + &pll_video0_clk.common.hw > +}; > +static CLK_FIXED_FACTOR_HWS(pll_video0_4x_clk, "pll-video0-4x", > + pll_video0_parents, > + 1, 4, CLK_SET_RATE_PARENT); > +static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x", > + pll_video0_parents, > + 1, 2, CLK_SET_RATE_PARENT); > + > +static const struct clk_hw *pll_video1_parents[] =3D { > + &pll_video1_clk.common.hw > +}; > +static CLK_FIXED_FACTOR_HWS(pll_video1_4x_clk, "pll-video1-4x", > + pll_video1_parents, > + 1, 4, CLK_SET_RATE_PARENT); > +static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x", > + pll_video1_parents, > + 1, 2, CLK_SET_RATE_PARENT); > + > +static const struct clk_hw *pll_video2_parents[] =3D { > + &pll_video2_clk.common.hw > +}; > +static CLK_FIXED_FACTOR_HWS(pll_video2_4x_clk, "pll-video2-4x", > + pll_video2_parents, > + 1, 4, CLK_SET_RATE_PARENT); > +static CLK_FIXED_FACTOR_HWS(pll_video2_2x_clk, "pll-video2-2x", > + pll_video2_parents, > + 1, 2, CLK_SET_RATE_PARENT); > + > +static const struct clk_hw *pll_video3_parents[] =3D { > + &pll_video3_clk.common.hw > +}; > +static CLK_FIXED_FACTOR_HWS(pll_video3_4x_clk, "pll-video3-4x", > + pll_video3_parents, > + 1, 4, CLK_SET_RATE_PARENT); > +static CLK_FIXED_FACTOR_HWS(pll_video3_2x_clk, "pll-video3-2x", > + pll_video3_parents, > + 1, 2, CLK_SET_RATE_PARENT); > + > +static struct ccu_common *sun50i_a100_ccu_clks[] =3D { > + &pll_cpux_clk.common, > + &pll_ddr0_clk.common, > + &pll_periph0_clk.common, > + &pll_periph1_clk.common, > + &pll_gpu_clk.common, > + &pll_video0_clk.common, > + &pll_video1_clk.common, > + &pll_video2_clk.common, > + &pll_video3_clk.common, > + &pll_ve_clk.common, > + &pll_com_clk.common, > + &pll_audio_clk.common, > + &cpux_clk.common, > + &axi_clk.common, > + &cpux_apb_clk.common, > + &psi_ahb1_ahb2_clk.common, > + &ahb3_clk.common, > + &apb1_clk.common, > + &apb2_clk.common, > + &mbus_clk.common, > + &de_clk.common, > + &bus_de_clk.common, > + &g2d_clk.common, > + &bus_g2d_clk.common, > + &gpu_clk.common, > + &bus_gpu_clk.common, > + &ce_clk.common, > + &bus_ce_clk.common, > + &ve_clk.common, > + &bus_ve_clk.common, > + &bus_dma_clk.common, > + &bus_msgbox_clk.common, > + &bus_spinlock_clk.common, > + &bus_hstimer_clk.common, > + &avs_clk.common, > + &bus_dbg_clk.common, > + &bus_psi_clk.common, > + &bus_pwm_clk.common, > + &bus_iommu_clk.common, > + &mbus_dma_clk.common, > + &mbus_ve_clk.common, > + &mbus_ce_clk.common, > + &mbus_nand_clk.common, > + &mbus_csi_clk.common, > + &mbus_isp_clk.common, > + &mbus_g2d_clk.common, > + &bus_dram_clk.common, > + &nand0_clk.common, > + &nand1_clk.common, > + &bus_nand_clk.common, > + &mmc0_clk.common, > + &mmc1_clk.common, > + &mmc2_clk.common, > + &bus_mmc0_clk.common, > + &bus_mmc1_clk.common, > + &bus_mmc2_clk.common, > + &bus_uart0_clk.common, > + &bus_uart1_clk.common, > + &bus_uart2_clk.common, > + &bus_uart3_clk.common, > + &bus_uart4_clk.common, > + &bus_i2c0_clk.common, > + &bus_i2c1_clk.common, > + &bus_i2c2_clk.common, > + &bus_i2c3_clk.common, > + &spi0_clk.common, > + &spi1_clk.common, > + &spi2_clk.common, > + &bus_spi0_clk.common, > + &bus_spi1_clk.common, > + &bus_spi2_clk.common, > + &emac_25m_clk.common, > + &bus_emac_clk.common, > + &ir_rx_clk.common, > + &bus_ir_rx_clk.common, > + &ir_tx_clk.common, > + &bus_ir_tx_clk.common, > + &bus_gpadc_clk.common, > + &bus_ths_clk.common, > + &i2s0_clk.common, > + &i2s1_clk.common, > + &i2s2_clk.common, > + &i2s3_clk.common, > + &bus_i2s0_clk.common, > + &bus_i2s1_clk.common, > + &bus_i2s2_clk.common, > + &bus_i2s3_clk.common, > + &spdif_clk.common, > + &bus_spdif_clk.common, > + &dmic_clk.common, > + &bus_dmic_clk.common, > + &audio_codec_dac_clk.common, > + &audio_codec_adc_clk.common, > + &audio_codec_4x_clk.common, > + &bus_audio_codec_clk.common, > + &usb_ohci0_clk.common, > + &usb_phy0_clk.common, > + &usb_ohci1_clk.common, > + &usb_phy1_clk.common, > + &bus_ohci0_clk.common, > + &bus_ohci1_clk.common, > + &bus_ehci0_clk.common, > + &bus_ehci1_clk.common, > + &bus_otg_clk.common, > + &bus_lradc_clk.common, > + &bus_dpss_top0_clk.common, > + &bus_dpss_top1_clk.common, > + &mipi_dsi_clk.common, > + &bus_mipi_dsi_clk.common, > + &tcon_lcd_clk.common, > + &bus_tcon_lcd_clk.common, > + &ledc_clk.common, > + &bus_ledc_clk.common, > + &csi_top_clk.common, > + &csi0_mclk_clk.common, > + &csi1_mclk_clk.common, > + &bus_csi_clk.common, > + &csi_isp_clk.common, > +}; > + > +static struct clk_hw_onecell_data sun50i_a100_hw_clks =3D { > + .hws =3D { > + [CLK_OSC12M] =3D &osc12M_clk.hw, > + [CLK_PLL_CPUX] =3D &pll_cpux_clk.common.hw, > + [CLK_PLL_DDR0] =3D &pll_ddr0_clk.common.hw, > + [CLK_PLL_PERIPH0] =3D &pll_periph0_clk.common.hw, > + [CLK_PLL_PERIPH0_2X] =3D &pll_periph0_2x_clk.hw, > + [CLK_PLL_PERIPH1] =3D &pll_periph1_clk.common.hw, > + [CLK_PLL_PERIPH1_2X] =3D &pll_periph1_2x_clk.hw, > + [CLK_PLL_GPU] =3D &pll_gpu_clk.common.hw, > + [CLK_PLL_VIDEO0] =3D &pll_video0_clk.common.hw, > + [CLK_PLL_VIDEO0_2X] =3D &pll_video0_2x_clk.hw, > + [CLK_PLL_VIDEO0_4X] =3D &pll_video0_4x_clk.hw, > + [CLK_PLL_VIDEO1] =3D &pll_video1_clk.common.hw, > + [CLK_PLL_VIDEO1_2X] =3D &pll_video1_2x_clk.hw, > + [CLK_PLL_VIDEO1_4X] =3D &pll_video1_4x_clk.hw, > + [CLK_PLL_VIDEO2] =3D &pll_video2_clk.common.hw, > + [CLK_PLL_VIDEO2_2X] =3D &pll_video2_2x_clk.hw, > + [CLK_PLL_VIDEO2_4X] =3D &pll_video2_4x_clk.hw, > + [CLK_PLL_VIDEO3] =3D &pll_video3_clk.common.hw, > + [CLK_PLL_VIDEO3_2X] =3D &pll_video3_2x_clk.hw, > + [CLK_PLL_VIDEO3_4X] =3D &pll_video3_4x_clk.hw, > + [CLK_PLL_VE] =3D &pll_ve_clk.common.hw, > + [CLK_PLL_COM] =3D &pll_com_clk.common.hw, > + [CLK_PLL_COM_AUDIO] =3D &pll_com_audio_clk.hw, > + [CLK_PLL_AUDIO] =3D &pll_audio_clk.common.hw, > + [CLK_CPUX] =3D &cpux_clk.common.hw, > + [CLK_AXI] =3D &axi_clk.common.hw, > + [CLK_CPUX_APB] =3D &cpux_apb_clk.common.hw, > + [CLK_PSI_AHB1_AHB2] =3D &psi_ahb1_ahb2_clk.common.hw, > + [CLK_AHB3] =3D &ahb3_clk.common.hw, > + [CLK_APB1] =3D &apb1_clk.common.hw, > + [CLK_APB2] =3D &apb2_clk.common.hw, > + [CLK_MBUS] =3D &mbus_clk.common.hw, > + [CLK_DE] =3D &de_clk.common.hw, > + [CLK_BUS_DE] =3D &bus_de_clk.common.hw, > + [CLK_G2D] =3D &g2d_clk.common.hw, > + [CLK_BUS_G2D] =3D &bus_g2d_clk.common.hw, > + [CLK_GPU] =3D &gpu_clk.common.hw, > + [CLK_BUS_GPU] =3D &bus_gpu_clk.common.hw, > + [CLK_CE] =3D &ce_clk.common.hw, > + [CLK_BUS_CE] =3D &bus_ce_clk.common.hw, > + [CLK_VE] =3D &ve_clk.common.hw, > + [CLK_BUS_VE] =3D &bus_ve_clk.common.hw, > + [CLK_BUS_DMA] =3D &bus_dma_clk.common.hw, > + [CLK_BUS_MSGBOX] =3D &bus_msgbox_clk.common.hw, > + [CLK_BUS_SPINLOCK] =3D &bus_spinlock_clk.common.hw, > + [CLK_BUS_HSTIMER] =3D &bus_hstimer_clk.common.hw, > + [CLK_AVS] =3D &avs_clk.common.hw, > + [CLK_BUS_DBG] =3D &bus_dbg_clk.common.hw, > + [CLK_BUS_PSI] =3D &bus_psi_clk.common.hw, > + [CLK_BUS_PWM] =3D &bus_pwm_clk.common.hw, > + [CLK_BUS_IOMMU] =3D &bus_iommu_clk.common.hw, > + [CLK_MBUS_DMA] =3D &mbus_dma_clk.common.hw, > + [CLK_MBUS_VE] =3D &mbus_ve_clk.common.hw, > + [CLK_MBUS_CE] =3D &mbus_ce_clk.common.hw, > + [CLK_MBUS_NAND] =3D &mbus_nand_clk.common.hw, > + [CLK_MBUS_CSI] =3D &mbus_csi_clk.common.hw, > + [CLK_MBUS_ISP] =3D &mbus_isp_clk.common.hw, > + [CLK_MBUS_G2D] =3D &mbus_g2d_clk.common.hw, > + [CLK_BUS_DRAM] =3D &bus_dram_clk.common.hw, > + [CLK_NAND0] =3D &nand0_clk.common.hw, > + [CLK_NAND1] =3D &nand1_clk.common.hw, > + [CLK_BUS_NAND] =3D &bus_nand_clk.common.hw, > + [CLK_MMC0] =3D &mmc0_clk.common.hw, > + [CLK_MMC1] =3D &mmc1_clk.common.hw, > + [CLK_MMC2] =3D &mmc2_clk.common.hw, > + [CLK_BUS_MMC0] =3D &bus_mmc0_clk.common.hw, > + [CLK_BUS_MMC1] =3D &bus_mmc1_clk.common.hw, > + [CLK_BUS_MMC2] =3D &bus_mmc2_clk.common.hw, > + [CLK_BUS_UART0] =3D &bus_uart0_clk.common.hw, > + [CLK_BUS_UART1] =3D &bus_uart1_clk.common.hw, > + [CLK_BUS_UART2] =3D &bus_uart2_clk.common.hw, > + [CLK_BUS_UART3] =3D &bus_uart3_clk.common.hw, > + [CLK_BUS_UART4] =3D &bus_uart4_clk.common.hw, > + [CLK_BUS_I2C0] =3D &bus_i2c0_clk.common.hw, > + [CLK_BUS_I2C1] =3D &bus_i2c1_clk.common.hw, > + [CLK_BUS_I2C2] =3D &bus_i2c2_clk.common.hw, > + [CLK_BUS_I2C3] =3D &bus_i2c3_clk.common.hw, > + [CLK_SPI0] =3D &spi0_clk.common.hw, > + [CLK_SPI1] =3D &spi1_clk.common.hw, > + [CLK_SPI2] =3D &spi2_clk.common.hw, > + [CLK_BUS_SPI0] =3D &bus_spi0_clk.common.hw, > + [CLK_BUS_SPI1] =3D &bus_spi1_clk.common.hw, > + [CLK_BUS_SPI2] =3D &bus_spi2_clk.common.hw, > + [CLK_EMAC_25M] =3D &emac_25m_clk.common.hw, > + [CLK_BUS_EMAC] =3D &bus_emac_clk.common.hw, > + [CLK_IR_RX] =3D &ir_rx_clk.common.hw, > + [CLK_BUS_IR_RX] =3D &bus_ir_rx_clk.common.hw, > + [CLK_IR_TX] =3D &ir_tx_clk.common.hw, > + [CLK_BUS_IR_TX] =3D &bus_ir_tx_clk.common.hw, > + [CLK_BUS_GPADC] =3D &bus_gpadc_clk.common.hw, > + [CLK_BUS_THS] =3D &bus_ths_clk.common.hw, > + [CLK_I2S0] =3D &i2s0_clk.common.hw, > + [CLK_I2S1] =3D &i2s1_clk.common.hw, > + [CLK_I2S2] =3D &i2s2_clk.common.hw, > + [CLK_I2S3] =3D &i2s3_clk.common.hw, > + [CLK_BUS_I2S0] =3D &bus_i2s0_clk.common.hw, > + [CLK_BUS_I2S1] =3D &bus_i2s1_clk.common.hw, > + [CLK_BUS_I2S2] =3D &bus_i2s2_clk.common.hw, > + [CLK_BUS_I2S3] =3D &bus_i2s3_clk.common.hw, > + [CLK_SPDIF] =3D &spdif_clk.common.hw, > + [CLK_BUS_SPDIF] =3D &bus_spdif_clk.common.hw, > + [CLK_DMIC] =3D &dmic_clk.common.hw, > + [CLK_BUS_DMIC] =3D &bus_dmic_clk.common.hw, > + [CLK_AUDIO_DAC] =3D &audio_codec_dac_clk.common.hw, > + [CLK_AUDIO_ADC] =3D &audio_codec_adc_clk.common.hw, > + [CLK_AUDIO_4X] =3D &audio_codec_4x_clk.common.hw, > + [CLK_BUS_AUDIO_CODEC] =3D &bus_audio_codec_clk.common.hw, > + [CLK_USB_OHCI0] =3D &usb_ohci0_clk.common.hw, > + [CLK_USB_PHY0] =3D &usb_phy0_clk.common.hw, > + [CLK_USB_OHCI1] =3D &usb_ohci1_clk.common.hw, > + [CLK_USB_PHY1] =3D &usb_phy1_clk.common.hw, > + [CLK_BUS_OHCI0] =3D &bus_ohci0_clk.common.hw, > + [CLK_BUS_OHCI1] =3D &bus_ohci1_clk.common.hw, > + [CLK_BUS_EHCI0] =3D &bus_ehci0_clk.common.hw, > + [CLK_BUS_EHCI1] =3D &bus_ehci1_clk.common.hw, > + [CLK_BUS_OTG] =3D &bus_otg_clk.common.hw, > + [CLK_BUS_LRADC] =3D &bus_lradc_clk.common.hw, > + [CLK_BUS_DPSS_TOP0] =3D &bus_dpss_top0_clk.common.hw, > + [CLK_BUS_DPSS_TOP1] =3D &bus_dpss_top1_clk.common.hw, > + [CLK_MIPI_DSI] =3D &mipi_dsi_clk.common.hw, > + [CLK_BUS_MIPI_DSI] =3D &bus_mipi_dsi_clk.common.hw, > + [CLK_TCON_LCD] =3D &tcon_lcd_clk.common.hw, > + [CLK_BUS_TCON_LCD] =3D &bus_tcon_lcd_clk.common.hw, > + [CLK_LEDC] =3D &ledc_clk.common.hw, > + [CLK_BUS_LEDC] =3D &bus_ledc_clk.common.hw, > + [CLK_CSI_TOP] =3D &csi_top_clk.common.hw, > + [CLK_CSI0_MCLK] =3D &csi0_mclk_clk.common.hw, > + [CLK_CSI1_MCLK] =3D &csi1_mclk_clk.common.hw, > + [CLK_BUS_CSI] =3D &bus_csi_clk.common.hw, > + [CLK_CSI_ISP] =3D &csi_isp_clk.common.hw, > + }, > + .num =3D CLK_NUMBER, > +}; > + > +static struct ccu_reset_map sun50i_a100_ccu_resets[] =3D { > + [RST_MBUS] =3D { 0x540, BIT(30) }, > + > + [RST_BUS_DE] =3D { 0x60c, BIT(16) }, > + [RST_BUS_G2D] =3D { 0x63c, BIT(16) }, > + [RST_BUS_GPU] =3D { 0x67c, BIT(16) }, > + [RST_BUS_CE] =3D { 0x68c, BIT(16) }, > + [RST_BUS_VE] =3D { 0x69c, BIT(16) }, > + [RST_BUS_DMA] =3D { 0x70c, BIT(16) }, > + [RST_BUS_MSGBOX] =3D { 0x71c, BIT(16) }, > + [RST_BUS_SPINLOCK] =3D { 0x72c, BIT(16) }, > + [RST_BUS_HSTIMER] =3D { 0x73c, BIT(16) }, > + [RST_BUS_DBG] =3D { 0x78c, BIT(16) }, > + [RST_BUS_PSI] =3D { 0x79c, BIT(16) }, > + [RST_BUS_PWM] =3D { 0x7ac, BIT(16) }, > + [RST_BUS_DRAM] =3D { 0x80c, BIT(16) }, > + [RST_BUS_NAND] =3D { 0x82c, BIT(16) }, > + [RST_BUS_MMC0] =3D { 0x84c, BIT(16) }, > + [RST_BUS_MMC1] =3D { 0x84c, BIT(17) }, > + [RST_BUS_MMC2] =3D { 0x84c, BIT(18) }, > + [RST_BUS_UART0] =3D { 0x90c, BIT(16) }, > + [RST_BUS_UART1] =3D { 0x90c, BIT(17) }, > + [RST_BUS_UART2] =3D { 0x90c, BIT(18) }, > + [RST_BUS_UART3] =3D { 0x90c, BIT(19) }, > + [RST_BUS_UART4] =3D { 0x90c, BIT(20) }, > + [RST_BUS_I2C0] =3D { 0x91c, BIT(16) }, > + [RST_BUS_I2C1] =3D { 0x91c, BIT(17) }, > + [RST_BUS_I2C2] =3D { 0x91c, BIT(18) }, > + [RST_BUS_I2C3] =3D { 0x91c, BIT(19) }, > + [RST_BUS_SPI0] =3D { 0x96c, BIT(16) }, > + [RST_BUS_SPI1] =3D { 0x96c, BIT(17) }, > + [RST_BUS_SPI2] =3D { 0x96c, BIT(18) }, > + [RST_BUS_EMAC] =3D { 0x97c, BIT(16) }, > + [RST_BUS_IR_RX] =3D { 0x99c, BIT(16) }, > + [RST_BUS_IR_TX] =3D { 0x9cc, BIT(16) }, > + [RST_BUS_GPADC] =3D { 0x9ec, BIT(16) }, > + [RST_BUS_THS] =3D { 0x9fc, BIT(16) }, > + [RST_BUS_I2S0] =3D { 0xa20, BIT(16) }, > + [RST_BUS_I2S1] =3D { 0xa20, BIT(17) }, > + [RST_BUS_I2S2] =3D { 0xa20, BIT(18) }, > + [RST_BUS_I2S3] =3D { 0xa20, BIT(19) }, > + [RST_BUS_SPDIF] =3D { 0xa2c, BIT(16) }, > + [RST_BUS_DMIC] =3D { 0xa4c, BIT(16) }, > + [RST_BUS_AUDIO_CODEC] =3D { 0xa5c, BIT(16) }, > + > + [RST_USB_PHY0] =3D { 0xa70, BIT(30) }, > + [RST_USB_PHY1] =3D { 0xa74, BIT(30) }, > + > + [RST_BUS_OHCI0] =3D { 0xa8c, BIT(16) }, > + [RST_BUS_OHCI1] =3D { 0xa8c, BIT(17) }, > + [RST_BUS_EHCI0] =3D { 0xa8c, BIT(20) }, > + [RST_BUS_EHCI1] =3D { 0xa8c, BIT(21) }, > + [RST_BUS_OTG] =3D { 0xa8c, BIT(24) }, > + > + [RST_BUS_LRADC] =3D { 0xa9c, BIT(16) }, > + [RST_BUS_DPSS_TOP0] =3D { 0xabc, BIT(16) }, > + [RST_BUS_DPSS_TOP1] =3D { 0xacc, BIT(16) }, > + [RST_BUS_MIPI_DSI] =3D { 0xb4c, BIT(16) }, > + [RST_BUS_TCON_LCD] =3D { 0xb7c, BIT(16) }, > + [RST_BUS_LVDS] =3D { 0xbac, BIT(16) }, > + [RST_BUS_LEDC] =3D { 0xbfc, BIT(16) }, > + [RST_BUS_CSI] =3D { 0xc1c, BIT(16) }, > + [RST_BUS_CSI_ISP] =3D { 0xc2c, BIT(16) }, > +}; > + > +static const struct sunxi_ccu_desc sun50i_a100_ccu_desc =3D { > + .ccu_clks =3D sun50i_a100_ccu_clks, > + .num_ccu_clks =3D ARRAY_SIZE(sun50i_a100_ccu_clks), > + > + .hw_clks =3D &sun50i_a100_hw_clks, > + > + .resets =3D sun50i_a100_ccu_resets, > + .num_resets =3D ARRAY_SIZE(sun50i_a100_ccu_resets), > +}; > + > +static const u32 pll_regs[] =3D { > + SUN50I_A100_PLL_CPUX_REG, > + SUN50I_A100_PLL_DDR0_REG, > + SUN50I_A100_PLL_PERIPH0_REG, > + SUN50I_A100_PLL_PERIPH1_REG, > + SUN50I_A100_PLL_GPU_REG, > + SUN50I_A100_PLL_VIDEO0_REG, > + SUN50I_A100_PLL_VIDEO1_REG, > + SUN50I_A100_PLL_VIDEO2_REG, > + SUN50I_A100_PLL_VIDEO3_REG, > + SUN50I_A100_PLL_VE_REG, > + SUN50I_A100_PLL_COM_REG, > + SUN50I_A100_PLL_AUDIO_REG, > +}; > + > +static const u32 pll_video_regs[] =3D { > + SUN50I_A100_PLL_VIDEO0_REG, > + SUN50I_A100_PLL_VIDEO1_REG, > + SUN50I_A100_PLL_VIDEO2_REG, > + SUN50I_A100_PLL_VIDEO3_REG, > +}; > + > +static const u32 usb2_clk_regs[] =3D { > + SUN50I_A100_USB0_CLK_REG, > + SUN50I_A100_USB1_CLK_REG, > +}; Using the same prefix that we use everywhere else would be nice too. > +static struct ccu_pll_nb sun50i_a100_pll_cpu_nb =3D { > + .common =3D &pll_cpux_clk.common, > + /* copy from pll_cpux_clk */ > + .enable =3D BIT(27), > + .lock =3D BIT(28), > +}; > + > +static struct ccu_mux_nb sun50i_a100_cpu_nb =3D { > + .common =3D &cpux_clk.common, > + .cm =3D &cpux_clk.mux, > + .delay_us =3D 1, > + .bypass_index =3D 4, /* index of pll periph0 */ > +}; > + > +static int sun50i_a100_ccu_probe(struct platform_device *pdev) > +{ > + void __iomem *reg; > + u32 val; > + int i, ret; > + > + reg =3D devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(reg)) > + return PTR_ERR(reg); > + > + /* Enable the lock bits on all PLLs */ > + for (i =3D 0; i < ARRAY_SIZE(pll_regs); i++) { > + val =3D readl(reg + pll_regs[i]); > + val |=3D BIT(29); Having a define for that would be nice here > + writel(val, reg + pll_regs[i]); > + } > + > + /* > + * In order to pass the EMI certification, the SDM function of > + * the peripheral 1 bus is enabled, and the frequency is still > + * calculated using the previous division factor. > + */ > + writel(0xd1303333, reg + SUN50I_A100_PLL_PERIPH1_PATTERN0_REG); Same here > + val =3D readl(reg + SUN50I_A100_PLL_PERIPH1_REG); > + val |=3D BIT(24); > + writel(val, reg + SUN50I_A100_PLL_PERIPH1_REG); Same here > + /* > + * Force the output divider of video PLLs to 0. > + * > + * See the comment before pll-video0 definition for the reason. > + */ > + for (i =3D 0; i < ARRAY_SIZE(pll_video_regs); i++) { > + val =3D readl(reg + pll_video_regs[i]); > + val &=3D ~BIT(0); > + writel(val, reg + pll_video_regs[i]); > + } > + > + /* Enforce m1 =3D 0, m0 =3D 1 for Audio PLL */ Why? > + val =3D readl(reg + SUN50I_A100_PLL_AUDIO_REG); > + val &=3D ~BIT(1); > + val |=3D BIT(0); > + writel(val, reg + SUN50I_A100_PLL_AUDIO_REG); > + > + /* > + * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) > + * > + * This clock mux is still mysterious, and the code just enforces > + * it to have a valid clock parent. > + */ > + for (i =3D 0; i < ARRAY_SIZE(usb2_clk_regs); i++) { > + val =3D readl(reg + usb2_clk_regs[i]); > + val &=3D ~GENMASK(25, 24); > + writel(val, reg + usb2_clk_regs[i]); > + } > + > + ret =3D sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc); > + if (ret) > + return ret; > + > + /* Gate then ungate PLL CPU after any rate changes */ > + ccu_pll_notifier_register(&sun50i_a100_pll_cpu_nb); > + > + /* Reparent CPU during PLL CPU rate changes */ > + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, > + &sun50i_a100_cpu_nb); > + > + return 0; > +} > + > +static const struct of_device_id sun50i_a100_ccu_ids[] =3D { > + { .compatible =3D "allwinner,sun50i-a100-ccu" }, > + { } > +}; > + > +static struct platform_driver sun50i_a100_ccu_driver =3D { > + .probe =3D sun50i_a100_ccu_probe, > + .driver =3D { > + .name =3D "sun50i-a100-ccu", > + .of_match_table =3D sun50i_a100_ccu_ids, > + }, > +}; > +module_platform_driver(sun50i_a100_ccu_driver); > diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.h b/drivers/clk/sunxi-n= g/ccu-sun50i-a100.h > new file mode 100644 > index 000000000000..4fbf2e1a6697 > --- /dev/null > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.h > @@ -0,0 +1,14 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Frank Lee > + */ > + > +#ifndef _CCU_SUN50I_A100_H_ > +#define _CCU_SUN50I_A100_H_ > + > +#include > +#include > + > +#define CLK_NUMBER (CLK_CSI_ISP + 1) > + > +#endif /* _CCU_SUN50I_A100_H_ */ > diff --git a/include/dt-bindings/clock/sun50i-a100-ccu.h b/include/dt-bin= dings/clock/sun50i-a100-ccu.h > new file mode 100644 > index 000000000000..8186b1a7bcfe > --- /dev/null > +++ b/include/dt-bindings/clock/sun50i-a100-ccu.h > @@ -0,0 +1,141 @@ > +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ > +/* > + * Copyright (c) 2020 Frank Lee > + */ > + > +#ifndef _DT_BINDINGS_CLK_SUN50I_A100_H_ > +#define _DT_BINDINGS_CLK_SUN50I_A100_H_ > + > +#define CLK_OSC12M 0 > +#define CLK_PLL_CPUX 1 > +#define CLK_PLL_DDR0 2 > +#define CLK_PLL_PERIPH0 3 > +#define CLK_PLL_PERIPH0_2X 4 > +#define CLK_PLL_PERIPH1 5 > +#define CLK_PLL_PERIPH1_2X 6 > +#define CLK_PLL_GPU 7 > +#define CLK_PLL_VIDEO0 8 > +#define CLK_PLL_VIDEO0_2X 9 > +#define CLK_PLL_VIDEO0_4X 10 > +#define CLK_PLL_VIDEO1 11 > +#define CLK_PLL_VIDEO1_2X 12 > +#define CLK_PLL_VIDEO1_4X 13 > +#define CLK_PLL_VIDEO2 14 > +#define CLK_PLL_VIDEO2_2X 15 > +#define CLK_PLL_VIDEO2_4X 16 > +#define CLK_PLL_VIDEO3 17 > +#define CLK_PLL_VIDEO3_2X 18 > +#define CLK_PLL_VIDEO3_4X 19 > +#define CLK_PLL_VE 20 > +#define CLK_PLL_COM 21 > +#define CLK_PLL_COM_AUDIO 22 > +#define CLK_PLL_AUDIO 23 > +#define CLK_CPUX 24 > +#define CLK_AXI 25 > +#define CLK_CPUX_APB 26 > +#define CLK_PSI_AHB1_AHB2 27 > +#define CLK_AHB3 28 > +#define CLK_APB1 29 > +#define CLK_APB2 30 > +#define CLK_MBUS 31 > +#define CLK_DE 32 > +#define CLK_BUS_DE 33 > +#define CLK_G2D 34 > +#define CLK_BUS_G2D 35 > +#define CLK_GPU 36 > +#define CLK_BUS_GPU 37 > +#define CLK_CE 38 > +#define CLK_BUS_CE 39 > +#define CLK_VE 40 > +#define CLK_BUS_VE 41 > +#define CLK_BUS_DMA 42 > +#define CLK_BUS_MSGBOX 43 > +#define CLK_BUS_SPINLOCK 44 > +#define CLK_BUS_HSTIMER 45 > +#define CLK_AVS 46 > +#define CLK_BUS_DBG 47 > +#define CLK_BUS_PSI 48 > +#define CLK_BUS_PWM 49 > +#define CLK_BUS_IOMMU 50 > +#define CLK_MBUS_DMA 51 > +#define CLK_MBUS_VE 52 > +#define CLK_MBUS_CE 53 > +#define CLK_MBUS_NAND 54 > +#define CLK_MBUS_CSI 55 > +#define CLK_MBUS_ISP 56 > +#define CLK_MBUS_G2D 57 > +#define CLK_BUS_DRAM 58 > +#define CLK_NAND0 59 > +#define CLK_NAND1 60 > +#define CLK_BUS_NAND 61 > +#define CLK_MMC0 62 > +#define CLK_MMC1 63 > +#define CLK_MMC2 64 > +#define CLK_MMC3 65 > +#define CLK_BUS_MMC0 66 > +#define CLK_BUS_MMC1 67 > +#define CLK_BUS_MMC2 68 > +#define CLK_BUS_UART0 69 > +#define CLK_BUS_UART1 70 > +#define CLK_BUS_UART2 71 > +#define CLK_BUS_UART3 72 > +#define CLK_BUS_UART4 73 > +#define CLK_BUS_I2C0 74 > +#define CLK_BUS_I2C1 75 > +#define CLK_BUS_I2C2 76 > +#define CLK_BUS_I2C3 77 > +#define CLK_SPI0 78 > +#define CLK_SPI1 79 > +#define CLK_SPI2 80 > +#define CLK_BUS_SPI0 81 > +#define CLK_BUS_SPI1 82 > +#define CLK_BUS_SPI2 83 > +#define CLK_EMAC_25M 84 > +#define CLK_BUS_EMAC 85 > +#define CLK_IR_RX 86 > +#define CLK_BUS_IR_RX 87 > +#define CLK_IR_TX 88 > +#define CLK_BUS_IR_TX 89 > +#define CLK_BUS_GPADC 90 > +#define CLK_BUS_THS 91 > +#define CLK_I2S0 92 > +#define CLK_I2S1 93 > +#define CLK_I2S2 94 > +#define CLK_I2S3 95 > +#define CLK_BUS_I2S0 96 > +#define CLK_BUS_I2S1 97 > +#define CLK_BUS_I2S2 98 > +#define CLK_BUS_I2S3 99 > +#define CLK_SPDIF 100 > +#define CLK_BUS_SPDIF 101 > +#define CLK_DMIC 102 > +#define CLK_BUS_DMIC 103 > +#define CLK_AUDIO_DAC 104 > +#define CLK_AUDIO_ADC 105 > +#define CLK_AUDIO_4X 106 > +#define CLK_BUS_AUDIO_CODEC 107 > +#define CLK_USB_OHCI0 108 > +#define CLK_USB_PHY0 109 > +#define CLK_USB_OHCI1 110 > +#define CLK_USB_PHY1 111 > +#define CLK_BUS_OHCI0 112 > +#define CLK_BUS_OHCI1 113 > +#define CLK_BUS_EHCI0 114 > +#define CLK_BUS_EHCI1 115 > +#define CLK_BUS_OTG 116 > +#define CLK_BUS_LRADC 117 > +#define CLK_BUS_DPSS_TOP0 118 > +#define CLK_BUS_DPSS_TOP1 119 > +#define CLK_MIPI_DSI 120 > +#define CLK_BUS_MIPI_DSI 121 > +#define CLK_TCON_LCD 122 > +#define CLK_BUS_TCON_LCD 123 > +#define CLK_LEDC 124 > +#define CLK_BUS_LEDC 125 > +#define CLK_CSI_TOP 126 > +#define CLK_CSI0_MCLK 127 > +#define CLK_CSI1_MCLK 128 > +#define CLK_BUS_CSI 129 > +#define CLK_CSI_ISP 130 > + > +#endif /* _DT_BINDINGS_CLK_SUN50I_A100_H_ */ So we don't really want to expose all the clocks in the binding here, but o= nly the one that are going to be used by the devices (and not the "internal" on= es), so that will be usually the bus gates and the module gates. If we need a PLL at some point, we can always export it, but that should be= the exception, not the default. > diff --git a/include/dt-bindings/clock/sun50i-a100-r-ccu.h b/include/dt-b= indings/clock/sun50i-a100-r-ccu.h > new file mode 100644 > index 000000000000..a4486c31924a > --- /dev/null > +++ b/include/dt-bindings/clock/sun50i-a100-r-ccu.h > @@ -0,0 +1,25 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright (c) 2020 Frank Lee > + */ > + > +#ifndef _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ > +#define _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ > + > +#define CLK_CPUS 0 > +#define CLK_R_AHB 1 > +#define CLK_R_APB1 2 > +#define CLK_R_APB2 3 > +#define CLK_R_APB1_TIMER 4 > +#define CLK_R_APB1_TWD 5 > +#define CLK_R_APB1_PWM 6 > +#define CLK_R_APB1_BUS_PWM 7 > +#define CLK_R_APB1_PPU 8 > +#define CLK_R_APB2_UART 9 > +#define CLK_R_APB2_I2C0 10 > +#define CLK_R_APB2_I2C1 11 > +#define CLK_R_APB1_IR 12 > +#define CLK_R_APB1_BUS_IR 13 > +#define CLK_R_AHB_BUS_RTC 14 > + > +#endif /* _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ */ Same story here Maxime --3gi2rcwjojrhvt23 Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCXsfsOwAKCRDj7w1vZxhR xV2QAQDpVzmo6iWcbyhnyZ+wBS0BjFgSIlEkzsJAQ7by9sZe4gEAxfGegMJadPBy P+1fNIn7+0w3/K5LAmDVDDoXV8IJvw0= =uvni -----END PGP SIGNATURE----- --3gi2rcwjojrhvt23--