Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 5/5] ARM: dts: imx7-colibri: add NAND support
From: Stefan Agner @ 2017-04-22  1:23 UTC (permalink / raw)
  To: dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	marek.vasut-Re5JQEeQqe8AvxtiuMwx3w, richard-/L3Ra7n9ekc,
	cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	shawnguo-DgEjT+Ai2ygdnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	han.xu-3arQi8VN3Tc, fabio.estevam-KZfg59tc24xl57MIdRCFDg,
	LW-bxm8fMRDkQLDiMYJYoSAnRvVK+yQ3ZXh,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Stefan Agner
In-Reply-To: <20170422012338.4635-1-stefan-XLVq0VzYD2Y@public.gmane.org>

The Colibri iMX7 modules come with 512MB on-module SLC NAND flash
populated. Make use of it by enabling the GPMI controller.

Signed-off-by: Stefan Agner <stefan-XLVq0VzYD2Y@public.gmane.org>
---
 arch/arm/boot/dts/imx7-colibri.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index 2d87489f9105..ad4ce19d455b 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -106,6 +106,15 @@
 	fsl,magic-packet;
 };
 
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	fsl,use-minimum-ecc;
+	nand-on-flash-bbt;
+	nand-ecc-mode = "hw";
+	status = "okay";
+};
+
 &i2c1 {
 	clock-frequency = <100000>;
 	pinctrl-names = "default";
-- 
2.12.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [PATCH V3 2/2] ARM64: dts: hi6220-hikey: Add clock binding for the pmic mfd
From: Stephen Boyd @ 2017-04-22  2:02 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: mturquette, lee.jones, xuwei5, linux-kernel, linux-clk,
	devicetree, linux-arm-kernel
In-Reply-To: <1492449567-31399-2-git-send-email-daniel.lezcano@linaro.org>

On 04/17, Daniel Lezcano wrote:
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
>  Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt | 6 ++++++
>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts             | 1 +
>  2 files changed, 7 insertions(+)
> 

I take it this goes through arm-soc? Not sure why I'm on To:
line.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH V2] clk: hi6220: Add the hi655x's pmic clock
From: Stephen Boyd @ 2017-04-22  2:14 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: mturquette, lee.jones, xuwei5, devicetree, linux-kernel,
	linux-arm-kernel, linux-clk
In-Reply-To: <20170419194737.GB2523@mai>

On 04/19, Daniel Lezcano wrote:
> On Wed, Apr 19, 2017 at 09:00:05AM -0700, Stephen Boyd wrote:
> > On 04/16, Daniel Lezcano wrote:
> > > On Wed, Apr 12, 2017 at 08:02:45AM -0700, Stephen Boyd wrote:
> > > > On 04/08, Daniel Lezcano wrote:
> 
> [ ... ]
> 
> > > > > +	ret = clk_hw_register_clkdev(&hi655x_clk->clk_hw, clk_name, NULL);
> > > > 
> > > > Missed this last time. Do you use this clkdev lookup? The name is
> > > > usually supposed to be based on what the device is expecting,
> > > > instead of clk_name, and we would want some device name for the
> > > > third argument here.
> > > 
> > > I'm not sure to get your comment. Are you saying the clk_name should be the
> > > third argument?
> > > 
> > > 
> > 
> > Sorry, no. I meant that con_id is typically something like "core"
> > or "ahb" or something like that, and dev_id is something like
> > "a456002.pmic_device" or whatever dev_name(pmic_dev) would return for
> > the consuming device. That way when we call clk_get(dev, "core")
> > it will find the lookup with "core" and "a456002.pmic_device" to
> > match up the clk lookup.
> > 
> > If anything, the clk_name should just go into the con_id for now,
> > and then it will need to be a globally unique identifier for the
> > clk. But that is going against how clkdev is supposed to be used.
> > Hence the question if you even need to use it. If not, just don't
> > add it. I can fix up v3 of this patch to put clk_name back at
> > con_id if you like. No need to resend.
> 
> Ok, I'm not very used with the CCF, so perhaps clk_name is not needed at all. I
> gave a try with the following combination:
> 
>  - con_id = NULL, dev_id = clk_name
>  - con_id = clk_name, dev_id = NULL
>  - con_id = NULL, dev_id = NULL
> 
> All worked.
> 
> And finally I removed the clk_hw_register_clkdev() call and it worked also.
> 
> So I'm not sure about this function.
> 

If you've removed it and it still works, then it means you're
using DT and you don't need clkdev at all. That's the of_clk
provider thing that you're using. So I'll go remove this clkdev
lookup because it's not used. If someone needs it they can add it
later.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH RFC 1/7] clk: samsung: Add enable/disable operation for PLL36XX clocks
From: Stephen Boyd @ 2017-04-22  2:51 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-samsung-soc, linux-clk, dri-devel, alsa-devel, devicetree,
	inki.dae, sw0312.kim, cw00.choi, javier, krzk, jy0922.shim,
	broonie, robh+dt, b.zolnierkie
In-Reply-To: <1492795191-31298-2-git-send-email-s.nawrocki@samsung.com>

On 04/21, Sylwester Nawrocki wrote:
> The existing enable/disable ops for PLL35XX are made more generic
> and used also for PLL36XX. This fixes issues in the kernel with
> PLL36XX PLLs when the PLL has not been already enabled by bootloader.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/clk/samsung/clk-pll.c | 85 +++++++++++++++++++++++++------------------
>  1 file changed, 49 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
> index 5229089..10c76eb 100644
> --- a/drivers/clk/samsung/clk-pll.c
> +++ b/drivers/clk/samsung/clk-pll.c
> @@ -23,6 +23,10 @@ struct samsung_clk_pll {
>  	struct clk_hw		hw;
>  	void __iomem		*lock_reg;
>  	void __iomem		*con_reg;
> +	/* PLL enable control bit offset in @con_reg register */
> +	unsigned short		enable_offs;
> +	/* PLL lock status bit offset in @con_reg register */
> +	unsigned short		lock_offs;
>  	enum samsung_pll_type	type;
>  	unsigned int		rate_count;
>  	const struct samsung_pll_rate_table *rate_table;
> @@ -61,6 +65,34 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
>  	return rate_table[i - 1].rate;
>  }
>  
> +static int samsung_pll3xxx_enable(struct clk_hw *hw)
> +{
> +	struct samsung_clk_pll *pll = to_clk_pll(hw);
> +	u32 tmp;
> +
> +	tmp = readl_relaxed(pll->con_reg);
> +	tmp |= BIT(pll->enable_offs);
> +	writel_relaxed(tmp, pll->con_reg);
> +
> +	/* wait lock time */
> +	do {
> +		cpu_relax();
> +		tmp = readl_relaxed(pll->con_reg);
> +	} while (!(tmp & BIT(pll->lock_offs)));

Not a problem with this patch because we're moving code around,
but this is a potential infinite loop that should have some sort
of timeout so we don't sit here forever trying to see a bit
toggle.


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH 3/4] net: phy: realtek: add disable RX delay hack for RTL8211E
From: kbuild test robot @ 2017-04-22  7:12 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: kbuild-all-JC7UmRfGjtg, Andrew Lunn, Florian Fainelli,
	Rob Herring, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170421232436.10924-4-icenowy-h8G6r0blFSE@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1674 bytes --]

Hi Icenowy,

[auto build test ERROR on net-next/master]
[also build test ERROR on v4.11-rc7 next-20170421]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Icenowy-Zheng/net-phy-realtek-change-macro-name-for-page-select-register/20170422-144641
config: i386-randconfig-x070-201716 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/net/phy/realtek.c: In function 'rtl8211e_config_init':
>> drivers/net/phy/realtek.c:147:3: error: expected ';' before 'phy_write'
      phy_write(phydev, RTL8211E_EXT_PAGE_SELECT, 0xa4);
      ^~~~~~~~~

vim +147 drivers/net/phy/realtek.c

   141			 *
   142			 * The datasheet of RTL8211E didn't cover this ext page.
   143			 *
   144			 * Select extension page 0xa4 here.
   145			 */
   146			phy_write(phydev, RTL8211_PAGE_SELECT, RTL8211E_EXT_PAGE)
 > 147			phy_write(phydev, RTL8211E_EXT_PAGE_SELECT, 0xa4);
   148	
   149			/* Write the magic number */
   150			phy_write(phydev, 0x1c, 0xb591);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24280 bytes --]

^ permalink raw reply

* [RFC PATH] of/pci/dma: fix DMA configruation for PCI masters
From: Oza Pawandeep via iommu @ 2017-04-22  8:08 UTC (permalink / raw)
  To: Joerg Roedel, Robin Murphy
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Oza Pawandeep,
	linux-pci-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

current device frmework and of framework integration assumes dma-ranges
in a way where memory-mapped devices define their dma-ranges.
dma-ranges: (child-bus-address, parent-bus-address, length).

but iproc based SOCs and other SOCs(suc as rcar) have PCI world dma-ranges.
dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;

of_dma_configure is specifically witten to take care of memory mapped devices.
but no implementation exists for pci to take care of pcie based memory ranges.
in fact pci world doesnt seem to define standard dma-ranges

this patch served following purposes

1) exposes intrface to the pci host driver for thir inbound memory ranges

2) provide an interface to callers such as of_dma_get_ranges.
so then the returned size get best possible (largest) dma_mask.
for e.g.
dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
we should get dev->coherent_dma_mask=0x7fffffffff.

3) this patch handles multiple inbound windows and dma-ranges.
it is left to the caller, how it wants to use them.
the new function returns the resources in a standard and unform way

4) this way the callers of of_dma_get_ranges does not need to change.
and

5) leaves scope of adding PCI flag handling for inbound memory
by the new function.

Signed-off-by: Oza Pawandeep <oza.oza-dY08KVG/lbpWk0Htik3J/w@public.gmane.org>

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..ec21191 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -6,6 +6,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 #include <linux/pci.h>
 #include <linux/pci_regs.h>
 #include <linux/sizes.h>
@@ -829,10 +830,30 @@ int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *siz
 	int len, naddr, nsize, pna;
 	int ret = 0;
 	u64 dmaaddr;
+	struct resource_entry *window;
+	LIST_HEAD(res);
 
 	if (!node)
 		return -EINVAL;
 
+	if (strcmp(np->name, "pci")) {
+		*size = 0;
+		ret = of_pci_get_dma_ranges(np, &res);
+		if (!ret) {
+			resource_list_for_each_entry(window, &res) {
+			struct resource *res_dma = window->res;
+
+			if (*size < resource_size(res_dma)) {
+				*dma_addr = res_dma->start - window->offset;
+				*paddr = res_dma->start;
+				*size = resource_size(res_dma);
+				}
+			}
+		}
+		pci_free_resource_list(&res);
+		goto out;
+	}
+
 	while (1) {
 		naddr = of_n_addr_cells(node);
 		nsize = of_n_size_cells(node);
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 0ee42c3..2aa9401 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -283,6 +283,83 @@ int of_pci_get_host_bridge_resources(struct device_node *dev,
 	return err;
 }
 EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
+
+/**
+ * of_pci_get_dma_ranges - Parse PCI host bridge inbound resources from DT
+ * @np: device node of the host bridge having the dma-ranges property
+ * @resources: list where the range of resources will be added after DT parsing
+ *
+ * It is the caller's job to free the @resources list.
+ *
+ * This function will parse the "dma-ranges" property of a
+ * PCI host bridge device node and setup the resource mapping based
+ * on its content.
+ *
+ * It returns zero if the range parsing has been successful or a standard error
+ * value if it failed.
+ */
+
+int of_pci_get_dma_ranges(struct device_node *np, struct list_head *resources)
+{
+	struct device_node *node = of_node_get(np);
+	int rlen;
+	int ret = 0;
+	const int na = 3, ns = 2;
+	struct resource *res;
+	struct of_pci_range_parser parser;
+	struct of_pci_range range;
+
+	if (!node)
+		return -EINVAL;
+
+	parser.node = node;
+	parser.pna = of_n_addr_cells(node);
+	parser.np = parser.pna + na + ns;
+
+	parser.range = of_get_property(node, "dma-ranges", &rlen);
+
+	if (!parser.range) {
+		pr_debug("pcie device has no dma-ranges defined for node(%s)\n",
+			  np->full_name);
+		ret = -ENODEV;
+		goto out;
+	}
+
+	parser.end = parser.range + rlen / sizeof(__be32);
+
+	for_each_of_pci_range(&parser, &range) {
+		/*
+		 * If we failed translation or got a zero-sized region
+		 * then skip this range
+		 */
+		if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
+			continue;
+
+		res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+		if (!res) {
+			ret = -ENOMEM;
+			goto parse_failed;
+		}
+
+		ret = of_pci_range_to_resource(&range, np, res);
+		if (ret) {
+			kfree(res);
+			continue;
+		}
+
+		pci_add_resource_offset(resources, res,
+					res->start - range.pci_addr);
+	}
+
+	return ret;
+
+parse_failed:
+	pci_free_resource_list(resources);
+out:
+	of_node_put(node);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_dma_ranges);
 #endif /* CONFIG_OF_ADDRESS */
 
 #ifdef CONFIG_PCI_MSI
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 0e0974e..617b90d 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -76,6 +76,7 @@ static inline void of_pci_check_probe_only(void) { }
 int of_pci_get_host_bridge_resources(struct device_node *dev,
 			unsigned char busno, unsigned char bus_max,
 			struct list_head *resources, resource_size_t *io_base);
+int of_pci_get_dma_ranges(struct device_node *np, struct list_head *resources);
 #else
 static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
 			unsigned char busno, unsigned char bus_max,
@@ -83,6 +84,12 @@ static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
 {
 	return -EINVAL;
 }
+
+static inline int of_pci_get_dma_ranges(struct device_node *np,
+					struct list_head *resources)
+{
+	return -EINVAL;
+}
 #endif
 
 #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-- 
1.9.1

^ permalink raw reply related

* Re: [RFC PATCH] of: Fix DMA configuration for non-DT masters
From: Oza Oza via iommu @ 2017-04-22  8:53 UTC (permalink / raw)
  To: Robin Murphy
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, Linux IOMMU,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <67d1f46172599be243405f4341665fd0ef9ab969.1490726288.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>

On Wed, Mar 29, 2017 at 12:27 AM, Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> wrote:
> For PCI masters not represented in DT, we pass the OF node of their
> associated host bridge to of_dma_configure(), such that they can inherit
> the appropriate DMA configuration from whatever is described there.
> Unfortunately, whilst this has worked for the "dma-coherent" property,
> it turns out to miss the case where the host bridge node has a non-empty
> "dma-ranges", since nobody is expecting the 'device' to be a bus itself.
>
> It transpires, though, that the de-facto interface since the prototype
> change in 1f5c69aa51f9 ("of: Move of_dma_configure() to device.c to help
> re-use") is very clear-cut: either the master_np argument is redundant
> with dev->of_node, or dev->of_node is NULL and master_np is the relevant
> parent bus. Let's ratify that behaviour, then teach the whole
> of_dma_configure() pipeline to cope with both cases properly.
>
> Signed-off-by: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
> ---
>
> This is what I'd consider the better fix - rather than adding yet more
> special cases - which will also make it simple to handle multiple
> "dma-ranges" entries with minimal further disruption. The callers now
> left passing dev->of_node as 'parent' are harmless, but look a bit silly
> and clearly want cleaning up - I'd be partial to renaming the existing
> function and having a single-argument wrapper for the 'normal' case, e.g.:
>
> static inline int of_dma_configure(struct device_node *dev)
> {
>         return of_dma_configure_parent(dev, NULL);
> }
>
> Thoughts?
>
> Robin.
>
>  drivers/iommu/of_iommu.c   |  7 ++++---
>  drivers/of/address.c       | 37 +++++++++++++++++++++++++------------
>  drivers/of/device.c        | 12 +++++++-----
>  include/linux/of_address.h |  7 ++++---
>  include/linux/of_device.h  |  4 ++--
>  include/linux/of_iommu.h   |  4 ++--
>  6 files changed, 44 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index 2683e9fc0dcf..35aff07bb5eb 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -138,21 +138,22 @@ static const struct iommu_ops
>  }
>
>  const struct iommu_ops *of_iommu_configure(struct device *dev,
> -                                          struct device_node *master_np)
> +                                          struct device_node *parent)
>  {
>         struct of_phandle_args iommu_spec;
> -       struct device_node *np;
> +       struct device_node *np, *master_np;
>         const struct iommu_ops *ops = NULL;
>         int idx = 0;
>
>         if (dev_is_pci(dev))
> -               return of_pci_iommu_configure(to_pci_dev(dev), master_np);
> +               return of_pci_iommu_configure(to_pci_dev(dev), parent);
>
>         /*
>          * We don't currently walk up the tree looking for a parent IOMMU.
>          * See the `Notes:' section of
>          * Documentation/devicetree/bindings/iommu/iommu.txt
>          */
> +       master_np = dev->of_node ? dev->of_node : parent;
>         while (!of_parse_phandle_with_args(master_np, "iommus",
>                                            "#iommu-cells", idx,
>                                            &iommu_spec)) {
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903fe9d2..833bc17f5e55 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -808,6 +808,7 @@ EXPORT_SYMBOL(of_io_request_and_map);
>  /**
>   * of_dma_get_range - Get DMA range info
>   * @np:                device node to get DMA range info
> + * @parent:    node of device's parent bus, if @np is NULL
>   * @dma_addr:  pointer to store initial DMA address of DMA range
>   * @paddr:     pointer to store initial CPU address of DMA range
>   * @size:      pointer to store size of DMA range
> @@ -822,36 +823,48 @@ EXPORT_SYMBOL(of_io_request_and_map);
>   * It returns -ENODEV if "dma-ranges" property was not found
>   * for this device in DT.
>   */
> -int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size)
> +int of_dma_get_range(struct device_node *np, struct device_node *parent,
> +                    u64 *dma_addr, u64 *paddr, u64 *size)
>  {
> -       struct device_node *node = of_node_get(np);
> +       struct device_node *node;
>         const __be32 *ranges = NULL;
>         int len, naddr, nsize, pna;
>         int ret = 0;
>         u64 dmaaddr;
>
> -       if (!node)
> -               return -EINVAL;
> -
> -       while (1) {
> +       if (np) {
> +               node = of_node_get(np);
>                 naddr = of_n_addr_cells(node);
>                 nsize = of_n_size_cells(node);
>                 node = of_get_next_parent(node);
> -               if (!node)
> -                       break;
> +       } else if (parent) {
> +               node = of_node_get(parent);
> +               np = parent;
> +               if (of_property_read_u32(node, "#address-cells", &naddr))
> +                       naddr = of_n_addr_cells(node);
> +               if (of_property_read_u32(node, "#size-cells", &nsize))
> +                       nsize = of_n_size_cells(node);
> +       } else {
> +               return -EINVAL;
> +       }
>
> +       while (node) {
>                 ranges = of_get_property(node, "dma-ranges", &len);
>
> -               /* Ignore empty ranges, they imply no translation required */
> -               if (ranges && len > 0)
> -                       break;
> -
>                 /*
>                  * At least empty ranges has to be defined for parent node if
>                  * DMA is supported
>                  */
>                 if (!ranges)
>                         break;
> +
> +               /* Ignore empty ranges, they imply no translation required */
> +               if (len > 0)
> +                       break;
> +
> +               naddr = of_n_addr_cells(node);
> +               nsize = of_n_size_cells(node);
> +               node = of_get_next_parent(node);
>         }
>
>         if (!ranges) {
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 9bb8518b28f2..57ec5324ed6c 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -73,7 +73,8 @@ int of_device_add(struct platform_device *ofdev)
>  /**
>   * of_dma_configure - Setup DMA configuration
>   * @dev:       Device to apply DMA configuration
> - * @np:                Pointer to OF node having DMA configuration
> + * @parent:    OF node of device's parent bus, if @dev is not
> + *             represented in DT (i.e. @dev->of_node is NULL)
>   *
>   * Try to get devices's DMA configuration from DT and update it
>   * accordingly.
> @@ -82,13 +83,14 @@ int of_device_add(struct platform_device *ofdev)
>   * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>   * to fix up DMA configuration.
>   */
> -void of_dma_configure(struct device *dev, struct device_node *np)
> +void of_dma_configure(struct device *dev, struct device_node *parent)
>  {
>         u64 dma_addr, paddr, size;
>         int ret;
>         bool coherent;
>         unsigned long offset;
>         const struct iommu_ops *iommu;
> +       struct device_node *np = dev->of_node;
>
>         /*
>          * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
> @@ -104,7 +106,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
>         if (!dev->dma_mask)
>                 dev->dma_mask = &dev->coherent_dma_mask;
>
> -       ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
> +       ret = of_dma_get_range(np, parent, &dma_addr, &paddr, &size);
>         if (ret < 0) {
>                 dma_addr = offset = 0;
>                 size = dev->coherent_dma_mask + 1;
> @@ -132,11 +134,11 @@ void of_dma_configure(struct device *dev, struct device_node *np)
>         dev->coherent_dma_mask = DMA_BIT_MASK(ilog2(dma_addr + size));
>         *dev->dma_mask = dev->coherent_dma_mask;
>
> -       coherent = of_dma_is_coherent(np);
> +       coherent = of_dma_is_coherent(np ? np : parent);
>         dev_dbg(dev, "device is%sdma coherent\n",
>                 coherent ? " " : " not ");
>
> -       iommu = of_iommu_configure(dev, np);
> +       iommu = of_iommu_configure(dev, parent);
>         dev_dbg(dev, "device is%sbehind an iommu\n",
>                 iommu ? " " : " not ");
>
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 37864734ca50..f1a507f3ae57 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -52,8 +52,8 @@ extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
>  extern struct of_pci_range *of_pci_range_parser_one(
>                                         struct of_pci_range_parser *parser,
>                                         struct of_pci_range *range);
> -extern int of_dma_get_range(struct device_node *np, u64 *dma_addr,
> -                               u64 *paddr, u64 *size);
> +extern int of_dma_get_range(struct device_node *np, struct device_node *parent,
> +                               u64 *dma_addr, u64 *paddr, u64 *size);
>  extern bool of_dma_is_coherent(struct device_node *np);
>  #else /* CONFIG_OF_ADDRESS */
>  static inline void __iomem *of_io_request_and_map(struct device_node *device,
> @@ -95,7 +95,8 @@ static inline struct of_pci_range *of_pci_range_parser_one(
>         return NULL;
>  }
>
> -static inline int of_dma_get_range(struct device_node *np, u64 *dma_addr,
> +static inline int of_dma_get_range(struct device_node *np,
> +                               struct device_node *parent, u64 *dma_addr,
>                                 u64 *paddr, u64 *size)
>  {
>         return -ENODEV;
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index c12dace043f3..bcd2b6fbeef3 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,7 +55,7 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>         return of_node_get(cpu_dev->of_node);
>  }
>
> -void of_dma_configure(struct device *dev, struct device_node *np);
> +void of_dma_configure(struct device *dev, struct device_node *parent);
>  #else /* CONFIG_OF */
>
>  static inline int of_driver_match_device(struct device *dev,
> @@ -103,7 +103,7 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
>  {
>         return NULL;
>  }
> -static inline void of_dma_configure(struct device *dev, struct device_node *np)
> +static inline void of_dma_configure(struct device *dev, struct device_node *parent)
>  {}
>  #endif /* CONFIG_OF */
>
> diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
> index 13394ac83c66..c02b62e8e6ed 100644
> --- a/include/linux/of_iommu.h
> +++ b/include/linux/of_iommu.h
> @@ -12,7 +12,7 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix,
>                              size_t *size);
>
>  extern const struct iommu_ops *of_iommu_configure(struct device *dev,
> -                                       struct device_node *master_np);
> +                                       struct device_node *parent);
>
>  #else
>
> @@ -24,7 +24,7 @@ static inline int of_get_dma_window(struct device_node *dn, const char *prefix,
>  }
>
>  static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
> -                                        struct device_node *master_np)
> +                                        struct device_node *parent)
>  {
>         return NULL;
>  }
> --
> 2.11.0.dirty
>

Hi Robin,

After some more thoughts to this, I have improved upon old patch design.
please check  https://lkml.org/lkml/2017/4/22/34

 this patch served following purposes

    1) exposes intrface to the pci host driver for thir inbound memory ranges

    2) provide an interface to callers such as of_dma_get_ranges.
    so then the returned size get best possible (largest) dma_mask.
    for e.g.
    dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
    we should get dev->coherent_dma_mask=0x7fffffffff.

    3) this patch handles multiple inbound windows and dma-ranges.
    it is left to the caller, how it wants to use them.
    the new function returns the resources in a standard and unform way

    4) this way the callers of of_dma_get_ranges does not need to change.
    and

    5) leaves scope of adding PCI flag handling for inbound memory
    by the new function.


