Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] counter: stm32: clean up indentation issue
From: Colin King @ 2019-09-25  9:51 UTC (permalink / raw)
  To: Fabrice Gasnier, William Breathitt Gray, Maxime Coquelin,
	Alexandre Torgue, linux-iio, linux-stm32, linux-arm-kernel
  Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

There is an if statement that is indented one level too deeply,
remove the extraneous tabs.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/counter/stm32-timer-cnt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 644ba18a72ad..613dcccf79e1 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -219,8 +219,8 @@ static ssize_t stm32_count_enable_write(struct counter_device *counter,
 
 	if (enable) {
 		regmap_read(priv->regmap, TIM_CR1, &cr1);
-			if (!(cr1 & TIM_CR1_CEN))
-				clk_enable(priv->clk);
+		if (!(cr1 & TIM_CR1_CEN))
+			clk_enable(priv->clk);
 
 		regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
 				   TIM_CR1_CEN);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH] firmware: imx: Skip return value check for some special SCU firmware APIs
From: Anson Huang @ 2019-09-25 10:07 UTC (permalink / raw)
  To: shawnguo, s.hauer, kernel, festevam, aisheng.dong,
	leonard.crestez, linux-arm-kernel, linux-kernel
  Cc: Linux-imx

The SCU firmware does NOT always have return value stored in message
header's function element even the API has response data, those special
APIs are defined as void function in SCU firmware, so they should be
treated as return success always.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
---
	- This patch is based on the patch of https://patchwork.kernel.org/patch/11129553/
---
 drivers/firmware/imx/imx-scu.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c
index 869be7a..ced5b12 100644
--- a/drivers/firmware/imx/imx-scu.c
+++ b/drivers/firmware/imx/imx-scu.c
@@ -78,6 +78,11 @@ static int imx_sc_linux_errmap[IMX_SC_ERR_LAST] = {
 	-EIO,	 /* IMX_SC_ERR_FAIL */
 };
 
+static const struct imx_sc_rpc_msg whitelist[] = {
+	{ .svc = IMX_SC_RPC_SVC_MISC, .func = IMX_SC_MISC_FUNC_UNIQUE_ID },
+	{ .svc = IMX_SC_RPC_SVC_MISC, .func = IMX_SC_MISC_FUNC_GET_BUTTON_STATUS },
+};
+
 static struct imx_sc_ipc *imx_sc_ipc_handle;
 
 static inline int imx_sc_to_linux_errno(int errno)
@@ -157,11 +162,24 @@ static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
 	return 0;
 }
 
+static bool imx_scu_call_skip_return_value_check(uint8_t svc, uint8_t func)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(whitelist); i++)
+		if (svc == whitelist[i].svc &&
+			func == whitelist[i].func)
+			return true;
+
+	return false;
+}
+
 /*
  * RPC command/response
  */
 int imx_scu_call_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp)
 {
+	uint8_t saved_svc, saved_func;
 	struct imx_sc_rpc_msg *hdr;
 	int ret;
 
@@ -171,8 +189,11 @@ int imx_scu_call_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp)
 	mutex_lock(&sc_ipc->lock);
 	reinit_completion(&sc_ipc->done);
 
-	if (have_resp)
+	if (have_resp) {
 		sc_ipc->msg = msg;
+		saved_svc = ((struct imx_sc_rpc_msg *)msg)->svc;
+		saved_func = ((struct imx_sc_rpc_msg *)msg)->func;
+	}
 	sc_ipc->count = 0;
 	ret = imx_scu_ipc_write(sc_ipc, msg);
 	if (ret < 0) {
@@ -190,7 +211,16 @@ int imx_scu_call_rpc(struct imx_sc_ipc *sc_ipc, void *msg, bool have_resp)
 
 		/* response status is stored in hdr->func field */
 		hdr = msg;
-		ret = hdr->func;
+		/*
+		 * Some special SCU firmware APIs do NOT have return value
+		 * in hdr->func, but they do have response data, those special
+		 * APIs are defined as void function in SCU firmware, so they
+		 * should be treated as return success always.
+		 */
+		if (!imx_scu_call_skip_return_value_check(saved_svc, saved_func))
+			ret = hdr->func;
+		else
+			ret = 0;
 	}
 
 out:
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH v2 00/22] mtd: spi-nor: Quad Enable and (un)lock methods
From: Tudor.Ambarus @ 2019-09-25 10:11 UTC (permalink / raw)
  To: linux-mtd, jonas
  Cc: vigneshr, geert+renesas, andrew, richard, linux-kernel, vz,
	marek.vasut, linux-aspeed, boris.brezillon, linux-mediatek, joel,
	miquel.raynal, matthias.bgg, computersforpeace, dwmw2,
	linux-arm-kernel
In-Reply-To: <20190924074533.6618-1-tudor.ambarus@microchip.com>

Hi, Jonas,

s25fl512s is impacted by this patch set. Would you please do a little test to
see if everything is ok for your flash with these patches applied? I don't have
the flash, so I can't do the tests by myself. There is a possible test method
described below in the cover letter.

You can find the patches at
https://patchwork.ozlabs.org/project/linux-mtd/list/?series=132270 or at
https://github.com/ambarus/linux-0day, branch spi-nor/quad-enable-rework-v2.

Thank you,
ta

On 09/24/2019 10:45 AM, Tudor Ambarus - M18064 wrote:
> From: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> Patches 1 - 14 are just clean up patches for the Flash Register
> Operations.
> 
> Patches 15 - 22 deal with the Quad Enable and the (un)lock methods.
> Fixed the clearing of QE bit on (un)lock() operations. Reworked the
> Quad Enable methods and the disabling of the block write protection
> at power-up.
> 
> Again, this is just compile tested, I don't have (yet) a relevant
> spansion-like flash memory to test the (un)lock() methods, so I'll need
> your help for testing this patch set.
> 
> The patch set can be tested using mtd-utils:
> 1/ do a read-erase-write-read-back test immediately after boot, to check
> the spi_nor_unlock_all() method. The focus is on the erase/write
> methods, we want to see if the flash is unlocked at power-up.
>         mtd_debug read /dev/mtd-yours offset size read-file
>         hexdump read-file
>         mtd_debug erase /dev/mtd-yours offset size
>         dd if=/dev/urandom of=write-file bs=please-choose count=please-choose
>         mtd_debug write /dev/mtd-yours offset write-file-size write-file
>         mtd_debug read /dev/mtd-yours offset write-file-size read-file
>         sha1sum read-file write-file
> 2/ lock flash then try to erase/write it, to see if the lock works
>         flash_lock /dev/mtd-yours offset block-count
>         Do the read-erase-write-read-back test from 1/. The contents of
>         flash should not change in the erase and write steps.
> 3/ unlock flash and do the read-erase-write-read-back from 1/. The value of the
>    QEE should not change and you should be able to erase and write the flash.
>    Test 1/ should be successful.
> 
> v2:
> - Introduce spi_nor_write_16bit_cr_and_check() as per Vignesh's suggestion. The
>   Configuration Register contains bits that can be updated in future: FREEZE,
>   CMP. Provide a generic method that allows updating all bits of the
>   Configuration Register.
> - Fix SNOR_F_NO_READ_CR case in
>   "mtd: spi-nor: Rework the disabling of block write protection". When the flash
>   doesn't support the CR Read command, we make an assumption about the value of
>   the QE bit. In spi_nor_init(), call spi_nor_quad_enable() first, then
>   spi_nor_unlock_all(), so that at the spi_nor_unlock_all() time we can be sure
>   the QE bit has value one, because of the previous call to spi_nor_quad_enable().
> - Fix if statement in spi_nor_write_sr_and_check():
>   if (nor->flags & SNOR_F_HAS_16BIT_SR)
> - Fix documentation warnings.
> - New patch: "mtd: spi-nor: Check all the bits written, not just the BP ones".
> - Drop Global Unlock patches, will send them in a different patch set.
> 
> Tudor Ambarus (22):
>   mtd: spi-nor: hisi-sfc: Drop nor->erase NULL assignment
>   mtd: spi-nor: Introduce 'struct spi_nor_controller_ops'
>   mtd: spi-nor: cadence-quadspi: Fix cqspi_command_read() definition
>   mtd: spi-nor: Rename nor->params to nor->flash
>   mtd: spi-nor: Rework read_sr()
>   mtd: spi-nor: Rework read_fsr()
>   mtd: spi-nor: Rework read_cr()
>   mtd: spi-nor: Rework write_enable/disable()
>   mtd: spi-nor: Fix retlen handling in sst_write()
>   mtd: spi-nor: Rework write_sr()
>   mtd: spi-nor: Rework spi_nor_read/write_sr2()
>   mtd: spi-nor: Report error in spi_nor_xread_sr()
>   mtd: spi-nor: Void return type for spi_nor_clear_sr/fsr()
>   mtd: spi-nor: Drop duplicated new line
>   mtd: spi-nor: Drop spansion_quad_enable()
>   mtd: spi-nor: Fix errno on quad_enable methods
>   mtd: spi-nor: Check all the bits written, not just the BP ones
>   mtd: spi-nor: Fix clearing of QE bit on lock()/unlock()
>   mtd: spi-nor: Rework macronix_quad_enable()
>   mtd: spi-nor: Rework spansion(_no)_read_cr_quad_enable()
>   mtd: spi-nor: Update sr2_bit7_quad_enable()
>   mtd: spi-nor: Rework the disabling of block write protection
> 
>  drivers/mtd/spi-nor/aspeed-smc.c      |   23 +-
>  drivers/mtd/spi-nor/cadence-quadspi.c |   54 +-
>  drivers/mtd/spi-nor/hisi-sfc.c        |   23 +-
>  drivers/mtd/spi-nor/intel-spi.c       |   24 +-
>  drivers/mtd/spi-nor/mtk-quadspi.c     |   25 +-
>  drivers/mtd/spi-nor/nxp-spifi.c       |   23 +-
>  drivers/mtd/spi-nor/spi-nor.c         | 1716 ++++++++++++++++++---------------
>  include/linux/mtd/spi-nor.h           |   74 +-
>  8 files changed, 1058 insertions(+), 904 deletions(-)
> 
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 02/11] PCI: altera: Use pci_parse_request_of_pci_ranges()
From: Andrew Murray @ 2019-09-25 10:24 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, linux-pci, rfi, Bjorn Helgaas, Ley Foon Tan,
	linux-arm-kernel
In-Reply-To: <20190924214630.12817-3-robh@kernel.org>

On Tue, Sep 24, 2019 at 04:46:21PM -0500, Rob Herring wrote:
> Convert altera host bridge to use the common
> pci_parse_request_of_pci_ranges().
> 
> Cc: Ley Foon Tan <lftan@altera.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: rfi@lists.rocketboards.org
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  drivers/pci/controller/pcie-altera.c | 38 ++--------------------------
>  1 file changed, 2 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
> index d2497ca43828..2ed00babff5a 100644
> --- a/drivers/pci/controller/pcie-altera.c
> +++ b/drivers/pci/controller/pcie-altera.c
> @@ -670,39 +670,6 @@ static void altera_pcie_isr(struct irq_desc *desc)
>  	chained_irq_exit(chip, desc);
>  }
>  
> -static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
> -{
> -	int err, res_valid = 0;
> -	struct device *dev = &pcie->pdev->dev;
> -	struct resource_entry *win;
> -
> -	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
> -						    &pcie->resources, NULL);
> -	if (err)
> -		return err;
> -
> -	err = devm_request_pci_bus_resources(dev, &pcie->resources);
> -	if (err)
> -		goto out_release_res;
> -
> -	resource_list_for_each_entry(win, &pcie->resources) {
> -		struct resource *res = win->res;
> -
> -		if (resource_type(res) == IORESOURCE_MEM)
> -			res_valid |= !(res->flags & IORESOURCE_PREFETCH);
> -	}
> -
> -	if (res_valid)
> -		return 0;
> -
> -	dev_err(dev, "non-prefetchable memory resource required\n");
> -	err = -EINVAL;
> -
> -out_release_res:
> -	pci_free_resource_list(&pcie->resources);
> -	return err;
> -}
> -
>  static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
>  {
>  	struct device *dev = &pcie->pdev->dev;
> @@ -833,9 +800,8 @@ static int altera_pcie_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	INIT_LIST_HEAD(&pcie->resources);
> -
> -	ret = altera_pcie_parse_request_of_pci_ranges(pcie);
> +	ret = pci_parse_request_of_pci_ranges(dev, &pcie->resources,

Does it matter that we now map any given IO ranges whereas we didn't
previously?

As far as I can tell there are no users that pass an IO range, if they
did then with the existing code the probe would fail and they'd get
a "I/O range found for %pOF. Please provide an io_base pointer...".
However with the new code if any IO range was given (which would
probably represent a misconfiguration), then we'd proceed to map the
IO range. When that IO is used, who knows what would happen.

I wonder if there is a better way for a host driver to indicate that
it doesn't support IO?

Thanks,

Andrew Murray

> +					      NULL);
>  	if (ret) {
>  		dev_err(dev, "Failed add resources\n");
>  		return ret;
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* RE: [RFC PATCH v3 4/6] psci: Add hvc call service for ptp_kvm.
From: Jianyong Wu (Arm Technology China) @ 2019-09-25 10:27 UTC (permalink / raw)
  To: Paolo Bonzini, netdev@vger.kernel.org, yangbo.lu@nxp.com,
	john.stultz@linaro.org, tglx@linutronix.de,
	sean.j.christopherson@intel.com, maz@kernel.org,
	richardcochran@gmail.com, Mark Rutland, Will Deacon,
	Suzuki Poulose
  Cc: Justin He (Arm Technology China), kvm@vger.kernel.org,
	Steve Capper, linux-kernel@vger.kernel.org,
	Kaly Xin (Arm Technology China), nd,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <06264d8a-b9c0-5f19-db2c-6190976a2a05@redhat.com>

Hi Paolo,

> -----Original Message-----
> From: Paolo Bonzini <pbonzini@redhat.com>
> Sent: Tuesday, September 24, 2019 10:20 PM
> To: Jianyong Wu (Arm Technology China) <Jianyong.Wu@arm.com>;
> netdev@vger.kernel.org; yangbo.lu@nxp.com; john.stultz@linaro.org;
> tglx@linutronix.de; sean.j.christopherson@intel.com; maz@kernel.org;
> richardcochran@gmail.com; Mark Rutland <Mark.Rutland@arm.com>; Will
> Deacon <Will.Deacon@arm.com>; Suzuki Poulose
> <Suzuki.Poulose@arm.com>
> Cc: linux-kernel@vger.kernel.org; kvm@vger.kernel.org; Steve Capper
> <Steve.Capper@arm.com>; Kaly Xin (Arm Technology China)
> <Kaly.Xin@arm.com>; Justin He (Arm Technology China)
> <Justin.He@arm.com>; nd <nd@arm.com>; linux-arm-
> kernel@lists.infradead.org
> Subject: Re: [RFC PATCH v3 4/6] psci: Add hvc call service for ptp_kvm.
> 
> On 23/09/19 06:57, Jianyong Wu (Arm Technology China) wrote:
> >> On 19/09/19 11:46, Jianyong Wu (Arm Technology China) wrote:
> >>>> On 18/09/19 11:57, Jianyong Wu (Arm Technology China) wrote:
> >>>>> Paolo Bonzini wrote:
> >>>>>> This is not Y2038-safe.  Please use ktime_get_real_ts64 instead,
> >>>>>> and split the 64-bit seconds value between val[0] and val[1].
> >>>
> >>> Val[] should be long not u32 I think, so in arm64 I can avoid that
> >>> Y2038_safe, but also need rewrite for arm32.
> >>
> >> I don't think there's anything inherently wrong with u32 val[], and
> >> as you notice it lets you reuse code between arm and arm64.  It's up
> >> to you and Marc to decide.
> >>
> > To compatible 32-bit, Integrates second value and nanosecond value as
> > a nanosecond value then split it into val[0] and val[1] and split cycle value
> into val[2] and val[3],  In this way, time will overflow at Y2262.
> > WDYT?
> 
> So if I understand correctly you'd multiply by 10^9 (or better shift by
> 30) the nanoseconds.
> 
Yeah, 
> That works, but why not provide 5 output registers?  Alternatively, take an
> address as input and write there.

It will be easy,  if I could have expanded the store room. But these code is the infrastructure for hypercall, I can't change them at my will.
I think only value but pointer can delivered by smccc_set_retval call.

> 
> Finally, on x86 we added an argument for the CLOCK_* that is being read
> (currently only CLOCK_REALTIME, but having room for extensibility in the API
> is always nice).
> 
IMO, I will be limited by the design of hypercall on arm64, I can only design my code under it. maybe it will be better sometime but for now I could just obey it.

Thanks
Jianyong  Wu

> Paolo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 05/11] PCI: versatile: Use pci_parse_request_of_pci_ranges()
From: Andrew Murray @ 2019-09-25 10:37 UTC (permalink / raw)
  To: Rob Herring; +Cc: Bjorn Helgaas, linux-pci, Lorenzo Pieralisi, linux-arm-kernel