which I feel much better approach/way than accommodating
of_dma_get_ranges to handle multiple dma-ranges, addressing PCI
masters.
also in your patch I think, you have to make emulated parent node
which is more work I suppose.

again I have tested this on our SOC and it works well.

Regards,
Oza.

^ permalink raw reply

* Re: [PATCH v2 0/5] mtd: nand: gpmi: add i.MX 7 support
From: Marek Vasut @ 2017-04-22 11:43 UTC (permalink / raw)
  To: Stefan Agner, dwmw2-wEGCiKHe2LqWVfeAwA7xHQ,
	computersforpeace-Re5JQEeQqe8AvxtiuMwx3w,
	boris.brezillon-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	richard-/L3Ra7n9ekc, cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	shawnguo-DgEjT+Ai2ygdnm+yROfE0A, kernel-bIcnvbaLZ9MEGnE8C9+IrQ,
	han.xu-3arQi8VN3Tc, fabio.estevam-KZfg59tc24xl57MIdRCFDg,
	LW-bxm8fMRDkQLDiMYJYoSAnRvVK+yQ3ZXh,
	linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170422012338.4635-1-stefan-XLVq0VzYD2Y@public.gmane.org>

On 04/22/2017 03:23 AM, Stefan Agner wrote:
> This patchset adds support for i.MX 7 SoC for the GPMI NAND controller.
> There have been similar patchsets already:
> https://lkml.org/lkml/2016/2/23/912
> 
> However, this patchset does not make use of any of the new features.
> The current feature set seems to work fine, I successfully run the MTD
> tests on a Colibri iMX7.
> 
> --
> Stefan
> 
> Changes since v1:
> - Make clks_count const
> - Introduce IS_IMX7D for i.MX 7 SoC's and make it part of GPMI_IS_MX6

Super, thanks.

-- 
Best regards,
Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 4/4] [DO NOT MERGE] arm64: allwinner: a64: enable RTL8211E PHY workaround
From: kbuild test robot @ 2017-04-22 12:27 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: kbuild-all-JC7UmRfGjtg, Andrew Lunn, Florian Fainelli,
	Rob Herring, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Icenowy Zheng
In-Reply-To: <20170421232436.10924-5-icenowy-h8G6r0blFSE@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 1365 bytes --]

Hi Icenowy,

[auto build test ERROR on net-next/master]
[also build test ERROR on v4.11-rc7 next-20170421]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Icenowy-Zheng/net-phy-realtek-change-macro-name-for-page-select-register/20170422-144641
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

>> Error: arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts:52.1-9 Label or path ext_phy not found
>> FATAL ERROR: Syntax error parsing input tree

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

-- 
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 34529 bytes --]

^ permalink raw reply

* Re: [PATCH v2 1/6] clk: sunxi-ng: Add sun4i/sun7i CCU driver
From: Jonathan Liu @ 2017-04-22 12:33 UTC (permalink / raw)
  To: plaes-q/aMd4JkU83YtjvyW6yDsg
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, linux-sunxi, Icenowy Zheng,
	Russell King, Chen-Yu Tsai, Maxime Ripard, Mark Rutland,
	Rob Herring, Stephen Boyd, Michael Turquette, Philipp Zabel
In-Reply-To: <ac8c4dab4f160ec605d52120517774bf1de87c2e.1490545262.git-series.plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>

Hi Priit,

On 27 March 2017 at 04:20, Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org> wrote:
> Introduce a clock controller driver for sun4i A10 and sun7i A20
> series SoCs.
>
> Signed-off-by: Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>
> ---
>  drivers/clk/sunxi-ng/Kconfig                  |   13 +-
>  drivers/clk/sunxi-ng/Makefile                 |    1 +-
>  drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c      | 1532 ++++++++++++++++++-
>  drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h      |   59 +-
>  include/dt-bindings/clock/sunxi-a10-a20-ccu.h |  208 ++-
>  include/dt-bindings/reset/sunxi-a10-a20-ccu.h |   66 +-
>  6 files changed, 1879 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
>  create mode 100644 include/dt-bindings/clock/sunxi-a10-a20-ccu.h
>  create mode 100644 include/dt-bindings/reset/sunxi-a10-a20-ccu.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index 213cf64..abed614 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -65,6 +65,19 @@ config SUN50I_A64_CCU
>         default ARM64 && ARCH_SUNXI
>         depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
>
> +config SUNXI_A10_A20_CCU
> +       bool "Support for the Allwinner A10/A20 CCU"
> +       select SUNXI_CCU_DIV
> +       select SUNXI_CCU_MULT
> +       select SUNXI_CCU_NK
> +       select SUNXI_CCU_NKM
> +       select SUNXI_CCU_NM
> +       select SUNXI_CCU_MP
> +       select SUNXI_CCU_PHASE
> +       default MACH_SUN4I
> +       default MACH_SUN7I
> +       depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
> +
>  config SUN5I_CCU
>         bool "Support for the Allwinner sun5i family CCM"
>         select SUNXI_CCU_DIV
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 6feaac0..90bab0e 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -21,6 +21,7 @@ obj-$(CONFIG_SUNXI_CCU_MP)    += ccu_mp.o
>  obj-$(CONFIG_SUN50I_A64_CCU)   += ccu-sun50i-a64.o
>  obj-$(CONFIG_SUN5I_CCU)                += ccu-sun5i.o
>  obj-$(CONFIG_SUN6I_A31_CCU)    += ccu-sun6i-a31.o
> +obj-$(CONFIG_SUNXI_A10_A20_CCU)        += ccu-sunxi-a10-a20.o
>  obj-$(CONFIG_SUN8I_A23_CCU)    += ccu-sun8i-a23.o
>  obj-$(CONFIG_SUN8I_A33_CCU)    += ccu-sun8i-a33.o
>  obj-$(CONFIG_SUN8I_H3_CCU)     += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
> new file mode 100644
> index 0000000..1884f5f
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.c
> @@ -0,0 +1,1532 @@
> +/*
> + * Copyright (c) 2017 Priit Laes. All rights reserved.
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/of_address.h>
> +
> +#include "ccu_common.h"
> +#include "ccu_reset.h"
> +
> +#include "ccu_div.h"
> +#include "ccu_gate.h"
> +#include "ccu_mp.h"
> +#include "ccu_mult.h"
> +#include "ccu_nk.h"
> +#include "ccu_nkm.h"
> +#include "ccu_nkmp.h"
> +#include "ccu_nm.h"
> +#include "ccu_phase.h"
> +
> +#include "ccu-sunxi-a10-a20.h"
> +
> +static struct ccu_nkmp pll_core_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .m              = _SUNXI_CCU_DIV(0, 2),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .common         = {
> +               .reg            = 0x000,
> +               .hw.init        = CLK_HW_INIT("pll-core",
> +                                             "hosc",
> +                                             &ccu_nkmp_ops,
> +                                             0),
> +       },
> +};
> +
> +/*
> + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
> + * the base (2x, 4x and 8x), and one variable divider (the one true
> + * pll audio).
> + *
> + * We don't have any need for the variable divider for now, so we just
> + * hardcode it to match with the clock names.
> + */
> +#define SUN4I_PLL_AUDIO_REG    0x008
> +static struct ccu_nm pll_audio_base_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 7, 0),
> +       .m              = _SUNXI_CCU_DIV_OFFSET(0, 5, 0),
> +       .common         = {
> +               .reg            = 0x008,
> +               .hw.init        = CLK_HW_INIT("pll-audio-base",
> +                                             "hosc",
> +                                             &ccu_nm_ops,
> +                                             0),
> +       },
> +
> +};
> +
> +static struct ccu_mult pll_video0_clk = {
> +       .enable         = BIT(31),
> +       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> +       .frac           = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> +                                         270000000, 297000000),
> +       .common         = {
> +               .reg            = 0x010,
> +               .features       = (CCU_FEATURE_FRACTIONAL |
> +                                  CCU_FEATURE_ALL_PREDIV),
> +               .prediv         = 8,
> +               .hw.init        = CLK_HW_INIT("pll-video0",
> +                                             "hosc",
> +                                             &ccu_mult_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nkmp pll_ve_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .m              = _SUNXI_CCU_DIV(0, 2),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .common         = {
> +               .reg            = 0x018,
> +               .hw.init        = CLK_HW_INIT("pll-ve",
> +                                             "hosc",
> +                                             &ccu_nkmp_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nk pll_ddr_base_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .common         = {
> +               .reg            = 0x020,
> +               .hw.init        = CLK_HW_INIT("pll-ddr-base",
> +                                             "hosc",
> +                                             &ccu_nk_ops,
> +                                             0),
> +       },
> +};
> +
> +static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2,
> +                  CLK_IS_CRITICAL);
> +
> +static struct ccu_div pll_ddr_other_clk = {
> +       .div            = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO),
> +
> +       .common         = {
> +               .reg            = 0x020,
> +               .hw.init        = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base",
> +                                             &ccu_div_ops,
> +                                             0),
> +       },
> +};
> +
> +static struct ccu_nk pll_periph_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .fixed_post_div = 2,
> +       .common         = {
> +               .reg            = 0x028,
> +               .features       = CCU_FEATURE_FIXED_POSTDIV,
> +               .hw.init        = CLK_HW_INIT("pll-periph",
> +                                             "hosc",
> +                                             &ccu_nk_ops,
> +                                             0),
> +       },
> +};
> +/* Not documented on A10 */
> +static SUNXI_CCU_GATE(pll_periph_sata_clk, "pll-periph-sata", "pll-periph",
> +                     0x028, BIT(14), 0);
> +
> +static struct ccu_mult pll_video1_clk = {
> +       .enable         = BIT(31),
> +       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127),
> +       .frac           = _SUNXI_CCU_FRAC(BIT(15), BIT(14),
> +                                 270000000, 297000000),
> +       .common         = {
> +               .reg            = 0x030,
> +               .features       = (CCU_FEATURE_FRACTIONAL |
> +                                  CCU_FEATURE_ALL_PREDIV),
> +               .prediv         = 8,
> +               .hw.init        = CLK_HW_INIT("pll-video1",
> +                                             "hosc",
> +                                             &ccu_mult_ops,
> +                                             0),
> +       },
> +};
> +
> +/* Not present on A10 */
> +static struct ccu_nk pll_gpu_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .common         = {
> +               .reg            = 0x040,
> +               .hw.init        = CLK_HW_INIT("pll-gpu",
> +                                             "hosc",
> +                                             &ccu_nk_ops,
> +                                             0),
> +       },
> +};
> +
> +static SUNXI_CCU_GATE(hosc_clk,        "hosc", "osc24M", 0x050, BIT(0), 0);
> +
> +static const char *const cpu_parents[] = { "osc32k", "hosc",
> +                                          "pll-core", "pll-periph" };
> +static const struct ccu_mux_fixed_prediv cpu_predivs[] = {
> +       { .index = 3, .div = 3, },
> +};
> +
> +#define SUN4I_AHB_REG          0x054
> +static struct ccu_mux cpu_clk = {
> +       .mux            = {
> +               .shift          = 16,
> +               .width          = 2,
> +               .fixed_predivs  = cpu_predivs,
> +               .n_predivs      = ARRAY_SIZE(cpu_predivs),
> +       },
> +       .common         = {
> +               .reg            = 0x054,
> +               .features       = CCU_FEATURE_FIXED_PREDIV,
> +               .hw.init        = CLK_HW_INIT_PARENTS("cpu",
> +                                                     cpu_parents,
> +                                                     &ccu_mux_ops,
> +                                                     CLK_IS_CRITICAL),
> +       }
> +};
> +
> +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0);
> +
> +static const char *const ahb_parents[] = { "axi", "pll-periph",
> +                                          "pll-periph-2x" };
> +static const struct ccu_mux_fixed_prediv ahb_predivs[] = {
> +       { .index = 2, .div = 2, },
> +};
> +
> +/* Undocumented on A10 */
> +static struct ccu_div ahb_clk = {
> +       .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
> +       .mux            = {
> +               .shift          = 6,
> +               .width          = 2,
> +               .fixed_predivs  = ahb_predivs,
> +               .n_predivs      = ARRAY_SIZE(ahb_predivs),
> +       },
> +
> +       .common         = {
> +               .reg            = 0x054,
> +               .hw.init        = CLK_HW_INIT_PARENTS("ahb",
> +                                                     ahb_parents,
> +                                                     &ccu_div_ops,
> +                                                     0),
> +       },
> +};
> +
> +static struct clk_div_table apb0_div_table[] = {
> +       { .val = 0, .div = 2 },
> +       { .val = 1, .div = 2 },
> +       { .val = 2, .div = 4 },
> +       { .val = 3, .div = 8 },
> +       { /* Sentinel */ },
> +};
> +static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb",
> +                          0x054, 8, 2, apb0_div_table, 0);
> +
> +static const char *const apb1_parents[] = { "hosc", "pll-periph", "osc32k" };
> +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058,
> +                            0, 5,      /* M */
> +                            16, 2,     /* P */
> +                            24, 2,     /* mux */
> +                            0);
> +
> +/* Not present on A20 */
> +static SUNXI_CCU_GATE(axi_dram_clk,    "axi-dram",     "ahb",
> +                     0x05c, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(ahb_otg_clk,     "ahb-otg",      "ahb",
> +                     0x060, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_ehci0_clk,   "ahb-ehci0",    "ahb",
> +                     0x060, BIT(1), 0);
> +static SUNXI_CCU_GATE(ahb_ohci0_clk,   "ahb-ohci0",    "ahb",
> +                     0x060, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_ehci1_clk,   "ahb-ehci1",    "ahb",
> +                     0x060, BIT(3), 0);
> +static SUNXI_CCU_GATE(ahb_ohci1_clk,   "ahb-ohci1",    "ahb",
> +                     0x060, BIT(4), 0);
> +static SUNXI_CCU_GATE(ahb_ss_clk,      "ahb-ss",       "ahb",
> +                     0x060, BIT(5), 0);
> +static SUNXI_CCU_GATE(ahb_dma_clk,     "ahb-dma",      "ahb",
> +                     0x060, BIT(6), 0);
> +static SUNXI_CCU_GATE(ahb_bist_clk,    "ahb-bist",     "ahb",
> +                     0x060, BIT(7), 0);
> +static SUNXI_CCU_GATE(ahb_mmc0_clk,    "ahb-mmc0",     "ahb",
> +                     0x060, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_mmc1_clk,    "ahb-mmc1",     "ahb",
> +                     0x060, BIT(9), 0);
> +static SUNXI_CCU_GATE(ahb_mmc2_clk,    "ahb-mmc2",     "ahb",
> +                     0x060, BIT(10), 0);
> +static SUNXI_CCU_GATE(ahb_mmc3_clk,    "ahb-mmc3",     "ahb",
> +                     0x060, BIT(11), 0);
> +static SUNXI_CCU_GATE(ahb_ms_clk,      "ahb-ms",       "ahb",
> +                     0x060, BIT(12), 0);
> +static SUNXI_CCU_GATE(ahb_nand_clk,    "ahb-nand",     "ahb",
> +                     0x060, BIT(13), 0);
> +static SUNXI_CCU_GATE(ahb_sdram_clk,   "ahb-sdram",    "ahb",
> +                     0x060, BIT(14), CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_GATE(ahb_ace_clk,     "ahb-ace",      "ahb",
> +                     0x060, BIT(16), 0);
> +static SUNXI_CCU_GATE(ahb_emac_clk,    "ahb-emac",     "ahb",
> +                     0x060, BIT(17), 0);
> +static SUNXI_CCU_GATE(ahb_ts_clk,      "ahb-ts",       "ahb",
> +                     0x060, BIT(18), 0);
> +static SUNXI_CCU_GATE(ahb_spi0_clk,    "ahb-spi0",     "ahb",
> +                     0x060, BIT(20), 0);
> +static SUNXI_CCU_GATE(ahb_spi1_clk,    "ahb-spi1",     "ahb",
> +                     0x060, BIT(21), 0);
> +static SUNXI_CCU_GATE(ahb_spi2_clk,    "ahb-spi2",     "ahb",
> +                     0x060, BIT(22), 0);
> +static SUNXI_CCU_GATE(ahb_spi3_clk,    "ahb-spi3",     "ahb",
> +                     0x060, BIT(23), 0);
> +static SUNXI_CCU_GATE(ahb_pata_clk,    "ahb-pata",     "ahb",
> +                     0x060, BIT(24), 0);
> +/* Not documented on A20 */
> +static SUNXI_CCU_GATE(ahb_sata_clk,    "ahb-sata",     "ahb",
> +                     0x060, BIT(25), 0);
> +/* Not present on A20 */
> +static SUNXI_CCU_GATE(ahb_gps_clk,     "ahb-gps",      "ahb",
> +                     0x060, BIT(26), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer",  "ahb",
> +                     0x060, BIT(28), 0);
> +
> +static SUNXI_CCU_GATE(ahb_ve_clk,      "ahb-ve",       "ahb",
> +                     0x064, BIT(0), 0);
> +static SUNXI_CCU_GATE(ahb_tvd_clk,     "ahb-tvd",      "ahb",
> +                     0x064, BIT(1), 0);
> +static SUNXI_CCU_GATE(ahb_tve0_clk,    "ahb-tve0",     "ahb",
> +                     0x064, BIT(2), 0);
> +static SUNXI_CCU_GATE(ahb_tve1_clk,    "ahb-tve1",     "ahb",
> +                     0x064, BIT(3), 0);
> +static SUNXI_CCU_GATE(ahb_lcd0_clk,    "ahb-lcd0",     "ahb",
> +                     0x064, BIT(4), 0);
> +static SUNXI_CCU_GATE(ahb_lcd1_clk,    "ahb-lcd1",     "ahb",
> +                     0x064, BIT(5), 0);
> +static SUNXI_CCU_GATE(ahb_csi0_clk,    "ahb-csi0",     "ahb",
> +                     0x064, BIT(8), 0);
> +static SUNXI_CCU_GATE(ahb_csi1_clk,    "ahb-csi1",     "ahb",
> +                     0x064, BIT(9), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_hdmi1_clk,   "ahb-hdmi1",    "ahb",
> +                     0x064, BIT(10), 0);
> +static SUNXI_CCU_GATE(ahb_hdmi0_clk,   "ahb-hdmi0",    "ahb",
> +                     0x064, BIT(11), 0);
> +static SUNXI_CCU_GATE(ahb_de_be0_clk,  "ahb-de-be0",   "ahb",
> +                     0x064, BIT(12), 0);
> +static SUNXI_CCU_GATE(ahb_de_be1_clk,  "ahb-de-be1",   "ahb",
> +                     0x064, BIT(13), 0);
> +static SUNXI_CCU_GATE(ahb_de_fe0_clk,  "ahb-de-fe0",   "ahb",
> +                     0x064, BIT(14), 0);
> +static SUNXI_CCU_GATE(ahb_de_fe1_clk,  "ahb-de-fe1",   "ahb",
> +                     0x064, BIT(15), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(ahb_gmac_clk,    "ahb-gmac",     "ahb",
> +                     0x064, BIT(17), 0);
> +static SUNXI_CCU_GATE(ahb_mp_clk,      "ahb-mp",       "ahb",
> +                     0x064, BIT(18), 0);
> +static SUNXI_CCU_GATE(ahb_gpu_clk,     "ahb-gpu",      "ahb",
> +                     0x064, BIT(20), 0);
> +
> +static SUNXI_CCU_GATE(apb0_codec_clk,  "apb0-codec",   "apb0",
> +                     0x068, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb0_spdif_clk,  "apb0-spdif",   "apb0",
> +                     0x068, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb0_ac97_clk,   "apb0-ac97",    "apb0",
> +                     0x068, BIT(2), 0);
> +static SUNXI_CCU_GATE(apb0_i2s0_clk,   "apb0-i2s0",    "apb0",
> +                     0x068, BIT(3), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb0_i2s1_clk,   "apb0-i2s1",    "apb0",
> +                     0x068, BIT(4), 0);
> +static SUNXI_CCU_GATE(apb0_pio_clk,    "apb0-pio",     "apb0",
> +                     0x068, BIT(5), 0);
> +static SUNXI_CCU_GATE(apb0_ir0_clk,    "apb0-ir0",     "apb0",
> +                     0x068, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb0_ir1_clk,    "apb0-ir1",     "apb0",
> +                     0x068, BIT(7), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb0_i2s2_clk,   "apb0-i2s2",    "apb0",
> +                     0x068, BIT(8), 0);
> +static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad",  "apb0",
> +                     0x068, BIT(10), 0);
> +
> +static SUNXI_CCU_GATE(apb1_i2c0_clk,   "apb1-i2c0",    "apb1",
> +                     0x06c, BIT(0), 0);
> +static SUNXI_CCU_GATE(apb1_i2c1_clk,   "apb1-i2c1",    "apb1",
> +                     0x06c, BIT(1), 0);
> +static SUNXI_CCU_GATE(apb1_i2c2_clk,   "apb1-i2c2",    "apb1",
> +                     0x06c, BIT(2), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb1_i2c3_clk,   "apb1-i2c3",    "apb1",
> +                     0x06c, BIT(3), 0);
> +static SUNXI_CCU_GATE(apb1_can_clk,    "apb1-can",     "apb1",
> +                     0x06c, BIT(4), 0);
> +static SUNXI_CCU_GATE(apb1_scr_clk,    "apb1-scr",     "apb1",
> +                     0x06c, BIT(5), 0);
> +static SUNXI_CCU_GATE(apb1_ps20_clk,   "apb1-ps20",    "apb1",
> +                     0x06c, BIT(6), 0);
> +static SUNXI_CCU_GATE(apb1_ps21_clk,   "apb1-ps21",    "apb1",
> +                     0x06c, BIT(7), 0);
> +/* Not present on A10 */
> +static SUNXI_CCU_GATE(apb1_i2c4_clk,   "apb1-i2c4",    "apb1",
> +                     0x06c, BIT(15), 0);
> +static SUNXI_CCU_GATE(apb1_uart0_clk,  "apb1-uart0",   "apb1",
> +                     0x06c, BIT(16), 0);
> +static SUNXI_CCU_GATE(apb1_uart1_clk,  "apb1-uart1",   "apb1",
> +                     0x06c, BIT(17), 0);
> +static SUNXI_CCU_GATE(apb1_uart2_clk,  "apb1-uart2",   "apb1",
> +                     0x06c, BIT(18), 0);
> +static SUNXI_CCU_GATE(apb1_uart3_clk,  "apb1-uart3",   "apb1",
> +                     0x06c, BIT(19), 0);
> +static SUNXI_CCU_GATE(apb1_uart4_clk,  "apb1-uart4",   "apb1",
> +                     0x06c, BIT(20), 0);
> +static SUNXI_CCU_GATE(apb1_uart5_clk,  "apb1-uart5",   "apb1",
> +                     0x06c, BIT(21), 0);
> +static SUNXI_CCU_GATE(apb1_uart6_clk,  "apb1-uart6",   "apb1",
> +                     0x06c, BIT(22), 0);
> +static SUNXI_CCU_GATE(apb1_uart7_clk,  "apb1-uart7",   "apb1",
> +                     0x06c, BIT(23), 0);
> +
> +static const char *const mod0_default_parents[] = { "hosc", "pll-periph",
> +                                                    "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ms_clk, "ms", mod0_default_parents, 0x084,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0",
> +                      0x088, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0",
> +                      0x088, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1",
> +                      0x08c, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1",
> +                      0x08c, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2",
> +                      0x090, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2",
> +                      0x090, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3_output", "mmc3",
> +                      0x094, 8, 3, 0);
> +/* Undocumented on A10 */
> +static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3_sample", "mmc3",
> +                      0x094, 20, 3, 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(pata_clk, "pata", mod0_default_parents, 0x0ac,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +/* TODO: Check whether A10 actually supports osc32k as 4th parent? */
> +static const char *const ir_parents_sun4i[] = { "hosc", "pll-periph",
> +                                               "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun4i_clk, "ir0", ir_parents_sun4i, 0x0b0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun4i_clk, "ir1", ir_parents_sun4i, 0x0b4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +static const char *const ir_parents_sun7i[] = { "hosc", "pll-periph",
> +                                               "pll-ddr-other", "osc32k" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun7i_clk, "ir0", ir_parents_sun7i, 0x0b0,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun7i_clk, "ir1", ir_parents_sun7i, 0x0b4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +static const char *const audio_parents[] = { "pll-audio-8x", "pll-audio-4x",
> +                                             "pll-audio-2x", "pll-audio" };
> +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", audio_parents,
> +                              0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", audio_parents,
> +                              0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", audio_parents,
> +                              0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static const char *const keypad_parents[] = { "hosc", "losc"};
> +static const u8 keypad_table[] = { 0, 2 };
> +static struct ccu_mp keypad_clk = {
> +       .enable         = BIT(31),
> +       .m              = _SUNXI_CCU_DIV(0, 5),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .mux            = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table),
> +       .common         = {
> +               .reg            = 0x0c4,
> +               .hw.init        = CLK_HW_INIT_PARENTS("keypad",
> +                                                     keypad_parents,
> +                                                     &ccu_mp_ops,
> +                                                     0),
> +       },
> +};
> +
> +/*
> + * TODO: SATA clock also supports external clock as parent via BIT(24)
> + * The external clock is probably an optional crystal or oscillator
> + * that can be connected to the SATA-CLKM / SATA-CLKP pins.
> + */
> +static SUNXI_CCU_GATE(sata_clk, "sata", "pll-periph-sata",
> +                     0x0c8, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(usb_ohci0_clk,   "usb-ohci0",    "pll-periph",
> +                     0x0cc, BIT(6), 0);
> +static SUNXI_CCU_GATE(usb_ohci1_clk,   "usb-ohci1",    "pll-periph",
> +                     0x0cc, BIT(7), 0);
> +static SUNXI_CCU_GATE(usb_phy_clk,     "usb-phy",      "pll-periph",
> +                     0x0cc, BIT(8), 0);
> +
> +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0d4,
> +                                 0, 4,         /* M */
> +                                 16, 2,        /* P */
> +                                 24, 2,        /* mux */
> +                                 BIT(31),      /* gate */
> +                                 0);
> +
> +/* Not present on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", audio_parents,
> +                              0x0d8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +/* Not present on A10 */
> +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", audio_parents,
> +                              0x0dc, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE(dram_ve_clk,     "dram-ve",      "pll-ddr",
> +                     0x100, BIT(0), 0);
> +static SUNXI_CCU_GATE(dram_csi0_clk,   "dram-csi0",    "pll-ddr",
> +                     0x100, BIT(1), 0);
> +static SUNXI_CCU_GATE(dram_csi1_clk,   "dram-csi1",    "pll-ddr",
> +                     0x100, BIT(2), 0);
> +static SUNXI_CCU_GATE(dram_ts_clk,     "dram-ts",      "pll-ddr",
> +                     0x100, BIT(3), 0);
> +static SUNXI_CCU_GATE(dram_tvd_clk,    "dram-tvd",     "pll-ddr",
> +                     0x100, BIT(4), 0);
> +static SUNXI_CCU_GATE(dram_tve0_clk,   "dram-tve0",    "pll-ddr",
> +                     0x100, BIT(5), 0);
> +static SUNXI_CCU_GATE(dram_tve1_clk,   "dram-tve1",    "pll-ddr",
> +                     0x100, BIT(6), 0);
> +
> +static SUNXI_CCU_GATE(dram_out_clk,    "dram-out",     "pll-ddr",
> +                     0x100, BIT(15), 0);
> +static SUNXI_CCU_GATE(dram_de_fe1_clk, "dram-de-fe1",  "pll-ddr",
> +                     0x100, BIT(24), 0);
> +static SUNXI_CCU_GATE(dram_de_fe0_clk, "dram-de-fe0",  "pll-ddr",
> +                     0x100, BIT(25), 0);
> +static SUNXI_CCU_GATE(dram_de_be0_clk, "dram-de-be0",  "pll-ddr",
> +                     0x100, BIT(26), 0);
> +static SUNXI_CCU_GATE(dram_de_be1_clk, "dram-de-be1",  "pll-ddr",
> +                     0x100, BIT(27), 0);
> +static SUNXI_CCU_GATE(dram_mp_clk,     "dram-mp",      "pll-ddr",
> +                     0x100, BIT(28), 0);
> +static SUNXI_CCU_GATE(dram_ace_clk,    "dram-ace",     "pll-ddr",
> +                     0x100, BIT(29), 0);
> +
> +static const char *const de_parents[] = { "pll-video0", "pll-video1",
> +                                          "pll-ddr-other" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_be0_clk, "de-be0", de_parents,
> +                                0x104, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_be1_clk, "de-be1", de_parents,
> +                                0x108, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe0_clk, "de-fe0", de_parents,
> +                                0x10c, 0, 4, 24, 2, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe1_clk, "de-fe1", de_parents,
> +                                0x110, 0, 4, 24, 2, BIT(31), 0);
> +
> +/* Undocumented on A10 */
> +static SUNXI_CCU_M_WITH_MUX_GATE(de_mp_clk, "de-mp", de_parents,
> +                                0x114, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const tcon_parents[] = { "pll-video0", "pll-video1",
> +                                           "pll-video0-2x", "pll-video1-2x" };
> +static SUNXI_CCU_MUX_WITH_GATE(tcon0_ch0_clk, "tcon0-ch0-sclk", tcon_parents,
> +                              0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +static SUNXI_CCU_MUX_WITH_GATE(tcon1_ch0_clk, "tcon1-ch0-sclk", tcon_parents,
> +                              0x11c, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
> +
> +static const char *const csi_isp_parents[] = { "pll-video0", "pll-ve",
> +                                              "pll-ddr-other", "pll-sata" };
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp",
> +                                csi_isp_parents,
> +                                0x120, 0, 4, 24, 2, BIT(31), 0);
> +
> +/* TVD clock setup for A10 */
> +static const char *const tvd_parents[] = { "pll-video0", "pll-video1" };
> +static SUNXI_CCU_MUX_WITH_GATE(tvd_sun4i_clk, "tvd", tvd_parents,
> +                              0x128, 24, 1, BIT(31), 0);
> +
> +/* TVD clock setup for A20 */
> +static SUNXI_CCU_MP_WITH_MUX_GATE(tvd_sclk2_sun7i_clk,
> +                                 "tvd-sclk2", tvd_parents,
> +                                 0x128,
> +                                 0, 4,         /* M */
> +                                 16, 4,        /* P */
> +                                 8, 1,         /* mux */
> +                                 BIT(15),      /* gate */
> +                                 0);
> +static SUNXI_CCU_M_WITH_GATE(tvd_sclk1_sun7i_clk, "tvd-sclk1", "tvd-sclk2",
> +                            0x128, 0, 4, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(tcon0_ch1_sclk2_clk, "tcon0-ch1-sclk2",
> +                                tcon_parents,
> +                                0x12c, 0, 4, 24, 2, BIT(31),
> +                                CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon0_ch1_clk,
> +                            "tcon0-ch1-sclk1", "tcon0-ch1-sclk2",
> +                            0x12c, 11, 1, BIT(15),
> +                            CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_ch1_sclk2_clk, "tcon1-ch1-sclk2",
> +                                tcon_parents,
> +                                0x130, 0, 4, 24, 2, BIT(31),
> +                                CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_WITH_GATE(tcon1_ch1_clk,
> +                            "tcon1-ch1-sclk1", "tcon1-ch1-sclk2",
> +                            0x130, 11, 1, BIT(15),
> +                            CLK_SET_RATE_PARENT);
> +
> +static const char *const csi_parents[] = { "hosc", "pll-video0", "pll-video1",
> +                                          "pll-video0-2x", "pll-video1-2x"};
> +static const u8 csi_table[] = { 0, 1, 2, 5, 6};
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_clk, "csi0",
> +                                      csi_parents, csi_table,
> +                                      0x134, 0, 5, 24, 3, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_clk, "csi1",
> +                                      csi_parents, csi_table,
> +                                      0x138, 0, 5, 24, 3, BIT(31), 0);
> +
> +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c, 16, 8, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio",
> +                     0x140, BIT(31), CLK_SET_RATE_PARENT);
> +static SUNXI_CCU_GATE(avs_clk, "avs", "hosc", 0x144, BIT(31), 0);
> +
> +static const char *const ace_parents[] = { "pll-ve", "pll-ddr-other" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(ace_clk, "ace", ace_parents,
> +                                0x148, 0, 4, 24, 1, BIT(31), 0);
> +

> +static const char *const hdmi_parents[] = { "pll-video0", "pll-video0-2x",
> +                                           "pll-vide01", "pll-video1-2x" };
"pll-vide01" should be "pll-video1"

> +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
> +                                0x150, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const gpu_parents_sun4i[] = { "pll-video0", "pll-ve",
> +                                                "pll-ddr-other",
> +                                                "pll-video1" };
> +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_sun4i_clk, "gpu", gpu_parents_sun4i,
> +                                0x154, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const gpu_parents_sun7i[] = { "pll-video0", "pll-ve",
> +                                                "pll-ddr-other", "pll-video1",
> +                                                "pll-gpu" };
> +static const u8 gpu_table_sun7i[] = { 0, 1, 2, 3, 4 };
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_sun7i_clk, "gpu",
> +                                      gpu_parents_sun7i, gpu_table_sun7i,
> +                                      0x154, 0, 4, 24, 3, BIT(31), 0);
> +
> +static const char *const mbus_parents[] = { "hosc", "pll-periph-2x",
> +                                           "pll-ddr-other" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
> +                                 0x15c, 0, 4, 16, 2, 24, 2, BIT(31),
> +                                 CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_GATE(hdmi1_slow_clk, "hdmi1-slow", "hosc", 0x178, BIT(31), 0);
> +
> +static const char *const hdmi1_parents[] = { "pll-video0", "pll-video1" };
> +static const u8 hdmi1_table[] = { 0, 1};
> +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi1_clk, "hdmi1",
> +                                      hdmi1_parents, hdmi1_table,
> +                                      0x17c, 0, 4, 24, 2, BIT(31), 0);
> +
> +static const char *const out_parents[] = { "hosc", "osc32k", "hosc" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(out_a_clk, "out-a", out_parents,
> +                                 0x1f0, 8, 5, 20, 2, 24, 2, BIT(31), 0);
> +static SUNXI_CCU_MP_WITH_MUX_GATE(out_b_clk, "out-b", out_parents,
> +                                 0x1f4, 8, 5, 20, 2, 24, 2, BIT(31), 0);
> +
> +static struct ccu_common *sun4i_a10_ccu_clks[] = {
> +       &hosc_clk.common,
> +       &pll_core_clk.common,
> +       &pll_audio_base_clk.common,
> +       &pll_video0_clk.common,
> +       &pll_ve_clk.common,
> +       &pll_ddr_base_clk.common,
> +       &pll_ddr_clk.common,
> +       &pll_ddr_other_clk.common,
> +       &pll_periph_clk.common,
> +       &pll_periph_sata_clk.common,
> +       &pll_video1_clk.common,
> +       &cpu_clk.common,
> +       &axi_clk.common,
> +       &axi_dram_clk.common,
> +       &ahb_clk.common,
> +       &apb0_clk.common,
> +       &apb1_clk.common,
> +       &ahb_otg_clk.common,
> +       &ahb_ehci0_clk.common,
> +       &ahb_ohci0_clk.common,
> +       &ahb_ehci1_clk.common,
> +       &ahb_ohci1_clk.common,
> +       &ahb_ss_clk.common,
> +       &ahb_dma_clk.common,
> +       &ahb_bist_clk.common,
> +       &ahb_mmc0_clk.common,
> +       &ahb_mmc1_clk.common,
> +       &ahb_mmc2_clk.common,
> +       &ahb_mmc3_clk.common,
> +       &ahb_ms_clk.common,
> +       &ahb_nand_clk.common,
> +       &ahb_sdram_clk.common,
> +       &ahb_ace_clk.common,
> +       &ahb_emac_clk.common,
> +       &ahb_ts_clk.common,
> +       &ahb_spi0_clk.common,
> +       &ahb_spi1_clk.common,
> +       &ahb_spi2_clk.common,
> +       &ahb_spi3_clk.common,
> +       &ahb_pata_clk.common,
> +       &ahb_sata_clk.common,
> +       &ahb_gps_clk.common,
> +       &ahb_ve_clk.common,
> +       &ahb_tvd_clk.common,
> +       &ahb_tve0_clk.common,
> +       &ahb_tve1_clk.common,
> +       &ahb_lcd0_clk.common,
> +       &ahb_lcd1_clk.common,
> +       &ahb_csi0_clk.common,
> +       &ahb_csi1_clk.common,
> +       &ahb_hdmi0_clk.common,
> +       &ahb_de_be0_clk.common,
> +       &ahb_de_be1_clk.common,
> +       &ahb_de_fe0_clk.common,
> +       &ahb_de_fe1_clk.common,
> +       &ahb_mp_clk.common,
> +       &ahb_gpu_clk.common,
> +       &apb0_codec_clk.common,
> +       &apb0_spdif_clk.common,
> +       &apb0_ac97_clk.common,
> +       &apb0_i2s0_clk.common,
> +       &apb0_pio_clk.common,
> +       &apb0_ir0_clk.common,
> +       &apb0_ir1_clk.common,
> +       &apb0_keypad_clk.common,
> +       &apb1_i2c0_clk.common,
> +       &apb1_i2c1_clk.common,
> +       &apb1_i2c2_clk.common,
> +       &apb1_can_clk.common,
> +       &apb1_scr_clk.common,
> +       &apb1_ps20_clk.common,
> +       &apb1_ps21_clk.common,
> +       &apb1_uart0_clk.common,
> +       &apb1_uart1_clk.common,
> +       &apb1_uart2_clk.common,
> +       &apb1_uart3_clk.common,
> +       &apb1_uart4_clk.common,
> +       &apb1_uart5_clk.common,
> +       &apb1_uart6_clk.common,
> +       &apb1_uart7_clk.common,
> +       &nand_clk.common,
> +       &ms_clk.common,
> +       &mmc0_clk.common,
> +       &mmc0_output_clk.common,
> +       &mmc0_sample_clk.common,
> +       &mmc1_clk.common,
> +       &mmc1_output_clk.common,
> +       &mmc1_sample_clk.common,
> +       &mmc2_clk.common,
> +       &mmc2_output_clk.common,
> +       &mmc2_sample_clk.common,
> +       &mmc3_clk.common,
> +       &mmc3_output_clk.common,
> +       &mmc3_sample_clk.common,
> +       &ts_clk.common,
> +       &ss_clk.common,
> +       &spi0_clk.common,
> +       &spi1_clk.common,
> +       &spi2_clk.common,
> +       &pata_clk.common,
> +       &ir0_sun4i_clk.common,
> +       &ir1_sun4i_clk.common,
> +       &i2s0_clk.common,
> +       &ac97_clk.common,
> +       &spdif_clk.common,
> +       &keypad_clk.common,
> +       &sata_clk.common,
> +       &usb_ohci0_clk.common,
> +       &usb_ohci1_clk.common,
> +       &usb_phy_clk.common,
> +       &spi3_clk.common,
> +       &dram_ve_clk.common,
> +       &dram_csi0_clk.common,
> +       &dram_csi1_clk.common,
> +       &dram_ts_clk.common,
> +       &dram_tvd_clk.common,
> +       &dram_tve0_clk.common,
> +       &dram_tve1_clk.common,
> +       &dram_out_clk.common,
> +       &dram_de_fe1_clk.common,
> +       &dram_de_fe0_clk.common,
> +       &dram_de_be0_clk.common,
> +       &dram_de_be1_clk.common,
> +       &dram_mp_clk.common,
> +       &dram_ace_clk.common,
> +       &de_mp_clk.common,
> +       &csi_isp_clk.common,
> +       &tvd_sun4i_clk.common,
> +       &tcon0_ch1_sclk2_clk.common,
> +       &tcon0_ch1_clk.common,
> +       &tcon1_ch1_sclk2_clk.common,
> +       &tcon1_ch1_clk.common,
> +       &csi0_clk.common,
> +       &csi1_clk.common,
> +       &ve_clk.common,
> +       &codec_clk.common,
> +       &avs_clk.common,
> +       &ace_clk.common,
> +       &hdmi_clk.common,
> +       &gpu_sun4i_clk.common,
> +};
> +
> +static struct ccu_common *sun7i_a20_ccu_clks[] = {
> +       &hosc_clk.common,
> +       &pll_core_clk.common,
> +       &pll_audio_base_clk.common,
> +       &pll_video0_clk.common,
> +       &pll_ve_clk.common,
> +       &pll_ddr_base_clk.common,
> +       &pll_ddr_clk.common,
> +       &pll_ddr_other_clk.common,
> +       &pll_periph_clk.common,
> +       &pll_periph_sata_clk.common,
> +       &pll_video1_clk.common,
> +       &pll_gpu_clk.common,
> +       &cpu_clk.common,
> +       &axi_clk.common,
> +       &ahb_clk.common,
> +       &apb0_clk.common,
> +       &apb1_clk.common,
> +       &ahb_otg_clk.common,
> +       &ahb_ehci0_clk.common,
> +       &ahb_ohci0_clk.common,
> +       &ahb_ehci1_clk.common,
> +       &ahb_ohci1_clk.common,
> +       &ahb_ss_clk.common,
> +       &ahb_dma_clk.common,
> +       &ahb_bist_clk.common,
> +       &ahb_mmc0_clk.common,
> +       &ahb_mmc1_clk.common,
> +       &ahb_mmc2_clk.common,
> +       &ahb_mmc3_clk.common,
> +       &ahb_ms_clk.common,
> +       &ahb_nand_clk.common,
> +       &ahb_sdram_clk.common,
> +       &ahb_ace_clk.common,
> +       &ahb_emac_clk.common,
> +       &ahb_ts_clk.common,
> +       &ahb_spi0_clk.common,
> +       &ahb_spi1_clk.common,
> +       &ahb_spi2_clk.common,
> +       &ahb_spi3_clk.common,
> +       &ahb_pata_clk.common,
> +       &ahb_sata_clk.common,
> +       &ahb_hstimer_clk.common,
> +       &ahb_ve_clk.common,
> +       &ahb_tvd_clk.common,
> +       &ahb_tve0_clk.common,
> +       &ahb_tve1_clk.common,
> +       &ahb_lcd0_clk.common,
> +       &ahb_lcd1_clk.common,
> +       &ahb_csi0_clk.common,
> +       &ahb_csi1_clk.common,
> +       &ahb_hdmi1_clk.common,
> +       &ahb_hdmi0_clk.common,
> +       &ahb_de_be0_clk.common,
> +       &ahb_de_be1_clk.common,
> +       &ahb_de_fe0_clk.common,
> +       &ahb_de_fe1_clk.common,
> +       &ahb_gmac_clk.common,
> +       &ahb_mp_clk.common,
> +       &ahb_gpu_clk.common,
> +       &apb0_codec_clk.common,
> +       &apb0_spdif_clk.common,
> +       &apb0_ac97_clk.common,
> +       &apb0_i2s0_clk.common,
> +       &apb0_i2s1_clk.common,
> +       &apb0_pio_clk.common,
> +       &apb0_ir0_clk.common,
> +       &apb0_ir1_clk.common,
> +       &apb0_i2s2_clk.common,
> +       &apb0_keypad_clk.common,
> +       &apb1_i2c0_clk.common,
> +       &apb1_i2c1_clk.common,
> +       &apb1_i2c2_clk.common,
> +       &apb1_i2c3_clk.common,
> +       &apb1_can_clk.common,
> +       &apb1_scr_clk.common,
> +       &apb1_ps20_clk.common,
> +       &apb1_ps21_clk.common,
> +       &apb1_i2c4_clk.common,
> +       &apb1_uart0_clk.common,
> +       &apb1_uart1_clk.common,
> +       &apb1_uart2_clk.common,
> +       &apb1_uart3_clk.common,
> +       &apb1_uart4_clk.common,
> +       &apb1_uart5_clk.common,
> +       &apb1_uart6_clk.common,
> +       &apb1_uart7_clk.common,
> +       &nand_clk.common,
> +       &ms_clk.common,
> +       &mmc0_clk.common,
> +       &mmc0_output_clk.common,
> +       &mmc0_sample_clk.common,
> +       &mmc1_clk.common,
> +       &mmc1_output_clk.common,
> +       &mmc1_sample_clk.common,
> +       &mmc2_clk.common,
> +       &mmc2_output_clk.common,
> +       &mmc2_sample_clk.common,
> +       &mmc3_clk.common,
> +       &mmc3_output_clk.common,
> +       &mmc3_sample_clk.common,
> +       &ts_clk.common,
> +       &ss_clk.common,
> +       &spi0_clk.common,
> +       &spi1_clk.common,
> +       &spi2_clk.common,
> +       &pata_clk.common,
> +       &ir0_sun7i_clk.common,
> +       &ir1_sun7i_clk.common,
> +       &i2s0_clk.common,
> +       &ac97_clk.common,
> +       &spdif_clk.common,
> +       &keypad_clk.common,
> +       &sata_clk.common,
> +       &usb_ohci0_clk.common,
> +       &usb_ohci1_clk.common,
> +       &usb_phy_clk.common,
> +       &spi3_clk.common,
> +       &i2s1_clk.common,
> +       &i2s2_clk.common,
> +       &dram_ve_clk.common,
> +       &dram_csi0_clk.common,
> +       &dram_csi1_clk.common,
> +       &dram_ts_clk.common,
> +       &dram_tvd_clk.common,
> +       &dram_tve0_clk.common,
> +       &dram_tve1_clk.common,
> +       &dram_out_clk.common,
> +       &dram_de_fe1_clk.common,
> +       &dram_de_fe0_clk.common,
> +       &dram_de_be0_clk.common,
> +       &dram_de_be1_clk.common,
> +       &dram_mp_clk.common,
> +       &dram_ace_clk.common,
> +       &de_be0_clk.common,
> +       &de_be1_clk.common,
> +       &de_fe0_clk.common,
> +       &de_fe1_clk.common,
> +       &de_mp_clk.common,
> +       &tcon0_ch0_clk.common,
> +       &tcon1_ch0_clk.common,
> +       &csi_isp_clk.common,
> +       &tvd_sclk1_sun7i_clk.common,
> +       &tvd_sclk2_sun7i_clk.common,
> +       &tcon0_ch1_sclk2_clk.common,
> +       &tcon0_ch1_clk.common,
> +       &tcon1_ch1_sclk2_clk.common,
> +       &tcon1_ch1_clk.common,
> +       &csi0_clk.common,
> +       &csi1_clk.common,
> +       &ve_clk.common,
> +       &codec_clk.common,
> +       &avs_clk.common,
> +       &ace_clk.common,
> +       &hdmi_clk.common,
> +       &gpu_sun7i_clk.common,
> +       &mbus_clk.common,
> +       &hdmi1_slow_clk.common,
> +       &hdmi1_clk.common,
> +       &out_a_clk.common,
> +       &out_b_clk.common
> +};
> +
> +/* Post-divider for pll-audio is hardcoded to 4 */
> +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
> +                       "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
> +                       "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
> +                       "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
> +                       "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_periph_2x_clk, "pll-periph-2x",
> +                       "pll-periph", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
> +                       "pll-video0", 1, 2, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x",
> +                       "pll-video1", 1, 2, CLK_SET_RATE_PARENT);
> +
> +
> +static struct clk_hw_onecell_data sun4i_a10_hw_clks = {
> +       .hws    = {
> +               [CLK_HOSC]              = &hosc_clk.common.hw,
> +               [CLK_PLL_CORE]          = &pll_core_clk.common.hw,
> +               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
> +               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
> +               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
> +               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
> +               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
> +               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
> +               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
> +               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
> +               [CLK_PLL_DDR_BASE]      = &pll_ddr_base_clk.common.hw,
> +               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
> +               [CLK_PLL_DDR_OTHER]     = &pll_ddr_other_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     = &pll_periph_2x_clk.hw,
> +               [CLK_PLL_PERIPH_SATA]   = &pll_periph_sata_clk.common.hw,
> +               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
> +               [CLK_PLL_VIDEO1_2X]     = &pll_video1_2x_clk.hw,
> +               [CLK_CPU]               = &cpu_clk.common.hw,
> +               [CLK_AXI]               = &axi_clk.common.hw,
> +               [CLK_AXI_DRAM]          = &axi_dram_clk.common.hw,
> +               [CLK_AHB]               = &ahb_clk.common.hw,
> +               [CLK_APB0]              = &apb0_clk.common.hw,
> +               [CLK_APB1]              = &apb1_clk.common.hw,
> +               [CLK_AHB_OTG]           = &ahb_otg_clk.common.hw,
> +               [CLK_AHB_EHCI0]         = &ahb_ehci0_clk.common.hw,
> +               [CLK_AHB_OHCI0]         = &ahb_ohci0_clk.common.hw,
> +               [CLK_AHB_EHCI1]         = &ahb_ehci1_clk.common.hw,
> +               [CLK_AHB_OHCI1]         = &ahb_ohci1_clk.common.hw,
> +               [CLK_AHB_SS]            = &ahb_ss_clk.common.hw,
> +               [CLK_AHB_DMA]           = &ahb_dma_clk.common.hw,
> +               [CLK_AHB_BIST]          = &ahb_bist_clk.common.hw,
> +               [CLK_AHB_MMC0]          = &ahb_mmc0_clk.common.hw,
> +               [CLK_AHB_MMC1]          = &ahb_mmc1_clk.common.hw,
> +               [CLK_AHB_MMC2]          = &ahb_mmc2_clk.common.hw,
> +               [CLK_AHB_MMC3]          = &ahb_mmc3_clk.common.hw,
> +               [CLK_AHB_MS]            = &ahb_ms_clk.common.hw,
> +               [CLK_AHB_NAND]          = &ahb_nand_clk.common.hw,
> +               [CLK_AHB_SDRAM]         = &ahb_sdram_clk.common.hw,
> +               [CLK_AHB_ACE]           = &ahb_ace_clk.common.hw,
> +               [CLK_AHB_EMAC]          = &ahb_emac_clk.common.hw,
> +               [CLK_AHB_TS]            = &ahb_ts_clk.common.hw,
> +               [CLK_AHB_SPI0]          = &ahb_spi0_clk.common.hw,
> +               [CLK_AHB_SPI1]          = &ahb_spi1_clk.common.hw,
> +               [CLK_AHB_SPI2]          = &ahb_spi2_clk.common.hw,
> +               [CLK_AHB_SPI3]          = &ahb_spi3_clk.common.hw,
> +               [CLK_AHB_PATA]          = &ahb_pata_clk.common.hw,
> +               [CLK_AHB_SATA]          = &ahb_sata_clk.common.hw,
> +               [CLK_AHB_GPS]           = &ahb_gps_clk.common.hw,
> +               [CLK_AHB_VE]            = &ahb_ve_clk.common.hw,
> +               [CLK_AHB_TVD]           = &ahb_tvd_clk.common.hw,
> +               [CLK_AHB_TVE0]          = &ahb_tve0_clk.common.hw,
> +               [CLK_AHB_TVE1]          = &ahb_tve1_clk.common.hw,
> +               [CLK_AHB_LCD0]          = &ahb_lcd0_clk.common.hw,
> +               [CLK_AHB_LCD1]          = &ahb_lcd1_clk.common.hw,
> +               [CLK_AHB_CSI0]          = &ahb_csi0_clk.common.hw,
> +               [CLK_AHB_CSI1]          = &ahb_csi1_clk.common.hw,
> +               [CLK_AHB_HDMI0]         = &ahb_hdmi0_clk.common.hw,
> +               [CLK_AHB_DE_BE0]        = &ahb_de_be0_clk.common.hw,
> +               [CLK_AHB_DE_BE1]        = &ahb_de_be1_clk.common.hw,
> +               [CLK_AHB_DE_FE0]        = &ahb_de_fe0_clk.common.hw,
> +               [CLK_AHB_DE_FE1]        = &ahb_de_fe1_clk.common.hw,
> +               [CLK_AHB_MP]            = &ahb_mp_clk.common.hw,
> +               [CLK_AHB_GPU]           = &ahb_gpu_clk.common.hw,
> +               [CLK_APB0_CODEC]        = &apb0_codec_clk.common.hw,
> +               [CLK_APB0_SPDIF]        = &apb0_spdif_clk.common.hw,
> +               [CLK_APB0_AC97]         = &apb0_ac97_clk.common.hw,
> +               [CLK_APB0_I2S0]         = &apb0_i2s0_clk.common.hw,
> +               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
> +               [CLK_APB0_IR0]          = &apb0_ir0_clk.common.hw,
> +               [CLK_APB0_IR1]          = &apb0_ir1_clk.common.hw,
> +               [CLK_APB0_KEYPAD]       = &apb0_keypad_clk.common.hw,
> +               [CLK_APB1_I2C0]         = &apb1_i2c0_clk.common.hw,
> +               [CLK_APB1_I2C1]         = &apb1_i2c1_clk.common.hw,
> +               [CLK_APB1_I2C2]         = &apb1_i2c2_clk.common.hw,
> +               [CLK_APB1_CAN]          = &apb1_can_clk.common.hw,
> +               [CLK_APB1_SCR]          = &apb1_scr_clk.common.hw,
> +               [CLK_APB1_PS20]         = &apb1_ps20_clk.common.hw,
> +               [CLK_APB1_PS21]         = &apb1_ps21_clk.common.hw,
> +               [CLK_APB1_UART0]        = &apb1_uart0_clk.common.hw,
> +               [CLK_APB1_UART1]        = &apb1_uart1_clk.common.hw,
> +               [CLK_APB1_UART2]        = &apb1_uart2_clk.common.hw,
> +               [CLK_APB1_UART3]        = &apb1_uart3_clk.common.hw,
> +               [CLK_APB1_UART4]        = &apb1_uart4_clk.common.hw,
> +               [CLK_APB1_UART5]        = &apb1_uart5_clk.common.hw,
> +               [CLK_APB1_UART6]        = &apb1_uart6_clk.common.hw,
> +               [CLK_APB1_UART7]        = &apb1_uart7_clk.common.hw,
> +               [CLK_NAND]              = &nand_clk.common.hw,
> +               [CLK_MS]                = &ms_clk.common.hw,
> +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> +               [CLK_MMC0_OUTPUT]       = &mmc0_output_clk.common.hw,
> +               [CLK_MMC0_SAMPLE]       = &mmc0_sample_clk.common.hw,
> +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> +               [CLK_MMC1_OUTPUT]       = &mmc1_output_clk.common.hw,
> +               [CLK_MMC1_SAMPLE]       = &mmc1_sample_clk.common.hw,
> +               [CLK_MMC2]              = &mmc2_clk.common.hw,
> +               [CLK_MMC2_OUTPUT]       = &mmc2_output_clk.common.hw,
> +               [CLK_MMC2_SAMPLE]       = &mmc2_sample_clk.common.hw,
> +               [CLK_MMC3]              = &mmc3_clk.common.hw,
> +               [CLK_MMC3_OUTPUT]       = &mmc3_output_clk.common.hw,
> +               [CLK_MMC3_SAMPLE]       = &mmc3_sample_clk.common.hw,
> +               [CLK_TS]                = &ts_clk.common.hw,
> +               [CLK_SS]                = &ss_clk.common.hw,
> +               [CLK_SPI0]              = &spi0_clk.common.hw,
> +               [CLK_SPI1]              = &spi1_clk.common.hw,
> +               [CLK_SPI2]              = &spi2_clk.common.hw,
> +               [CLK_PATA]              = &pata_clk.common.hw,
> +               [CLK_IR0]               = &ir0_sun4i_clk.common.hw,
> +               [CLK_IR1]               = &ir1_sun4i_clk.common.hw,
> +               [CLK_I2S0]              = &i2s0_clk.common.hw,
> +               [CLK_AC97]              = &ac97_clk.common.hw,
> +               [CLK_SPDIF]             = &spdif_clk.common.hw,
> +               [CLK_KEYPAD]            = &keypad_clk.common.hw,
> +               [CLK_SATA]              = &sata_clk.common.hw,
> +               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
> +               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
> +               [CLK_USB_PHY]           = &usb_phy_clk.common.hw,
> +               [CLK_SPI3]              = &spi3_clk.common.hw,
> +               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
> +               [CLK_DRAM_CSI0]         = &dram_csi0_clk.common.hw,
> +               [CLK_DRAM_CSI1]         = &dram_csi1_clk.common.hw,
> +               [CLK_DRAM_TS]           = &dram_ts_clk.common.hw,
> +               [CLK_DRAM_TVD]          = &dram_tvd_clk.common.hw,
> +               [CLK_DRAM_TVE0]         = &dram_tve0_clk.common.hw,
> +               [CLK_DRAM_TVE1]         = &dram_tve1_clk.common.hw,
> +               [CLK_DRAM_OUT]          = &dram_out_clk.common.hw,
> +               [CLK_DRAM_DE_FE1]       = &dram_de_fe1_clk.common.hw,
> +               [CLK_DRAM_DE_FE0]       = &dram_de_fe0_clk.common.hw,
> +               [CLK_DRAM_DE_BE0]       = &dram_de_be0_clk.common.hw,
> +               [CLK_DRAM_DE_BE1]       = &dram_de_be1_clk.common.hw,
> +               [CLK_DRAM_MP]           = &dram_mp_clk.common.hw,
> +               [CLK_DRAM_ACE]          = &dram_ace_clk.common.hw,
> +               [CLK_DE_BE0]            = &de_be0_clk.common.hw,
> +               [CLK_DE_BE1]            = &de_be1_clk.common.hw,
> +               [CLK_DE_FE0]            = &de_fe0_clk.common.hw,
> +               [CLK_DE_FE1]            = &de_fe1_clk.common.hw,
> +               [CLK_DE_MP]             = &de_mp_clk.common.hw,
> +               [CLK_TCON0_CH0]         = &tcon0_ch0_clk.common.hw,
> +               [CLK_TCON1_CH0]         = &tcon1_ch0_clk.common.hw,
> +               [CLK_CSI_ISP]           = &csi_isp_clk.common.hw,
> +               [CLK_TVD]               = &tvd_sun4i_clk.common.hw,
> +               [CLK_TCON0_CH1_SCLK2]   = &tcon0_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON0_CH1]         = &tcon0_ch1_clk.common.hw,
> +               [CLK_TCON1_CH1_SCLK2]   = &tcon1_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON1_CH1]         = &tcon1_ch1_clk.common.hw,
> +               [CLK_CSI0]              = &csi0_clk.common.hw,
> +               [CLK_CSI1]              = &csi1_clk.common.hw,
> +               [CLK_VE]                = &ve_clk.common.hw,
> +               [CLK_CODEC]             = &codec_clk.common.hw,
> +               [CLK_AVS]               = &avs_clk.common.hw,
> +               [CLK_ACE]               = &ace_clk.common.hw,
> +               [CLK_HDMI]              = &hdmi_clk.common.hw,
> +               [CLK_GPU]               = &gpu_sun7i_clk.common.hw,
> +       },
> +       .num    = CLK_NUMBER_SUN4I,
> +};
> +static struct clk_hw_onecell_data sun7i_a20_hw_clks = {
> +       .hws    = {
> +               [CLK_HOSC]              = &hosc_clk.common.hw,
> +               [CLK_PLL_CORE]          = &pll_core_clk.common.hw,
> +               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
> +               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
> +               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
> +               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
> +               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
> +               [CLK_PLL_VIDEO0]        = &pll_video0_clk.common.hw,
> +               [CLK_PLL_VIDEO0_2X]     = &pll_video0_2x_clk.hw,
> +               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
> +               [CLK_PLL_DDR_BASE]      = &pll_ddr_base_clk.common.hw,
> +               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
> +               [CLK_PLL_DDR_OTHER]     = &pll_ddr_other_clk.common.hw,
> +               [CLK_PLL_PERIPH]        = &pll_periph_clk.common.hw,
> +               [CLK_PLL_PERIPH_2X]     = &pll_periph_2x_clk.hw,
> +               [CLK_PLL_PERIPH_SATA]   = &pll_periph_sata_clk.common.hw,
> +               [CLK_PLL_VIDEO1]        = &pll_video1_clk.common.hw,
> +               [CLK_PLL_VIDEO1_2X]     = &pll_video1_2x_clk.hw,
> +               [CLK_PLL_GPU]           = &pll_gpu_clk.common.hw,
> +               [CLK_CPU]               = &cpu_clk.common.hw,
> +               [CLK_AXI]               = &axi_clk.common.hw,
> +               [CLK_AHB]               = &ahb_clk.common.hw,
> +               [CLK_APB0]              = &apb0_clk.common.hw,
> +               [CLK_APB1]              = &apb1_clk.common.hw,
> +               [CLK_AHB_OTG]           = &ahb_otg_clk.common.hw,
> +               [CLK_AHB_EHCI0]         = &ahb_ehci0_clk.common.hw,
> +               [CLK_AHB_OHCI0]         = &ahb_ohci0_clk.common.hw,
> +               [CLK_AHB_EHCI1]         = &ahb_ehci1_clk.common.hw,
> +               [CLK_AHB_OHCI1]         = &ahb_ohci1_clk.common.hw,
> +               [CLK_AHB_SS]            = &ahb_ss_clk.common.hw,
> +               [CLK_AHB_DMA]           = &ahb_dma_clk.common.hw,
> +               [CLK_AHB_BIST]          = &ahb_bist_clk.common.hw,
> +               [CLK_AHB_MMC0]          = &ahb_mmc0_clk.common.hw,
> +               [CLK_AHB_MMC1]          = &ahb_mmc1_clk.common.hw,
> +               [CLK_AHB_MMC2]          = &ahb_mmc2_clk.common.hw,
> +               [CLK_AHB_MMC3]          = &ahb_mmc3_clk.common.hw,
> +               [CLK_AHB_MS]            = &ahb_ms_clk.common.hw,
> +               [CLK_AHB_NAND]          = &ahb_nand_clk.common.hw,
> +               [CLK_AHB_SDRAM]         = &ahb_sdram_clk.common.hw,
> +               [CLK_AHB_ACE]           = &ahb_ace_clk.common.hw,
> +               [CLK_AHB_EMAC]          = &ahb_emac_clk.common.hw,
> +               [CLK_AHB_TS]            = &ahb_ts_clk.common.hw,
> +               [CLK_AHB_SPI0]          = &ahb_spi0_clk.common.hw,
> +               [CLK_AHB_SPI1]          = &ahb_spi1_clk.common.hw,
> +               [CLK_AHB_SPI2]          = &ahb_spi2_clk.common.hw,
> +               [CLK_AHB_SPI3]          = &ahb_spi3_clk.common.hw,
> +               [CLK_AHB_PATA]          = &ahb_pata_clk.common.hw,
> +               [CLK_AHB_SATA]          = &ahb_sata_clk.common.hw,
> +               [CLK_AHB_HSTIMER]       = &ahb_hstimer_clk.common.hw,
> +               [CLK_AHB_VE]            = &ahb_ve_clk.common.hw,
> +               [CLK_AHB_TVD]           = &ahb_tvd_clk.common.hw,
> +               [CLK_AHB_TVE0]          = &ahb_tve0_clk.common.hw,
> +               [CLK_AHB_TVE1]          = &ahb_tve1_clk.common.hw,
> +               [CLK_AHB_LCD0]          = &ahb_lcd0_clk.common.hw,
> +               [CLK_AHB_LCD1]          = &ahb_lcd1_clk.common.hw,
> +               [CLK_AHB_CSI0]          = &ahb_csi0_clk.common.hw,
> +               [CLK_AHB_CSI1]          = &ahb_csi1_clk.common.hw,
> +               [CLK_AHB_HDMI1]         = &ahb_hdmi1_clk.common.hw,
> +               [CLK_AHB_HDMI0]         = &ahb_hdmi0_clk.common.hw,
> +               [CLK_AHB_DE_BE0]        = &ahb_de_be0_clk.common.hw,
> +               [CLK_AHB_DE_BE1]        = &ahb_de_be1_clk.common.hw,
> +               [CLK_AHB_DE_FE0]        = &ahb_de_fe0_clk.common.hw,
> +               [CLK_AHB_DE_FE1]        = &ahb_de_fe1_clk.common.hw,
> +               [CLK_AHB_GMAC]          = &ahb_gmac_clk.common.hw,
> +               [CLK_AHB_MP]            = &ahb_mp_clk.common.hw,
> +               [CLK_AHB_GPU]           = &ahb_gpu_clk.common.hw,
> +               [CLK_APB0_CODEC]        = &apb0_codec_clk.common.hw,
> +               [CLK_APB0_SPDIF]        = &apb0_spdif_clk.common.hw,
> +               [CLK_APB0_AC97]         = &apb0_ac97_clk.common.hw,
> +               [CLK_APB0_I2S0]         = &apb0_i2s0_clk.common.hw,
> +               [CLK_APB0_I2S1]         = &apb0_i2s1_clk.common.hw,
> +               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
> +               [CLK_APB0_IR0]          = &apb0_ir0_clk.common.hw,
> +               [CLK_APB0_IR1]          = &apb0_ir1_clk.common.hw,
> +               [CLK_APB0_I2S2]         = &apb0_i2s2_clk.common.hw,
> +               [CLK_APB0_KEYPAD]       = &apb0_keypad_clk.common.hw,
> +               [CLK_APB1_I2C0]         = &apb1_i2c0_clk.common.hw,
> +               [CLK_APB1_I2C1]         = &apb1_i2c1_clk.common.hw,
> +               [CLK_APB1_I2C2]         = &apb1_i2c2_clk.common.hw,
> +               [CLK_APB1_I2C3]         = &apb1_i2c3_clk.common.hw,
> +               [CLK_APB1_CAN]          = &apb1_can_clk.common.hw,
> +               [CLK_APB1_SCR]          = &apb1_scr_clk.common.hw,
> +               [CLK_APB1_PS20]         = &apb1_ps20_clk.common.hw,
> +               [CLK_APB1_PS21]         = &apb1_ps21_clk.common.hw,
> +               [CLK_APB1_I2C4]         = &apb1_i2c4_clk.common.hw,
> +               [CLK_APB1_UART0]        = &apb1_uart0_clk.common.hw,
> +               [CLK_APB1_UART1]        = &apb1_uart1_clk.common.hw,
> +               [CLK_APB1_UART2]        = &apb1_uart2_clk.common.hw,
> +               [CLK_APB1_UART3]        = &apb1_uart3_clk.common.hw,
> +               [CLK_APB1_UART4]        = &apb1_uart4_clk.common.hw,
> +               [CLK_APB1_UART5]        = &apb1_uart5_clk.common.hw,
> +               [CLK_APB1_UART6]        = &apb1_uart6_clk.common.hw,
> +               [CLK_APB1_UART7]        = &apb1_uart7_clk.common.hw,
> +               [CLK_NAND]              = &nand_clk.common.hw,
> +               [CLK_MS]                = &ms_clk.common.hw,
> +               [CLK_MMC0]              = &mmc0_clk.common.hw,
> +               [CLK_MMC0_OUTPUT]       = &mmc0_output_clk.common.hw,
> +               [CLK_MMC0_SAMPLE]       = &mmc0_sample_clk.common.hw,
> +               [CLK_MMC1]              = &mmc1_clk.common.hw,
> +               [CLK_MMC1_OUTPUT]       = &mmc1_output_clk.common.hw,
> +               [CLK_MMC1_SAMPLE]       = &mmc1_sample_clk.common.hw,
> +               [CLK_MMC2]              = &mmc2_clk.common.hw,
> +               [CLK_MMC2_OUTPUT]       = &mmc2_output_clk.common.hw,
> +               [CLK_MMC2_SAMPLE]       = &mmc2_sample_clk.common.hw,
> +               [CLK_MMC3]              = &mmc3_clk.common.hw,
> +               [CLK_MMC3_OUTPUT]       = &mmc3_output_clk.common.hw,
> +               [CLK_MMC3_SAMPLE]       = &mmc3_sample_clk.common.hw,
> +               [CLK_TS]                = &ts_clk.common.hw,
> +               [CLK_SS]                = &ss_clk.common.hw,
> +               [CLK_SPI0]              = &spi0_clk.common.hw,
> +               [CLK_SPI1]              = &spi1_clk.common.hw,
> +               [CLK_SPI2]              = &spi2_clk.common.hw,
> +               [CLK_PATA]              = &pata_clk.common.hw,
> +               [CLK_IR0]               = &ir0_sun7i_clk.common.hw,
> +               [CLK_IR1]               = &ir1_sun7i_clk.common.hw,
> +               [CLK_I2S0]              = &i2s0_clk.common.hw,
> +               [CLK_AC97]              = &ac97_clk.common.hw,
> +               [CLK_SPDIF]             = &spdif_clk.common.hw,
> +               [CLK_KEYPAD]            = &keypad_clk.common.hw,
> +               [CLK_SATA]              = &sata_clk.common.hw,
> +               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
> +               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
> +               [CLK_USB_PHY]           = &usb_phy_clk.common.hw,
> +               [CLK_SPI3]              = &spi3_clk.common.hw,
> +               [CLK_I2S1]              = &i2s1_clk.common.hw,
> +               [CLK_I2S2]              = &i2s2_clk.common.hw,
> +               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
> +               [CLK_DRAM_CSI0]         = &dram_csi0_clk.common.hw,
> +               [CLK_DRAM_CSI1]         = &dram_csi1_clk.common.hw,
> +               [CLK_DRAM_TS]           = &dram_ts_clk.common.hw,
> +               [CLK_DRAM_TVD]          = &dram_tvd_clk.common.hw,
> +               [CLK_DRAM_TVE0]         = &dram_tve0_clk.common.hw,
> +               [CLK_DRAM_TVE1]         = &dram_tve1_clk.common.hw,
> +               [CLK_DRAM_OUT]          = &dram_out_clk.common.hw,
> +               [CLK_DRAM_DE_FE1]       = &dram_de_fe1_clk.common.hw,
> +               [CLK_DRAM_DE_FE0]       = &dram_de_fe0_clk.common.hw,
> +               [CLK_DRAM_DE_BE0]       = &dram_de_be0_clk.common.hw,
> +               [CLK_DRAM_DE_BE1]       = &dram_de_be1_clk.common.hw,
> +               [CLK_DRAM_MP]           = &dram_mp_clk.common.hw,
> +               [CLK_DRAM_ACE]          = &dram_ace_clk.common.hw,
> +               [CLK_DE_BE0]            = &de_be0_clk.common.hw,
> +               [CLK_DE_BE1]            = &de_be1_clk.common.hw,
> +               [CLK_DE_FE0]            = &de_fe0_clk.common.hw,
> +               [CLK_DE_FE1]            = &de_fe1_clk.common.hw,
> +               [CLK_DE_MP]             = &de_mp_clk.common.hw,
> +               [CLK_TCON0_CH0]         = &tcon0_ch0_clk.common.hw,
> +               [CLK_TCON1_CH0]         = &tcon1_ch0_clk.common.hw,
> +               [CLK_CSI_ISP]           = &csi_isp_clk.common.hw,
> +               [CLK_TVD_SCLK2]         = &tvd_sclk2_sun7i_clk.common.hw,
> +               [CLK_TVD]               = &tvd_sclk1_sun7i_clk.common.hw,
> +               [CLK_TCON0_CH1_SCLK2]   = &tcon0_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON0_CH1]         = &tcon0_ch1_clk.common.hw,
> +               [CLK_TCON1_CH1_SCLK2]   = &tcon1_ch1_sclk2_clk.common.hw,
> +               [CLK_TCON1_CH1]         = &tcon1_ch1_clk.common.hw,
> +               [CLK_CSI0]              = &csi0_clk.common.hw,
> +               [CLK_CSI1]              = &csi1_clk.common.hw,
> +               [CLK_VE]                = &ve_clk.common.hw,
> +               [CLK_CODEC]             = &codec_clk.common.hw,
> +               [CLK_AVS]               = &avs_clk.common.hw,
> +               [CLK_ACE]               = &ace_clk.common.hw,
> +               [CLK_HDMI]              = &hdmi_clk.common.hw,
> +               [CLK_GPU]               = &gpu_sun7i_clk.common.hw,
> +               [CLK_MBUS]              = &mbus_clk.common.hw,
> +               [CLK_HDMI1_SLOW]        = &hdmi1_slow_clk.common.hw,
> +               [CLK_HDMI1]             = &hdmi1_clk.common.hw,
> +               [CLK_OUT_A]             = &out_a_clk.common.hw,
> +               [CLK_OUT_B]             = &out_b_clk.common.hw,
> +       },
> +       .num    = CLK_NUMBER_SUN7I,
> +};
> +
> +static struct ccu_reset_map sun4i_a10_ccu_resets[] = {
> +       [RST_USB_PHY0]          = { 0x0cc, BIT(0) },
> +       [RST_USB_PHY1]          = { 0x0cc, BIT(1) },
> +       [RST_USB_PHY2]          = { 0x0cc, BIT(2) },
> +       [RST_DE_BE0]            = { 0x104, BIT(30) },
> +       [RST_DE_BE1]            = { 0x108, BIT(30) },
> +       [RST_DE_FE0]            = { 0x10c, BIT(30) },
> +       [RST_DE_FE1]            = { 0x110, BIT(30) },
> +       [RST_DE_MP]             = { 0x114, BIT(30) },
> +       [RST_TCON0]             = { 0x118, BIT(30) },
> +       [RST_TCON1]             = { 0x11c, BIT(30) },
> +       [RST_CSI0]              = { 0x134, BIT(30) },
> +       [RST_CSI1]              = { 0x138, BIT(30) },
> +       [RST_VE]                = { 0x13c, BIT(0) },
> +       [RST_ACE]               = { 0x148, BIT(16) },
> +       [RST_LVDS]              = { 0x14c, BIT(0) },
> +       [RST_GPU]               = { 0x154, BIT(30) },
> +};
> +
> +static struct ccu_reset_map sun7i_a20_ccu_resets[] = {
> +       [RST_USB_PHY0]          = { 0x0cc, BIT(0) },
> +       [RST_USB_PHY1]          = { 0x0cc, BIT(1) },
> +       [RST_USB_PHY2]          = { 0x0cc, BIT(2) },
> +       [RST_DE_BE0]            = { 0x104, BIT(30) },
> +       [RST_DE_BE1]            = { 0x108, BIT(30) },
> +       [RST_DE_FE0]            = { 0x10c, BIT(30) },
> +       [RST_DE_FE1]            = { 0x110, BIT(30) },
> +       [RST_DE_MP]             = { 0x114, BIT(30) },
> +       [RST_TCON0]             = { 0x118, BIT(30) },
> +       [RST_TCON1]             = { 0x11c, BIT(30) },
> +       [RST_CSI0]              = { 0x134, BIT(30) },
> +       [RST_CSI1]              = { 0x138, BIT(30) },
> +       [RST_VE]                = { 0x13c, BIT(0) },
> +       [RST_ACE]               = { 0x148, BIT(16) },
> +       [RST_LVDS]              = { 0x14c, BIT(0) },
> +       [RST_GPU]               = { 0x154, BIT(30) },
> +       [RST_HDMI_H]            = { 0x170, BIT(0) },
> +       [RST_HDMI_SYS]          = { 0x170, BIT(1) },
> +       [RST_HDMI_AUDIO_DMA]    = { 0x170, BIT(2) },
> +};
> +
> +static const struct sunxi_ccu_desc sun4i_a10_ccu_desc = {
> +       .ccu_clks       = sun4i_a10_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun4i_a10_ccu_clks),
> +
> +       .hw_clks        = &sun4i_a10_hw_clks,
> +
> +       .resets         = sun4i_a10_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun4i_a10_ccu_resets),
> +};
> +
> +static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = {
> +       .ccu_clks       = sun7i_a20_ccu_clks,
> +       .num_ccu_clks   = ARRAY_SIZE(sun7i_a20_ccu_clks),
> +
> +       .hw_clks        = &sun7i_a20_hw_clks,
> +
> +       .resets         = sun7i_a20_ccu_resets,
> +       .num_resets     = ARRAY_SIZE(sun7i_a20_ccu_resets),
> +};
> +
> +static void init_clocks(void __iomem *reg)
> +{
> +       u32 val;
> +
> +       /* Force the PLL-Audio-1x divider to 4 */
> +       val = readl(reg + SUN4I_PLL_AUDIO_REG);
> +       val &= ~GENMASK(19, 16);
> +       writel(val | (3 << 16), reg + SUN4I_PLL_AUDIO_REG);
> +
> +       /* Use PLL6 as parent for AHB */
> +       val = readl(reg + SUN4I_AHB_REG);
> +       val &= ~GENMASK(7, 6);
> +       writel(val | (2 << 6), reg + SUN4I_AHB_REG);
> +}
> +
> +static void __init sun4i_a10_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +
> +       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%s: Could not map the clock registers\n",
> +                      of_node_full_name(node));
> +               return;
> +       }
> +
> +       init_clocks(reg);
> +
> +       sunxi_ccu_probe(node, reg, &sun4i_a10_ccu_desc);
> +}
> +
> +static void __init sun7i_a20_ccu_setup(struct device_node *node)
> +{
> +       void __iomem *reg;
> +
> +       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> +       if (IS_ERR(reg)) {
> +               pr_err("%s: Could not map the clock registers\n",
> +                      of_node_full_name(node));
> +               return;
> +       }
> +
> +       init_clocks(reg);
> +
> +       sunxi_ccu_probe(node, reg, &sun7i_a20_ccu_desc);
> +}
> +
> +CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu",
> +              sun4i_a10_ccu_setup);
> +CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu",
> +              sun7i_a20_ccu_setup);
> diff --git a/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
> new file mode 100644
> index 0000000..bca224d
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sunxi-a10-a20.h
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright 2017 Priit Laes
> + *
> + * Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef _CCU_SUNXI_A10_A20_H_
> +#define _CCU_SUNXI_A10_A20_H_
> +
> +#include <dt-bindings/clock/sunxi-a10-a20-ccu.h>
> +#include <dt-bindings/reset/sunxi-a10-a20-ccu.h>
> +
> +/* The HOSC is exported */
> +#define CLK_PLL_CORE           2
> +#define CLK_PLL_AUDIO_BASE     3
> +#define CLK_PLL_AUDIO          4
> +#define CLK_PLL_AUDIO_2X       5
> +#define CLK_PLL_AUDIO_4X       6
> +#define CLK_PLL_AUDIO_8X       7
> +#define CLK_PLL_VIDEO0         8
> +#define CLK_PLL_VIDEO0_2X      9
> +#define CLK_PLL_VE             10
> +#define CLK_PLL_DDR_BASE       11
> +#define CLK_PLL_DDR            12
> +#define CLK_PLL_DDR_OTHER      13
> +#define CLK_PLL_PERIPH         14
> +#define CLK_PLL_PERIPH_2X      15
> +#define CLK_PLL_VIDEO1         17
> +#define CLK_PLL_VIDEO1_2X      18
> +#define CLK_PLL_GPU            19
> +
> +/* The CPU clock is exported */
> +#define CLK_AXI                        21
> +#define CLK_AXI_DRAM           22
> +#define CLK_AHB                        23
> +#define CLK_APB0               24
> +#define CLK_APB1               25
> +
> +/* AHB gates are exported (23..68) */
> +/* APB0 gates are exported (69..78) */
> +/* APB1 gates are exported (79..95) */
> +/* IP module clocks are exported (96..128) */
> +/* DRAM gates are exported (129..142)*/
> +/* Media (display engine clocks & etc) are exported (143..169) */
> +
> +#define CLK_NUMBER_SUN4I       (CLK_GPU + 1)
> +#define CLK_NUMBER_SUN7I       (CLK_OUT_B + 1)
> +
> +#endif /* _CCU_SUNXI_A10_A20_H_ */
> diff --git a/include/dt-bindings/clock/sunxi-a10-a20-ccu.h b/include/dt-bindings/clock/sunxi-a10-a20-ccu.h
> new file mode 100644
> index 0000000..364ccbe
> --- /dev/null
> +++ b/include/dt-bindings/clock/sunxi-a10-a20-ccu.h
> @@ -0,0 +1,208 @@
> +/*
> + * Copyright (C) 2017 Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This file is distributed in the hope that it will be useful,
> + *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *     GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_CLK_SUNXI_A10_A20_H_
> +#define _DT_BINDINGS_CLK_SUNXI_A10_A20_H_
> +
> +#define CLK_HOSC               1
> +#define CLK_PLL_PERIPH_SATA    16
> +#define CLK_CPU                        20
> +
> +/* AHB Gates */
> +#define CLK_AHB_OTG            26
> +#define CLK_AHB_EHCI0          27
> +#define CLK_AHB_OHCI0          28
> +#define CLK_AHB_EHCI1          29
> +#define CLK_AHB_OHCI1          30
> +#define CLK_AHB_SS             31
> +#define CLK_AHB_DMA            32
> +#define CLK_AHB_BIST           33
> +#define CLK_AHB_MMC0           34
> +#define CLK_AHB_MMC1           35
> +#define CLK_AHB_MMC2           36
> +#define CLK_AHB_MMC3           37
> +#define CLK_AHB_MS             38
> +#define CLK_AHB_NAND           39
> +#define CLK_AHB_SDRAM          40
> +#define CLK_AHB_ACE            41
> +#define CLK_AHB_EMAC           42
> +#define CLK_AHB_TS             43
> +#define CLK_AHB_SPI0           44
> +#define CLK_AHB_SPI1           45
> +#define CLK_AHB_SPI2           46
> +#define CLK_AHB_SPI3           47
> +#define CLK_AHB_PATA           48
> +#define CLK_AHB_SATA           49
> +#define CLK_AHB_GPS            50
> +#define CLK_AHB_HSTIMER                51
> +#define CLK_AHB_VE             52
> +#define CLK_AHB_TVD            53
> +#define CLK_AHB_TVE0           54
> +#define CLK_AHB_TVE1           55
> +#define CLK_AHB_LCD0           56
> +#define CLK_AHB_LCD1           57
> +#define CLK_AHB_CSI0           58
> +#define CLK_AHB_CSI1           59
> +#define CLK_AHB_HDMI0          60
> +#define CLK_AHB_HDMI1          61
> +#define CLK_AHB_DE_BE0         62
> +#define CLK_AHB_DE_BE1         63
> +#define CLK_AHB_DE_FE0         64
> +#define CLK_AHB_DE_FE1         65
> +#define CLK_AHB_GMAC           66
> +#define CLK_AHB_MP             67
> +#define CLK_AHB_GPU            68
> +
> +/* APB0 Gates */
> +#define CLK_APB0_CODEC         69
> +#define CLK_APB0_SPDIF         70
> +#define CLK_APB0_I2S0          71
> +#define CLK_APB0_AC97          72
> +#define CLK_APB0_I2S1          73
> +#define CLK_APB0_PIO           74
> +#define CLK_APB0_IR0           75
> +#define CLK_APB0_IR1           76
> +#define CLK_APB0_I2S2          77
> +#define CLK_APB0_KEYPAD                78
> +
> +/* APB1 Gates */
> +#define CLK_APB1_I2C0          79
> +#define CLK_APB1_I2C1          80
> +#define CLK_APB1_I2C2          81
> +#define CLK_APB1_I2C3          82
> +#define CLK_APB1_CAN           83
> +#define CLK_APB1_SCR           84
> +#define CLK_APB1_PS20          85
> +#define CLK_APB1_PS21          86
> +#define CLK_APB1_I2C4          87
> +#define CLK_APB1_UART0         88
> +#define CLK_APB1_UART1         89
> +#define CLK_APB1_UART2         90
> +#define CLK_APB1_UART3         91
> +#define CLK_APB1_UART4         92
> +#define CLK_APB1_UART5         93
> +#define CLK_APB1_UART6         94
> +#define CLK_APB1_UART7         95
> +
> +/* IP clocks */
> +#define CLK_NAND               96
> +#define CLK_MS                 97
> +#define CLK_MMC0               98
> +#define CLK_MMC0_OUTPUT                99
> +#define CLK_MMC0_SAMPLE                100
> +#define CLK_MMC1               101
> +#define CLK_MMC1_OUTPUT                102
> +#define CLK_MMC1_SAMPLE                103
> +#define CLK_MMC2               104
> +#define CLK_MMC2_OUTPUT                105
> +#define CLK_MMC2_SAMPLE                106
> +#define CLK_MMC3               107
> +#define CLK_MMC3_OUTPUT                108
> +#define CLK_MMC3_SAMPLE                109
> +#define CLK_TS                 110
> +#define CLK_SS                 111
> +#define CLK_SPI0               112
> +#define CLK_SPI1               113
> +#define CLK_SPI2               114
> +#define CLK_PATA               115
> +#define CLK_IR0                        116
> +#define CLK_IR1                        117
> +#define CLK_I2S0               118
> +#define CLK_AC97               119
> +#define CLK_SPDIF              120
> +#define CLK_KEYPAD             121
> +#define CLK_SATA               122
> +#define CLK_USB_OHCI0          123
> +#define CLK_USB_OHCI1          124
> +#define CLK_USB_PHY            125
> +#define CLK_SPI3               126
> +#define CLK_I2S1               127
> +#define CLK_I2S2               128
> +
> +/* DRAM Gates */
> +#define CLK_DRAM_VE            129
> +#define CLK_DRAM_CSI0          130
> +#define CLK_DRAM_CSI1          131
> +#define CLK_DRAM_TS            132
> +#define CLK_DRAM_TVD           133
> +#define CLK_DRAM_TVE0          134
> +#define CLK_DRAM_TVE1          135
> +#define CLK_DRAM_OUT           136
> +#define CLK_DRAM_DE_FE1                137
> +#define CLK_DRAM_DE_FE0                138
> +#define CLK_DRAM_DE_BE0                139
> +#define CLK_DRAM_DE_BE1                140
> +#define CLK_DRAM_MP            141
> +#define CLK_DRAM_ACE           142
> +
> +/* Display Engine Clocks */
> +#define CLK_DE_BE0             143
> +#define CLK_DE_BE1             144
> +#define CLK_DE_FE0             145
> +#define CLK_DE_FE1             146
> +#define CLK_DE_MP              147
> +#define CLK_TCON0_CH0          148
> +#define CLK_TCON1_CH0          149
> +#define CLK_CSI_ISP            150
> +#define CLK_TVD_SCLK2          151
> +#define CLK_TVD                        152
> +#define CLK_TCON0_CH1_SCLK2    153
> +#define CLK_TCON0_CH1          154
> +#define CLK_TCON1_CH1_SCLK2    155
> +#define CLK_TCON1_CH1          156
> +#define CLK_CSI0               157
> +#define CLK_CSI1               158
> +#define CLK_CODEC              159
> +#define CLK_VE                 160
> +#define CLK_AVS                        161
> +#define CLK_ACE                        162
> +#define CLK_HDMI               163
> +#define CLK_GPU                        164
> +
> +/* Following only exist on sun7i-a20 */
> +#define CLK_MBUS               165
> +#define CLK_HDMI1_SLOW         166
> +#define CLK_HDMI1              167
> +#define CLK_OUT_A              168
> +#define CLK_OUT_B              169
> +
> +#endif /* _DT_BINDINGS_CLK_SUNXI_A10_A20_H_ */
> diff --git a/include/dt-bindings/reset/sunxi-a10-a20-ccu.h b/include/dt-bindings/reset/sunxi-a10-a20-ccu.h
> new file mode 100644
> index 0000000..9845cee
> --- /dev/null
> +++ b/include/dt-bindings/reset/sunxi-a10-a20-ccu.h
> @@ -0,0 +1,66 @@
> +/*
> + * Copyright (C) 2017 Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>
> + *
> + * This file is dual-licensed: you can use it either under the terms
> + * of the GPL or the X11 license, at your option. Note that this dual
> + * licensing only applies to this file, and not this project as a
> + * whole.
> + *
> + *  a) This file is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This file is distributed in the hope that it will be useful,
> + *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *     GNU General Public License for more details.
> + *
> + * Or, alternatively,
> + *
> + *  b) Permission is hereby granted, free of charge, to any person
> + *     obtaining a copy of this software and associated documentation
> + *     files (the "Software"), to deal in the Software without
> + *     restriction, including without limitation the rights to use,
> + *     copy, modify, merge, publish, distribute, sublicense, and/or
> + *     sell copies of the Software, and to permit persons to whom the
> + *     Software is furnished to do so, subject to the following
> + *     conditions:
> + *
> + *     The above copyright notice and this permission notice shall be
> + *     included in all copies or substantial portions of the Software.
> + *
> + *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> + *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> + *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> + *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> + *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> + *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + *     OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef _DT_BINDINGS_RST_SUNXI_A10_A10_H
> +#define _DT_BINDINGS_RST_SUNXI_A10_A10_H
> +
> +#define        RST_USB_PHY0            1
> +#define        RST_USB_PHY1            2
> +#define        RST_USB_PHY2            3
> +#define        RST_DE_BE0              4
> +#define        RST_DE_BE1              5
> +#define        RST_DE_FE0              6
> +#define        RST_DE_FE1              7
> +#define        RST_DE_MP               8
> +#define        RST_TCON0               9
> +#define        RST_TCON1               10
> +#define        RST_CSI0                11
> +#define        RST_CSI1                12
> +#define        RST_VE                  13
> +#define        RST_ACE                 14
> +#define        RST_LVDS                15
> +#define        RST_GPU                 16
> +#define        RST_HDMI_H              17
> +#define        RST_HDMI_SYS            18
> +#define        RST_HDMI_AUDIO_DMA      19
> +
> +#endif /* DT_BINDINGS_RST_SUNXI_A10_A10_H */
> --
> git-series 0.9.1
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
> For more options, visit https://groups.google.com/d/optout.