In-Reply-To: <20190924214630.12817-6-robh@kernel.org>

On Tue, Sep 24, 2019 at 04:46:24PM -0500, Rob Herring wrote:
> Convert ARM Versatile host bridge to use the common
> pci_parse_request_of_pci_ranges().
> 
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  drivers/pci/controller/pci-versatile.c | 62 +++++---------------------
>  1 file changed, 11 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/pci/controller/pci-versatile.c b/drivers/pci/controller/pci-versatile.c
> index f59ad2728c0b..237b1abb26f2 100644
> --- a/drivers/pci/controller/pci-versatile.c
> +++ b/drivers/pci/controller/pci-versatile.c
> @@ -62,60 +62,12 @@ static struct pci_ops pci_versatile_ops = {
>  	.write	= pci_generic_config_write,
>  };
>  
> -static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
> -						     struct list_head *res)
> -{
> -	int err, mem = 1, res_valid = 0;
> -	resource_size_t iobase;
> -	struct resource_entry *win, *tmp;
> -
> -	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, res, &iobase);
> -	if (err)
> -		return err;
> -
> -	err = devm_request_pci_bus_resources(dev, res);
> -	if (err)
> -		goto out_release_res;
> -
> -	resource_list_for_each_entry_safe(win, tmp, res) {
> -		struct resource *res = win->res;
> -
> -		switch (resource_type(res)) {
> -		case IORESOURCE_IO:
> -			err = devm_pci_remap_iospace(dev, res, iobase);
> -			if (err) {
> -				dev_warn(dev, "error %d: failed to map resource %pR\n",
> -					 err, res);
> -				resource_list_destroy_entry(win);
> -			}
> -			break;
> -		case IORESOURCE_MEM:
> -			res_valid |= !(res->flags & IORESOURCE_PREFETCH);
> -
> -			writel(res->start >> 28, PCI_IMAP(mem));
> -			writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
> -			mem++;
> -
> -			break;
> -		}
> -	}
> -
> -	if (res_valid)
> -		return 0;
> -
> -	dev_err(dev, "non-prefetchable memory resource required\n");
> -	err = -EINVAL;
> -
> -out_release_res:
> -	pci_free_resource_list(res);
> -	return err;
> -}
> -
>  static int versatile_pci_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	struct resource *res;
> -	int ret, i, myslot = -1;
> +	struct resource_entry *entry;
> +	int ret, i, myslot = -1, mem = 0;

I think 'mem' should be initialised to 1, at least that's what the original
code did. However I'm not sure why it should start from 1.

Thanks,

Andrew Murray

>  	u32 val;
>  	void __iomem *local_pci_cfg_base;
>  	struct pci_bus *bus, *child;
> @@ -141,10 +93,18 @@ static int versatile_pci_probe(struct platform_device *pdev)
>  	if (IS_ERR(versatile_cfg_base[1]))
>  		return PTR_ERR(versatile_cfg_base[1]);
>  
> -	ret = versatile_pci_parse_request_of_pci_ranges(dev, &pci_res);
> +	ret = pci_parse_request_of_pci_ranges(dev, &pci_res, NULL);
>  	if (ret)
>  		return ret;
>  
> +	resource_list_for_each_entry(entry, &pci_res) {
> +		if (resource_type(entry->res) == IORESOURCE_MEM) {
> +			writel(entry->res->start >> 28, PCI_IMAP(mem));
> +			writel(PHYS_OFFSET >> 28, PCI_SMAP(mem));
> +			mem++;
> +		}
> +	}
> +
>  	/*
>  	 * We need to discover the PCI core first to configure itself
>  	 * before the main PCI probing is performed
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: ARM core blob list
From: Maxime Ripard @ 2019-09-25 11:02 UTC (permalink / raw)
  To: Sergey Brutyan; +Cc: linux-arm-kernel
In-Reply-To: <7c52fab5-825a-b019-ec46-6fb731336cfe@ehayq.am>


[-- Attachment #1.1: Type: text/plain, Size: 898 bytes --]

On Fri, Sep 20, 2019 at 02:15:37PM +0400, Sergey Brutyan wrote:
> Dear all we are company of hard/soft design and integration mostly based
> on ARM cores.
> We are currently working on Libre Linux development for ARM based SBC.
>
> And ready to put professional effort for having complete blob-free Linux
> kernel, as we have done research there is most problem with bootloaders
> and Mali or PowerVR GPU units in SoC.
>
> We are looking forward to cooperate and  now have several need of
> information.
>
> Can you send us list for blob drivers for this SoC:
>
>     Allwinner A20
>     Allwinner R40

Aside from the Mali that you already mentionned (and wifi, usually,
depending on the board you're using), there's no blob involved on
those two SoCs.

And the Mali itself is being worked on as part of the lima effort, so
it shouldn't be a problem for very long.

Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v3 2/2] crypto: sun4i-ss: enable pm_runtime
From: Maxime Ripard @ 2019-09-25 11:05 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: herbert, linux-sunxi, linux-kernel, wens, linux-crypto, davem,
	linux-arm-kernel
In-Reply-To: <20190924080832.18694-3-clabbe.montjoie@gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 427 bytes --]

On Tue, Sep 24, 2019 at 10:08:32AM +0200, Corentin Labbe wrote:
> This patch enables power management on the Security System.
> sun4i-ss now depends on PM because it simplify code and prevent some ifdef.
> But this is not a problem since arch maintainer want ARCH_SUNXI to
> depend on PM in the future.
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>

Acked-by: Maxime Ripard <mripard@kernel.org>

Thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] arm64: dts: allwinner: a64: Drop PMU node
From: Maxime Ripard @ 2019-09-25 11:08 UTC (permalink / raw)
  To: Vasily Khoruzhick
  Cc: Mark Rutland, devicetree, Jared D . McNeill, Chen-Yu Tsai,
	Rob Herring, Harald Geyer, Robin Murphy, arm-linux
In-Reply-To: <CA+E=qVeArUV0u_17ty=HgaU35TwcBfQjSOJf0A5yM6L6+W-0Og@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 4868 bytes --]

On Mon, Sep 23, 2019 at 04:55:59PM -0700, Vasily Khoruzhick wrote:
> On Mon, Sep 23, 2019 at 4:51 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> >
> > On Mon, Aug 12, 2019 at 10:39 PM Maxime Ripard
> > <maxime.ripard@bootlin.com> wrote:
> > >
> > > On Mon, Aug 12, 2019 at 11:01:51AM -0700, Vasily Khoruzhick wrote:
> > > > On Mon, Aug 12, 2019 at 1:04 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > >
> > > > > On Thu, Aug 08, 2019 at 12:59:07PM -0700, Vasily Khoruzhick wrote:
> > > > > > On Thu, Aug 8, 2019 at 9:26 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > >
> > > > > > > On Wed, Aug 07, 2019 at 10:36:08AM -0700, Vasily Khoruzhick wrote:
> > > > > > > > On Wed, Aug 7, 2019 at 4:56 AM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > > > > > > > >
> > > > > > > > > On Tue, Aug 06, 2019 at 07:39:26PM -0700, Vasily Khoruzhick wrote:
> > > > > > > > > > On Tue, Aug 6, 2019 at 2:14 PM Robin Murphy <robin.murphy@arm.com> wrote:
> > > > > > > > > > >
> > > > > > > > > > > On 2019-08-06 9:52 pm, Vasily Khoruzhick wrote:
> > > > > > > > > > > > On Tue, Aug 6, 2019 at 1:19 PM Harald Geyer <harald@ccbib.org> wrote:
> > > > > > > > > > > >>
> > > > > > > > > > > >> Vasily Khoruzhick writes:
> > > > > > > > > > > >>> On Tue, Aug 6, 2019 at 7:35 AM Robin Murphy <robin.murphy@arm.com> wrote:
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>> On 06/08/2019 15:01, Vasily Khoruzhick wrote:
> > > > > > > > > > > >>>>> Looks like PMU in A64 is broken, it generates no interrupts at all and
> > > > > > > > > > > >>>>> as result 'perf top' shows no events.
> > > > > > > > > > > >>>>
> > > > > > > > > > > >>>> Does something like 'perf stat sleep 1' at least count cycles correctly?
> > > > > > > > > > > >>>> It could well just be that the interrupt numbers are wrong...
> > > > > > > > > > > >>>
> > > > > > > > > > > >>> Looks like it does, at least result looks plausible:
> > > > > > > > > > > >>
> > > > > > > > > > > >> I'm using perf stat regularly (cache benchmarks) and it works fine.
> > > > > > > > > > > >>
> > > > > > > > > > > >> Unfortunately I wasn't aware that perf stat is a poor test for
> > > > > > > > > > > >> the interrupts part of the node, when I added it. So I'm not too
> > > > > > > > > > > >> surprised I got it wrong.
> > > > > > > > > > > >>
> > > > > > > > > > > >> However, it would be unfortunate if the node got removed completely,
> > > > > > > > > > > >> because perf stat would not work anymore. Maybe we can only remove
> > > > > > > > > > > >> the interrupts or just fix them even if the HW doesn't work?
> > > > > > > > > > > >
> > > > > > > > > > > > I'm not familiar with PMU driver. Is it possible to get it working
> > > > > > > > > > > > without interrupts?
> > > > > > > > > > >
> > > > > > > > > > > Yup - you get a grumpy message from the driver, it will refuse sampling
> > > > > > > > > > > events (the ones which weren't working anyway), and if you measure
> > > > > > > > > > > anything for long enough that a counter overflows you'll get wonky
> > > > > > > > > > > results. But for counting hardware events over relatively short periods
> > > > > > > > > > > it'll still do the job.
> > > > > > > > > >
> > > > > > > > > > I tried to drop interrupts completely from the node but 'perf top' is
> > > > > > > > > > still broken. Though now in different way: it complains "cycles: PMU
> > > > > > > > > > Hardware doesn't support sampling/overflow-interrupts. Try 'perf
> > > > > > > > > > stat'"
> > > > > > > > >
> > > > > > > > > I have no idea if that's the culprit, but what is the state of the
> > > > > > > > > 0x09010000 register?
> > > > > > > >
> > > > > > > > What register is that and how do I check it?
> > > > > > >
> > > > > > > It's in the CPUX Configuration block, and the bits are labelled as CPU
> > > > > > > Debug Reset.
> > > > > > >
> > > > > > > And if you have busybox, you can use devmem.
> > > > > >
> > > > > > CPUX configuration block is at 0x01700000 according to A64 user
> > > > > > manual, and particular register you're interested in is at 0x01700080,
> > > > > > its value is 0x1110110F.
> > > > > >
> > > > > > Bits 16-19 are not defined in user manual and are not set.
> > > > >
> > > > > Sorry, I somehow thought this was for the H6...
> > > > >
> > > > > I don't have any idea then :/
> > > >
> > > > OK, so what should we do? 'perf top'/'perf record' work fine if PMU
> > > > node is dropped, but they don't work if PMU node is present (even with
> > > > interrupts dropped). I'd prefer to have 'perf top' and 'perf record'
> > > > working instead of 'perf stat'
> > >
> > > Well, it doesn't work so we should just remove the node, and if
> > > someone wants it back, they should figure it out.
> >
> > Hey Maxime,
> >
> > So can you merge this patch?
>
> Added new Maxime's email to CC

Queued as a fix for 5.4, thanks!
Maxime

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH] drm/rockchip: Add AFBC support
From: Daniel Vetter @ 2019-09-25 11:12 UTC (permalink / raw)
  To: Ayan Halder
  Cc: kernel@collabora.com, Tomeu Vizoso, David Airlie, Sean Paul,
	linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
	Andrzej Pietrasiewicz, linux-rockchip@lists.infradead.org,
	Maxime Ripard, nd, Ezequiel Garcia,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190925093500.GB21018@arm.com>

On Wed, Sep 25, 2019 at 11:35 AM Ayan Halder <Ayan.Halder@arm.com> wrote:
>
> On Mon, Sep 23, 2019 at 02:20:13PM +0200, Andrzej Pietrasiewicz wrote:
> > From: Ezequiel Garcia <ezequiel@collabora.com>
> >
> > AFBC is a proprietary lossless image compression protocol and format.
> > It helps reduce memory bandwidth of the graphics pipeline operations.
> > This, in turn, improves power efficiency.
> >
> > Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com>
> > [locking improvements]
> > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > [squashing the above, commit message and Rockchip AFBC modifier]
> > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> > ---
> >  drivers/gpu/drm/rockchip/rockchip_drm_fb.c  | 27 ++++++
> >  drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 94 ++++++++++++++++++++-
> >  drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 12 +++
> >  drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 18 ++++
> >  include/uapi/drm/drm_fourcc.h               |  3 +
> >  5 files changed, 151 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> > index 64ca87cf6d50..5178939a9c29 100644
> > --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> > @@ -24,6 +24,27 @@ static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
> >       .dirty         = drm_atomic_helper_dirtyfb,
> >  };
> >
> > +static int
> > +rockchip_verify_afbc_mod(struct drm_device *dev,
> > +                      const struct drm_mode_fb_cmd2 *mode_cmd)
> > +{
> > +     if (mode_cmd->modifier[0] &
> > +         ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
> > +             DRM_DEV_ERROR(dev->dev,
> > +                           "Unsupported format modifier 0x%llx\n",
> > +                           mode_cmd->modifier[0]);
> > +             return -EINVAL;
> > +     }
> > +
> > +     if (mode_cmd->width > 2560) {
> > +             DRM_DEV_ERROR(dev->dev,
> > +                           "Unsupported width %d\n", mode_cmd->width);
> > +             return -EINVAL;
> > +     }
> > +
> I think you are missing one additional check here.
> framebuffer width and height should be aligned to 16 pixels as you are
> using AFBC_FORMAT_MOD_BLOCK_SIZE_16x16.
> Please have a look at malidp_verify_afbc_framebuffer_caps()

Maybe time to extract that into a helper, so that there's only one
copy of the code that validates a buffer with afbc modifier set?
-Daniel

>
> > +     return 0;
> > +}
> > +
> >  static struct drm_framebuffer *
> >  rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
> >                 struct drm_gem_object **obj, unsigned int num_planes)
> > @@ -32,6 +53,12 @@ rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cm
> >       int ret;
> >       int i;
> >
> > +     if (mode_cmd->modifier[0]) {
> > +             ret = rockchip_verify_afbc_mod(dev, mode_cmd);
> > +             if (ret)
> > +                     return ERR_PTR(ret);
> > +     }
> > +
> >       fb = kzalloc(sizeof(*fb), GFP_KERNEL);
> >       if (!fb)
> >               return ERR_PTR(-ENOMEM);
> > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> > index 21b68eea46cc..50bf214d21da 100644
> > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> > @@ -46,6 +46,13 @@
> >               vop_reg_set(vop, &win->phy->scl->ext->name, \
> >                           win->base, ~0, v, #name)
> >
> > +#define VOP_AFBC_SET(x, name, v) \
> > +     do { \
> > +             if (vop->data->afbc) \
> > +                     vop_reg_set(vop, &vop->data->afbc->name, \
> > +                             0, ~0, v, #name); \
> > +     } while (0)
> > +
> >  #define VOP_WIN_YUV2YUV_SET(vop, win_yuv2yuv, name, v) \
> >       do { \
> >               if (win_yuv2yuv && win_yuv2yuv->name.mask) \
> > @@ -123,6 +130,8 @@ struct vop {
> >       struct drm_device *drm_dev;
> >       bool is_enabled;
> >
> > +     struct vop_win *afbc_win;
> > +
> >       struct completion dsp_hold_completion;
> >
> >       /* protected by dev->event_lock */
> > @@ -245,6 +254,30 @@ static bool has_rb_swapped(uint32_t format)
> >       }
> >  }
> >
> > +#define AFBC_FMT_RGB565        0x0
> > +#define AFBC_FMT_U8U8U8U8      0x5
> > +#define AFBC_FMT_U8U8U8        0x4
> > +
> > +static int vop_convert_afbc_format(uint32_t format)
> > +{
> > +     switch (format) {
> > +     case DRM_FORMAT_XRGB8888:
> > +     case DRM_FORMAT_ARGB8888:
> > +     case DRM_FORMAT_XBGR8888:
> > +     case DRM_FORMAT_ABGR8888:
> > +             return AFBC_FMT_U8U8U8U8;
> > +     case DRM_FORMAT_RGB888:
> > +     case DRM_FORMAT_BGR888:
> > +             return AFBC_FMT_U8U8U8;
> > +     case DRM_FORMAT_RGB565:
> > +     case DRM_FORMAT_BGR565:
> > +             return AFBC_FMT_RGB565;
> > +     default:
> > +             DRM_ERROR("unsupported afbc format[%08x]\n", format);
> > +             return -EINVAL;
> > +     }
> > +}
> > +
> >  static enum vop_data_format vop_convert_format(uint32_t format)
> >  {
> >       switch (format) {
> > @@ -587,10 +620,16 @@ static int vop_enable(struct drm_crtc *crtc)
> >
> >               vop_win_disable(vop, win);
> >       }
> > -     spin_unlock(&vop->reg_lock);
> > +
> > +     if (vop->data->afbc) {
> > +             VOP_AFBC_SET(vop, enable, 0);
> > +             vop->afbc_win = NULL;
> > +     }
> >
> >       vop_cfg_done(vop);
> >
> > +     spin_unlock(&vop->reg_lock);
> > +
> >       /*
> >        * At here, vop clock & iommu is enable, R/W vop regs would be safe.
> >        */
> > @@ -719,6 +758,32 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
> >               return -EINVAL;
> >       }
> >
> > +     if (fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
> > +             struct vop *vop = to_vop(crtc);
> > +
> > +             if (!vop->data->afbc) {
> > +                     DRM_ERROR("VOP does not support AFBC\n");
> > +                     return -EINVAL;
> > +             }
> > +
> > +             ret = vop_convert_afbc_format(fb->format->format);
> > +             if (ret < 0)
> > +                     return ret;
> > +
> > +             if (state->src.x1 || state->src.y1) {
> > +                     DRM_ERROR("AFBC does not support offset display\n");
> > +                     DRM_ERROR("xpos=%d, ypos=%d, offset=%d\n",
> > +                             state->src.x1, state->src.y1, fb->offsets[0]);
> > +                     return -EINVAL;
> > +             }
> > +
> > +             if (state->rotation && state->rotation != DRM_MODE_ROTATE_0) {
> > +                     DRM_ERROR("AFBC does not support rotation\n");
> > +                     DRM_ERROR("rotation=%d\n", state->rotation);
> > +                     return -EINVAL;
> > +             }
> > +     }
> > +
> >       return 0;
> >  }
> >
> > @@ -732,6 +797,9 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
> >       if (!old_state->crtc)
> >               return;
> >
> > +     if (vop->afbc_win == vop_win)
> > +             vop->afbc_win = NULL;
> > +
> >       spin_lock(&vop->reg_lock);
> >
> >       vop_win_disable(vop, win);
> > @@ -774,6 +842,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
> >       if (WARN_ON(!vop->is_enabled))
> >               return;
> >
> > +     if (vop->afbc_win == vop_win)
> > +             vop->afbc_win = NULL;
> > +
> >       if (!state->visible) {
> >               vop_plane_atomic_disable(plane, old_state);
> >               return;
> > @@ -808,6 +879,20 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
> >
> >       spin_lock(&vop->reg_lock);
> >
> > +     if (fb->modifier & DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP)) {
> > +             int afbc_format = vop_convert_afbc_format(fb->format->format);
> > +
> > +             VOP_AFBC_SET(vop, format, afbc_format | 1 << 4);
> > +             VOP_AFBC_SET(vop, hreg_block_split, 0);
> > +             VOP_AFBC_SET(vop, win_sel, win_index);
> > +             VOP_AFBC_SET(vop, hdr_ptr, dma_addr);
> > +             VOP_AFBC_SET(vop, pic_size, act_info);
> > +
> > +             vop->afbc_win = vop_win;
> > +
> > +             pr_info("AFBC on plane %s\n", plane->name);
> > +     }
> > +
> >       VOP_WIN_SET(vop, win, format, format);
> >       VOP_WIN_SET(vop, win, yrgb_vir, DIV_ROUND_UP(fb->pitches[0], 4));
> >       VOP_WIN_SET(vop, win, yrgb_mst, dma_addr);
> > @@ -1163,6 +1248,7 @@ static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
> >
> >       spin_lock(&vop->reg_lock);
> >
> > +     VOP_AFBC_SET(vop, enable, vop->afbc_win ? 0x1 : 0);
> >       vop_cfg_done(vop);
> >
> >       spin_unlock(&vop->reg_lock);
> > @@ -1471,7 +1557,8 @@ static int vop_create_crtc(struct vop *vop)
> >                                              0, &vop_plane_funcs,
> >                                              win_data->phy->data_formats,
> >                                              win_data->phy->nformats,
> > -                                            NULL, win_data->type, NULL);
> > +                                            win_data->phy->format_modifiers,
> > +                                            win_data->type, NULL);
> >               if (ret) {
> >                       DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
> >                                     ret);
> > @@ -1511,7 +1598,8 @@ static int vop_create_crtc(struct vop *vop)
> >                                              &vop_plane_funcs,
> >                                              win_data->phy->data_formats,
> >                                              win_data->phy->nformats,
> > -                                            NULL, win_data->type, NULL);
> > +                                            win_data->phy->format_modifiers,
> > +                                            win_data->type, NULL);
> >               if (ret) {
> >                       DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
> >                                     ret);
> > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
> > index 2149a889c29d..dc8b12025269 100644
> > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
> > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
> > @@ -77,6 +77,16 @@ struct vop_misc {
> >       struct vop_reg global_regdone_en;
> >  };
> >
> > +struct vop_afbc {
> > +     struct vop_reg enable;
> > +     struct vop_reg win_sel;
> > +     struct vop_reg format;
> > +     struct vop_reg hreg_block_split;
> > +     struct vop_reg pic_size;
> > +     struct vop_reg hdr_ptr;
> > +     struct vop_reg rstn;
> > +};
> > +
> >  struct vop_intr {
> >       const int *intrs;
> >       uint32_t nintrs;
> > @@ -128,6 +138,7 @@ struct vop_win_phy {
> >       const struct vop_scl_regs *scl;
> >       const uint32_t *data_formats;
> >       uint32_t nformats;
> > +     const uint64_t *format_modifiers;
> >
> >       struct vop_reg enable;
> >       struct vop_reg gate;
> > @@ -169,6 +180,7 @@ struct vop_data {
> >       const struct vop_output *output;
> >       const struct vop_win_yuv2yuv_data *win_yuv2yuv;
> >       const struct vop_win_data *win;
> > +     const struct vop_afbc *afbc;
> >       unsigned int win_size;
> >
> >  #define VOP_FEATURE_OUTPUT_RGB10     BIT(0)
> > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
> > index 7b9c74750f6d..e9ff0c43c396 100644
> > --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
> > +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
> > @@ -30,6 +30,12 @@
> >  #define VOP_REG_MASK_SYNC(off, _mask, _shift) \
> >               _VOP_REG(off, _mask, _shift, true, false)
> >
> > +static const uint64_t format_modifiers_afbc[] = {
> > +     DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_ROCKCHIP),
> > +     DRM_FORMAT_MOD_LINEAR,
> > +     DRM_FORMAT_MOD_INVALID
> > +};
> > +
> >  static const uint32_t formats_win_full[] = {
> >       DRM_FORMAT_XRGB8888,
> >       DRM_FORMAT_ARGB8888,
> > @@ -667,6 +673,7 @@ static const struct vop_win_phy rk3368_win01_data = {
> >       .scl = &rk3288_win_full_scl,
> >       .data_formats = formats_win_full,
> >       .nformats = ARRAY_SIZE(formats_win_full),
> > +     .format_modifiers = format_modifiers_afbc,
> >       .enable = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 0),
> >       .format = VOP_REG(RK3368_WIN0_CTRL0, 0x7, 1),
> >       .rb_swap = VOP_REG(RK3368_WIN0_CTRL0, 0x1, 12),
> > @@ -758,6 +765,16 @@ static const struct vop_data rk3366_vop = {
> >       .win_size = ARRAY_SIZE(rk3368_vop_win_data),
> >  };
> >
> > +static const struct vop_afbc rk3399_afbc = {
> > +     .rstn = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 3),
> > +     .enable = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 0),
> > +     .win_sel = VOP_REG(RK3399_AFBCD0_CTRL, 0x3, 1),
> > +     .format = VOP_REG(RK3399_AFBCD0_CTRL, 0x1f, 16),
> > +     .hreg_block_split = VOP_REG(RK3399_AFBCD0_CTRL, 0x1, 21),
> > +     .hdr_ptr = VOP_REG(RK3399_AFBCD0_HDR_PTR, 0xffffffff, 0),
> > +     .pic_size = VOP_REG(RK3399_AFBCD0_PIC_SIZE, 0xffffffff, 0),
> > +};
> > +
> >  static const struct vop_output rk3399_output = {
> >       .dp_pin_pol = VOP_REG(RK3399_DSP_CTRL1, 0xf, 16),
> >       .rgb_pin_pol = VOP_REG(RK3368_DSP_CTRL1, 0xf, 16),
> > @@ -808,6 +825,7 @@ static const struct vop_data rk3399_vop_big = {
> >       .modeset = &rk3288_modeset,
> >       .output = &rk3399_output,
> >       .misc = &rk3368_misc,
> > +     .afbc = &rk3399_afbc,
> >       .win = rk3368_vop_win_data,
> >       .win_size = ARRAY_SIZE(rk3368_vop_win_data),
> >       .win_yuv2yuv = rk3399_vop_big_win_yuv2yuv_data,
> > diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
> > index 3feeaa3f987a..ba6caf06c824 100644
> > --- a/include/uapi/drm/drm_fourcc.h
> > +++ b/include/uapi/drm/drm_fourcc.h
> > @@ -742,6 +742,9 @@ extern "C" {
> >   */
> >  #define AFBC_FORMAT_MOD_BCH     (1ULL << 11)
> >
> > +#define AFBC_FORMAT_MOD_ROCKCHIP \
> > +     (AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE)
> > +
> >  /*
> >   * Allwinner tiled modifier
> >   *
> > --
> > 2.17.1
> >
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 0/5] arm64: KVM: Add workaround for errata 1319367 and 1319537
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry

Similarily to erratum 1165522 that affects Cortex-A76, our good old
friends A57 and A72 respectively suffer from errata 1319367 and
1319537, potentially resulting in TLB corruption if the CPU speculates
an AT instruction while switching guests.

The fix is slightly more involved since we don't have VHE to help us
here, but the idea is the same: When switching a guest in, we must
prevent any speculated AT from being able to parse the page tables
until S2 is up and running. Only at this stage can we allow AT to take
place.

For this, we always restore the guest sysregs first, except for its
SCTLR and TCR registers, which must be set with SCTLR.M=1 and
TCR.EPD{0,1} = {1, 1}, effectively disabling the PTW and TLB
allocation. Once S2 is setup, we restore the guest's SCTLR and
TCR. Similar things must be done on TLB invalidation... Fun.

This has been tested on an AMD Seattle box.

Marc Zyngier (5):
  arm64: Add ARM64_WORKAROUND_1319367 for all A57 and A72 versions
  arm64: KVM: Reorder system register restoration and stage-2 activation
  arm64: KVM: Disable EL1 PTW when invalidating S2 TLBs
  arm64: KVM: Prevent speculative S1 PTW when restoring vcpu context
  arm64: Enable and document ARM errata 1319367 and 1319537

 Documentation/arm64/silicon-errata.rst |  4 +++
 arch/arm64/Kconfig                     | 10 ++++++
 arch/arm64/include/asm/cpucaps.h       |  3 +-
 arch/arm64/kernel/cpu_errata.c         | 13 +++++--
 arch/arm64/kvm/hyp/switch.c            | 48 ++++++++++++++++++++++----
 arch/arm64/kvm/hyp/sysreg-sr.c         | 14 ++++++--
 arch/arm64/kvm/hyp/tlb.c               | 23 ++++++++++++
 7 files changed, 103 insertions(+), 12 deletions(-)

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/5] arm64: Add ARM64_WORKAROUND_1319367 for all A57 and A72 versions
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry
In-Reply-To: <20190925111941.88103-1-maz@kernel.org>

Rework the EL2 vector hardening that is only selected for A57 and A72
so that the table can also be used for ARM64_WORKAROUND_1319367.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/include/asm/cpucaps.h |  3 ++-
 arch/arm64/kernel/cpu_errata.c   | 13 ++++++++++---
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index f19fe4b9acc4..277e37b2a513 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -52,7 +52,8 @@
 #define ARM64_HAS_IRQ_PRIO_MASKING		42
 #define ARM64_HAS_DCPODP			43
 #define ARM64_WORKAROUND_1463225		44
+#define ARM64_WORKAROUND_1319367		45
 
-#define ARM64_NCAPS				45
+#define ARM64_NCAPS				46
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 1e43ba5c79b7..1640c988d5a1 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -623,9 +623,9 @@ check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
 	return (need_wa > 0);
 }
 
-#ifdef CONFIG_HARDEN_EL2_VECTORS
+#if defined(CONFIG_HARDEN_EL2_VECTORS) || defined(CONFIG_ARM64_ERRATUM_1319367)
 
-static const struct midr_range arm64_harden_el2_vectors[] = {
+static const struct midr_range ca57_a72[] = {
 	MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
 	MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
 	{},
@@ -819,7 +819,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 	{
 		.desc = "EL2 vector hardening",
 		.capability = ARM64_HARDEN_EL2_VECTORS,
-		ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors),
+		ERRATA_MIDR_RANGE_LIST(ca57_a72),
 	},
 #endif
 	{
@@ -851,6 +851,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
 		.matches = has_cortex_a76_erratum_1463225,
 	},
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1319367
+	{
+		.desc = "ARM erratum 1319367",
+		.capability = ARM64_WORKAROUND_1319367,
+		ERRATA_MIDR_RANGE_LIST(ca57_a72),
+	},
 #endif
 	{
 	}
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 2/5] arm64: KVM: Reorder system register restoration and stage-2 activation
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry
In-Reply-To: <20190925111941.88103-1-maz@kernel.org>

In order to prepare for handling erratum 1319367, we need to make
sure that all system registers (and most importantly the registers
configuring the virtual memory) are set before we enable stage-2
translation.

This results in a minor reorganisation of the load sequence, without
any functional change.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/switch.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index a15baca9aca0..e6adb90c12ae 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -605,18 +605,23 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
 
 	__sysreg_save_state_nvhe(host_ctxt);
 
-	__activate_vm(kern_hyp_va(vcpu->kvm));
-	__activate_traps(vcpu);
-
-	__hyp_vgic_restore_state(vcpu);
-	__timer_enable_traps(vcpu);
-
 	/*
 	 * We must restore the 32-bit state before the sysregs, thanks
 	 * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72).
+	 *
+	 * Also, and in order to be able to deal with erratum #1319537 (A57)
+	 * and #1319367 (A72), we must ensure that all VM-related sysreg are
+	 * restored before we enable S2 translation.
 	 */
 	__sysreg32_restore_state(vcpu);
 	__sysreg_restore_state_nvhe(guest_ctxt);
+
+	__activate_vm(kern_hyp_va(vcpu->kvm));
+	__activate_traps(vcpu);
+
+	__hyp_vgic_restore_state(vcpu);
+	__timer_enable_traps(vcpu);
+
 	__debug_switch_to_guest(vcpu);
 
 	__set_guest_arch_workaround_state(vcpu);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 3/5] arm64: KVM: Disable EL1 PTW when invalidating S2 TLBs
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry
In-Reply-To: <20190925111941.88103-1-maz@kernel.org>

When erratum 1319367 is being worked around, special care must
be taken not to allow the page table walker to populate TLBs
while we have the stage-2 translation enabled (which would otherwise
result in a bizare mix of the host S1 and the guest S2).

We enforce this by setting TCR_EL1.EPD{0,1} before restoring the S2
configuration, and clear the same bits after having disabled S2.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/tlb.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c
index eb0efc5557f3..4ef0bf0d76a6 100644
--- a/arch/arm64/kvm/hyp/tlb.c
+++ b/arch/arm64/kvm/hyp/tlb.c
@@ -63,6 +63,22 @@ static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm,
 static void __hyp_text __tlb_switch_to_guest_nvhe(struct kvm *kvm,
 						  struct tlb_inv_context *cxt)
 {
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1319367)) {
+		u64 val;
+
+		/*
+		 * For CPUs that are affected by ARM 1319367, we need to
+		 * avoid a host Stage-1 walk while we have the guest's
+		 * Stage-2 set in the VTTBR in order to invalidate TLBs.
+		 * We're guaranteed that the S1 MMU is enabled, so we can
+		 * simply set the EPD bits to avoid any further TLB fill.
+		 */
+		val = cxt->tcr = read_sysreg_el1(SYS_TCR);
+		val |= TCR_EPD1_MASK | TCR_EPD0_MASK;
+		write_sysreg_el1(val, SYS_TCR);
+		isb();
+	}
+
 	__load_guest_stage2(kvm);
 	isb();
 }
@@ -100,6 +116,13 @@ static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm,
 						 struct tlb_inv_context *cxt)
 {
 	write_sysreg(0, vttbr_el2);
+
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1319367)) {
+		/* Ensure stage-2 is actually disabled */
+		isb();
+		/* Restore the host's TCR_EL1 */
+		write_sysreg_el1(cxt->tcr, SYS_TCR);
+	}
 }
 
 static void __hyp_text __tlb_switch_to_host(struct kvm *kvm,
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 4/5] arm64: KVM: Prevent speculative S1 PTW when restoring vcpu context
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry
In-Reply-To: <20190925111941.88103-1-maz@kernel.org>