Regards,
Jonathan

^ permalink raw reply

* Re: [PATCH V3 2/2] ARM64: dts: hi6220-hikey: Add clock binding for the pmic mfd
From: Daniel Lezcano @ 2017-04-22 14:09 UTC (permalink / raw)
  To: Stephen Boyd, lee.jones
  Cc: devicetree, mturquette, linux-kernel, xuwei5, linux-clk,
	linux-arm-kernel
In-Reply-To: <20170422020233.GA7065@codeaurora.org>

On 22/04/2017 04:02, Stephen Boyd wrote:
> On 04/17, Daniel Lezcano wrote:
>> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
>> ---
>>  Documentation/devicetree/bindings/mfd/hisilicon,hi655x.txt | 6 ++++++
>>  arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts             | 1 +
>>  2 files changed, 7 insertions(+)
>>
> 
> I take it this goes through arm-soc? Not sure why I'm on To:
> line.

Probably it should go through Lee's tree.


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


_______________________________________________
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 v2 1/6] clk: sunxi-ng: Add sun4i/sun7i CCU driver
From: Jonathan Liu @ 2017-04-22 14:46 UTC (permalink / raw)
  To: plaes-q/aMd4JkU83YtjvyW6yDsg
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, devicetree,
	linux-clk-u79uwXL29TY76Z2rM5mHXA, linux-sunxi, Icenowy Zheng,
	Russell King, Chen-Yu Tsai, Maxime Ripard, Mark Rutland,
	Rob Herring, Stephen Boyd, Michael Turquette, Philipp Zabel