When handling erratum 1319367, we must ensure that the page table
walker cannot parse the S1 page tables while the guest is in an
inconsistent state. This is done as follows:

On guest entry:
- TCR_EL1.EPD{0,1} are set, ensuring that no PTW can occur
- all system registers are restored, except for TCR_EL1 and SCTLR_EL1
- stage-2 is restored
- SCTLR_EL1 and TCR_EL1 are restored

On guest exit:
- SCTLR_EL1.M and TCR_EL1.EPD{0,1} are set, ensuring that no PTW can occur
- stage-2 is disabled
- All host system registers are restored

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm64/kvm/hyp/switch.c    | 31 +++++++++++++++++++++++++++++++
 arch/arm64/kvm/hyp/sysreg-sr.c | 14 ++++++++++++--
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index e6adb90c12ae..4df47d013bec 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -118,6 +118,20 @@ static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
 	}
 
 	write_sysreg(val, cptr_el2);
+
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1319367)) {
+		struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt;
+
+		isb();
+		/*
+		 * At this stage, and thanks to the above isb(), S2 is
+		 * configured and enabled. We can now restore the guest's S1
+		 * configuration: SCTLR, and only then TCR.
+		 */
+		write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1],	SYS_SCTLR);
+		isb();
+		write_sysreg_el1(ctxt->sys_regs[TCR_EL1],	SYS_TCR);
+	}
 }
 
 static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
@@ -156,6 +170,23 @@ static void __hyp_text __deactivate_traps_nvhe(void)
 {
 	u64 mdcr_el2 = read_sysreg(mdcr_el2);
 
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1319367)) {
+		u64 val;
+
+		/*
+		 * Set the TCR and SCTLR registers in the exact opposite
+		 * sequence as __activate_traps_nvhe (first prevent walks,
+		 * then force the MMU on). A generous sprinkling of isb()
+		 * ensure that things happen in this exact order.
+		 */
+		val = read_sysreg_el1(SYS_TCR);
+		write_sysreg_el1(val | TCR_EPD1_MASK | TCR_EPD0_MASK, SYS_TCR);
+		isb();
+		val = read_sysreg_el1(SYS_SCTLR);
+		write_sysreg_el1(val | SCTLR_ELx_M, SYS_SCTLR);
+		isb();
+	}
+
 	__deactivate_traps_common();
 
 	mdcr_el2 &= MDCR_EL2_HPMN_MASK;
diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
index 7ddbc849b580..adabdceacc10 100644
--- a/arch/arm64/kvm/hyp/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/sysreg-sr.c
@@ -117,12 +117,22 @@ static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
 {
 	write_sysreg(ctxt->sys_regs[MPIDR_EL1],		vmpidr_el2);
 	write_sysreg(ctxt->sys_regs[CSSELR_EL1],	csselr_el1);
-	write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1],	SYS_SCTLR);
+
+	/* Must only be done for guest registers, hence the context test */
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1319367) &&
+	    !ctxt->__hyp_running_vcpu) {
+		write_sysreg_el1(ctxt->sys_regs[TCR_EL1] |
+				 TCR_EPD1_MASK | TCR_EPD0_MASK,	SYS_TCR);
+		isb();
+	} else {
+		write_sysreg_el1(ctxt->sys_regs[SCTLR_EL1],	SYS_SCTLR);
+		write_sysreg_el1(ctxt->sys_regs[TCR_EL1],	SYS_TCR);
+	}
+
 	write_sysreg(ctxt->sys_regs[ACTLR_EL1],		actlr_el1);
 	write_sysreg_el1(ctxt->sys_regs[CPACR_EL1],	SYS_CPACR);
 	write_sysreg_el1(ctxt->sys_regs[TTBR0_EL1],	SYS_TTBR0);
 	write_sysreg_el1(ctxt->sys_regs[TTBR1_EL1],	SYS_TTBR1);
-	write_sysreg_el1(ctxt->sys_regs[TCR_EL1],	SYS_TCR);
 	write_sysreg_el1(ctxt->sys_regs[ESR_EL1],	SYS_ESR);
 	write_sysreg_el1(ctxt->sys_regs[AFSR0_EL1],	SYS_AFSR0);
 	write_sysreg_el1(ctxt->sys_regs[AFSR1_EL1],	SYS_AFSR1);
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 5/5] arm64: Enable and document ARM errata 1319367 and 1319537
From: Marc Zyngier @ 2019-09-25 11:19 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Suzuki K Poulose, Catalin Marinas, James Morse,
	Will Deacon, Julien Thierry
In-Reply-To: <20190925111941.88103-1-maz@kernel.org>

Now that everything is in place, let's get the ball rolling
by allowing the corresponding config option to be selected.
Also add the required information to silicon_arrata.rst.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 Documentation/arm64/silicon-errata.rst |  4 ++++
 arch/arm64/Kconfig                     | 10 ++++++++++
 2 files changed, 14 insertions(+)

diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
index 3e57d09246e6..b90a977fc748 100644
--- a/Documentation/arm64/silicon-errata.rst
+++ b/Documentation/arm64/silicon-errata.rst
@@ -70,8 +70,12 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220        |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A57      | #1319537        | ARM64_ERRATUM_1319367       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A72      | #853709         | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A72      | #1319367        | ARM64_ERRATUM_1319367       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3adcec05b1f6..c50cd4f83bc4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -523,6 +523,16 @@ config ARM64_ERRATUM_1286807
 	  invalidated has been observed by other observers. The
 	  workaround repeats the TLBI+DSB operation.
 
+config ARM64_ERRATUM_1319367
+	bool "Cortex-A57/A72: Speculative AT instruction using out-of-context translation regime could cause subsequent request to generate an incorrect translation"
+	default y
+	help
+	  This option adds work arounds for ARM Cortex-A57 erratum 1319537
+	  and A72 erratum 1319367
+
+	  Cortex-A57 and A72 cores could end-up with corrupted TLBs by
+	  speculating an AT instruction during a guest context switch.
+
 	  If unsure, say Y.
 
 config ARM64_ERRATUM_1463225
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH] ASoC: stm32: sai: clean up indentation issue
From: Colin King @ 2019-09-25 11:26 UTC (permalink / raw)
  To: Olivier Moysan, Arnaud Pouliquen, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai, Maxime Coquelin, Alexandre Torgue,
	alsa-devel, linux-stm32, linux-arm-kernel
  Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

There is a statement that is indented one level too deeply,
remove the extraneous tab.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 sound/soc/stm/stm32_sai.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c
index ef4273361d0d..e20267504b16 100644
--- a/sound/soc/stm/stm32_sai.c
+++ b/sound/soc/stm/stm32_sai.c
@@ -100,7 +100,7 @@ static int stm32_sai_sync_conf_provider(struct stm32_sai_data *sai, int synco)
 		dev_err(&sai->pdev->dev, "%pOFn%s already set as sync provider\n",
 			sai->pdev->dev.of_node,
 			prev_synco == STM_SAI_SYNC_OUT_A ? "A" : "B");
-			stm32_sai_pclk_disable(&sai->pdev->dev);
+		stm32_sai_pclk_disable(&sai->pdev->dev);
 		return -EINVAL;
 	}
 
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* RE: [PATCH v5 11/15] dmaengine: imx-sdma: fix ecspi1 rx dma not work on i.mx8mm
From: Robin Gong @ 2019-09-25 11:26 UTC (permalink / raw)
  To: Schrempf Frieder
  Cc: Fabio Estevam, s.hauer@pengutronix.de,
	linux-kernel@vger.kernel.org, vkoul@kernel.org, dl-linux-imx,
	Pengutronix Kernel Team, dmaengine@vger.kernel.org,
	dan.j.williams@intel.com, shawnguo@kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <29cf9f29-bdb4-94db-00b0-56ec36386f7a@kontron.de>

On 2019-9-24 21:28 Schrempf Frieder <frieder.schrempf@kontron.de> wrote:
> 
> Hi Robin,
> 
> > From: Robin Gong <yibin.gong at nxp.com>
> >
> > Because the number of ecspi1 rx event on i.mx8mm is 0, the condition
> > check ignore such special case without dma channel enabled, which
> > caused
> > ecspi1 rx works failed. Actually, no need to check event_id0/event_id1
> > and replace checking 'event_id1' with 'DMA_DEV_TO_DEV', so that
> > configure
> > event_id1 only in case DEV_TO_DEV.
> >
> > Signed-off-by: Robin Gong <yibin.gong at nxp.com>
> > Acked-by: Vinod Koul <vkoul at kernel.org>
> 
> I have a custom board with i.MX8MM and SPI flash on ecspi1. I'm currently
> testing with v5.3 and as SPI didn't work, I tried two different things:
> 
> 1. Removing 'dmas' and 'dma-names' from the ecspi1 node in imx8mm.dtsi,
>     to use PIO instead of DMA. This works as expected and the driver
>     boots with the following messages:
> 
>         spi_imx 30820000.spi: dma setup error -19, use pio
>         m25p80 spi0.0: mx25v8035f (1024 Kbytes)
>         spi_imx 30820000.spi: probed
> 
> 2. Applying your patchset and use DMA. In this case, the flash also
>     works fine, but there are some error messages printed while booting:
> 
>         spi_master spi0: I/O Error in DMA RX
>         m25p80 spi0.0: SPI transfer failed: -110
>         spi_master spi0: failed to transfer one message from queue
>         m25p80 spi0.0: mx25v8035f (1024 Kbytes)
>         spi_imx 30820000.spi: probed
> 
> It would be great to get your patches merged and fix SPI + DMA, but for
> i.MX8MM, we need to get rid of the error messages. Do you have an idea,
> what's wrong?
Could you check if the length of spi message is bigger than fifo_size during
spi_nor probe? If yes, at that time maybe sdma firmware not loaded.
if (transfer->len < spi_imx->devtype_data->fifo_size)
> Thanks,
> Frieder
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH 03/11] PCI: mediatek: Use pci_parse_request_of_pci_ranges()
From: Andrew Murray @ 2019-09-25 11:34 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lorenzo Pieralisi, linux-pci, Matthias Brugger, Ryder Lee,
	linux-mediatek, Bjorn Helgaas, linux-arm-kernel
In-Reply-To: <20190924214630.12817-4-robh@kernel.org>

On Tue, Sep 24, 2019 at 04:46:22PM -0500, Rob Herring wrote:
> Convert Mediatek host bridge to use the common
> pci_parse_request_of_pci_ranges().
> 
> Cc: Ryder Lee <ryder.lee@mediatek.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: linux-mediatek@lists.infradead.org
> Signed-off-by: Rob Herring <robh@kernel.org>
> ---
>  drivers/pci/controller/pcie-mediatek.c | 47 ++++++++++----------------
>  1 file changed, 17 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
> index 80601e1b939e..cea4112b5309 100644
> --- a/drivers/pci/controller/pcie-mediatek.c
> +++ b/drivers/pci/controller/pcie-mediatek.c
> @@ -211,7 +211,6 @@ struct mtk_pcie {
>  	void __iomem *base;
>  	struct clk *free_ck;
>  
> -	struct resource mem;
>  	struct list_head ports;
>  	const struct mtk_pcie_soc *soc;
>  	unsigned int busnr;
> @@ -658,11 +657,23 @@ static int mtk_pcie_setup_irq(struct mtk_pcie_port *port,
>  static int mtk_pcie_startup_port_v2(struct mtk_pcie_port *port)
>  {
>  	struct mtk_pcie *pcie = port->pcie;
> -	struct resource *mem = &pcie->mem;
> +	struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
> +	struct resource *mem = NULL;
> +	struct resource_entry *entry;
>  	const struct mtk_pcie_soc *soc = port->pcie->soc;
>  	u32 val;
>  	int err;
>  
> +	resource_list_for_each_entry(entry, &host->windows) {
> +		if (resource_type(entry->res) != IORESOURCE_MEM)
> +			continue;
> +
> +		mem = entry->res;
> +		break;
> +	}
> +	if (!mem)
> +		return -EINVAL;
> +
>  	/* MT7622 platforms need to enable LTSSM and ASPM from PCIe subsys */
>  	if (pcie->base) {
>  		val = readl(pcie->base + PCIE_SYS_CFG_V2);
> @@ -1017,39 +1028,15 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie)
>  	struct mtk_pcie_port *port, *tmp;
>  	struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
>  	struct list_head *windows = &host->windows;
> -	struct resource_entry *win, *tmp_win;
> -	resource_size_t io_base;
> +	struct resource *bus;
>  	int err;
>  
> -	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff,
> -						    windows, &io_base);
> +	err = pci_parse_request_of_pci_ranges(dev, windows,
> +					      &bus);
>  	if (err)
>  		return err;
>  
> -	err = devm_request_pci_bus_resources(dev, windows);
> -	if (err < 0)
> -		return err;
> -
> -	/* Get the I/O and memory ranges from DT */
> -	resource_list_for_each_entry_safe(win, tmp_win, windows) {
> -		switch (resource_type(win->res)) {
> -		case IORESOURCE_IO:
> -			err = devm_pci_remap_iospace(dev, win->res, io_base);
> -			if (err) {
> -				dev_warn(dev, "error %d: failed to map resource %pR\n",
> -					 err, win->res);
> -				resource_list_destroy_entry(win);
> -			}
> -			break;
> -		case IORESOURCE_MEM:
> -			memcpy(&pcie->mem, win->res, sizeof(*win->res));
> -			pcie->mem.name = "non-prefetchable";

Using pci_parse_request_of_pci_ranges will now guard against using only
prefetchable memory ranges, whereas the existing code didn't do that. Given
that the current DT users all provide a non-prefetchable range I think this is
OK.

Reviewed-by: Andrew murray <andrew.murray@arm.com>

> -			break;
> -		case IORESOURCE_BUS:
> -			pcie->busnr = win->res->start;
> -			break;
> -		}
> -	}
> +	pcie->busnr = bus->start;
>  
>  	for_each_available_child_of_node(node, child) {
>  		int slot;
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH RESEND] drm/meson: vclk: use the correct G12A frac max value
From: Neil Armstrong @ 2019-09-25 11:41 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-amlogic, linux-kernel, linux-arm-kernel
In-Reply-To: <20190828132311.23881-1-narmstrong@baylibre.com>

Ping, could someone review this patch ?

Neil

On 28/08/2019 15:23, Neil Armstrong wrote:
> When calculating the HDMI PLL settings for a DMT mode PHY frequency,
> use the correct max fractional PLL value for G12A VPU.
> 
> With this fix, we can finally setup the 1024x768-60 mode.
> 
> Fixes: 202b9808f8ed ("drm/meson: Add G12A Video Clock setup")
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> ---
> Fixed typo in commit log, 1024x76 => 1024x768
> 
>  drivers/gpu/drm/meson/meson_vclk.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
> index ac491a781952..f690793ae2d5 100644
> --- a/drivers/gpu/drm/meson/meson_vclk.c
> +++ b/drivers/gpu/drm/meson/meson_vclk.c
> @@ -638,13 +638,18 @@ static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
>  		if (frac >= HDMI_FRAC_MAX_GXBB)
>  			return false;
>  	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
> -		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
> -		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
>  		/* Empiric supported min/max dividers */
>  		if (m < 106 || m > 247)
>  			return false;
>  		if (frac >= HDMI_FRAC_MAX_GXL)
>  			return false;
> +	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
> +		/* Empiric supported min/max dividers */
> +		if (m < 106 || m > 247)
> +			return false;
> +		if (frac >= HDMI_FRAC_MAX_G12A)
> +			return false;
>  	}
>  
>  	return true;
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 0/2] add Amlogic A1 clock controller driver
From: Jian Hu @ 2019-09-25 11:44 UTC (permalink / raw)
  To: Jerome Brunet, Neil Armstrong
  Cc: Rob Herring, Jianxin Pan, devicetree, Martin Blumenstingl,
	Kevin Hilman, Michael Turquette, linux-kernel, Stephen Boyd,
	Jian Hu, Qiufang Dai, linux-amlogic, linux-clk, linux-arm-kernel

add support for Amlogic A1 clock driver, the clock includes 
three parts: peripheral clocks, pll clocks, CPU clocks.
sys pll and CPU clocks will be sent in next patch.

Unlike the previous series, there is no EE/AO domain in A1
clock controllers.

Jian Hu (2):
  dt-bindings: clock: meson: add A1 clock controller bindings
  clk: meson: a1: add support for Amlogic A1 clock driver

 .../devicetree/bindings/clock/amlogic,a1-clkc.yaml |   65 +
 arch/arm64/Kconfig.platforms                       |    1 +
 drivers/clk/meson/Kconfig                          |   10 +
 drivers/clk/meson/Makefile                         |    1 +
 drivers/clk/meson/a1.c                             | 2617 ++++++++++++++++++++
 drivers/clk/meson/a1.h                             |  172 ++
 include/dt-bindings/clock/a1-clkc.h                |  102 +
 7 files changed, 2968 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml
 create mode 100644 drivers/clk/meson/a1.c
 create mode 100644 drivers/clk/meson/a1.h
 create mode 100644 include/dt-bindings/clock/a1-clkc.h

-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/2] dt-bindings: clock: meson: add A1 clock controller bindings
From: Jian Hu @ 2019-09-25 11:44 UTC (permalink / raw)
  To: Jerome Brunet, Neil Armstrong
  Cc: Rob Herring, Jianxin Pan, devicetree, Martin Blumenstingl,
	Kevin Hilman, Michael Turquette, linux-kernel, Stephen Boyd,
	Jian Hu, Qiufang Dai, linux-amlogic, linux-clk, linux-arm-kernel
In-Reply-To: <1569411888-98116-1-git-send-email-jian.hu@amlogic.com>

Add the documentation to support Amlogic A1 clock driver,
and add A1 clock controller bindings.

Signed-off-by: Jian Hu <jian.hu@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
---
 .../devicetree/bindings/clock/amlogic,a1-clkc.yaml |  65 +++++++++++++
 include/dt-bindings/clock/a1-clkc.h                | 102 +++++++++++++++++++++
 2 files changed, 167 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml
 create mode 100644 include/dt-bindings/clock/a1-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml
new file mode 100644
index 0000000..f012eb2
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/clock/amlogic,a1-clkc.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic Meson A1 Clock Control Unit Device Tree Bindings
+
+maintainers:
+  - Neil Armstrong <narmstrong@baylibre.com>
+  - Jerome Brunet <jbrunet@baylibre.com>
+  - Jian Hu <jian.hu@jian.hu.com>
+
+properties:
+  compatible:
+    - enum:
+        - amlogic,a1-clkc
+
+  reg:
+    minItems: 1
+    maxItems: 3
+    items:
+      - description: peripheral registers
+      - description: cpu registers
+      - description: pll registers
+
+  reg-names:
+    items:
+      - const: peripheral
+      - const: pll
+      - const: cpu
+
+  clocks:
+    maxItems: 1
+    items:
+      - description: Input Oscillator (usually at 24MHz)
+
+  clock-names:
+    maxItems: 1
+    items:
+      - const: xtal
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - "#clock-cells"
+
+examples:
+  - |
+    clkc: clock-controller {
+        compatible = "amlogic,a1-clkc";
+        reg = <0x0 0xfe000800 0x0 0x100>,
+              <0x0 0xfe007c00 0x0 0x21c>,
+              <0x0 0xfd000080 0x0 0x20>;
+        reg-names = "peripheral", "pll", "cpu";
+        clocks = <&xtal;
+        clock-names = "xtal";
+        #clock-cells = <1>;
+    };
diff --git a/include/dt-bindings/clock/a1-clkc.h b/include/dt-bindings/clock/a1-clkc.h
new file mode 100644
index 0000000..69fbf37
--- /dev/null
+++ b/include/dt-bindings/clock/a1-clkc.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __A1_CLKC_H
+#define __A1_CLKC_H
+
+#define CLKID_FIXED_PLL				1
+#define CLKID_FCLK_DIV2				2
+#define CLKID_FCLK_DIV3				3
+#define CLKID_FCLK_DIV5				4
+#define CLKID_FCLK_DIV7				5
+#define CLKID_FCLK_DIV2_DIV			6
+#define CLKID_FCLK_DIV3_DIV			7
+#define CLKID_FCLK_DIV5_DIV			8
+#define CLKID_FCLK_DIV7_DIV			9
+#define CLKID_SYS_CLK				16
+#define CLKID_HIFI_PLL				17
+#define CLKID_CLKTREE				25
+#define CLKID_RESET_CTRL			26
+#define CLKID_ANALOG_CTRL			27
+#define CLKID_PWR_CTRL				28
+#define CLKID_PAD_CTRL				29
+#define CLKID_SYS_CTRL				30
+#define CLKID_TEMP_SENSOR			31
+#define CLKID_AM2AXI_DIV			32
+#define CLKID_SPICC_B				33
+#define CLKID_SPICC_A				34
+#define CLKID_CLK_MSR				35
+#define CLKID_AUDIO				36
+#define CLKID_JTAG_CTRL				37
+#define CLKID_SARADC				38
+#define CLKID_PWM_EF				39
+#define CLKID_PWM_CD				40
+#define CLKID_PWM_AB				41
+#define CLKID_CEC				42
+#define CLKID_I2C_S				43
+#define CLKID_IR_CTRL				44
+#define CLKID_I2C_M_D				45
+#define CLKID_I2C_M_C				46
+#define CLKID_I2C_M_B				47
+#define CLKID_I2C_M_A				48
+#define CLKID_ACODEC				49
+#define CLKID_OTP				50
+#define CLKID_SD_EMMC_A				51
+#define CLKID_USB_PHY				52
+#define CLKID_USB_CTRL				53
+#define CLKID_SYS_DSPB				54
+#define CLKID_SYS_DSPA				55
+#define CLKID_DMA				56
+#define CLKID_IRQ_CTRL				57
+#define CLKID_NIC				58
+#define CLKID_GIC				59
+#define CLKID_UART_C				60
+#define CLKID_UART_B				61
+#define CLKID_UART_A				62
+#define CLKID_SYS_PSRAM				63
+#define CLKID_RSA				64
+#define CLKID_CORESIGHT				65
+#define CLKID_AM2AXI_VAD			66
+#define CLKID_AUDIO_VAD				67
+#define CLKID_AXI_DMC				68
+#define CLKID_AXI_PSRAM				69
+#define CLKID_RAMB				70
+#define CLKID_RAMA				71
+#define CLKID_AXI_SPIFC				72
+#define CLKID_AXI_NIC				73
+#define CLKID_AXI_DMA				74
+#define CLKID_CPU_CTRL				75
+#define CLKID_ROM				76
+#define CLKID_PROC_I2C				77
+#define CLKID_DSPA_SEL				84
+#define CLKID_DSPB_SEL				91
+#define CLKID_DSPA_EN_DSPA			92
+#define CLKID_DSPA_EN_NIC			93
+#define CLKID_DSPB_EN_DSPB			94
+#define CLKID_DSPB_EN_NIC			95
+#define CLKID_RTC_CLK				100
+#define CLKID_CECA_32K				105
+#define CLKID_CECB_32K				110
+#define CLKID_24M				111
+#define CLKID_12M				112
+#define CLKID_FCLK_DIV2_DIVN			114
+#define CLKID_GEN				118
+#define CLKID_SARADC_SEL			119
+#define CLKID_SARADC_CLK			121
+#define CLKID_PWM_A				124
+#define CLKID_PWM_B				127
+#define CLKID_PWM_C				130
+#define CLKID_PWM_D				133
+#define CLKID_PWM_E				136
+#define CLKID_PWM_F				139
+#define CLKID_SPICC				143
+#define CLKID_TS				145
+#define CLKID_SPIFC				149
+#define CLKID_USB_BUS				152
+#define CLKID_SD_EMMC				156
+#define CLKID_PSRAM				160
+#define CLKID_DMC				164
+
+#endif /* __A1_CLKC_H */
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* [PATCH 2/2] clk: meson: a1: add support for Amlogic A1 clock driver
From: Jian Hu @ 2019-09-25 11:44 UTC (permalink / raw)
  To: Jerome Brunet, Neil Armstrong
  Cc: Rob Herring, Jianxin Pan, devicetree, Martin Blumenstingl,
	Kevin Hilman, Michael Turquette, linux-kernel, Stephen Boyd,
	Jian Hu, Qiufang Dai, linux-amlogic, linux-clk, linux-arm-kernel
In-Reply-To: <1569411888-98116-1-git-send-email-jian.hu@amlogic.com>

The Amlogic A1 clock includes three parts:
peripheral clocks, pll clocks, CPU clocks.
sys pll and CPU clocks will be sent in next patch.

Unlike the previous series, there is no EE/AO domain
in A1 CLK controllers.

Signed-off-by: Jian Hu <jian.hu@amlogic.com>
Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
---
 arch/arm64/Kconfig.platforms |    1 +
 drivers/clk/meson/Kconfig    |   10 +
 drivers/clk/meson/Makefile   |    1 +
 drivers/clk/meson/a1.c       | 2617 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/meson/a1.h       |  172 +++
 5 files changed, 2801 insertions(+)
 create mode 100644 drivers/clk/meson/a1.c
 create mode 100644 drivers/clk/meson/a1.h

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 16d7614..a48f67d 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -138,6 +138,7 @@ config ARCH_MESON
 	select COMMON_CLK_AXG
 	select COMMON_CLK_G12A
 	select MESON_IRQ_GPIO
+	select COMMON_CLK_A1
 	help
 	  This enables support for the arm64 based Amlogic SoCs
 	  such as the s905, S905X/D, S912, A113X/D or S905X/D2
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index dabeb43..e6cb4c3 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -107,3 +107,13 @@ config COMMON_CLK_G12A
 	help
 	  Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
 	  devices, aka g12a. Say Y if you want peripherals to work.
+
+config COMMON_CLK_A1
+	bool
+	depends on ARCH_MESON
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_DUALDIV
+	select COMMON_CLK_MESON_PLL
+	help
+	  Support for the clock controller on Amlogic A113L device,
+	  aka a1. Say Y if you want peripherals to work.
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3939f21..6be3a8f 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
 obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