In-Reply-To: <ac8c4dab4f160ec605d52120517774bf1de87c2e.1490545262.git-series.plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org>

Hi Priit,

On 27 March 2017 at 04:20, Priit Laes <plaes-q/aMd4JkU83YtjvyW6yDsg@public.gmane.org> wrote:
> +static struct ccu_nkmp pll_ve_clk = {
> +       .enable         = BIT(31),
> +       .n              = _SUNXI_CCU_MULT_OFFSET(8, 5, 0),
> +       .k              = _SUNXI_CCU_MULT(4, 2),
> +       .m              = _SUNXI_CCU_DIV(0, 2),
> +       .p              = _SUNXI_CCU_DIV(16, 2),
> +       .common         = {
> +               .reg            = 0x018,
> +               .hw.init        = CLK_HW_INIT("pll-ve",
> +                                             "hosc",
> +                                             &ccu_nkmp_ops,
> +                                             0),
> +       },
> +};

pll-ve is a NKMP clock in A10 but a NK clock in A20.

> +static const char *const hdmi_parents[] = { "pll-video0", "pll-video0-2x",
> +                                           "pll-vide01", "pll-video1-2x" };

"pll-vide01" should be "pll-video1".

Regards,
Jonathan

^ permalink raw reply

* Re: [PATCH v3 14/37] mtd: nand: denali: support "nand-ecc-strength" DT property
From: Masahiro Yamada @ 2017-04-22 15:00 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mark Rutland, devicetree, Richard Weinberger, Marek Vasut,
	Artem Bityutskiy, Cyrille Pitchen, Linux Kernel Mailing List,
	Dinh Nguyen, Rob Herring, linux-mtd, Masami Hiramatsu,
	Chuanxiao Dong, Jassi Brar, Brian Norris, Enrico Jorns,
	David Woodhouse, Graham Moore
In-Reply-To: <20170414101928.5255736e@bbrezillon>

Hi Boris,


2017-04-14 17:19 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
> On Fri, 14 Apr 2017 16:57:23 +0900
> Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>
>> Hi Boris,
>>
>>
>> 2017-04-11 16:56 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> > Hi Masahiro,
>> >
>> > On Tue, 11 Apr 2017 15:19:21 +0900
>> > Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>> >
>> >> Hi Boris,
>> >>
>> >>
>> >>
>> >> 2017-04-10 1:33 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> >> > On Mon, 3 Apr 2017 12:16:34 +0900
>> >> > Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>> >> >
>> >> >> Hi Boris,
>> >> >>
>> >> >>
>> >> >>
>> >> >> 2017-03-31 18:46 GMT+09:00 Boris Brezillon <boris.brezillon@free-electrons.com>:
>> >> >>
>> >> >> > You can try something like that when no explicit ecc.strength and
>> >> >> > ecc.size has been set in the DT and when ECC_MAXIMIZE was not passed.
>> >> >> >
>> >> >> > static int
>> >> >> > denali_get_closest_ecc_strength(struct denali_nand_info *denali,
>> >> >> >                                 int strength)
>> >> >> > {
>> >> >> >         /*
>> >> >> >          * Whatever you need to select a strength that is greater than
>> >> >> >          * or equal to strength.
>> >> >> >          */
>> >> >> >
>> >> >> >         return X;
>> >> >> > }
>> >> >>
>> >> >>
>> >> >> Is here anything specific to Denali?
>> >> >
>> >> > Well, only the denali driver knows what the hardware supports, though
>> >> > having a generic function that takes a table of supported strengths
>> >> > would work.
>> >> >
>> >> >>
>> >> >>
>> >> >> > static int denali_try_to_match_ecc_req(struct denali_nand_info *denali)
>> >> >> > {
>> >> >> >         struct nand_chip *chip = &denali->nand;
>> >> >> >         struct mtd_info *mtd = nand_to_mtd(chip);
>> >> >> >         int max_ecc_bytes = mtd->oobsize - denali->bbtskipbytes;
>> >> >> >         int ecc_steps, ecc_strength, ecc_bytes;
>> >> >> >         int ecc_size = chip->ecc_step_ds;
>> >> >> >         int ecc_strength = chip->ecc_strength_ds;
>> >> >> >
>> >> >> >         /*
>> >> >> >          * No information provided by the NAND chip, let the core
>> >> >> >          * maximize the strength.
>> >> >> >          */
>> >> >> >         if (!ecc_size || !ecc_strength)
>> >> >> >                 return -ENOTSUPP;
>> >> >> >
>> >> >> >         if (ecc_size > 512)
>> >> >> >                 ecc_size = 1024;
>> >> >> >         else
>> >> >> >                 ecc_size = 512;
>> >> >> >
>> >> >> >         /* Adjust ECC step size based on hardware support. */
>> >> >> >         if (ecc_size == 1024 &&
>> >> >> >             !(denali->caps & DENALI_CAP_ECC_SIZE_1024))
>> >> >> >                 ecc_size = 512;
>> >> >> >         else if(ecc_size == 512 &&
>> >> >> >                 !(denali->caps & DENALI_CAP_ECC_SIZE_512))
>> >> >> >                 ecc_size = 1024;
>> >> >> >
>> >> >> >         if (ecc_size < chip->ecc_size_ds) {
>> >> >> >                 /*
>> >> >> >                  * When the selected size if smaller than the expected
>> >> >> >                  * one we try to use the same strength but on 512 blocks
>> >> >> >                  * so that we can still fix the same number of errors
>> >> >> >                  * even if they are concentrated in the first 512bytes
>> >> >> >                  * of a 1024bytes portion.
>> >> >> >                  */
>> >> >> >                 ecc_strength = chip->ecc_strength_ds;
>> >> >> >                 ecc_strength = denali_get_closest_ecc_strength(denali,
>> >> >> >                                                                ecc_strength);
>> >> >> >         } else {
>> >> >> >                 /* Always prefer 1024bytes ECC blocks when possible. */
>> >> >> >                 if (ecc_size != 1024 &&
>> >> >> >                     (denali->caps & DENALI_CAP_ECC_SIZE_1024) &&
>> >> >> >                     mtd->writesize > 1024)
>> >> >> >                         ecc_size = 1024;
>> >> >> >
>> >> >> >                 /*
>> >> >> >                  * Adjust the strength based on the selected ECC step
>> >> >> >                  * size.
>> >> >> >                  */
>> >> >> >                 ecc_strength = DIV_ROUND_UP(ecc_size,
>> >> >> >                                             chip->ecc_step_ds) *
>> >> >> >                                chip->ecc_strength_ds;
>> >> >> >         }
>> >> >> >
>> >> >> >         ecc_bytes = denali_calc_ecc_bytes(ecc_size,
>> >> >> >                                           ecc_strength);
>> >> >> >         ecc_bytes *= mtd->writesize / ecc_size;
>> >> >> >
>> >> >> >         /*
>> >> >> >          * If we don't have enough space, let the core maximize
>> >> >> >          * the strength.
>> >> >> >          */
>> >> >> >         if (ecc_bytes > max_ecc_bytes)
>> >> >> >                 return -ENOTSUPP;
>> >> >> >
>> >> >> >         chip->ecc.strength = ecc_strength;
>> >> >> >         chip->ecc.size = ecc_size;
>> >> >> >
>> >> >> >         return 0;
>> >> >> > }
>> >> >>
>> >> >>
>> >> >> As a whole, this does not seem to driver-specific.
>> >> >
>> >> > It's almost controller-agnostic, except for the denali_calc_ecc_bytes()
>> >> > function, but I guess we could ask drivers to implement a hook that is
>> >> > passed the ECC step size and strength and returns the associated
>> >> > number of ECC bytes.
>> >> >
>> >> >>
>> >> >>
>> >> >> [1] A driver provides some pairs of (ecc_strength, ecc_size)
>> >> >>     it can support.
>> >> >>
>> >> >> [2] The core framework knows the chip's requirement
>> >> >>     (ecc_strength_ds, ecc_size_ds).
>> >> >>
>> >> >>
>> >> >> Then, the core framework provides a function
>> >> >> to return a most recommended (ecc_strength, ecc_size).
>> >> >>
>> >> >>
>> >> >>
>> >> >> struct nand_ecc_spec {
>> >> >>        int ecc_strength;
>> >> >>        int ecc_size;
>> >> >> };
>> >> >>
>> >> >> /*
>> >> >>  * This function choose the most recommented (ecc_str, ecc_size)
>> >> >>  * "recommended" means: minimum ecc stregth that meets
>> >> >>  * the chip's requirment.
>> >> >>  *
>> >> >>  *
>> >> >>  * @chip   - nand_chip
>> >> >>  * @controller_ecc_spec - Array of (ecc_str, ecc_size) supported by the
>> >> >>                           controller. (terminated by NULL as sentinel)
>> >> >>  */
>> >> >> struct nand_ecc_spec * nand_try_to_match_ecc_req(struct nand_chip *chip,
>> >> >>                                                  struct nand_ecc_spec
>> >> >> *controller_ecc_spec)
>> >> >> {
>> >> >>       /*
>> >> >>        * Return the pointer to the most recommended
>> >> >>        * struct nand_ecc_spec.
>> >> >>        * If nothing suitable found, return NULL.
>> >> >>        */
>> >> >> }
>> >> >>
>> >> >
>> >> > I like the idea, except I would do this slightly differently to avoid
>> >> > declaring all combinations of stepsize and strengths
>> >> >
>> >> > struct nand_ecc_stepsize_info {
>> >> >         int stepsize;
>> >> >         int nstrengths;
>> >> >         int *strengths;
>> >> > };
>> >> >
>> >> > struct nand_ecc_engine_caps {
>> >> >         int nstepsizes;
>> >> >         struct nand_ecc_stepsize_info *stepsizes;
>> >> >         int (*calc_ecc_bytes)(int stepsize, int strength);
>> >> > };
>> >> >
>> >> > int nand_try_to_match_ecc_req(struct nand_chip *chip,
>> >> >                               const struct nand_ecc_engine_caps *caps,
>> >> >                               struct nand_ecc_spec *spec)
>> >> > {
>> >> >         /*
>> >> >          * Find the most appropriate setting based on the ECC engine
>> >> >          * caps and fill the spec object accordingly.
>> >> >          * Returns 0 in case of success and a negative error code
>> >> >          * otherwise.
>> >> >          */
>> >> > }
>> >> >
>> >> > Note that nand_try_to_match_ecc_req() has to be more generic than
>> >> > denali_try_to_match_ecc_req() WRT step sizes, which will probably
>> >> > complexify the logic.
>> >>
>> >>
>> >> After I fiddle with this generic approach for a while,
>> >> I started to feel like giving up.
>> >
>> > I don't get it. What was the problem with my initial suggestion (the
>> > denali specific one, not the generic approach)? You proposed to make it
>> > generic, which, I agree, is a bit more complicated.
>> >
>> >>
>> >> I wonder if we really want over-implementation
>> >> for covering _theoretically_ possible cases.
>> >
>> > Okay, one more theoretical case I'd like to expose: you have board
>> > design with different NAND parts which have different ECC requirements.
>> > If you were about to describe the exact ECC strength you want for each
>> > board you'll have to have different DTs.
>>
>> In this case, fixed ecc-strength in DT is not feasible.
>>
>> > Maximizing the ECC strength
>> > would still work, but what if the MTD user needs some OOB bytes (like
>> > is the case with JFFS2) and ECC maximization reserved all of the
>> > available bytes?
>>
>> JFFS2 needs some bytes in oob-free area for the clean marker.
>> You are right.
>> This implies NAND_ECC_MAXIMIZE is not very useful.
>> We do not know whether we have enough space left in oob, or not.
>>
>>
>>
>> > The other reason I prefer to have the drivers automatically guessing
>> > what's appropriate is because then you don't have to care when writing
>> > your DT.
>> >
>> >>
>> >> In practice, there are not so many ECC settings possible
>> >> on a single controller.
>> >>
>> >> As for Denali IP, it would be theoretically possible to instantiate
>> >> multiple ECC engines.  However, in practice, there is no sensible
>> >> reason to do so.  At least, I do not know any real chip to support that.
>> >>
>> >> So, I'd like to simplify the logic for Denali.
>> >>
>> >>   - Support either 512 or 1024 ECC size.
>> >>     If there is (ever) a controller that supports both,
>> >>     1024 should be chosen.
>> >>
>> >>   - ECC strength is not specified via DT, it is simply maximized.
>> >>
>> >> This simplifies the logic much and I believe this is enough.
>> >>
>> >> One more reason is, as we talked before,
>> >> we need to match ECC setting between Linux and firmware (boot-loader),
>> >
>> > If the bootloader implements the same logic it should match.
>> >
>> >> so anyway we end up with using a fixed setting specified by DT.
>> >>
>> >
>> > Really, I don't see what's the problem with the function I proposed,
>> > but I'm willing to make a concession.
>> > Make the nand-ecc-strength+nand-ecc-step-size or nand-ecc-maximize
>> > mandatory so that if someone ever needs to support the 'match NAND
>> > requirements' feature we won't have to add a vendor specific property
>> > like this one [1].
>> >
>> > Are you fine with that?
>>
>> No.  This requirement seems too strong.
>
> Hm, can you give more details? All I want is a solution where we can
> later support the feature I'm asking without adding a extra DT
> property, and, in order to do that we must make sure the case you want
> to support as a first step are explicitly requested in the DT.
>
> It's as simple as:
>
>         if ((!ecc->strength || !ecc->size) &&
>             !(ecc->options & NAND_ECC_MAXIMIZE))
>                 return -ENOTSUPP;

If a controller supports only one possible value for nand-ecc-step-size,
users have no choice anyway.

For UniPhier SoCs,
    nand-ecc-step-size = <1024>;
    nand-ecc-strength = <8> or <16> or <24>;

But, it is harmless even if we specify nand-ecc-step-size explicitly.
So, I do not argue here.



>> At least, it is a problem for non-DT platforms.
>
> Well, for non-DT platforms you have to keep ECC maximization anyway,
> otherwise you're not backward compatible.
>
>>
>>
>> If a driver provides ECC engine caps info,
>> perhaps ECC maximizing could be a generalized helper function as well.
>
> I don't get it. I thought the generic helper was too hard to implement.
> Now you want to add a new functionality.
>
> I'm not against this idea, but maybe it's easier to provide a denali
> specific implementation before tackling the generic one.


I think there is a common logic in matching request and maximizing.

I could not explain well in my words, so I wrote a patch:
http://patchwork.ozlabs.org/patch/752107/

Could you check it?



-- 
Best Regards
Masahiro Yamada

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply

* Re: [PATCH RFC 1/7] clk: samsung: Add enable/disable operation for PLL36XX clocks
From: Krzysztof Kozlowski @ 2017-04-22 15:22 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-samsung-soc, linux-clk, dri-devel, alsa-devel, devicetree,
	inki.dae, sw0312.kim, cw00.choi, javier, jy0922.shim, broonie,
	robh+dt, b.zolnierkie
In-Reply-To: <1492795191-31298-2-git-send-email-s.nawrocki@samsung.com>

On Fri, Apr 21, 2017 at 07:19:45PM +0200, Sylwester Nawrocki wrote:
> The existing enable/disable ops for PLL35XX are made more generic
> and used also for PLL36XX. This fixes issues in the kernel with
> PLL36XX PLLs when the PLL has not been already enabled by bootloader.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/clk/samsung/clk-pll.c | 85 +++++++++++++++++++++++++------------------
>  1 file changed, 49 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
> index 5229089..10c76eb 100644
> --- a/drivers/clk/samsung/clk-pll.c
> +++ b/drivers/clk/samsung/clk-pll.c
> @@ -23,6 +23,10 @@ struct samsung_clk_pll {
>  	struct clk_hw		hw;
>  	void __iomem		*lock_reg;
>  	void __iomem		*con_reg;
> +	/* PLL enable control bit offset in @con_reg register */
> +	unsigned short		enable_offs;
> +	/* PLL lock status bit offset in @con_reg register */
> +	unsigned short		lock_offs;
>  	enum samsung_pll_type	type;
>  	unsigned int		rate_count;
>  	const struct samsung_pll_rate_table *rate_table;
> @@ -61,6 +65,34 @@ static long samsung_pll_round_rate(struct clk_hw *hw,
>  	return rate_table[i - 1].rate;
>  }
>  
> +static int samsung_pll3xxx_enable(struct clk_hw *hw)
> +{
> +	struct samsung_clk_pll *pll = to_clk_pll(hw);
> +	u32 tmp;
> +
> +	tmp = readl_relaxed(pll->con_reg);
> +	tmp |= BIT(pll->enable_offs);
> +	writel_relaxed(tmp, pll->con_reg);
> +
> +	/* wait lock time */
> +	do {
> +		cpu_relax();
> +		tmp = readl_relaxed(pll->con_reg);
> +	} while (!(tmp & BIT(pll->lock_offs)));
> +
> +	return 0;
> +}
> +
> +static void samsung_pll3xxx_disable(struct clk_hw *hw)
> +{
> +	struct samsung_clk_pll *pll = to_clk_pll(hw);
> +	u32 tmp;
> +
> +	tmp = readl_relaxed(pll->con_reg);
> +	tmp |= BIT(pll->enable_offs);

I think you meant here:
	tmp &= ~BIT()

> +	writel_relaxed(tmp, pll->con_reg);
> +}
> +
>  /*
>   * PLL2126 Clock Type
>   */
> @@ -142,34 +174,6 @@ static unsigned long samsung_pll3000_recalc_rate(struct clk_hw *hw,
>  #define PLL35XX_LOCK_STAT_SHIFT	(29)
>  #define PLL35XX_ENABLE_SHIFT	(31)
>  
> -static int samsung_pll35xx_enable(struct clk_hw *hw)
> -{
> -	struct samsung_clk_pll *pll = to_clk_pll(hw);
> -	u32 tmp;
> -
> -	tmp = readl_relaxed(pll->con_reg);
> -	tmp |= BIT(PLL35XX_ENABLE_SHIFT);
> -	writel_relaxed(tmp, pll->con_reg);
> -
> -	/* wait_lock_time */
> -	do {
> -		cpu_relax();
> -		tmp = readl_relaxed(pll->con_reg);
> -	} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
> -
> -	return 0;
> -}
> -
> -static void samsung_pll35xx_disable(struct clk_hw *hw)
> -{
> -	struct samsung_clk_pll *pll = to_clk_pll(hw);
> -	u32 tmp;
> -
> -	tmp = readl_relaxed(pll->con_reg);
> -	tmp &= ~BIT(PLL35XX_ENABLE_SHIFT);
> -	writel_relaxed(tmp, pll->con_reg);
> -}
> -
>  static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
>  				unsigned long parent_rate)
>  {
> @@ -239,11 +243,11 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
>  	writel_relaxed(tmp, pll->con_reg);
>  
>  	/* wait_lock_time if enabled */
> -	if (tmp & BIT(PLL35XX_ENABLE_SHIFT)) {
> +	if (tmp & BIT(pll->enable_offs)) {
>  		do {
>  			cpu_relax();
>  			tmp = readl_relaxed(pll->con_reg);
> -		} while (!(tmp & BIT(PLL35XX_LOCK_STAT_SHIFT)));
> +		} while (!(tmp & BIT(pll->lock_offs)));
>  	}
>  	return 0;
>  }
> @@ -252,8 +256,8 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
>  	.recalc_rate = samsung_pll35xx_recalc_rate,
>  	.round_rate = samsung_pll_round_rate,
>  	.set_rate = samsung_pll35xx_set_rate,
> -	.enable = samsung_pll35xx_enable,
> -	.disable = samsung_pll35xx_disable,
> +	.enable = samsung_pll3xxx_enable,
> +	.disable = samsung_pll3xxx_disable,
>  };
>  
>  static const struct clk_ops samsung_pll35xx_clk_min_ops = {
> @@ -275,6 +279,7 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate,
>  #define PLL36XX_SDIV_SHIFT	(0)
>  #define PLL36XX_KDIV_SHIFT	(0)
>  #define PLL36XX_LOCK_STAT_SHIFT	(29)
> +#define PLL36XX_ENABLE_SHIFT	(31)
>  
>  static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
>  				unsigned long parent_rate)
> @@ -354,10 +359,12 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate,
>  	writel_relaxed(pll_con1, pll->con_reg + 4);
>  
>  	/* wait_lock_time */
> -	do {
> -		cpu_relax();
> -		tmp = readl_relaxed(pll->con_reg);
> -	} while (!(tmp & (1 << PLL36XX_LOCK_STAT_SHIFT)));
> +	if (pll_con0 & BIT(pll->enable_offs)) {

Why this additional if() is needed?

> +		do {
> +			cpu_relax();
> +			tmp = readl_relaxed(pll->con_reg);
> +		} while (!(tmp & BIT(PLL36XX_LOCK_STAT_SHIFT)));

To be consistent:
BIT(pll->lock_offs)?

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH RFC 2/7] clk: samsung: Add definitions of some audio related clocks
From: Krzysztof Kozlowski @ 2017-04-22 15:27 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-samsung-soc, linux-clk, dri-devel, alsa-devel, devicetree,
	inki.dae, sw0312.kim, cw00.choi, javier, jy0922.shim, broonie,
	robh+dt, b.zolnierkie
In-Reply-To: <1492795191-31298-3-git-send-email-s.nawrocki@samsung.com>

On Fri, Apr 21, 2017 at 07:19:46PM +0200, Sylwester Nawrocki wrote:
> This patch adds missing definitions of mux clocks required for using
> EPLL as the audio subsystem root clock on exynos5420/exynos5422 SoCs.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos5420.c   | 13 ++++++++-----
>  include/dt-bindings/clock/exynos5420.h |  3 +++
>  2 files changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c
> index cdc092a..87c711a 100644
> --- a/drivers/clk/samsung/clk-exynos5420.c
> +++ b/drivers/clk/samsung/clk-exynos5420.c
> @@ -477,8 +477,7 @@ static void __init exynos5420_clk_sleep_init(void) {}
>  					"mout_sclk_mpll", "ff_dout_spll2",
>  					"mout_sclk_spll", "mout_sclk_epll"};
>  PNAME(mout_mau_epll_clk_5800_p)	= { "mout_sclk_epll", "mout_sclk_dpll",
> -					"mout_sclk_mpll",
> -					"ff_dout_spll2" };
> +					"mout_sclk_mpll", "ff_dout_spll2" };

Please split up cleaning from adding new features/clocks. While in
cleaning mode, you might also consider fixing some checkpatch errors and
warnings. There are few (without --strict).

>  PNAME(mout_group8_5800_p)	= { "dout_aclk432_scaler", "dout_sclk_sw" };
>  PNAME(mout_group9_5800_p)	= { "dout_osc_div", "mout_sw_aclk432_scaler" };
>  PNAME(mout_group10_5800_p)	= { "dout_aclk432_cam", "dout_sclk_sw" };
> @@ -487,6 +486,7 @@ static void __init exynos5420_clk_sleep_init(void) {}
>  PNAME(mout_group13_5800_p)	= { "dout_osc_div", "mout_sw_aclkfl1_550_cam" };
>  PNAME(mout_group14_5800_p)	= { "dout_aclk550_cam", "dout_sclk_sw" };
>  PNAME(mout_group15_5800_p)	= { "dout_osc_div", "mout_sw_aclk550_cam" };
> +PNAME(mout_group16_5800_p)	= { "dout_osc_div", "mout_mau_epll_clk" };
>  
>  /* fixed rate clocks generated outside the soc */
>  static struct samsung_fixed_rate_clock
> @@ -536,8 +536,8 @@ static void __init exynos5420_clk_sleep_init(void) {}
>  
>  	MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore",
>  			mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2),
> -	MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7,
> -			20, 2),
> +	MUX(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p,
> +							SRC_TOP7, 20, 2),

How about not changing the indention level of new line? On the other
hand, if you want to change it so maybe align it with opening
parenthesis?

(same in other places below)

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH RFC 3/7] clk: samsung: exynos542x: Add EPLL rate table
From: Krzysztof Kozlowski @ 2017-04-22 15:28 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-samsung-soc, linux-clk, dri-devel, alsa-devel, devicetree,
	inki.dae, sw0312.kim, cw00.choi, javier, jy0922.shim, broonie,
	robh+dt, b.zolnierkie
In-Reply-To: <1492795191-31298-4-git-send-email-s.nawrocki@samsung.com>

On Fri, Apr 21, 2017 at 07:19:47PM +0200, Sylwester Nawrocki wrote:
> A specific clock rate table is added for EPLL so it is possible
> to set frequency of the EPLL output clock as multiple of various
> audio sampling rates.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos5420.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
> 

Looks correct although I didn't check the numbers.
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>

Best regards,
Krzysztof

^ permalink raw reply

* Re: [PATCH RFC 4/7] drm: exynos: Add driver for HDMI audio interface
From: Krzysztof Kozlowski @ 2017-04-22 15:31 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: linux-samsung-soc, linux-clk, dri-devel, alsa-devel, devicetree,
	inki.dae, sw0312.kim, cw00.choi, javier, jy0922.shim, broonie,
	robh+dt, b.zolnierkie
In-Reply-To: <1492795191-31298-5-git-send-email-s.nawrocki@samsung.com>

On Fri, Apr 21, 2017 at 07:19:48PM +0200, Sylwester Nawrocki wrote:
> The hdmi-codec interface added in this patch is required to properly
> support HDMI audio. Currently the audio part of the SoC internal
> HDMI transmitter is configured with fixed values, which makes HDMI
> audio working by chance, only on boards equipped with external audio
> codec connected in parallel with the HDMI audio transmitter I2S input
> interface.
> 
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
>  drivers/gpu/drm/exynos/Kconfig       |   1 +
>  drivers/gpu/drm/exynos/exynos_hdmi.c | 220 +++++++++++++++++++++++++++++------
>  2 files changed, 188 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
> index 1d18534..a6edbb6 100644
> --- a/drivers/gpu/drm/exynos/Kconfig
> +++ b/drivers/gpu/drm/exynos/Kconfig
> @@ -3,6 +3,7 @@ config DRM_EXYNOS
>  	depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
>  	select DRM_KMS_HELPER
>  	select VIDEOMODE_HELPERS
> +	select SND_SOC_HDMI_CODEC if SND_SOC
>  	help
>  	  Choose this option if you have a Samsung SoC EXYNOS chipset.
>  	  If M is selected the module will be called exynosdrm.
> diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
> index 88ccc04..be18023 100644
> --- a/drivers/gpu/drm/exynos/exynos_hdmi.c
> +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
> @@ -40,7 +40,7 @@
>  #include <linux/component.h>
>  #include <linux/mfd/syscon.h>
>  #include <linux/regmap.h>
> -
> +#include <sound/hdmi-codec.h>
>  #include <drm/exynos_drm.h>
>  
>  #include "exynos_drm_drv.h"
> @@ -110,13 +110,23 @@ struct hdmi_driver_data {
>  	struct string_array_spec clk_muxes;
>  };
>  
> +struct hdmi_audio {
> +	struct platform_device *pdev;
> +	struct hdmi_audio_infoframe infoframe;
> +	unsigned int sample_rate;
> +	unsigned int sample_width;
> +	u8 enable;
> +};
> +
>  struct hdmi_context {
>  	struct drm_encoder		encoder;
>  	struct device			*dev;
>  	struct drm_device		*drm_dev;
>  	struct drm_connector		connector;
> +	struct hdmi_audio		audio;
>  	bool				powered;
>  	bool				dvi_mode;
> +	struct mutex			mutex;

I find short documentation what is protected by mutex usually quite
useful. Can you add such?

>  	struct delayed_work		hotplug_work;
>  	struct drm_display_mode		current_mode;
>  	const struct hdmi_driver_data	*drv_data;
> @@ -766,6 +776,22 @@ static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy)
>  	return ret;
>  }
>  
> +static int hdmi_audio_infoframe_apply(struct hdmi_context *hdata)
> +{
> +	struct hdmi_audio_infoframe *infoframe = &hdata->audio.infoframe;
> +	u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)];
> +	int len;
> +
> +	len = hdmi_audio_infoframe_pack(infoframe, buf, sizeof(buf));
> +	if (len < 0)
> +		return len;
> +
> +	hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
> +	hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, len);
> +
> +	return 0;
> +}
> +
>  static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>  {
>  	union hdmi_infoframe frm;
> @@ -803,15 +829,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata)
>  		hdmi_reg_write_buf(hdata, HDMI_VSI_DATA(0), buf + 3, ret - 3);
>  	}
>  
> -	ret = hdmi_audio_infoframe_init(&frm.audio);
> -	if (!ret) {
> -		frm.audio.channels = 2;
> -		ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf));
> -	}
> -	if (ret > 0) {
> -		hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
> -		hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret);
> -	}
> +	hdmi_audio_infoframe_apply(hdata);
>  }
>  
>  static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
> @@ -993,23 +1011,18 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq)
>  	hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
>  }
>  
> -static void hdmi_audio_init(struct hdmi_context *hdata)
> +static void hdmi_audio_config(struct hdmi_context *hdata)
>  {
> -	u32 sample_rate, bits_per_sample;
> -	u32 data_num, bit_ch, sample_frq;
> -	u32 val;
> +	u32 data_num, sample_freq, val;
> +	u32 bit_ch = 1;
>  
> -	sample_rate = 44100;
> -	bits_per_sample = 16;
>  
> -	switch (bits_per_sample) {
> +	switch (hdata->audio.sample_width) {
>  	case 20:
>  		data_num = 2;
> -		bit_ch = 1;
>  		break;
>  	case 24:
>  		data_num = 3;
> -		bit_ch = 1;
>  		break;
>  	default:
>  		data_num = 1;
> @@ -1017,7 +1030,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
>  		break;
>  	}
>  
> -	hdmi_reg_acr(hdata, sample_rate);
> +	hdmi_reg_acr(hdata, hdata->audio.sample_rate);
>  
>  	hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
>  				| HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
> @@ -1028,10 +1041,21 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
>  
>  	hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
>  
> -	sample_frq = (sample_rate == 44100) ? 0 :
> -			(sample_rate == 48000) ? 2 :
> -			(sample_rate == 32000) ? 3 :
> -			(sample_rate == 96000) ? 0xa : 0x0;
> +	switch(hdata->audio.sample_rate) {
> +	case 32000:
> +		sample_freq = 0x3;
> +		break;
> +	case 48000:
> +		sample_freq = 0x2;
> +		break;
> +	case 96000:
> +		sample_freq = 0xa;
> +		break;
> +	case 44100:
> +	default:
> +		sample_freq = 0;
> +		break;
> +	}
>  
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
> @@ -1065,7 +1089,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
> -			| HDMI_I2S_SET_SMP_FREQ(sample_frq));
> +			| HDMI_I2S_SET_SMP_FREQ(sample_freq));
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
>  			HDMI_I2S_ORG_SMP_FREQ_44_1
>  			| HDMI_I2S_WORD_LEN_MAX24_24BITS
> @@ -1074,13 +1098,15 @@ static void hdmi_audio_init(struct hdmi_context *hdata)
>  	hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
>  }
>  
> -static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
> +static void hdmi_audio_control(struct hdmi_context *hdata)
>  {
> +	bool enable = hdata->audio.enable;
> +
>  	if (hdata->dvi_mode)
>  		return;
>  
> -	hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
> -	hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
> +	hdmi_reg_writeb(hdata, HDMI_AUI_CON, enable ? 2 : 0);
> +	hdmi_reg_writemask(hdata, HDMI_CON_0, enable ?
>  			HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
>  }
>  
> @@ -1400,9 +1426,9 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
>  {
>  	hdmi_start(hdata, false);
>  	hdmi_conf_init(hdata);
> -	hdmi_audio_init(hdata);
> +	hdmi_audio_config(hdata);
>  	hdmi_mode_apply(hdata);
> -	hdmi_audio_control(hdata, true);
> +	hdmi_audio_control(hdata);
>  }
>  
>  static void hdmi_mode_set(struct drm_encoder *encoder,
> @@ -1476,8 +1502,12 @@ static void hdmi_enable(struct drm_encoder *encoder)
>  {
>  	struct hdmi_context *hdata = encoder_to_hdmi(encoder);
>  
> +	mutex_lock(&hdata->mutex);
> +
>  	hdmiphy_enable(hdata);
>  	hdmi_conf_apply(hdata);
> +
> +	mutex_unlock(&hdata->mutex);
>  }
>  
>  static void hdmi_disable(struct drm_encoder *encoder)
> @@ -1486,6 +1516,8 @@ static void hdmi_disable(struct drm_encoder *encoder)
>  	struct drm_crtc *crtc = encoder->crtc;
>  	const struct drm_crtc_helper_funcs *funcs = NULL;
>  
> +	mutex_lock(&hdata->mutex);
> +
>  	if (!hdata->powered)

Need to unlock mutex (here and maybe in other exit paths?).


Best regards,
Krzysztof

^ permalink raw reply

* [RFC 1/3] dt-binding: soc: qcom: Add binding for RFSA
From: Bjorn Andersson @ 2017-04-22 17:35 UTC (permalink / raw)
  To: Andy Gross, David Brown, Frank Rowand, Rob Herring, Mark Rutland
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

This adds the binding for describing shared memory buffers for
implementing the remote filesystem protocol.

Signed-off-by: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---

My initial attempt was to mimic the ramoops of just adding the compatible to
the reserved-memory node, but I have not been able to figure out a sane way of
getting hold of the base address in the case that the memory region is
described my a "size" only (done on some platforms).

The problem is that we create the reserved_mem objects (and remove the
memblocks) while we're still operating on the flattened representation, so
without a phandle it doesn't seem like we have anything to perform the
comparison with later on.

 .../devicetree/bindings/soc/qcom/qcom,rfsa.txt     | 43 ++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,rfsa.txt

diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rfsa.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,rfsa.txt
new file mode 100644
index 000000000000..b4de0de74e46
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rfsa.txt
@@ -0,0 +1,43 @@
+Qualcomm Remote File System Access binding
+
+This binding describes the Qualcomm RFSA, which serves the purpose of managing
+the shared memory region used for remote processors to access block device data
+using the Remote Filesystem protocol.
+
+- compatible:
+	Usage: required
+	Value type: <stringlist>
+	Definition: must be:
+		    "qcom,rfsa"
+
+- memory-region:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: handle to memory reservation the associated rfsa region.
+
+- qcom,client-id:
+	Usage: required
+	Value type: <u32>
+	Definition: identifier of the client to use this region for buffers.
+
+= EXAMPLE
+The following example shows the RFSA setup for APQ8016, with the RFSA region
+for the Hexagon DSP (id #1) located at 0x86700000.
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		rmtfs: rmtfs@86700000 {
+			reg = <0x0 0x86700000 0x0 0xe0000>;
+			no-map;
+		};
+	};
+
+	hexagon-rfsa {
+		compatible = "qcom,rfsa";
+		memory-region = <&rmtfs>;
+
+		qcom,client-id = <1>;
+	};
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [RFC 2/3] of: reserved_mem: Accessor for acquiring reserved_mem
From: Bjorn Andersson @ 2017-04-22 17:35 UTC (permalink / raw)
  To: Andy Gross, David Brown, Frank Rowand, Rob Herring, Mark Rutland
  Cc: linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170422173519.5782-1-bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

In some cases drivers referencing a reserved-memory region might want to
remap the entire region, but when defining the reserved-memory by "size"
the client driver has no means to know the associated base address of
the reserved memory region.

This patch adds an accessor for such drivers to acquire a handle to
their associated reserved-memory for this purpose.

Signed-off-by: Bjorn Andersson <bjorn.andersson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---

I would have preferred if we could provide a mechanism for drivers to find the
reserved_mem of their own device_node, but without a phandle I have not been
able to figure out a sane way to make the match.

Suggestions are very welcome.

 drivers/of/of_reserved_mem.c    | 26 ++++++++++++++++++++++++++
 include/linux/of_reserved_mem.h |  8 ++++++++
 2 files changed, 34 insertions(+)

diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index d507c3569a88..aa69c9590a5c 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -397,3 +397,29 @@ void of_reserved_mem_device_release(struct device *dev)
 	rmem->ops->device_release(rmem, dev);
 }
 EXPORT_SYMBOL_GPL(of_reserved_mem_device_release);
+
+/**
+ * of_get_reserved_mem_by_idx() - acquire reserved_mem from memory-region
+ * @np:		node pointer containing the "memory-region"
+ * @idx:	index within memory-region
+ *
+ * This function allows drivers to acquire a reference to the reserved_mem
+ * struct which is referenced by their memory-region.
+ *
+ * Returns a reserved_mem reference, or NULL on error.
+ */
+struct reserved_mem *of_get_reserved_mem_by_idx(struct device_node *np, int idx)
+{
+	struct device_node *target;
+	struct reserved_mem *rmem;
+
+	target = of_parse_phandle(np, "memory-region", idx);
+	if (!target)
+		return NULL;
+
+	rmem = __find_rmem(target);
+	of_node_put(target);
+
+	return rmem;
+}
+EXPORT_SYMBOL_GPL(of_get_reserved_mem_by_idx);
diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h
index f8e1992d6423..a9abbe7dd3de 100644
--- a/include/linux/of_reserved_mem.h
+++ b/include/linux/of_reserved_mem.h
@@ -34,6 +34,8 @@ int of_reserved_mem_device_init_by_idx(struct device *dev,
 				       struct device_node *np, int idx);
 void of_reserved_mem_device_release(struct device *dev);
 
+struct reserved_mem *of_get_reserved_mem_by_idx(struct device_node *np, int idx);
+
 int early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
 					     phys_addr_t align,
 					     phys_addr_t start,
@@ -52,6 +54,12 @@ static inline int of_reserved_mem_device_init_by_idx(struct device *dev,
 }
 static inline void of_reserved_mem_device_release(struct device *pdev) { }
 
+static inline struct reserved_mem *of_get_reserved_mem_by_idx(struct device_node *np,
+							      int idx);
+{
+	return NULL;
+}
+
 static inline void fdt_init_reserved_mem(void) { }
 static inline void fdt_reserved_mem_save_node(unsigned long node,
 		const char *uname, phys_addr_t base, phys_addr_t size) { }
-- 
2.12.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [RFC 3/3] soc: qcom: rfsa driver
From: Bjorn Andersson @ 2017-04-22 17:35 UTC (permalink / raw)
  To: Andy Gross, David Brown, Frank Rowand, Rob Herring, Mark Rutland
  Cc: linux-arm-msm, linux-soc, devicetree, linux-kernel
In-Reply-To: <20170422173519.5782-1-bjorn.andersson@linaro.org>

The rfsa driver is used for allocating and exposing regions of shared
memory with remote processors for the purpose of exchanging sector-data
between the remote filesystem service and its clients.

It provides accessors for the properties needed by the user space remote
filesystem implementation through sysfs and a character device that can be used
to read and write the requested chunks of data.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/soc/qcom/Kconfig  |   8 ++
 drivers/soc/qcom/Makefile |   1 +
 drivers/soc/qcom/rfsa.c   | 261 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 270 insertions(+)
 create mode 100644 drivers/soc/qcom/rfsa.c

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 9fca977ef18d..788a63cd430e 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -24,6 +24,14 @@ config QCOM_PM
 	  modes. It interface with various system drivers to put the cores in
 	  low power modes.
 
+config QCOM_RFSA
+	tristate "Qualcomm Remote Filesystem Access driver"
+	help
+	  The Qualcomm remote filesystem access driver is used for allocating
+	  and exposing regions of shared memory with remote processors for the
+	  purpose of exchanging sector-data between the remote filesystem
+	  service and its clients.
+
 config QCOM_SMEM
 	tristate "Qualcomm Shared Memory Manager (SMEM)"
 	depends on ARCH_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 414f0de274fa..d1bbc791ddc0 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)	+= mdt_loader.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
+obj-$(CONFIG_QCOM_RFSA)	+=	rfsa.o
 obj-$(CONFIG_QCOM_SMD_RPM)	+= smd-rpm.o
 obj-$(CONFIG_QCOM_SMEM) +=	smem.o
 obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
diff --git a/drivers/soc/qcom/rfsa.c b/drivers/soc/qcom/rfsa.c
new file mode 100644
index 000000000000..1b79976dad9d
--- /dev/null
+++ b/drivers/soc/qcom/rfsa.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2017 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/cdev.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/of_fdt.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#define QCOM_RFSA_DEV_MAX	(MINORMASK + 1)
+
+static dev_t qcom_rfsa_major;
+
+struct qcom_rfsa {
+	struct device dev;
+	struct cdev cdev;
+
+	void *base;
+	phys_addr_t addr;
+	phys_addr_t size;
+
+	unsigned int client_id;
+};
+
+static ssize_t qcom_rfsa_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf);
+
+static DEVICE_ATTR(phys_addr, 0400, qcom_rfsa_show, NULL);
+static DEVICE_ATTR(size, 0400, qcom_rfsa_show, NULL);
+static DEVICE_ATTR(client_id, 0400, qcom_rfsa_show, NULL);
+
+static ssize_t qcom_rfsa_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct qcom_rfsa *rfsa = container_of(dev, struct qcom_rfsa, dev);
+
+	if (attr == &dev_attr_phys_addr)
+		return sprintf(buf, "%pa\n", &rfsa->addr);
+	if (attr == &dev_attr_size)
+		return sprintf(buf, "%pa\n", &rfsa->size);
+	if (attr == &dev_attr_client_id)
+		return sprintf(buf, "%d\n", rfsa->client_id);
+
+	return -EINVAL;
+}
+
+static struct attribute *qcom_rfsa_attrs[] = {
+	&dev_attr_phys_addr.attr,
+	&dev_attr_size.attr,
+	&dev_attr_client_id.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(qcom_rfsa);
+
+static int qcom_rfsa_open(struct inode *inode, struct file *filp)
+{
+	struct qcom_rfsa *rfsa = container_of(inode->i_cdev, struct qcom_rfsa, cdev);
+
+	get_device(&rfsa->dev);
+	filp->private_data = rfsa;
+
+	return 0;
+}
+static ssize_t qcom_rfsa_read(struct file *filp,
+			      char __user *buf, size_t count, loff_t *f_pos)
+{
+	struct qcom_rfsa *rfsa = filp->private_data;
+
+	if (*f_pos >= rfsa->size)
+		return 0;
+
+	if (*f_pos + count >= rfsa->size)
+		count = rfsa->size - *f_pos;
+
+	if (copy_to_user(buf, rfsa->base + *f_pos, count))
+		return -EFAULT;
+
+	*f_pos += count;
+	return count;
+}
+
+static ssize_t qcom_rfsa_write(struct file *filp,
+			       const char __user *buf, size_t count,
+			       loff_t *f_pos)
+{
+	struct qcom_rfsa *rfsa = filp->private_data;
+
+	if (*f_pos >= rfsa->size)
+		return 0;
+
+	if (*f_pos + count >= rfsa->size)
+		count = rfsa->size - *f_pos;
+
+	if (copy_from_user(rfsa->base + *f_pos, buf, count))
+		return -EFAULT;
+
+	*f_pos += count;
+	return count;
+}
+
+static int qcom_rfsa_release(struct inode *inode, struct file *filp)
+{
+	struct qcom_rfsa *rfsa = filp->private_data;
+
+	put_device(&rfsa->dev);
+
+	return 0;
+}
+
+static const struct file_operations qcom_rfsa_fops = {
+	.owner = THIS_MODULE,
+	.open = qcom_rfsa_open,
+	.read = qcom_rfsa_read,
+	.write = qcom_rfsa_write,
+	.release = qcom_rfsa_release,
+	.llseek = default_llseek,
+};
+
+static void qcom_rfsa_release_device(struct device *dev)
+{
+	struct qcom_rfsa *rfsa = container_of(dev, struct qcom_rfsa, dev);
+
+	kfree(rfsa);
+}
+
+static int qcom_rfsa_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct reserved_mem *rmem;
+	struct qcom_rfsa *rfsa;
+	u32 client_id;
+	int ret;
+
+	rmem = of_get_reserved_mem_by_idx(node, 0);
+	if (!rmem) {
+		dev_err(&pdev->dev, "failed to acquire memory region\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "qcom,client-id", &client_id);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to parse \"qcom,client-id\"\n");
+		return ret;
+
+	}
+
+	rfsa = kzalloc(sizeof(*rfsa), GFP_KERNEL);
+	if (!rfsa)
+		return -ENOMEM;
+
+	rfsa->addr = rmem->base;
+	rfsa->client_id = client_id;
+	rfsa->size = rmem->size;
+
+	device_initialize(&rfsa->dev);
+	rfsa->dev.parent = &pdev->dev;
+	rfsa->dev.groups = qcom_rfsa_groups;
+
+	cdev_init(&rfsa->cdev, &qcom_rfsa_fops);
+	rfsa->cdev.owner = THIS_MODULE;
+
+	dev_set_name(&rfsa->dev, "qcom_rfsa%d", client_id);
+	rfsa->dev.id = client_id;
+	rfsa->dev.devt = MKDEV(MAJOR(qcom_rfsa_major), client_id);
+
+	ret = cdev_device_add(&rfsa->cdev, &rfsa->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add cdev: %d\n", ret);
+		put_device(&rfsa->dev);
+		return ret;
+	}
+
+	rfsa->dev.release = qcom_rfsa_release_device;
+
+	rfsa->base = devm_memremap(&rfsa->dev, rfsa->addr, rfsa->size, MEMREMAP_WC);
+	if (IS_ERR(rfsa->base)) {
+		dev_err(&pdev->dev, "failed to remap rfsa region\n");
+
+		device_del(&rfsa->dev);
+		put_device(&rfsa->dev);
+
+		return PTR_ERR(rfsa->base);
+	}
+
+	dev_set_drvdata(&pdev->dev, rfsa);
+
+	return 0;
+}
+
+static int qcom_rfsa_remove(struct platform_device *pdev)
+{
+	struct qcom_rfsa *rfsa = dev_get_drvdata(&pdev->dev);
+
+	cdev_del(&rfsa->cdev);
+	device_del(&rfsa->dev);
+	put_device(&rfsa->dev);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_rfsa_of_match[] = {
+	{ .compatible = "qcom,rfsa" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, qcom_rfsa_of_match);
+
+static struct platform_driver qcom_rfsa_driver = {
+	.probe = qcom_rfsa_probe,
+	.remove = qcom_rfsa_remove,
+	.driver  = {
+		.name  = "qcom_rfsa",
+		.of_match_table = qcom_rfsa_of_match,
+	},
+};
+
+static int qcom_rfsa_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&qcom_rfsa_major, 0, QCOM_RFSA_DEV_MAX,
+				  "qcom_rfsa");
+	if (ret < 0) {
+		pr_err("qcom_rfsa: failed to allocate char dev region\n");
+		return ret;
+	}
+
+	ret = platform_driver_register(&qcom_rfsa_driver);
+	if (ret < 0) {
+		pr_err("qcom_rfsa: failed to register rfsa driver\n");
+		unregister_chrdev_region(qcom_rfsa_major, QCOM_RFSA_DEV_MAX);
+	}
+
+	return ret;
+}
+module_init(qcom_rfsa_init);
+
+static void qcom_rfsa_exit(void)
+{
+	platform_driver_unregister(&qcom_rfsa_driver);
+	unregister_chrdev_region(qcom_rfsa_major, QCOM_RFSA_DEV_MAX);
+}
+module_exit(qcom_rfsa_exit);
-- 
2.12.0

^ permalink raw reply related

* Re: [PATCH] rtc: ds1374: Add trickle charger device tree binding
From: Moritz Fischer @ 2017-04-22 17:54 UTC (permalink / raw)
  To: Rob Herring
  Cc: Moritz Fischer, rtc-linux, Devicetree List, Alessandro Zummo,
	Alexandre Belloni, Mark Rutland
In-Reply-To: <20170420172538.GA13892-R0KNJUYl863z/wjs7L+eiWPmTBeX6bocVpNB7YpNyf8@public.gmane.org>

On Thu, Apr 20, 2017 at 10:25 AM, Moritz Fischer <mdf-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Thu, Apr 20, 2017 at 10:56:34AM -0500, Rob Herring wrote:
>> On Mon, Apr 17, 2017 at 03:40:10PM -0700, Moritz Fischer wrote:
>> > Introduce a device tree binding for specifying the trickle charger
>> > configuration for ds1374. This is based on the code for ds13390.
>> >
>> > Signed-off-by: Moritz Fischer <mdf-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>> > ---
>> >  .../devicetree/bindings/rtc/dallas,ds1374.txt      | 18 ++++++++
>> >  drivers/rtc/rtc-ds1374.c                           | 54 ++++++++++++++++++++++
>> >  2 files changed, 72 insertions(+)
>> >  create mode 100644 Documentation/devicetree/bindings/rtc/dallas,ds1374.txt
>> >
>> > diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1374.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1374.txt
>> > new file mode 100644
>> > index 0000000..4cf5bd7
>> > --- /dev/null
>> > +++ b/Documentation/devicetree/bindings/rtc/dallas,ds1374.txt
>> > @@ -0,0 +1,18 @@
>> > +* Dallas DS1374            I2C Real-Time Clock / WDT
>>
>> Please remove from trivial-devices.txt, too. (which is moving in 4.12
>> BTW)
>
> Ok, I'll redo this on top of b7e252fcddfa573bb1ee275b53bba6cef85671d4
> (Documentation: devicetree: move trivial-devices out of I2C realm) then.

Follow up question, right now one selects between WDT and ALARM mode with
a CONFIG_RTC_DRV_DS1374_WDT=y statically at compile time.

I'd like to add a 'dallas,mode = <DS1374_WDT>;' or
dallas,enable-watchdog property
to the binding, same goes for the ability to remap the WDT reset output to the
interrupt pin (which is currently not supported, but my hardware needs this).

Would be the right way to add the remapping something like
'dallas,remap-reset-to-int' ?

Ideas? This change would obviously break people's setups where they
select one or
the other behavior via the build time option. Is that acceptable seen
that relying on
build time CONFIG_FOO seems like a bad assumption to begin with?

A bit of background: I currently started cleaning up a bunch of issues
in this driver,
like refactoring it to use the watchdog framework instead of open
coding everything,
make setting the timeout actually work (right now it the timeout to
tick conversion is
hosed).

Thanks,

Moritz
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* 26843 devicetree
From: sushildhimanphotography-/E1597aS9LQAvxtiuMwx3w @ 2017-04-22 18:35 UTC (permalink / raw)
  To: devicetree-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: 69.zip --]
[-- Type: application/zip, Size: 1562 bytes --]

^ permalink raw reply

* Re: [PATCH V5 4/7] ARM: pxa: Use - instead of @ for DT OPP entries
From: Robert Jarzmik @ 2017-04-22 19:29 UTC (permalink / raw)
  To: Viresh Kumar
  Cc: arm, Daniel Mack, Haojian Zhuang, Rob Herring, Mark Rutland,
	linaro-kernel, linux-arm-kernel, linux-pm, Rafael Wysocki,
	Krzysztof Kozlowski, Masahiro Yamada, Rob Herring, devicetree,
	linux-kernel
In-Reply-To: <874lxhkauf.fsf@belgarion.home>

Robert Jarzmik <robert.jarzmik@free.fr> writes:

> Viresh Kumar <viresh.kumar@linaro.org> writes:
>
>> On 20-04-17, 22:14, Robert Jarzmik wrote:
>>> Viresh Kumar <viresh.kumar@linaro.org> writes:
>>> 
>>> > Compiling the DT file with W=1, DTC warns like follows:
>>> >
>>> > Warning (unit_address_vs_reg): Node /opp_table0/opp@1000000000 has a
>>> > unit name, but no reg property
>>> >
>>> > Fix this by replacing '@' with '-' as the OPP nodes will never have a
>>> > "reg" property.
>>> >
>>> > Reported-by: Krzysztof Kozlowski <krzk@kernel.org>
>>> > Reported-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>>> > Suggested-by: Mark Rutland <mark.rutland@arm.com>
>>> > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>>> > Acked-by: Rob Herring <robh@kernel.org>
>>> Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
>>
>> Thanks. But I need you to pick it up for your pull request for arm-soc.
Applied to pxa/dt tree, thanks.

Cheers.

-- 
Robert

^ permalink raw reply

* [PATCH 0/2] Add PCIe phy driver for some Mediatek SoCs
From: Ryder Lee @ 2017-04-23  8:17 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Rob Herring
  Cc: devicetree, Ryder Lee, linux-kernel, linux-mediatek,
	Matthias Brugger, linux-arm-kernel

Hi,

This patch series add PCIe phy driver and related dt-binding file for
Mediatek mt7623 SoCs families.

Thanks.

Ryder Lee (2):
  phy: add PCIe phy driver for mt7623 SoCs families
  dt-bindings: phy: Add documentation for Mediatek PCIe PHY

 .../devicetree/bindings/phy/phy-mt7623-pcie.txt    |  67 +++++
 drivers/phy/Kconfig                                |   9 +
 drivers/phy/Makefile                               |   1 +
 drivers/phy/phy-mt7623-pcie.c                      | 290 +++++++++++++++++++++
 4 files changed, 367 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-mt7623-pcie.txt
 create mode 100644 drivers/phy/phy-mt7623-pcie.c

-- 
1.9.1

^ permalink raw reply

* [PATCH 1/2] phy: add PCIe phy driver for mt7623 SoCs families
From: Ryder Lee @ 2017-04-23  8:17 UTC (permalink / raw)
  To: Kishon Vijay Abraham I, Rob Herring
  Cc: devicetree, Ryder Lee, linux-kernel, linux-mediatek,
	Matthias Brugger, linux-arm-kernel
In-Reply-To: <1492935453-17373-1-git-send-email-ryder.lee@mediatek.com>

support PCIe phy of mt7623 SoCs families

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
 drivers/phy/Kconfig           |   9 ++
 drivers/phy/Makefile          |   1 +
 drivers/phy/phy-mt7623-pcie.c | 290 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+)
 create mode 100644 drivers/phy/phy-mt7623-pcie.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index dc5277a..00ab313 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -518,4 +518,13 @@ config PHY_NSP_USB3
 	help
 	  Enable this to support the Broadcom Northstar plus USB3 PHY.
 	  If unsure, say N.
+
+config PHY_MT7623_PCIE
+	tristate "Mediatek PCIe PHY driver for MT7623 SoC families"
+	depends on ARCH_MEDIATEK && OF
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Say 'Y' here to add support for Mediatek PCIe PHY driver which
+	  can be found on the MT7623 SoC families.
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e7b0feb..95032d6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -63,3 +63,4 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
 obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
 obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
 obj-$(CONFIG_PHY_NSP_USB3)		+= phy-bcm-nsp-usb3.o
+obj-$(CONFIG_PHY_MT7623_PCIE)		+= phy-mt7623-pcie.o
diff --git a/drivers/phy/phy-mt7623-pcie.c b/drivers/phy/phy-mt7623-pcie.c
new file mode 100644
index 0000000..4096c12
--- /dev/null
+++ b/drivers/phy/phy-mt7623-pcie.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Ryder Lee <ryder.lee@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Offsets of sub-segment in each port registers */
+#define PCIE_SIFSLV_PHYD_BANK2_BASE	0xa00
+#define SSUSB_SIFSLV_PHYA_BASE		0xb00
+#define SSUSB_SIFSLV_PHYA_DA_BASE	0xc00
+
+/*
+ * RX detection stable - 1 scale represent 8 reference cycles
+ * cover reference clock from 1M~100MHz, 7us~40us
+ */
+#define B2_PHYD_RXDET1			(PCIE_SIFSLV_PHYD_BANK2_BASE + 0x28)
+#define RG_SSUSB_RXDET_STB2		GENMASK(17, 9)
+#define RG_SSUSB_RXDET_STB2_VAL(x)	((0x1ff & (x)) << 9)
+
+#define B2_PHYD_RXDET2			(PCIE_SIFSLV_PHYD_BANK2_BASE + 0x2c)
+#define RG_SSUSB_RXDET_STB2_P3		GENMASK(8, 0)
+#define RG_SSUSB_RXDET_STB2_P3_VAL(x)	(0x1ff & (x))
+
+#define U3_PHYA_REG0			(SSUSB_SIFSLV_PHYA_BASE + 0x00)
+#define RG_PCIE_CLKDRV_OFFSET		GENMASK(3, 1)
+#define RG_PCIE_CLKDRV_OFFSET_VAL(x)	((0x3 & (x)) << 2)
+
+#define U3_PHYA_REG1			(SSUSB_SIFSLV_PHYA_BASE + 0x04)
+#define RG_PCIE_CLKDRV_AMP		GENMASK(31, 29)
+#define RG_PCIE_CLKDRV_AMP_VAL(x)	((0x7 & (x)) << 29)
+
+#define DA_SSUSB_CDR_REFCK_SEL		(SSUSB_SIFSLV_PHYA_DA_BASE + 0x00)
+#define RG_SSUSB_XTAL_EXT_PE1H		GENMASK(13, 12)
+#define RG_SSUSB_XTAL_EXT_PE1H_VAL(x)	((0x3 & (x)) << 12)
+#define RG_SSUSB_XTAL_EXT_PE2H		GENMASK(17, 16)
+#define RG_SSUSB_XTAL_EXT_PE2H_VAL(x)		((0x3 & (x)) << 16)
+
+#define DA_SSUSB_PLL_IC			(SSUSB_SIFSLV_PHYA_DA_BASE + 0x0c)
+#define RG_SSUSB_PLL_IC_PE2H		GENMASK(15, 12)
+#define RG_SSUSB_PLL_IC_PE2H_VAL(x)	((0xf & (x)) << 12)
+#define RG_SSUSB_PLL_BR_PE2H		GENMASK(29, 28)
+#define RG_SSUSB_PLL_BR_PE2H_VAL(x)	((0x3 & (x)) << 28)
+
+#define DA_SSUSB_PLL_BC			(SSUSB_SIFSLV_PHYA_DA_BASE + 0x08)
+#define RG_SSUSB_PLL_DIVEN_PE2H		GENMASK(21, 19)
+#define RG_SSUSB_PLL_BC_PE2H		GENMASK(7, 6)
+#define RG_SSUSB_PLL_BC_PE2H_VAL(x)	((0x3 & (x)) << 6)
+
+#define DA_SSUSB_PLL_IR			(SSUSB_SIFSLV_PHYA_DA_BASE + 0x10)
+#define RG_SSUSB_PLL_IR_PE2H		GENMASK(19, 16)
+#define RG_SSUSB_PLL_IR_PE2H_VAL(x)	((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_BP			(SSUSB_SIFSLV_PHYA_DA_BASE + 0x14)
+#define RG_SSUSB_PLL_BP_PE2H		GENMASK(19, 16)
+#define RG_SSUSB_PLL_BP_PE2H_VAL(x)	((0xf & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA1_REG20	(SSUSB_SIFSLV_PHYA_DA_BASE + 0x3c)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H		GENMASK(31, 16)
+#define RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(x)	((0xffff & (x)) << 16)
+
+#define DA_SSUSB_PLL_SSC_DELTA_REG25	(SSUSB_SIFSLV_PHYA_DA_BASE + 0x48)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H		GENMASK(15, 0)
+#define RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(x)	(0xffff & (x))
+
+#define HIF_SYSCFG1			0x14
+#define HIF_SYSCFG1_PHY2_MASK		(0x3 << 20)
+
+struct mtk_pcie_phy {
+	struct device *dev;
+	void __iomem *base;
+	struct regmap *hif;
+	struct clk *phya_ref;
+	struct phy *phy;
+};
+
+static inline u32 phy_read(struct mtk_pcie_phy *phy, u32 reg)
+{
+	return readl(phy->base + reg);
+}
+
+static inline void phy_write(struct mtk_pcie_phy *phy, u32 val, u32 reg)
+{
+	writel(val, phy->base + reg);
+}
+
+static int mtk_pcie_phy_power_on(struct phy *phy)
+{
+	struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+	int err;
+	u32 val;
+
+	/* PCIe port2 PHY is shared with USB u3phy2 */
+	if (mtk_phy->hif)
+		regmap_update_bits(mtk_phy->hif, HIF_SYSCFG1,
+				   HIF_SYSCFG1_PHY2_MASK, 0);
+
+	err = clk_prepare_enable(mtk_phy->phya_ref);
+	if (err) {
+		dev_err(mtk_phy->dev, "failed to enable PCIe phy clock\n");
+		return err;
+	}
+
+	val = phy_read(mtk_phy, DA_SSUSB_CDR_REFCK_SEL);
+	val &= ~(RG_SSUSB_XTAL_EXT_PE1H | RG_SSUSB_XTAL_EXT_PE2H);
+	val |= RG_SSUSB_XTAL_EXT_PE1H_VAL(0x2) |
+	       RG_SSUSB_XTAL_EXT_PE2H_VAL(0x2);
+	phy_write(mtk_phy, val, DA_SSUSB_CDR_REFCK_SEL);
+
+	/* ref clk drive */
+	val = phy_read(mtk_phy, U3_PHYA_REG1);
+	val &= ~RG_PCIE_CLKDRV_AMP;
+	val |= RG_PCIE_CLKDRV_AMP_VAL(0x4);
+	phy_write(mtk_phy, val, U3_PHYA_REG1);
+
+	val = phy_read(mtk_phy, U3_PHYA_REG0);
+	val &= ~RG_PCIE_CLKDRV_OFFSET;
+	val |= RG_PCIE_CLKDRV_OFFSET_VAL(0x1);
+	phy_write(mtk_phy, val, U3_PHYA_REG0);
+
+	/* SSC delta -5000ppm */
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+	val &= ~RG_SSUSB_PLL_SSC_DELTA1_PE2H;
+	val |= RG_SSUSB_PLL_SSC_DELTA1_PE2H_VAL(0x3c);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA1_REG20);
+
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_SSC_DELTA_REG25);
+	val &= ~RG_SSUSB_PLL_SSC_DELTA_PE2H;
+	val |= RG_SSUSB_PLL_SSC_DELTA_PE2H_VAL(0x36);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_SSC_DELTA_REG25);
+
+	/* change pll BW 0.6M */
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+	val &= ~RG_SSUSB_PLL_BR_PE2H;
+	val |= RG_SSUSB_PLL_BR_PE2H_VAL(0x1);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_BC);
+	val &= ~(RG_SSUSB_PLL_DIVEN_PE2H | RG_SSUSB_PLL_BC_PE2H);
+	val |= RG_SSUSB_PLL_BC_PE2H_VAL(0x3);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_BC);
+
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_IR);
+	val &= ~RG_SSUSB_PLL_IR_PE2H;
+	val |= RG_SSUSB_PLL_IR_PE2H_VAL(0x2);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_IR);
+
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_IC);
+	val &= ~RG_SSUSB_PLL_IC_PE2H;
+	val |= RG_SSUSB_PLL_IC_PE2H_VAL(0x1);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_IC);
+
+	val = phy_read(mtk_phy, DA_SSUSB_PLL_BP);
+	val &= ~RG_SSUSB_PLL_BP_PE2H;
+	val |= RG_SSUSB_PLL_BP_PE2H_VAL(0xa);
+	phy_write(mtk_phy, val, DA_SSUSB_PLL_BP);
+
+	/* Tx Detect Rx Timing: 10us -> 5us */
+	val = phy_read(mtk_phy, B2_PHYD_RXDET1);
+	val &= ~RG_SSUSB_RXDET_STB2;
+	val |= RG_SSUSB_RXDET_STB2_VAL(0x10);
+	phy_write(mtk_phy, val, B2_PHYD_RXDET1);
+
+	val = phy_read(mtk_phy, B2_PHYD_RXDET2);
+	val &= ~RG_SSUSB_RXDET_STB2_P3;
+	val |= RG_SSUSB_RXDET_STB2_P3_VAL(0x10);
+	phy_write(mtk_phy, val, B2_PHYD_RXDET2);
+
+	/* wait for PCIe subsys(MAC layer) register to active */
+	usleep_range(2500, 3000);
+
+	return 0;
+}
+
+static int mtk_pcie_phy_power_off(struct phy *phy)
+{
+	struct mtk_pcie_phy *mtk_phy = phy_get_drvdata(phy);
+
+	clk_disable_unprepare(mtk_phy->phya_ref);
+
+	return 0;
+}
+
+static struct phy_ops mtk_pcie_phy_ops = {
+	.power_on	= mtk_pcie_phy_power_on,
+	.power_off	= mtk_pcie_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id mtk_pcie_phy_of_match[];
+
+static int mtk_pcie_phy_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	const struct of_device_id *match;
+	struct phy_provider *phy_provider;
+	struct mtk_pcie_phy *mtk_phy;
+	struct resource *res;
+	struct phy *phy;
+
+	match = of_match_device(mtk_pcie_phy_of_match, &pdev->dev);
+	if (!match)
+		return -ENODEV;
+
+	mtk_phy = devm_kzalloc(&pdev->dev, sizeof(*mtk_phy), GFP_KERNEL);
+	if (!mtk_phy)
+		return -ENOMEM;
+
+	mtk_phy->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mtk_phy->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(mtk_phy->base)) {
+		dev_err(&pdev->dev, "failed to get phy base\n");
+		return PTR_ERR(mtk_phy->base);
+	}
+
+	mtk_phy->phya_ref = devm_clk_get(&pdev->dev, "pciephya_ref");
+	if (IS_ERR(mtk_phy->phya_ref)) {
+		dev_err(&pdev->dev, "error to get pciephya_ref\n");
+		return PTR_ERR(mtk_phy->phya_ref);
+	}
+
+	if (of_find_property(np, "phy-switch", NULL)) {
+		mtk_phy->hif = syscon_regmap_lookup_by_phandle(
+						np, "phy-switch");
+		if (IS_ERR(mtk_phy->hif)) {
+			dev_err(&pdev->dev, "missing \"phy-switch\" phandle\n");
+			return PTR_ERR(mtk_phy->hif);
+		}
+	}
+
+	platform_set_drvdata(pdev, mtk_phy);
+	phy = devm_phy_create(&pdev->dev, NULL, &mtk_pcie_phy_ops);
+	if (IS_ERR(phy)) {
+		dev_err(&pdev->dev, "failed to create phy device\n");
+		return PTR_ERR(phy);
+	}
+
+	mtk_phy->phy = phy;
+	phy_set_drvdata(phy, mtk_phy);
+
+	phy_provider = devm_of_phy_provider_register(&pdev->dev,
+						     of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(&pdev->dev, "failed to register phy provider\n");
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id mtk_pcie_phy_of_match[] = {
+	{ .compatible = "mediatek,mt7623-pcie-phy"},
+	{ .compatible = "mediatek,mt2701-pcie-phy"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, mtk_pcie_phy_of_match);
+
+static struct platform_driver mtk_pcie_phy_driver = {
+	.probe	= mtk_pcie_phy_probe,
+	.driver = {
+		.name	= "mtk-pcie-phy",
+		.of_match_table	= mtk_pcie_phy_of_match,
+	}
+};
+module_platform_driver(mtk_pcie_phy_driver);
+
+MODULE_AUTHOR("Ryder Lee <ryder.lee@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek PCIe phy driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1

^ permalink raw reply related


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