+obj-$(CONFIG_COMMON_CLK_A1) += a1.o
diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
new file mode 100644
index 0000000..26edae0f
--- /dev/null
+++ b/drivers/clk/meson/a1.c
@@ -0,0 +1,2617 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include "clk-mpll.h"
+#include "clk-pll.h"
+#include "clk-regmap.h"
+#include "vid-pll-div.h"
+#include "clk-dualdiv.h"
+#include "meson-eeclk.h"
+#include "a1.h"
+
+/* PLLs clock in gates, its parent is xtal */
+static struct clk_regmap a1_xtal_clktree = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 0,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_clktree",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_fixpll = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 1,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_fixpll",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_usb_phy = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 2,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_usb_phy",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_usb_ctrl = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 3,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_usb_ctrl",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_hifipll = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 4,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_hifipll",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_syspll = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 5,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_syspll",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_xtal_dds = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_OSCIN_CTRL,
+		.bit_idx = 6,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "xtal_dds",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+/* fixed pll = 1536M
+ *
+ * fixed pll ----- fclk_div2 = 768M
+ *           |
+ *           ----- fclk_div3 = 512M
+ *           |
+ *           ----- fclk_div5 = 307.2M
+ *           |
+ *           ----- fclk_div7 = 219.4M
+ */
+static struct clk_regmap a1_fixed_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = ANACTRL_FIXPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = ANACTRL_FIXPLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = ANACTRL_FIXPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.frac = {
+			.reg_off = ANACTRL_FIXPLL_CTRL1,
+			.shift   = 0,
+			.width   = 19,
+		},
+		.l = {
+			.reg_off = ANACTRL_FIXPLL_CTRL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = ANACTRL_FIXPLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fixed_pll_dco",
+		.ops = &meson_clk_pll_ro_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_xtal_fixpll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fixed_pll = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANACTRL_FIXPLL_CTRL0,
+		.bit_idx = 20,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "fixed_pll",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fixed_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_IGNORE_UNUSED,
+	},
+};
+
+static const struct pll_params_table a1_hifi_pll_params_table[] = {
+	PLL_PARAMS(128, 5), /* DCO = 614.4M */
+};
+
+static const struct reg_sequence a1_hifi_init_regs[] = {
+	{ .reg = ANACTRL_HIFIPLL_CTRL1,	.def = 0x01800000 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL2,	.def = 0x00001100 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL3,	.def = 0x10022200 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL4,	.def = 0x00301000 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f19480 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x11f19480, .delay_us = 10 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL0,	.def = 0x15f11480, .delay_us = 40 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL2,	.def = 0x00001140 },
+	{ .reg = ANACTRL_HIFIPLL_CTRL2,	.def = 0x00001100 },
+};
+
+/*
+ * The Meson A1 HIFI PLL is 614.4M, it requires
+ * a strict register sequence to enable the PLL.
+ * set meson_clk_pcie_pll_ops as its ops
+ */
+static struct clk_regmap a1_hifi_pll = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = ANACTRL_HIFIPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = ANACTRL_HIFIPLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = ANACTRL_HIFIPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.frac = {
+			.reg_off = ANACTRL_HIFIPLL_CTRL1,
+			.shift   = 0,
+			.width   = 19,
+		},
+		.l = {
+			.reg_off = ANACTRL_HIFIPLL_STS,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.table = a1_hifi_pll_params_table,
+		.init_regs = a1_hifi_init_regs,
+		.init_count = ARRAY_SIZE(a1_hifi_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hifi_pll",
+		.ops = &meson_clk_pcie_pll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_xtal_hifipll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_fixed_factor a1_fclk_div2_div = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div2_div",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fixed_pll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div2 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANACTRL_FIXPLL_CTRL0,
+		.bit_idx = 21,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div2",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2_div.hw
+		},
+		.num_parents = 1,
+		/*
+		 * add CLK_IS_CRITICAL flag to avoid being disabled by clk core
+		 * or its children clocks.
+		 */
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_fixed_factor a1_fclk_div3_div = {
+	.mult = 1,
+	.div = 3,
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div3_div",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fixed_pll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div3 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANACTRL_FIXPLL_CTRL0,
+		.bit_idx = 22,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div3",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div3_div.hw
+		},
+		.num_parents = 1,
+		/*
+		 * add CLK_IS_CRITICAL flag to avoid being disabled by clk core
+		 * its children clocks.
+		 */
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_fixed_factor a1_fclk_div5_div = {
+	.mult = 1,
+	.div = 5,
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div5_div",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fixed_pll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div5 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANACTRL_FIXPLL_CTRL0,
+		.bit_idx = 23,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div5",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div5_div.hw
+		},
+		.num_parents = 1,
+		/*
+		 * add CLK_IS_CRITICAL flag to avoid being disabled by clk core
+		 * its children clocks.
+		 */
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_fixed_factor a1_fclk_div7_div = {
+	.mult = 1,
+	.div = 7,
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div7_div",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fixed_pll.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div7 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANACTRL_FIXPLL_CTRL0,
+		.bit_idx = 23,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div7",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div7_div.hw
+		},
+		.num_parents = 1,
+		/*
+		 * add CLK_IS_CRITICAL flag to avoid being disabled by clk core
+		 * or its children clock.
+		 */
+		.flags = CLK_IS_CRITICAL,
+	},
+};
+
+/* sys clk = 64M */
+static u32 mux_table_sys_ab_clk[] = { 0, 1, 2, 3};
+static const struct clk_parent_data sys_ab_clk_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_fclk_div2.hw },
+	{ .hw = &a1_fclk_div3.hw },
+	{ .hw = &a1_fclk_div5.hw },
+};
+
+static struct clk_regmap a1_sys_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SYS_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+		.table = mux_table_sys_ab_clk,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_b_sel",
+		.ops = &clk_regmap_mux_ro_ops,
+		.parent_data = sys_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(sys_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_sys_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SYS_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sys_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_sys_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "sys_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sys_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_sys_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SYS_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+		.table = mux_table_sys_ab_clk,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_a_sel",
+		.ops = &clk_regmap_mux_ro_ops,
+		.parent_data = sys_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(sys_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_sys_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SYS_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sys_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_sys_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SYS_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "sys_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sys_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+	},
+};
+
+static struct clk_regmap a1_sys_clk = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SYS_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_clk",
+		.ops = &clk_regmap_mux_ro_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sys_a.hw, &a1_sys_b.hw,
+		},
+		.num_parents = 2,
+	},
+};
+
+/* rtc 32k clock in */
+static struct clk_regmap a1_rtc_32k_clkin = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_32k_clkin",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct meson_clk_dualdiv_param a1_32k_div_table[] = {
+	{
+		.dual		= 1,
+		.n1		= 733,
+		.m1		= 8,
+		.n2		= 732,
+		.m2		= 11,
+	}, {}
+};
+
+static struct clk_regmap a1_rtc_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = a1_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_rtc_32k_clkin.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_rtc_32k_xtal = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = RTC_BY_OSCIN_CTRL1,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_32k_xtal",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_rtc_32k_clkin.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static u32 rtc_32k_sel[] = { 0, 1 };
+
+static struct clk_regmap a1_rtc_32k_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_CTRL,
+		.mask = 0x3,
+		.shift = 0,
+		.table = rtc_32k_sel,
+		.flags = CLK_MUX_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_rtc_32k_xtal.hw,
+			&a1_rtc_32k_div.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+struct clk_regmap a1_rtc_clk = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_clk",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_rtc_32k_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* dsp a clk */
+static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 };
+static const struct clk_parent_data dsp_ab_clk_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_fclk_div2.hw },
+	{ .hw = &a1_fclk_div3.hw },
+	{ .hw = &a1_fclk_div5.hw },
+	{ .hw = &a1_hifi_pll.hw },
+	{ .hw = &a1_rtc_clk.hw },
+};
+
+static struct clk_regmap a1_dspa_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+		.table = mux_table_dsp_ab,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_a_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = dsp_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_dspa_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspa_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspa_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+		.table = mux_table_dsp_ab,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_b_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = dsp_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_dspa_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspa_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspa_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_dspa_a.hw },
+			{ .hw = &a1_dspa_b.hw },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspa_en_dspa = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_EN,
+		.bit_idx = 1,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_en_dspa",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspa_en_nic = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_EN,
+		.bit_idx = 0,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_en_nic",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspa_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* dsp b clk */
+static struct clk_regmap a1_dspb_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+		.table = mux_table_dsp_ab,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_a_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = dsp_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_dspb_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPB_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspb_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspb_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+		.table = mux_table_dsp_ab,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_b_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = dsp_ab_clk_parent_data,
+		.num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_dspb_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPB_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspb_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspb_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_a.hw, &a1_dspb_b.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dspb_en_dspb = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_EN,
+		.bit_idx = 1,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_en_dspb",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_dspb_en_nic = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_EN,
+		.bit_idx = 0,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_en_nic",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dspb_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* 12M/24M clock */
+static struct clk_regmap a1_24m = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "24m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_fixed_factor a1_24m_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "24m_div2",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_24m.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_12m = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 10,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "12m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_24m_div2.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div2_divn_pre = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = CLK12_24_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div2_divn_pre",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_fclk_div2_divn = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 12,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fclk_div2_divn",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2_divn_pre.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* gen clk */
+static u32 gen_clk_table[] = { 0, 1, 3, 5, 6, 7, 8 };
+static const struct clk_parent_data gen_clk_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_rtc_clk.hw },
+	{ .hw = &a1_hifi_pll.hw },
+	{ .hw = &a1_fclk_div2.hw },
+	{ .hw = &a1_fclk_div3.hw },
+	{ .hw = &a1_fclk_div5.hw },
+	{ .hw = &a1_fclk_div7.hw },
+};
+
+static struct clk_regmap a1_gen_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = GEN_CLK_CTRL,
+		.mask = 0xf,
+		.shift = 12,
+		.table = gen_clk_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gen_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = gen_clk_parent_data,
+		.num_parents = ARRAY_SIZE(gen_clk_parent_data),
+	},
+};
+
+static struct clk_regmap a1_gen_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = GEN_CLK_CTRL,
+		.shift = 0,
+		.width = 11,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gen_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_gen_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_gen = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = GEN_CLK_CTRL,
+		.bit_idx = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gen",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_gen_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_saradc_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SAR_ADC_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "saradc_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .fw_name = "xtal", },
+			{ .hw = &a1_sys_clk.hw, },
+		},
+		.num_parents = 2,
+	},
+};
+
+static struct clk_regmap a1_saradc_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SAR_ADC_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "saradc_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_saradc_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_saradc_clk = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SAR_ADC_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "saradc_clk",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_saradc_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* pwm a/b/c/d parent data */
+static const struct clk_parent_data pwm_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_sys_clk.hw },
+};
+
+/*
+ * add CLK_IGNORE_UNUSED flag for pwm controller GATE
+ * clk core will disable unused clock, it may disable
+ * vddcore voltage which contrlled by one pwm in bl21.
+ * add the flag to avoid changing cpu voltage.
+ */
+/* pwm a clk */
+static struct clk_regmap a1_pwm_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.mask = 0x1,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_a_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* pwm b clk */
+static struct clk_regmap a1_pwm_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.mask = 0x1,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_b_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.shift = 16,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_AB_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* pwm c clk */
+static struct clk_regmap a1_pwm_c_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.mask = 0x1,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_c_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_c_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_c_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_c_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_c = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_c",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_c_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* pwm d clk */
+static struct clk_regmap a1_pwm_d_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.mask = 0x1,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_d_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_d_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.shift = 16,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_d_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_d_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_d = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_CD_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_d",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_d_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static const struct clk_parent_data pwm_ef_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_sys_clk.hw },
+	{ .hw = &a1_fclk_div5.hw },
+	{ .hw = &a1_rtc_clk.hw },
+};
+
+/* pwm e clk */
+static struct clk_regmap a1_pwm_e_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_e_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_ef_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_ef_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_e_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_e_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_e_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_e = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_e",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_e_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* pwm f clk */
+static struct clk_regmap a1_pwm_f_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.mask = 0x3,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_f_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = pwm_ef_parent_data,
+		.num_parents = ARRAY_SIZE(pwm_ef_parent_data),
+	},
+};
+
+static struct clk_regmap a1_pwm_f_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.shift = 16,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pwm_f_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_f_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_pwm_f = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PWM_CLK_EF_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "pwm_f",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_pwm_f_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* spicc clk */
+
+/*    div2   |\         |\       _____
+ *  ---------| |---DIV--| |     |     |    spicc out
+ *  ---------| |        | |-----|GATE |---------
+ *     ..... |/         | /     |_____|
+ *  --------------------|/
+ *                 24M
+ */
+
+static struct clk_regmap a1_spicc_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SPICC_CLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spicc_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2.hw,
+			&a1_fclk_div3.hw,
+			&a1_fclk_div5.hw,
+			&a1_hifi_pll.hw,
+		},
+		.num_parents = 4,
+	},
+};
+
+static struct clk_regmap a1_spicc_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SPICC_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spicc_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_spicc_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_spicc_sel2 = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SPICC_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spicc_sel2",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_spicc_div.hw },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_spicc = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SPICC_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "spicc",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_spicc_sel2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* ts clk */
+static struct clk_regmap a1_ts_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = TS_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ts_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_ts = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = TS_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "ts",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_ts_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* spifc clk */
+static struct clk_regmap a1_spifc_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SPIFC_CLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spifc_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2.hw,
+			&a1_fclk_div3.hw,
+			&a1_fclk_div5.hw,
+			&a1_hifi_pll.hw,
+		},
+		.num_parents = 4,
+	},
+};
+
+static struct clk_regmap a1_spifc_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SPIFC_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spifc_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_spifc_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_spifc_sel2 = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SPIFC_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "spifc_sel2",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_spifc_div.hw },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_spifc = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SPIFC_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "spifc",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_spifc_sel2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* usb bus clk */
+static const struct clk_parent_data usb_bus_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .hw = &a1_sys_clk.hw },
+	{ .hw = &a1_fclk_div3.hw },
+	{ .hw = &a1_fclk_div5.hw },
+};
+
+static struct clk_regmap a1_usb_bus_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = USB_BUSCLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_bus_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = usb_bus_parent_data,
+		.num_parents = ARRAY_SIZE(usb_bus_parent_data),
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_usb_bus_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = USB_BUSCLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_bus_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_usb_bus_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+static struct clk_regmap a1_usb_bus = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = USB_BUSCLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "usb_bus",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_usb_bus_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* sd emmc clk */
+static u32 mux_table_sd_emmc[] = { 0, 1, 2 };
+
+static struct clk_regmap a1_sd_emmc_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SD_EMMC_CLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+		.table = mux_table_sd_emmc,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sd_emmc_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_fclk_div2.hw,
+			&a1_fclk_div3.hw,
+			&a1_fclk_div5.hw,
+		},
+		.num_parents = 3,
+	},
+};
+
+static struct clk_regmap a1_sd_emmc_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = SD_EMMC_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sd_emmc_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sd_emmc_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_sd_emmc_sel2 = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = SD_EMMC_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sd_emmc_sel2",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_sd_emmc_div.hw },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_sd_emmc = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = SD_EMMC_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "sd_emmc",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_sd_emmc_sel2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* psram clk */
+static const struct clk_hw *psram_parent_hws[] = {
+	&a1_fclk_div2.hw,
+	&a1_fclk_div3.hw,
+	&a1_fclk_div5.hw,
+	&a1_hifi_pll.hw,
+};
+
+static struct clk_regmap a1_psram_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PSRAM_CLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "psram_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = psram_parent_hws,
+		.num_parents = ARRAY_SIZE(psram_parent_hws),
+	},
+};
+
+static struct clk_regmap a1_psram_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PSRAM_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "psram_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_psram_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_psram_sel2 = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = PSRAM_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "psram_sel2",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_psram_div.hw },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_psram = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = PSRAM_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "psram",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_psram_sel2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* dmc clk */
+static const struct clk_hw *dmc_parent_hws[] = {
+	&a1_fclk_div2.hw,
+	&a1_fclk_div3.hw,
+	&a1_fclk_div5.hw,
+	&a1_hifi_pll.hw,
+};
+
+static struct clk_regmap a1_dmc_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DMC_CLK_CTRL,
+		.mask = 0x3,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dmc_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = dmc_parent_hws,
+		.num_parents = ARRAY_SIZE(dmc_parent_hws),
+	},
+};
+
+static struct clk_regmap a1_dmc_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DMC_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dmc_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dmc_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dmc_sel2 = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DMC_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dmc_sel2",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &a1_dmc_div.hw },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_dmc = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DMC_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dmc",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_dmc_sel2.hw
+		},
+		.num_parents = 1,
+		/*
+		 * add CLK_IGNORE_UNUSED to avoid hangup
+		 * DDR clock should not change at runtime
+		 */
+		.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+	},
+};
+
+/* cec A clock */
+static struct clk_regmap a1_ceca_32k_clkin = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECA_CLK_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "ceca_32k_clkin",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_ceca_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = CECA_CLK_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = CECA_CLK_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = CECA_CLK_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = CECA_CLK_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = CECA_CLK_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = a1_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_ceca_32k_clkin.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_ceca_32k_sel_pre = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECA_CLK_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+		.flags = CLK_MUX_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_sel_pre",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_ceca_32k_div.hw,
+			&a1_ceca_32k_clkin.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_ceca_32k_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECA_CLK_CTRL1,
+		.mask = 0x1,
+		.shift = 31,
+		.flags = CLK_MUX_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_ceca_32k_sel_pre.hw,
+			&a1_rtc_clk.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_ceca_32k_clkout = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECA_CLK_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_clkout",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_ceca_32k_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* cec B clock */
+static struct clk_regmap a1_cecb_32k_clkin = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECB_CLK_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "cecb_32k_clkin",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_cecb_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = CECB_CLK_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = CECB_CLK_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = CECB_CLK_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = CECB_CLK_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = CECB_CLK_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = a1_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_cecb_32k_clkin.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a1_cecb_32k_sel_pre = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECB_CLK_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+		.flags = CLK_MUX_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_sel_pre",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_cecb_32k_div.hw,
+			&a1_cecb_32k_clkin.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_cecb_32k_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECB_CLK_CTRL1,
+		.mask = 0x1,
+		.shift = 31,
+		.flags = CLK_MUX_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_cecb_32k_sel_pre.hw,
+			&a1_rtc_clk.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a1_cecb_32k_clkout = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECB_CLK_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_clkout",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a1_cecb_32k_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+#define MESON_GATE(_name, _reg, _bit) \
+	MESON_PCLK(_name, _reg, _bit, &a1_sys_clk.hw)
+
+/* CLKTREE_SYS_CLK_EN0 */
+static MESON_GATE(a1_clk_tree,		SYS_CLK_EN0,	0);
+static MESON_GATE(a1_reset_ctrl,	SYS_CLK_EN0,	1);
+static MESON_GATE(a1_analog_ctrl,	SYS_CLK_EN0,	2);
+static MESON_GATE(a1_pwr_ctrl,		SYS_CLK_EN0,	3);
+static MESON_GATE(a1_pad_ctrl,		SYS_CLK_EN0,	4);
+static MESON_GATE(a1_sys_ctrl,		SYS_CLK_EN0,	5);
+static MESON_GATE(a1_temp_sensor,	SYS_CLK_EN0,	6);
+static MESON_GATE(a1_am2axi_dev,	SYS_CLK_EN0,	7);
+static MESON_GATE(a1_spicc_b,		SYS_CLK_EN0,	8);
+static MESON_GATE(a1_spicc_a,		SYS_CLK_EN0,	9);
+static MESON_GATE(a1_clk_msr,		SYS_CLK_EN0,	10);
+static MESON_GATE(a1_audio,		SYS_CLK_EN0,	11);
+static MESON_GATE(a1_jtag_ctrl,		SYS_CLK_EN0,	12);
+static MESON_GATE(a1_saradc,		SYS_CLK_EN0,	13);
+static MESON_GATE(a1_pwm_ef,		SYS_CLK_EN0,	14);
+static MESON_GATE(a1_pwm_cd,		SYS_CLK_EN0,	15);
+static MESON_GATE(a1_pwm_ab,		SYS_CLK_EN0,	16);
+static MESON_GATE(a1_cec,		SYS_CLK_EN0,	17);
+static MESON_GATE(a1_i2c_s,		SYS_CLK_EN0,	18);
+static MESON_GATE(a1_ir_ctrl,		SYS_CLK_EN0,	19);
+static MESON_GATE(a1_i2c_m_d,		SYS_CLK_EN0,	20);
+static MESON_GATE(a1_i2c_m_c,		SYS_CLK_EN0,	21);
+static MESON_GATE(a1_i2c_m_b,		SYS_CLK_EN0,	22);
+static MESON_GATE(a1_i2c_m_a,		SYS_CLK_EN0,	23);
+static MESON_GATE(a1_acodec,		SYS_CLK_EN0,	24);
+static MESON_GATE(a1_otp,		SYS_CLK_EN0,	25);
+static MESON_GATE(a1_sd_emmc_a,		SYS_CLK_EN0,	26);
+static MESON_GATE(a1_usb_phy,		SYS_CLK_EN0,	27);
+static MESON_GATE(a1_usb_ctrl,		SYS_CLK_EN0,	28);
+static MESON_GATE(a1_sys_dspb,		SYS_CLK_EN0,	29);
+static MESON_GATE(a1_sys_dspa,		SYS_CLK_EN0,	30);
+static MESON_GATE(a1_dma,		SYS_CLK_EN0,	31);
+/* CLKTREE_SYS_CLK_EN1 */
+static MESON_GATE(a1_irq_ctrl,		SYS_CLK_EN1,	0);
+static MESON_GATE(a1_nic,		SYS_CLK_EN1,	1);
+static MESON_GATE(a1_gic,		SYS_CLK_EN1,	2);
+static MESON_GATE(a1_uart_c,		SYS_CLK_EN1,	3);
+static MESON_GATE(a1_uart_b,		SYS_CLK_EN1,	4);
+static MESON_GATE(a1_uart_a,		SYS_CLK_EN1,	5);
+static MESON_GATE(a1_sys_psram,		SYS_CLK_EN1,	6);
+static MESON_GATE(a1_rsa,		SYS_CLK_EN1,	8);
+static MESON_GATE(a1_coresight,		SYS_CLK_EN1,	9);
+/* CLKTREE_AXI_CLK_EN */
+static MESON_GATE(a1_am2axi_vad,	AXI_CLK_EN,	0);
+static MESON_GATE(a1_audio_vad,		AXI_CLK_EN,	1);
+static MESON_GATE(a1_axi_dmc,		AXI_CLK_EN,	3);
+static MESON_GATE(a1_axi_psram,		AXI_CLK_EN,	4);
+static MESON_GATE(a1_ramb,		AXI_CLK_EN,	5);
+static MESON_GATE(a1_rama,		AXI_CLK_EN,	6);
+static MESON_GATE(a1_axi_spifc,		AXI_CLK_EN,	7);
+static MESON_GATE(a1_axi_nic,		AXI_CLK_EN,	8);
+static MESON_GATE(a1_axi_dma,		AXI_CLK_EN,	9);
+static MESON_GATE(a1_cpu_ctrl,		AXI_CLK_EN,	10);
+static MESON_GATE(a1_rom,		AXI_CLK_EN,	11);
+static MESON_GATE(a1_prod_i2c,		AXI_CLK_EN,	12);
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw_onecell_data a1_hw_onecell_data = {
+	.hws = {
+		[CLKID_FIXED_PLL_DCO]		= &a1_fixed_pll_dco.hw,
+		[CLKID_FIXED_PLL]		= &a1_fixed_pll.hw,
+		[CLKID_HIFI_PLL]		= &a1_hifi_pll.hw,
+		[CLKID_FCLK_DIV2]		= &a1_fclk_div2.hw,
+		[CLKID_FCLK_DIV3]		= &a1_fclk_div3.hw,
+		[CLKID_FCLK_DIV5]		= &a1_fclk_div5.hw,
+		[CLKID_FCLK_DIV7]		= &a1_fclk_div7.hw,
+		[CLKID_FCLK_DIV2_DIV]		= &a1_fclk_div2_div.hw,
+		[CLKID_FCLK_DIV3_DIV]		= &a1_fclk_div3_div.hw,
+		[CLKID_FCLK_DIV5_DIV]		= &a1_fclk_div5_div.hw,
+		[CLKID_FCLK_DIV7_DIV]		= &a1_fclk_div7_div.hw,
+		[CLKID_SYS_B_SEL]		= &a1_sys_b_sel.hw,
+		[CLKID_SYS_B_DIV]		= &a1_sys_b_div.hw,
+		[CLKID_SYS_B]			= &a1_sys_b.hw,
+		[CLKID_SYS_A_SEL]		= &a1_sys_a_sel.hw,
+		[CLKID_SYS_A_DIV]		= &a1_sys_a_div.hw,
+		[CLKID_SYS_A]			= &a1_sys_a.hw,
+		[CLKID_SYS_CLK]			= &a1_sys_clk.hw,
+		[CLKID_XTAL_CLKTREE]		= &a1_xtal_clktree.hw,
+		[CLKID_XTAL_FIXPLL]		= &a1_xtal_fixpll.hw,
+		[CLKID_XTAL_USB_PHY]		= &a1_xtal_usb_phy.hw,
+		[CLKID_XTAL_USB_CTRL]		= &a1_xtal_usb_ctrl.hw,
+		[CLKID_XTAL_HIFIPLL]		= &a1_xtal_hifipll.hw,
+		[CLKID_XTAL_SYSPLL]		= &a1_xtal_syspll.hw,
+		[CLKID_XTAL_DDS]		= &a1_xtal_dds.hw,
+		[CLKID_CLKTREE]			= &a1_clk_tree.hw,
+		[CLKID_RESET_CTRL]		= &a1_reset_ctrl.hw,
+		[CLKID_ANALOG_CTRL]		= &a1_analog_ctrl.hw,
+		[CLKID_PWR_CTRL]		= &a1_pwr_ctrl.hw,
+		[CLKID_PAD_CTRL]		= &a1_pad_ctrl.hw,
+		[CLKID_SYS_CTRL]		= &a1_sys_ctrl.hw,
+		[CLKID_TEMP_SENSOR]		= &a1_temp_sensor.hw,
+		[CLKID_AM2AXI_DIV]		= &a1_am2axi_dev.hw,
+		[CLKID_SPICC_B]			= &a1_spicc_b.hw,
+		[CLKID_SPICC_A]			= &a1_spicc_a.hw,
+		[CLKID_CLK_MSR]			= &a1_clk_msr.hw,
+		[CLKID_AUDIO]			= &a1_audio.hw,
+		[CLKID_JTAG_CTRL]		= &a1_jtag_ctrl.hw,
+		[CLKID_SARADC]			= &a1_saradc.hw,
+		[CLKID_PWM_EF]			= &a1_pwm_ef.hw,
+		[CLKID_PWM_CD]			= &a1_pwm_cd.hw,
+		[CLKID_PWM_AB]			= &a1_pwm_ab.hw,
+		[CLKID_CEC]			= &a1_cec.hw,
+		[CLKID_I2C_S]			= &a1_i2c_s.hw,
+		[CLKID_IR_CTRL]			= &a1_ir_ctrl.hw,
+		[CLKID_I2C_M_D]			= &a1_i2c_m_d.hw,
+		[CLKID_I2C_M_C]			= &a1_i2c_m_c.hw,
+		[CLKID_I2C_M_B]			= &a1_i2c_m_b.hw,
+		[CLKID_I2C_M_A]			= &a1_i2c_m_a.hw,
+		[CLKID_ACODEC]			= &a1_acodec.hw,
+		[CLKID_OTP]			= &a1_otp.hw,
+		[CLKID_SD_EMMC_A]		= &a1_sd_emmc_a.hw,
+		[CLKID_USB_PHY]			= &a1_usb_phy.hw,
+		[CLKID_USB_CTRL]		= &a1_usb_ctrl.hw,
+		[CLKID_SYS_DSPB]		= &a1_sys_dspb.hw,
+		[CLKID_SYS_DSPA]		= &a1_sys_dspa.hw,
+		[CLKID_DMA]			= &a1_dma.hw,
+		[CLKID_IRQ_CTRL]		= &a1_irq_ctrl.hw,
+		[CLKID_NIC]			= &a1_nic.hw,
+		[CLKID_GIC]			= &a1_gic.hw,
+		[CLKID_UART_C]			= &a1_uart_c.hw,
+		[CLKID_UART_B]			= &a1_uart_b.hw,
+		[CLKID_UART_A]			= &a1_uart_a.hw,
+		[CLKID_SYS_PSRAM]		= &a1_sys_psram.hw,
+		[CLKID_RSA]			= &a1_rsa.hw,
+		[CLKID_CORESIGHT]		= &a1_coresight.hw,
+		[CLKID_AM2AXI_VAD]		= &a1_am2axi_vad.hw,
+		[CLKID_AUDIO_VAD]		= &a1_audio_vad.hw,
+		[CLKID_AXI_DMC]			= &a1_axi_dmc.hw,
+		[CLKID_AXI_PSRAM]		= &a1_axi_psram.hw,
+		[CLKID_RAMB]			= &a1_ramb.hw,
+		[CLKID_RAMA]			= &a1_rama.hw,
+		[CLKID_AXI_SPIFC]		= &a1_axi_spifc.hw,
+		[CLKID_AXI_NIC]			= &a1_axi_nic.hw,
+		[CLKID_AXI_DMA]			= &a1_axi_dma.hw,
+		[CLKID_CPU_CTRL]		= &a1_cpu_ctrl.hw,
+		[CLKID_ROM]			= &a1_rom.hw,
+		[CLKID_PROC_I2C]		= &a1_prod_i2c.hw,
+		[CLKID_DSPA_A_SEL]		= &a1_dspa_a_sel.hw,
+		[CLKID_DSPA_A_DIV]		= &a1_dspa_a_div.hw,
+		[CLKID_DSPA_A]			= &a1_dspa_a.hw,
+		[CLKID_DSPA_B_SEL]		= &a1_dspa_b_sel.hw,
+		[CLKID_DSPA_B_DIV]		= &a1_dspa_b_div.hw,
+		[CLKID_DSPA_B]			= &a1_dspa_b.hw,
+		[CLKID_DSPA_SEL]		= &a1_dspa_sel.hw,
+		[CLKID_DSPB_A_SEL]		= &a1_dspb_a_sel.hw,
+		[CLKID_DSPB_A_DIV]		= &a1_dspb_a_div.hw,
+		[CLKID_DSPB_A]			= &a1_dspb_a.hw,
+		[CLKID_DSPB_B_SEL]		= &a1_dspb_b_sel.hw,
+		[CLKID_DSPB_B_DIV]		= &a1_dspb_b_div.hw,
+		[CLKID_DSPB_B]			= &a1_dspb_b.hw,
+		[CLKID_DSPB_SEL]		= &a1_dspb_sel.hw,
+		[CLKID_DSPA_EN_DSPA]		= &a1_dspa_en_dspa.hw,
+		[CLKID_DSPA_EN_NIC]		= &a1_dspa_en_nic.hw,
+		[CLKID_DSPB_EN_DSPB]		= &a1_dspb_en_dspb.hw,
+		[CLKID_DSPB_EN_NIC]		= &a1_dspb_en_nic.hw,
+		[CLKID_24M]			= &a1_24m.hw,
+		[CLKID_24M_DIV2]		= &a1_24m_div2.hw,
+		[CLKID_12M]			= &a1_12m.hw,
+		[CLKID_DIV2_PRE]		= &a1_fclk_div2_divn_pre.hw,
+		[CLKID_FCLK_DIV2_DIVN]		= &a1_fclk_div2_divn.hw,
+		[CLKID_GEN_SEL]			= &a1_gen_sel.hw,
+		[CLKID_GEN_DIV]			= &a1_gen_div.hw,
+		[CLKID_GEN]			= &a1_gen.hw,
+		[CLKID_SARADC_SEL]		= &a1_saradc_sel.hw,
+		[CLKID_SARADC_DIV]		= &a1_saradc_div.hw,
+		[CLKID_SARADC_CLK]		= &a1_saradc_clk.hw,
+		[CLKID_PWM_A_SEL]		= &a1_pwm_a_sel.hw,
+		[CLKID_PWM_A_DIV]		= &a1_pwm_a_div.hw,
+		[CLKID_PWM_A]			= &a1_pwm_a.hw,
+		[CLKID_PWM_B_SEL]		= &a1_pwm_b_sel.hw,
+		[CLKID_PWM_B_DIV]		= &a1_pwm_b_div.hw,
+		[CLKID_PWM_B]			= &a1_pwm_b.hw,
+		[CLKID_PWM_C_SEL]		= &a1_pwm_c_sel.hw,
+		[CLKID_PWM_C_DIV]		= &a1_pwm_c_div.hw,
+		[CLKID_PWM_C]			= &a1_pwm_c.hw,
+		[CLKID_PWM_D_SEL]		= &a1_pwm_d_sel.hw,
+		[CLKID_PWM_D_DIV]		= &a1_pwm_d_div.hw,
+		[CLKID_PWM_D]			= &a1_pwm_d.hw,
+		[CLKID_PWM_E_SEL]		= &a1_pwm_e_sel.hw,
+		[CLKID_PWM_E_DIV]		= &a1_pwm_e_div.hw,
+		[CLKID_PWM_E]			= &a1_pwm_e.hw,
+		[CLKID_PWM_F_SEL]		= &a1_pwm_f_sel.hw,
+		[CLKID_PWM_F_DIV]		= &a1_pwm_f_div.hw,
+		[CLKID_PWM_F]			= &a1_pwm_f.hw,
+		[CLKID_SPICC_SEL]		= &a1_spicc_sel.hw,
+		[CLKID_SPICC_DIV]		= &a1_spicc_div.hw,
+		[CLKID_SPICC_SEL2]		= &a1_spicc_sel2.hw,
+		[CLKID_SPICC]			= &a1_spicc.hw,
+		[CLKID_TS_DIV]			= &a1_ts_div.hw,
+		[CLKID_TS]			= &a1_ts.hw,
+		[CLKID_SPIFC_SEL]		= &a1_spifc_sel.hw,
+		[CLKID_SPIFC_DIV]		= &a1_spifc_div.hw,
+		[CLKID_SPIFC_SEL2]		= &a1_spifc_sel2.hw,
+		[CLKID_SPIFC]			= &a1_spifc.hw,
+		[CLKID_USB_BUS_SEL]		= &a1_usb_bus_sel.hw,
+		[CLKID_USB_BUS_DIV]		= &a1_usb_bus_div.hw,
+		[CLKID_USB_BUS]			= &a1_usb_bus.hw,
+		[CLKID_SD_EMMC_SEL]		= &a1_sd_emmc_sel.hw,
+		[CLKID_SD_EMMC_DIV]		= &a1_sd_emmc_div.hw,
+		[CLKID_SD_EMMC_SEL2]		= &a1_sd_emmc_sel2.hw,
+		[CLKID_SD_EMMC]			= &a1_sd_emmc.hw,
+		[CLKID_PSRAM_SEL]		= &a1_psram_sel.hw,
+		[CLKID_PSRAM_DIV]		= &a1_psram_div.hw,
+		[CLKID_PSRAM_SEL2]		= &a1_psram_sel2.hw,
+		[CLKID_PSRAM]			= &a1_psram.hw,
+		[CLKID_DMC_SEL]			= &a1_dmc_sel.hw,
+		[CLKID_DMC_DIV]			= &a1_dmc_div.hw,
+		[CLKID_DMC_SEL2]		= &a1_dmc_sel2.hw,
+		[CLKID_DMC]			= &a1_dmc.hw,
+		[CLKID_RTC_32K_CLKIN]		= &a1_rtc_32k_clkin.hw,
+		[CLKID_RTC_32K_DIV]		= &a1_rtc_32k_div.hw,
+		[CLKID_RTC_32K_XTAL]		= &a1_rtc_32k_xtal.hw,
+		[CLKID_RTC_32K_SEL]		= &a1_rtc_32k_sel.hw,
+		[CLKID_RTC_CLK]			= &a1_rtc_clk.hw,
+		[CLKID_CECA_32K_CLKIN]		= &a1_ceca_32k_clkin.hw,
+		[CLKID_CECA_32K_DIV]		= &a1_ceca_32k_div.hw,
+		[CLKID_CECA_32K_SEL_PRE]	= &a1_ceca_32k_sel_pre.hw,
+		[CLKID_CECA_32K_SEL]		= &a1_ceca_32k_sel.hw,
+		[CLKID_CECA_32K]		= &a1_ceca_32k_clkout.hw,
+		[CLKID_CECB_32K_CLKIN]		= &a1_cecb_32k_clkin.hw,
+		[CLKID_CECB_32K_DIV]		= &a1_cecb_32k_div.hw,
+		[CLKID_CECB_32K_SEL_PRE]	= &a1_cecb_32k_sel_pre.hw,
+		[CLKID_CECB_32K_SEL]		= &a1_cecb_32k_sel.hw,
+		[CLKID_CECB_32K]		= &a1_cecb_32k_clkout.hw,
+		[NR_CLKS]			= NULL,
+	},
+	.num = NR_CLKS,
+};
+
+/* Convenience table to populate regmap in .probe
+ * Peripheral clock register base address is 0xfe000800
+ */
+static struct clk_regmap *const a1_clk_regmaps[] = {
+	&a1_xtal_clktree,
+	&a1_xtal_fixpll,
+	&a1_xtal_usb_phy,
+	&a1_xtal_usb_ctrl,
+	&a1_xtal_hifipll,
+	&a1_xtal_syspll,
+	&a1_xtal_dds,
+	&a1_clk_tree,
+	&a1_reset_ctrl,
+	&a1_analog_ctrl,
+	&a1_pwr_ctrl,
+	&a1_sys_ctrl,
+	&a1_temp_sensor,
+	&a1_am2axi_dev,
+	&a1_spicc_b,
+	&a1_spicc_a,
+	&a1_clk_msr,
+	&a1_audio,
+	&a1_jtag_ctrl,
+	&a1_saradc,
+	&a1_pwm_ef,
+	&a1_pwm_cd,
+	&a1_pwm_ab,
+	&a1_cec,
+	&a1_i2c_s,
+	&a1_ir_ctrl,
+	&a1_i2c_m_d,
+	&a1_i2c_m_c,
+	&a1_i2c_m_b,
+	&a1_i2c_m_a,
+	&a1_acodec,
+	&a1_otp,
+	&a1_sd_emmc_a,
+	&a1_usb_phy,
+	&a1_usb_ctrl,
+	&a1_sys_dspb,
+	&a1_sys_dspa,
+	&a1_dma,
+	&a1_irq_ctrl,
+	&a1_nic,
+	&a1_gic,
+	&a1_uart_c,
+	&a1_uart_b,
+	&a1_uart_a,
+	&a1_sys_psram,
+	&a1_rsa,
+	&a1_coresight,
+	&a1_am2axi_vad,
+	&a1_audio_vad,
+	&a1_axi_dmc,
+	&a1_axi_psram,
+	&a1_ramb,
+	&a1_rama,
+	&a1_axi_spifc,
+	&a1_axi_nic,
+	&a1_axi_dma,
+	&a1_cpu_ctrl,
+	&a1_rom,
+	&a1_prod_i2c,
+	&a1_dspa_a_sel,
+	&a1_dspa_a_div,
+	&a1_dspa_a,
+	&a1_dspa_b_sel,
+	&a1_dspa_b_div,
+	&a1_dspa_b,
+	&a1_dspa_sel,
+	&a1_dspb_a_sel,
+	&a1_dspb_a_div,
+	&a1_dspb_a,
+	&a1_dspb_b_sel,
+	&a1_dspb_b_div,
+	&a1_dspb_b,
+	&a1_dspb_sel,
+	&a1_dspa_en_dspa,
+	&a1_dspa_en_nic,
+	&a1_dspb_en_dspb,
+	&a1_dspb_en_nic,
+	&a1_24m,
+	&a1_12m,
+	&a1_fclk_div2_divn_pre,
+	&a1_fclk_div2_divn,
+	&a1_gen_sel,
+	&a1_gen_div,
+	&a1_gen,
+	&a1_saradc_sel,
+	&a1_saradc_div,
+	&a1_saradc_clk,
+	&a1_pwm_a_sel,
+	&a1_pwm_a_div,
+	&a1_pwm_a,
+	&a1_pwm_b_sel,
+	&a1_pwm_b_div,
+	&a1_pwm_b,
+	&a1_pwm_c_sel,
+	&a1_pwm_c_div,
+	&a1_pwm_c,
+	&a1_pwm_d_sel,
+	&a1_pwm_d_div,
+	&a1_pwm_d,
+	&a1_pwm_e_sel,
+	&a1_pwm_e_div,
+	&a1_pwm_e,
+	&a1_pwm_f_sel,
+	&a1_pwm_f_div,
+	&a1_pwm_f,
+	&a1_spicc_sel,
+	&a1_spicc_div,
+	&a1_spicc_sel2,
+	&a1_spicc,
+	&a1_ts_div,
+	&a1_ts,
+	&a1_spifc_sel,
+	&a1_spifc_div,
+	&a1_spifc_sel2,
+	&a1_spifc,
+	&a1_usb_bus_sel,
+	&a1_usb_bus_div,
+	&a1_usb_bus,
+	&a1_sd_emmc_sel,
+	&a1_sd_emmc_div,
+	&a1_sd_emmc_sel2,
+	&a1_sd_emmc,
+	&a1_psram_sel,
+	&a1_psram_div,
+	&a1_psram_sel2,
+	&a1_psram,
+	&a1_dmc_sel,
+	&a1_dmc_div,
+	&a1_dmc_sel2,
+	&a1_dmc,
+	&a1_sys_b_sel,
+	&a1_sys_b_div,
+	&a1_sys_b,
+	&a1_sys_a_sel,
+	&a1_sys_a_div,
+	&a1_sys_a,
+	&a1_sys_clk,
+	&a1_rtc_32k_clkin,
+	&a1_rtc_32k_div,
+	&a1_rtc_32k_xtal,
+	&a1_rtc_32k_sel,
+	&a1_rtc_clk,
+	&a1_ceca_32k_clkin,
+	&a1_ceca_32k_div,
+	&a1_ceca_32k_sel_pre,
+	&a1_ceca_32k_sel,
+	&a1_ceca_32k_clkout,
+	&a1_cecb_32k_clkin,
+	&a1_cecb_32k_div,
+	&a1_cecb_32k_sel_pre,
+	&a1_cecb_32k_sel,
+	&a1_cecb_32k_clkout,
+};
+
+/*
+ * cpu clock register base address is 0xfd000080
+ */
+static struct clk_regmap *const a1_cpu_clk_regmaps[] = {
+	/* TODO */
+};
+
+/*
+ * pll clock register base address is 0xfe007c00
+ */
+static struct clk_regmap *const a1_pll_clk_regmaps[] = {
+	&a1_fixed_pll_dco,
+	&a1_fixed_pll,
+	&a1_hifi_pll,
+	&a1_fclk_div2,
+	&a1_fclk_div3,
+	&a1_fclk_div5,
+	&a1_fclk_div7,
+};
+
+static struct regmap_config clkc_regmap_config = {
+	.reg_bits       = 32,
+	.val_bits       = 32,
+	.reg_stride     = 4,
+};
+
+static struct regmap *a1_regmap_resource(struct device *dev, char *name)
+{
+	struct resource res;
+	void __iomem *base;
+	int i;
+	struct device_node *node = dev->of_node;
+
+	i = of_property_match_string(node, "reg-names", name);
+	if (of_address_to_resource(node, i, &res))
+		return ERR_PTR(-ENOENT);
+
+	base = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(base))
+		return ERR_CAST(base);
+
+	clkc_regmap_config.max_register = resource_size(&res) - 4;
+	clkc_regmap_config.name = devm_kasprintf(dev, GFP_KERNEL,
+						 "%s-%s", node->name,
+						 name);
+	if (!clkc_regmap_config.name)
+		return ERR_PTR(-ENOMEM);
+
+	return devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
+}
+
+static int a1_clkc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct regmap *peripheral_map, *pll_map, *cpu_map;
+	int ret, i;
+
+	/* Get regmap for different clock area */
+	peripheral_map = a1_regmap_resource(dev, "peripheral");
+	if (IS_ERR(peripheral_map)) {
+		dev_err(dev, "peripheral clk registers not found\n");
+		return PTR_ERR(peripheral_map);
+	}
+
+	pll_map = a1_regmap_resource(dev, "pll");
+	if (IS_ERR(pll_map)) {
+		dev_err(dev, "pll clk registers not found\n");
+		return PTR_ERR(pll_map);
+	}
+
+	cpu_map = a1_regmap_resource(dev, "cpu");
+	if (IS_ERR(cpu_map)) {
+		dev_err(dev, "cpu clk registers not found\n");
+		return PTR_ERR(cpu_map);
+	}
+
+	/* Populate regmap for the regmap backed clocks */
+	for (i = 0; i < ARRAY_SIZE(a1_clk_regmaps); i++)
+		a1_clk_regmaps[i]->map = peripheral_map;
+
+	for (i = 0; i < ARRAY_SIZE(a1_cpu_clk_regmaps); i++)
+		a1_cpu_clk_regmaps[i]->map = cpu_map;
+
+	for (i = 0; i < ARRAY_SIZE(a1_pll_clk_regmaps); i++)
+		a1_pll_clk_regmaps[i]->map = pll_map;
+
+	for (i = 0; i < a1_hw_onecell_data.num; i++) {
+		/* array might be sparse */
+		if (!a1_hw_onecell_data.hws[i])
+			continue;
+
+		ret = devm_clk_hw_register(dev, a1_hw_onecell_data.hws[i]);
+		if (ret) {
+			dev_err(dev, "Clock registration failed\n");
+			return ret;
+		}
+	}
+
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+					   &a1_hw_onecell_data);
+}
+
+static const struct of_device_id clkc_match_table[] = {
+	{ .compatible = "amlogic,a1-clkc" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver a1_driver = {
+	.probe		= a1_clkc_probe,
+	.driver		= {
+		.name	= "a1-clkc",
+		.of_match_table = clkc_match_table,
+	},
+};
+
+builtin_platform_driver(a1_driver);
diff --git a/drivers/clk/meson/a1.h b/drivers/clk/meson/a1.h
new file mode 100644
index 0000000..f2291c4
--- /dev/null
+++ b/drivers/clk/meson/a1.h
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __A1_H
+#define __A1_H
+
+/*
+ * peripheral clock controller register address
+ * APB_BASE:  APB0_BASE_ADDR = 0xfe000800
+ */
+#define SYS_OSCIN_CTRL			0x0
+#define RTC_BY_OSCIN_CTRL0		0x4
+#define RTC_BY_OSCIN_CTRL1		0x8
+#define RTC_CTRL			0xc
+#define SYS_CLK_CTRL0			0x10
+#define AXI_CLK_CTRL0			0x14
+#define SYS_CLK_EN0			0x1c
+#define SYS_CLK_EN1			0x20
+#define AXI_CLK_EN			0x24
+#define DSPA_CLK_EN			0x28
+#define DSPB_CLK_EN			0x2c
+#define DSPA_CLK_CTRL0			0x30
+#define DSPB_CLK_CTRL0			0x34
+#define CLK12_24_CTRL			0x38
+#define GEN_CLK_CTRL			0x3c
+#define TIMESTAMP_CTRL0			0x40
+#define TIMESTAMP_CTRL1			0x44
+#define TIMESTAMP_CTRL2			0x48
+#define TIMESTAMP_VAL0			0x4c
+#define TIMESTAMP_VAL1			0x50
+#define TIMEBASE_CTRL0			0x54
+#define TIMEBASE_CTRL1			0x58
+#define SAR_ADC_CLK_CTRL		0xc0
+#define PWM_CLK_AB_CTRL			0xc4
+#define PWM_CLK_CD_CTRL			0xc8
+#define PWM_CLK_EF_CTRL			0xcc
+#define SPICC_CLK_CTRL			0xd0
+#define TS_CLK_CTRL			0xd4
+#define SPIFC_CLK_CTRL			0xd8
+#define USB_BUSCLK_CTRL			0xdc
+#define SD_EMMC_CLK_CTRL		0xe0
+#define CECA_CLK_CTRL0			0xe4
+#define CECA_CLK_CTRL1			0xe8
+#define CECB_CLK_CTRL0			0xec
+#define CECB_CLK_CTRL1			0xf0
+#define PSRAM_CLK_CTRL			0xf4
+#define DMC_CLK_CTRL			0xf8
+#define FCLK_DIV1_SEL			0xfc
+#define TST_CTRL			0x100
+/*
+ * For PLL register offset
+ * APB_BASE:  APB0_BASE_ADDR = 0xfe007c00
+ */
+#define ANACTRL_FIXPLL_CTRL0		0x80
+#define ANACTRL_FIXPLL_CTRL1		0x84
+#define ANACTRL_FIXPLL_CTRL2		0x88
+#define ANACTRL_FIXPLL_CTRL3		0x8c
+#define ANACTRL_FIXPLL_CTRL4		0x90
+#define ANACTRL_FIXPLL_STS		0x94
+#define ANACTRL_SYSPLL_CTRL0		0x100
+#define ANACTRL_SYSPLL_CTRL1		0x104
+#define ANACTRL_SYSPLL_CTRL2		0x108
+#define ANACTRL_SYSPLL_CTRL3		0x10c
+#define ANACTRL_SYSPLL_CTRL4		0x110
+#define ANACTRL_SYSPLL_STS		0x114
+#define ANACTRL_HIFIPLL_CTRL0		0x140
+#define ANACTRL_HIFIPLL_CTRL1		0x144
+#define ANACTRL_HIFIPLL_CTRL2		0x148
+#define ANACTRL_HIFIPLL_CTRL3		0x14c
+#define ANACTRL_HIFIPLL_CTRL4		0x150
+#define ANACTRL_HIFIPLL_STS		0x154
+#define ANACTRL_AUDDDS_CTRL0		0x180
+#define ANACTRL_AUDDDS_CTRL1		0x184
+#define ANACTRL_AUDDDS_CTRL2		0x188
+#define ANACTRL_AUDDDS_CTRL3		0x18c
+#define ANACTRL_AUDDDS_CTRL4		0x190
+#define ANACTRL_AUDDDS_STS		0x194
+#define ANACTRL_MISCTOP_CTRL0		0x1c0
+#define ANACTRL_POR_CNTL		0x208
+/*
+ * CPU clok register offset
+ * APB_BASE:  APB1_BASE_ADDR = 0xfd000080
+ */
+#define CPUCTRL_CLK_CTRL0		0x00
+#define CPUCTRL_CLK_CTRL1		0x04
+#define CPUCTRL_CLK_CTRL2		0x08
+#define CPUCTRL_CLK_CTRL3		0x0c
+#define CPUCTRL_CLK_CTRL4		0x10
+#define CPUCTRL_CLK_CTRL5		0x14
+#define CPUCTRL_CLK_CTRL6		0x18
+#define CPUCTRL_CLK_CTRL7		0x1c
+
+#define CLKID_FIXED_PLL_DCO		0
+#define CLKID_SYS_A_SEL			10
+#define CLKID_SYS_A_DIV			11
+#define CLKID_SYS_A			12
+#define CLKID_SYS_B_SEL			13
+#define CLKID_SYS_B_DIV			14
+#define CLKID_SYS_B			15
+#define CLKID_XTAL_CLKTREE		18
+#define CLKID_XTAL_FIXPLL		19
+#define CLKID_XTAL_USB_PHY		20
+#define CLKID_XTAL_USB_CTRL		21
+#define CLKID_XTAL_HIFIPLL		22
+#define CLKID_XTAL_SYSPLL		23
+#define CLKID_XTAL_DDS			24
+#define CLKID_DSPA_A_SEL		78
+#define CLKID_DSPA_A_DIV		79
+#define CLKID_DSPA_A			80
+#define CLKID_DSPA_B_SEL		81
+#define CLKID_DSPA_B_DIV		82
+#define CLKID_DSPA_B			83
+#define CLKID_DSPB_A_SEL		85
+#define CLKID_DSPB_A_DIV		86
+#define CLKID_DSPB_A			87
+#define CLKID_DSPB_B_SEL		88
+#define CLKID_DSPB_B_DIV		89
+#define CLKID_DSPB_B			90
+#define CLKID_RTC_32K_CLKIN		96
+#define CLKID_RTC_32K_DIV		97
+#define CLKID_RTC_32K_XTAL		98
+#define CLKID_RTC_32K_SEL		99
+#define CLKID_CECB_32K_CLKIN		106
+#define CLKID_CECB_32K_DIV		107
+#define CLKID_CECB_32K_SEL_PRE		108
+#define CLKID_CECB_32K_SEL		109
+#define CLKID_CECA_32K_CLKIN		101
+#define CLKID_CECA_32K_DIV		102
+#define CLKID_CECA_32K_SEL_PRE		103
+#define CLKID_CECA_32K_SEL		104
+#define CLKID_DIV2_PRE			113
+#define CLKID_24M_DIV2			115
+#define CLKID_GEN_SEL			116
+#define CLKID_GEN_DIV			117
+#define CLKID_SARADC_DIV		120
+#define CLKID_PWM_A_SEL			122
+#define CLKID_PWM_A_DIV			123
+#define CLKID_PWM_B_SEL			125
+#define CLKID_PWM_B_DIV			126
+#define CLKID_PWM_C_SEL			128
+#define CLKID_PWM_C_DIV			129
+#define CLKID_PWM_D_SEL			131
+#define CLKID_PWM_D_DIV			132
+#define CLKID_PWM_E_SEL			134
+#define CLKID_PWM_E_DIV			135
+#define CLKID_PWM_F_SEL			137
+#define CLKID_PWM_F_DIV			138
+#define CLKID_SPICC_SEL			140
+#define CLKID_SPICC_DIV			141
+#define CLKID_SPICC_SEL2		142
+#define CLKID_TS_DIV			144
+#define CLKID_SPIFC_SEL			146
+#define CLKID_SPIFC_DIV			147
+#define CLKID_SPIFC_SEL2		148
+#define CLKID_USB_BUS_SEL		150
+#define CLKID_USB_BUS_DIV		151
+#define CLKID_SD_EMMC_SEL		153
+#define CLKID_SD_EMMC_DIV		154
+#define CLKID_SD_EMMC_SEL2		155
+#define CLKID_PSRAM_SEL			157
+#define CLKID_PSRAM_DIV			158
+#define CLKID_PSRAM_SEL2		159
+#define CLKID_DMC_SEL			161
+#define CLKID_DMC_DIV			162
+#define CLKID_DMC_SEL2			163
+#define NR_CLKS				165
+
+#include <dt-bindings/clock/a1-clkc.h>
+
+#endif /* __A1_H */
-- 
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related

* Re: [PATCH net v2] net: stmmac: selftests: Flow Control test can also run with ASYM Pause
From: David Miller @ 2019-09-25 11:58 UTC (permalink / raw)
  To: Jose.Abreu
  Cc: Joao.Pinto, alexandre.torgue, netdev, linux-kernel,
	mcoquelin.stm32, peppe.cavallaro, linux-stm32, linux-arm-kernel
In-Reply-To: <efc49b6ea500115ff1442ddebe9dc7d956eb19e9.1569224900.git.Jose.Abreu@synopsys.com>

From: Jose Abreu <Jose.Abreu@synopsys.com>
Date: Mon, 23 Sep 2019 09:49:08 +0200

> The Flow Control selftest is also available with ASYM Pause. Lets add
> this check to the test and fix eventual false positive failures.
> 
> Fixes: 091810dbded9 ("net: stmmac: Introduce selftests support")
> Signed-off-by: Jose Abreu <Jose.Abreu@synopsys.com>

Applied.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v3] PCI: aardvark: Fix PCI_EXP_RTCTL register configuration
From: Thomas Petazzoni @ 2019-09-25 12:08 UTC (permalink / raw)
  To: Remi Pommarel
  Cc: Ellie Reeves, Lorenzo Pieralisi, linux-pci, linux-kernel,
	Bjorn Helgaas, linux-arm-kernel
In-Reply-To: <20190614101059.1664-1-repk@triplefau.lt>

On Fri, 14 Jun 2019 12:10:59 +0200
Remi Pommarel <repk@triplefau.lt> wrote:

> PCI_EXP_RTCTL is used to activate PME interrupt only, so writing into it
> should not modify other interrupts' mask. The ISR mask polarity was also
> inverted, when PCI_EXP_RTCTL_PMEIE is set PCIE_MSG_PM_PME_MASK mask bit
> should actually be cleared.
> 
> Fixes: 8a3ebd8de328 ("PCI: aardvark: Implement emulated root PCI bridge config space")
> Signed-off-by: Remi Pommarel <repk@triplefau.lt>

Sorry for the long delay, but:

Acked-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>

I did verify that indeed the polarity of the PME interrupt bit is
different between the standard PCI_EXP_RTCTL register and the
Aardvark-specific ISR0 mask register. And obviously, we shouldn't
clobber other bits of the ISR0 mask register when changing the PME
interrupt enable/disable state.

I did a quick test with a E1000E NIC and it worked fine.

Thanks!

Thomas
-- 
Thomas Petazzoni, CTO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox